Moved func and arg members from GRealThread to GThread, such that they can
[platform/upstream/glib.git] / tests / thread-test.c
1 #include <glib.h>
2
3 /* GMutex */
4
5 static GMutex* test_g_mutex_mutex = NULL;
6 static guint test_g_mutex_int = 0;
7 G_LOCK_DEFINE_STATIC (test_g_mutex);
8
9 static gpointer
10 test_g_mutex_thread (gpointer data)
11 {
12   g_assert (GPOINTER_TO_INT (data) == 42);
13   g_assert (g_mutex_trylock (test_g_mutex_mutex) == FALSE);
14   g_assert (G_TRYLOCK (test_g_mutex) == FALSE);
15   g_mutex_lock (test_g_mutex_mutex);
16   g_assert (test_g_mutex_int == 42);
17   g_mutex_unlock (test_g_mutex_mutex);
18
19   return GINT_TO_POINTER (41);
20 }
21
22 static void
23 test_g_mutex (void)
24 {
25   GThread *thread;
26   test_g_mutex_mutex = g_mutex_new ();
27
28   g_assert (g_mutex_trylock (test_g_mutex_mutex));
29   g_assert (G_TRYLOCK (test_g_mutex));
30   thread = g_thread_create (test_g_mutex_thread, 
31                             GINT_TO_POINTER (42),
32                             0, TRUE, TRUE, G_THREAD_PRIORITY_NORMAL, NULL);
33   g_usleep (G_USEC_PER_SEC);
34   test_g_mutex_int = 42;
35   G_UNLOCK (test_g_mutex);
36   g_mutex_unlock (test_g_mutex_mutex);
37   g_assert (GPOINTER_TO_INT (g_thread_join (thread)) == 41);
38   g_mutex_free (test_g_mutex_mutex);
39 }
40
41 /* GStaticRecMutex */
42
43 static GStaticRecMutex test_g_static_rec_mutex_mutex = G_STATIC_REC_MUTEX_INIT;
44 static guint test_g_static_rec_mutex_int = 0;
45
46 static gpointer
47 test_g_static_rec_mutex_thread (gpointer data)
48 {
49   g_assert (GPOINTER_TO_INT (data) == 42);
50   g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex) 
51             == FALSE);
52   g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
53   g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
54   g_assert (test_g_static_rec_mutex_int == 42);
55   g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
56   g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
57
58   g_thread_exit (GINT_TO_POINTER (43));
59   
60   g_assert_not_reached ();
61   return NULL;
62 }
63
64 static void
65 test_g_static_rec_mutex (void)
66 {
67   GThread *thread;
68
69   g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
70   thread = g_thread_create (test_g_static_rec_mutex_thread, 
71                             GINT_TO_POINTER (42),
72                             0, TRUE, TRUE, G_THREAD_PRIORITY_NORMAL, NULL);
73   g_usleep (G_USEC_PER_SEC);
74   g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
75   g_usleep (G_USEC_PER_SEC);
76   test_g_static_rec_mutex_int = 41;
77   g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
78   test_g_static_rec_mutex_int = 42;  
79   g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
80   g_usleep (G_USEC_PER_SEC);
81   g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
82   test_g_static_rec_mutex_int = 0;  
83   g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
84
85   g_assert (GPOINTER_TO_INT (g_thread_join (thread)) == 43);
86 }
87
88 /* GStaticPrivate */
89
90 #define THREADS 10
91
92 static GStaticPrivate test_g_static_private_private1 = G_STATIC_PRIVATE_INIT;
93 static GStaticPrivate test_g_static_private_private2 = G_STATIC_PRIVATE_INIT;
94 static GStaticMutex test_g_static_private_mutex = G_STATIC_MUTEX_INIT;
95 static guint test_g_static_private_counter = 0;
96 static guint test_g_static_private_ready = 0;
97
98 static gpointer
99 test_g_static_private_constructor (void)
100 {
101   g_static_mutex_lock (&test_g_static_private_mutex);
102   test_g_static_private_counter++;
103   g_static_mutex_unlock (&test_g_static_private_mutex);  
104   return g_new (guint,1);
105 }
106
107 static void
108 test_g_static_private_destructor (gpointer data)
109 {
110   g_static_mutex_lock (&test_g_static_private_mutex);
111   test_g_static_private_counter--;
112   g_static_mutex_unlock (&test_g_static_private_mutex);  
113   g_free (data);
114 }
115
116
117 static gpointer
118 test_g_static_private_thread (gpointer data)
119 {
120   guint number = GPOINTER_TO_INT (data);
121   guint i;
122   guint *private1, *private2;
123   for (i = 0; i < 10; i++)
124     {
125       number = number * 11 + 1; /* A very simple and bad RNG ;-) */
126       private1 = g_static_private_get (&test_g_static_private_private1);
127       if (!private1 || number % 7 > 3)
128         {
129           private1 = test_g_static_private_constructor ();
130           g_static_private_set (&test_g_static_private_private1, private1,
131                                 test_g_static_private_destructor);
132         }
133       *private1 = number;
134       private2 = g_static_private_get (&test_g_static_private_private2);
135       if (!private2 || number % 13 > 5)
136         {
137           private2 = test_g_static_private_constructor ();
138           g_static_private_set (&test_g_static_private_private2, private2,
139                                 test_g_static_private_destructor);
140         }
141       *private2 = number * 2;
142       g_usleep (G_USEC_PER_SEC / 5);
143       g_assert (number == *private1);
144       g_assert (number * 2 == *private2);      
145     }
146   g_static_mutex_lock (&test_g_static_private_mutex);
147   test_g_static_private_ready++;
148   g_static_mutex_unlock (&test_g_static_private_mutex);  
149
150   /* Busy wait is not nice but that's just a test */
151   while (test_g_static_private_ready != 0)
152     g_usleep (G_USEC_PER_SEC / 5);  
153
154   for (i = 0; i < 10; i++)
155     {
156       private2 = g_static_private_get (&test_g_static_private_private2);
157       number = number * 11 + 1; /* A very simple and bad RNG ;-) */
158       if (!private2 || number % 13 > 5)
159         {
160           private2 = test_g_static_private_constructor ();
161           g_static_private_set (&test_g_static_private_private2, private2,
162                                 test_g_static_private_destructor);
163         }      
164       *private2 = number * 2;
165       g_usleep (G_USEC_PER_SEC / 5);
166       g_assert (number * 2 == *private2);      
167     }
168
169   return GINT_TO_POINTER (GPOINTER_TO_INT (data) * 3);
170 }
171
172 static void
173 test_g_static_private (void)
174 {
175   GThread *threads[THREADS];
176   guint i;
177
178   test_g_static_private_ready = 0;
179
180   for (i = 0; i < THREADS; i++)
181     {
182       threads[i] = g_thread_create (test_g_static_private_thread, 
183                                     GINT_TO_POINTER (i),
184                                     0, TRUE, TRUE, 
185                                     G_THREAD_PRIORITY_NORMAL, NULL);      
186     }
187
188   /* Busy wait is not nice but that's just a test */
189   while (test_g_static_private_ready != THREADS)
190     g_usleep (G_USEC_PER_SEC / 5);
191
192   /* Reuse the static private */
193   g_static_private_free (&test_g_static_private_private2);
194   g_static_private_init (&test_g_static_private_private2);
195   
196   test_g_static_private_ready = 0;
197
198   for (i = 0; i < THREADS; i++)
199     g_assert (GPOINTER_TO_INT (g_thread_join (threads[i])) == i * 3);
200     
201   g_assert (test_g_static_private_counter == 0); 
202 }
203
204 /* GStaticRWLock */
205
206 /* -1 = writing; >0 = # of readers */
207 static gint test_g_static_rw_lock_state = 0; 
208 G_LOCK_DEFINE (test_g_static_rw_lock_state);
209
210 static gboolean test_g_static_rw_lock_run = TRUE; 
211 static GStaticRWLock test_g_static_rw_lock_lock = G_STATIC_RW_LOCK_INIT;
212
213 static gpointer
214 test_g_static_rw_lock_thread (gpointer data)
215 {
216   while (test_g_static_rw_lock_run)
217     {
218       if (g_random_double() > .2) /* I'm a reader */
219         {
220           
221           if (g_random_double() > .2) /* I'll block */
222             g_static_rw_lock_reader_lock (&test_g_static_rw_lock_lock);
223           else /* I'll only try */
224             if (!g_static_rw_lock_reader_trylock (&test_g_static_rw_lock_lock))
225               continue;
226           G_LOCK (test_g_static_rw_lock_state);
227           g_assert (test_g_static_rw_lock_state >= 0);
228           test_g_static_rw_lock_state++;
229           G_UNLOCK (test_g_static_rw_lock_state);
230
231           g_usleep (10);
232
233           G_LOCK (test_g_static_rw_lock_state);
234           test_g_static_rw_lock_state--;
235           G_UNLOCK (test_g_static_rw_lock_state);
236
237           g_static_rw_lock_reader_unlock (&test_g_static_rw_lock_lock);
238         }
239       else /* I'm a writer */
240         {
241           
242           if (g_random_double() > .2) /* I'll block */ 
243             g_static_rw_lock_writer_lock (&test_g_static_rw_lock_lock);
244           else /* I'll only try */
245             if (!g_static_rw_lock_writer_trylock (&test_g_static_rw_lock_lock))
246               continue;
247           G_LOCK (test_g_static_rw_lock_state);
248           g_assert (test_g_static_rw_lock_state == 0);
249           test_g_static_rw_lock_state = -1;
250           G_UNLOCK (test_g_static_rw_lock_state);
251
252           g_usleep (10);
253
254           G_LOCK (test_g_static_rw_lock_state);
255           test_g_static_rw_lock_state = 0;
256           G_UNLOCK (test_g_static_rw_lock_state);
257
258           g_static_rw_lock_writer_unlock (&test_g_static_rw_lock_lock);
259         }
260     }
261   return NULL;
262 }
263
264 static void
265 test_g_static_rw_lock ()
266 {
267   GThread *threads[THREADS];
268   guint i;
269   for (i = 0; i < THREADS; i++)
270     {
271       threads[i] = g_thread_create (test_g_static_rw_lock_thread, 
272                                     0, 0, TRUE, TRUE, 
273                                     G_THREAD_PRIORITY_NORMAL, NULL);      
274     }
275   g_usleep (G_USEC_PER_SEC);
276   test_g_static_rw_lock_run = FALSE;
277   for (i = 0; i < THREADS; i++)
278     {
279       g_thread_join (threads[i]);
280     }
281   g_assert (test_g_static_rw_lock_state == 0);
282 }
283
284 /* run all the tests */
285 void
286 run_all_tests()
287 {
288   test_g_mutex ();
289   test_g_static_rec_mutex ();
290   test_g_static_private ();
291   test_g_static_rw_lock ();
292 }
293
294 int 
295 main (int   argc,
296       char *argv[])
297 {
298   /* Only run the test, if threads are enabled and a default thread
299      implementation is available */
300 #if defined(G_THREADS_ENABLED) && ! defined(G_THREADS_IMPL_NONE)
301   g_thread_init (NULL);
302   run_all_tests ();
303
304   /* Now we rerun all tests, but this time we fool the system into
305    * thinking, that the available thread system is not native, but
306    * userprovided. */
307
308   g_thread_use_default_impl = FALSE;
309   run_all_tests ();
310   
311 #endif
312   return 0;
313 }