#include "config.h" #include #define main testglib_main #include #undef main #define TEST_PRIVATE_THREADS 9 #define TEST_PRIVATE_ROUNDS 5 void test_mutexes (void) { GMutex *mutex = NULL; GCond *cond = NULL; GStaticMutex static_mutex = G_STATIC_MUTEX_INIT; G_LOCK_DEFINE (test_me); if (g_thread_supported ()) { mutex = g_mutex_new (); cond = g_cond_new (); } g_mutex_lock (mutex); g_mutex_unlock (mutex); g_static_mutex_lock (&static_mutex); g_static_mutex_unlock (&static_mutex); g_cond_signal (cond); g_cond_broadcast (cond); G_LOCK (test_me); G_UNLOCK (test_me); if (g_thread_supported ()) { g_cond_free (cond); g_mutex_free (mutex); } } #if defined(G_THREADS_IMPL_NSPR) #warning "note, that you have to link with whatever library" #warning "nspr is building upon, it might otherwise (as on solaris) lead to" #warning "run time failure, as the mutex functions are defined in libc, but" #warning "as noops, that will make some nspr assertions fail." #include gpointer new_thread (GHookFunc func, gpointer data) { PRThread *thread = PR_CreateThread (PR_SYSTEM_THREAD, func, data, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); return thread; } #define join_thread(thread) PR_JoinThread (thread) #define self_thread() PR_GetCurrentThread () #elif defined(G_THREADS_IMPL_SOLARIS) #include gpointer new_thread (GHookFunc func, gpointer data) { thread_t thread; thr_create (NULL, 0, (void *(*)(void *)) func, data, THR_BOUND, &thread); return GUINT_TO_POINTER (thread); } #define join_thread(thread) \ thr_join ((thread_t)GPOINTER_TO_UINT (thread), NULL, NULL) #define self_thread() GUINT_TO_POINTER (thr_self ()) #elif defined(G_THREADS_IMPL_POSIX) #include gpointer new_thread(GHookFunc func, gpointer data) { pthread_t thread; pthread_attr_t pthread_attr; pthread_attr_init (&pthread_attr); /* This is the default, it seems, so leave that out for now pthread_attr_setdetachstate (&pthread_attr, PTHREAD_CREATE_JOINABLE); */ pthread_create (&thread, &pthread_attr, (void *(*)(void *)) func, data); return GUINT_TO_POINTER (thread); } #define join_thread(thread) \ pthread_join ((pthread_t)GPOINTER_TO_UINT (thread), NULL) #define self_thread() GUINT_TO_POINTER (pthread_self ()) #else /* we are not having a thread implementation, do nothing */ #define new_thread(func,data) (NULL) #define join_thread(thread) ((void)0) #define self_thread() NULL #endif #define G_MICROSEC 1000000 void wait_thread (double seconds) { GMutex *mutex; GCond *cond; GTimeVal current_time; g_get_current_time (¤t_time); mutex = g_mutex_new (); cond = g_cond_new (); current_time.tv_sec += (guint) seconds; seconds -= (guint) seconds; current_time.tv_usec += (guint) (seconds * G_MICROSEC); while (current_time.tv_usec >= G_MICROSEC) { current_time.tv_usec -= G_MICROSEC; current_time.tv_sec++; } g_mutex_lock (mutex); g_cond_timed_wait (cond, mutex, ¤t_time); g_mutex_unlock (mutex); g_mutex_free (mutex); g_cond_free (cond); } gpointer private_constructor (void) { gpointer *result = g_new (gpointer, 2); result[0] = 0; result[1] = self_thread (); g_print ("allocating data for the thread %p.\n", result[1]); return result; } void private_destructor (gpointer data) { gpointer *real = data; g_print ("freeing data for the thread %p.\n", real[1]); g_free (real); } GStaticPrivate private_key; void test_private_func (void *data) { guint i = 0; static unsigned int seed = 0; if (!seed) { GTimeVal now; g_get_current_time (&now); seed = now.tv_usec; } wait_thread (1); while (i < TEST_PRIVATE_ROUNDS) { #ifdef HAVE_RAND_R guint random_value = rand_r (&seed) % 10000; #else guint random_value = rand() % 10000; #endif guint *data = g_static_private_get (&private_key); if (!data) { data = private_constructor (); g_static_private_set (&private_key, data, private_destructor); } *data = random_value; wait_thread (.2); g_assert (*(guint *) g_static_private_get (&private_key) == random_value); i++; } } void test_private (void) { int i; gpointer threads[TEST_PRIVATE_THREADS]; for (i = 0; i < TEST_PRIVATE_THREADS; i++) { threads[i] = new_thread (test_private_func, GINT_TO_POINTER(i)); } for (i = 0; i < TEST_PRIVATE_THREADS; i++) { join_thread (threads[i]); } g_print ("\n"); } int main (void) { test_mutexes (); g_thread_init (NULL); test_mutexes (); test_private (); /* later we might want to start n copies of that */ testglib_main (0, NULL); return 0; }