Changed signature of all g_static_mutex_* functions to take a pointer
[platform/upstream/glib.git] / gthread / testgthread.c
1 #include "config.h"
2
3 #include <stdlib.h>
4
5 #define main testglib_main
6 #include <testglib.c>
7 #undef main
8
9 #define TEST_PRIVATE_THREADS 9
10 #define TEST_PRIVATE_ROUNDS 5
11
12 void
13 test_mutexes (void)
14 {
15   GMutex *mutex = NULL;
16   GCond *cond = NULL;
17   GStaticMutex static_mutex = G_STATIC_MUTEX_INIT;
18   G_LOCK_DEFINE (test_me);
19
20   if (g_thread_supported ())
21     {
22       mutex = g_mutex_new ();
23       cond = g_cond_new ();
24     }
25
26   g_mutex_lock (mutex);
27   g_mutex_unlock (mutex);
28
29   g_static_mutex_lock (&static_mutex);
30   g_static_mutex_unlock (&static_mutex);
31
32   g_cond_signal (cond);
33   g_cond_broadcast (cond);
34
35   G_LOCK (test_me);
36   G_UNLOCK (test_me);
37
38   if (g_thread_supported ())
39     {
40       g_cond_free (cond);
41       g_mutex_free (mutex);
42     }
43 }
44
45 #if defined(G_THREADS_IMPL_NSPR)        
46 #warning "note, that you have to link with whatever library"
47 #warning "nspr is building upon, it might otherwise (as on solaris) lead to"
48 #warning "run time failure, as the mutex functions are defined in libc, but"
49 #warning "as noops, that will make some nspr assertions fail."
50 #include <prthread.h>
51
52 gpointer
53 new_thread (GHookFunc func, gpointer data)
54 {
55   PRThread *thread = PR_CreateThread (PR_SYSTEM_THREAD, func, data,
56                                       PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
57                                       PR_JOINABLE_THREAD, 0);
58   return thread;
59 }
60 #define join_thread(thread) PR_JoinThread (thread)
61 #define self_thread() PR_GetCurrentThread ()
62
63 #elif defined(G_THREADS_IMPL_SOLARIS)   
64 #include <thread.h>
65
66 gpointer
67 new_thread (GHookFunc func, gpointer data)
68 {
69   thread_t thread;
70   thr_create (NULL, 0, (void *(*)(void *)) func, data, THR_BOUND, &thread);
71   return GUINT_TO_POINTER (thread);
72 }
73 #define join_thread(thread) \
74   thr_join ((thread_t)GPOINTER_TO_UINT (thread), NULL, NULL)
75 #define self_thread()  GUINT_TO_POINTER (thr_self ())
76
77 #elif defined(G_THREADS_IMPL_POSIX)
78 #include <pthread.h>
79
80 gpointer
81 new_thread(GHookFunc func, gpointer data)
82 {
83   pthread_t thread;
84   pthread_attr_t pthread_attr;
85   pthread_attr_init (&pthread_attr);
86   /* This is the default, it seems, so leave that out for now 
87      pthread_attr_setdetachstate (&pthread_attr, PTHREAD_CREATE_JOINABLE);
88   */
89   pthread_create (&thread, &pthread_attr, (void *(*)(void *)) func, data);
90   return GUINT_TO_POINTER (thread);
91 }
92 #define join_thread(thread) \
93   pthread_join ((pthread_t)GPOINTER_TO_UINT (thread), NULL)
94 #define self_thread() GUINT_TO_POINTER (pthread_self ())
95
96 #else /* we are not having a thread implementation, do nothing */
97
98 #define new_thread(func,data) (NULL)
99 #define join_thread(thread) ((void)0)
100 #define self_thread() NULL
101
102 #endif
103
104 #define G_MICROSEC 1000000
105
106 void
107 wait_thread (double seconds)
108 {
109   GMutex *mutex;
110   GCond *cond;
111   GTimeVal current_time;
112
113   g_get_current_time (&current_time);
114   mutex = g_mutex_new ();
115   cond = g_cond_new ();
116
117   current_time.tv_sec += (guint) seconds;
118   seconds -= (guint) seconds;
119   current_time.tv_usec += (guint) (seconds * G_MICROSEC);
120   while (current_time.tv_usec >= G_MICROSEC)
121     {
122       current_time.tv_usec -= G_MICROSEC;
123       current_time.tv_sec++;
124     }
125
126   g_mutex_lock (mutex);
127   g_cond_timed_wait (cond, mutex, &current_time);
128   g_mutex_unlock (mutex);
129
130   g_mutex_free (mutex);
131   g_cond_free (cond);
132 }
133
134 gpointer
135 private_constructor (void)
136 {
137   gpointer *result = g_new (gpointer, 2);
138   result[0] = 0;
139   result[1] = self_thread ();
140   g_print ("allocating data for the thread %p.\n", result[1]);
141   return result;
142 }
143
144 void
145 private_destructor (gpointer data)
146 {
147   gpointer *real = data;
148   g_print ("freeing data for the thread %p.\n", real[1]);
149   g_free (real);
150 }
151
152 GStaticPrivate private_key;
153
154 void
155 test_private_func (void *data)
156 {
157   guint i = 0;
158   static unsigned int seed = 0;
159   if (!seed)
160     {
161       GTimeVal now;
162       g_get_current_time (&now);
163       seed = now.tv_usec;
164     }
165   wait_thread (1);
166   while (i < TEST_PRIVATE_ROUNDS)
167     {
168 #ifdef HAVE_RAND_R
169       guint random_value = rand_r (&seed) % 10000;
170 #else
171       guint random_value = rand() % 10000;
172 #endif
173       guint *data = g_static_private_get (&private_key);
174       if (!data)
175         {
176           data = private_constructor ();
177           g_static_private_set (&private_key, data, private_destructor);
178         }
179       *data = random_value;
180       wait_thread (.2);
181       g_assert (*(guint *) g_static_private_get (&private_key) == random_value);
182       i++;
183     }
184 }
185
186 void
187 test_private (void)
188 {
189   int i;
190   gpointer threads[TEST_PRIVATE_THREADS];
191   for (i = 0; i < TEST_PRIVATE_THREADS; i++)
192     {
193       threads[i] = new_thread (test_private_func, GINT_TO_POINTER(i));
194     }
195   for (i = 0; i < TEST_PRIVATE_THREADS; i++)
196     {
197       join_thread (threads[i]);
198     }
199   g_print ("\n");
200 }
201
202 int
203 main (void)
204 {
205   test_mutexes ();
206
207   g_thread_init (NULL);
208
209   test_mutexes ();
210
211   test_private ();
212
213   /* later we might want to start n copies of that */
214   testglib_main (0, NULL);
215
216   return 0;
217 }