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