Branch data Line data Source code
1 : : #ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
2 : : #define GLIB_DISABLE_DEPRECATION_WARNINGS
3 : : #endif
4 : :
5 : : #include <glib.h>
6 : :
7 : : /* GMutex */
8 : :
9 : : static GMutex test_g_mutex_mutex;
10 : : static guint test_g_mutex_int = 0;
11 : : static gboolean test_g_mutex_thread_ready;
12 : : G_LOCK_DEFINE_STATIC (test_g_mutex);
13 : :
14 : : static gpointer
15 : 2 : test_g_mutex_thread (gpointer data)
16 : : {
17 : 2 : g_assert_cmpint (GPOINTER_TO_INT (data), ==, 42);
18 : 2 : g_assert_false (g_mutex_trylock (&test_g_mutex_mutex));
19 : 2 : g_assert_false (G_TRYLOCK (test_g_mutex));
20 : 2 : test_g_mutex_thread_ready = TRUE;
21 : 2 : g_mutex_lock (&test_g_mutex_mutex);
22 : 2 : g_assert_cmpint (test_g_mutex_int, ==, 42);
23 : 2 : g_mutex_unlock (&test_g_mutex_mutex);
24 : :
25 : 2 : return GINT_TO_POINTER (41);
26 : : }
27 : :
28 : : static void
29 : 2 : test_g_mutex (void)
30 : : {
31 : : GThread *thread;
32 : :
33 : 2 : g_assert_true (g_mutex_trylock (&test_g_mutex_mutex));
34 : 2 : g_assert_true (G_TRYLOCK (test_g_mutex));
35 : 2 : test_g_mutex_thread_ready = FALSE;
36 : 2 : thread = g_thread_create (test_g_mutex_thread, GINT_TO_POINTER (42),
37 : : TRUE, NULL);
38 : : /* This busy wait is only for testing purposes and not an example of
39 : : * good code!*/
40 [ + + ]: 4 : while (!test_g_mutex_thread_ready)
41 : 2 : g_usleep (G_USEC_PER_SEC / 5);
42 : 2 : test_g_mutex_int = 42;
43 : 2 : G_UNLOCK (test_g_mutex);
44 : 2 : g_mutex_unlock (&test_g_mutex_mutex);
45 : 2 : g_assert_cmpint (GPOINTER_TO_INT (g_thread_join (thread)), ==, 41);
46 : 2 : }
47 : :
48 : : /* GStaticRecMutex */
49 : :
50 : : static GStaticRecMutex test_g_static_rec_mutex_mutex = G_STATIC_REC_MUTEX_INIT;
51 : : static guint test_g_static_rec_mutex_int = 0;
52 : : static gboolean test_g_static_rec_mutex_thread_ready;
53 : :
54 : : static gpointer
55 : 2 : test_g_static_rec_mutex_thread (gpointer data)
56 : : {
57 : 2 : g_assert_cmpint (GPOINTER_TO_INT (data), ==, 42);
58 : 2 : g_assert_false (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
59 : :
60 : 2 : test_g_static_rec_mutex_thread_ready = TRUE;
61 : 2 : g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
62 : 2 : g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
63 : 2 : g_assert_cmpint (test_g_static_rec_mutex_int, ==, 42);
64 : :
65 : 2 : test_g_static_rec_mutex_thread_ready = FALSE;
66 : 2 : g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
67 : 2 : g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
68 : :
69 : 2 : g_thread_exit (GINT_TO_POINTER (43));
70 : :
71 : : g_assert_not_reached ();
72 : : return NULL;
73 : : }
74 : :
75 : : static void
76 : 2 : test_g_static_rec_mutex (void)
77 : : {
78 : : GThread *thread;
79 : :
80 : 2 : g_assert_true (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
81 : 2 : test_g_static_rec_mutex_thread_ready = FALSE;
82 : 2 : thread = g_thread_create (test_g_static_rec_mutex_thread,
83 : : GINT_TO_POINTER (42), TRUE, NULL);
84 : : /* This busy wait is only for testing purposes and not an example of
85 : : * good code!*/
86 [ + + ]: 4 : while (!test_g_static_rec_mutex_thread_ready)
87 : 2 : g_usleep (G_USEC_PER_SEC / 5);
88 : :
89 : 2 : g_assert_true (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
90 : 2 : test_g_static_rec_mutex_int = 41;
91 : 2 : g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
92 : 2 : test_g_static_rec_mutex_int = 42;
93 : 2 : g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
94 : :
95 : : /* This busy wait is only for testing purposes and not an example of
96 : : * good code!*/
97 [ + + ]: 4 : while (test_g_static_rec_mutex_thread_ready)
98 : 2 : g_usleep (G_USEC_PER_SEC / 5);
99 : :
100 : 2 : g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
101 : 2 : test_g_static_rec_mutex_int = 0;
102 : 2 : g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
103 : :
104 : 2 : g_assert_cmpint (GPOINTER_TO_INT (g_thread_join (thread)), ==, 43);
105 : 2 : }
106 : :
107 : : /* GStaticPrivate */
108 : :
109 : : #define THREADS 10
110 : :
111 : : static GStaticPrivate test_g_static_private_private1 = G_STATIC_PRIVATE_INIT;
112 : : static GStaticPrivate test_g_static_private_private2 = G_STATIC_PRIVATE_INIT;
113 : : static GMutex test_g_static_private_mutex;
114 : : static guint test_g_static_private_counter = 0;
115 : : static guint test_g_static_private_ready = 0;
116 : :
117 : : static gpointer
118 : 313 : test_g_static_private_constructor (void)
119 : : {
120 : 313 : g_mutex_lock (&test_g_static_private_mutex);
121 : 313 : test_g_static_private_counter++;
122 : 313 : g_mutex_unlock (&test_g_static_private_mutex);
123 : 313 : return g_new (guint,1);
124 : : }
125 : :
126 : : static void
127 : 313 : test_g_static_private_destructor (gpointer data)
128 : : {
129 : 313 : g_mutex_lock (&test_g_static_private_mutex);
130 : 313 : test_g_static_private_counter--;
131 : 313 : g_mutex_unlock (&test_g_static_private_mutex);
132 : 313 : g_free (data);
133 : 313 : }
134 : :
135 : :
136 : : static gpointer
137 : 20 : test_g_static_private_thread (gpointer data)
138 : : {
139 : 20 : guint number = GPOINTER_TO_INT (data);
140 : : guint i;
141 : : guint *private1, *private2;
142 [ + + ]: 220 : for (i = 0; i < 10; i++)
143 : : {
144 : 200 : number = number * 11 + 1; /* A very simple and bad RNG ;-) */
145 : 200 : private1 = g_static_private_get (&test_g_static_private_private1);
146 [ + + + + ]: 200 : if (!private1 || number % 7 > 3)
147 : : {
148 : 86 : private1 = test_g_static_private_constructor ();
149 : 86 : g_static_private_set (&test_g_static_private_private1, private1,
150 : : test_g_static_private_destructor);
151 : : }
152 : 200 : *private1 = number;
153 : 200 : private2 = g_static_private_get (&test_g_static_private_private2);
154 [ + + + + ]: 200 : if (!private2 || number % 13 > 5)
155 : : {
156 : 118 : private2 = test_g_static_private_constructor ();
157 : 118 : g_static_private_set (&test_g_static_private_private2, private2,
158 : : test_g_static_private_destructor);
159 : : }
160 : 200 : *private2 = number * 2;
161 : 200 : g_usleep (G_USEC_PER_SEC / 5);
162 : 200 : g_assert_cmpint (number, ==, *private1);
163 : 200 : g_assert_cmpint (number * 2, ==, *private2);
164 : : }
165 : 20 : g_mutex_lock (&test_g_static_private_mutex);
166 : 20 : test_g_static_private_ready++;
167 : 20 : g_mutex_unlock (&test_g_static_private_mutex);
168 : :
169 : : /* Busy wait is not nice but that's just a test */
170 [ + + ]: 50 : while (test_g_static_private_ready != 0)
171 : 30 : g_usleep (G_USEC_PER_SEC / 5);
172 : :
173 [ + + ]: 220 : for (i = 0; i < 10; i++)
174 : : {
175 : 200 : private2 = g_static_private_get (&test_g_static_private_private2);
176 : 200 : number = number * 11 + 1; /* A very simple and bad RNG ;-) */
177 [ + + + + ]: 200 : if (!private2 || number % 13 > 5)
178 : : {
179 : 109 : private2 = test_g_static_private_constructor ();
180 : 109 : g_static_private_set (&test_g_static_private_private2, private2,
181 : : test_g_static_private_destructor);
182 : : }
183 : 200 : *private2 = number * 2;
184 : 200 : g_usleep (G_USEC_PER_SEC / 5);
185 : 200 : g_assert_cmpint (number * 2, ==, *private2);
186 : : }
187 : :
188 : 20 : return GINT_TO_POINTER (GPOINTER_TO_INT (data) * 3);
189 : : }
190 : :
191 : : static void
192 : 2 : test_g_static_private (void)
193 : : {
194 : : GThread *threads[THREADS];
195 : : guint i;
196 : :
197 : 2 : test_g_static_private_ready = 0;
198 : :
199 [ + + ]: 22 : for (i = 0; i < THREADS; i++)
200 : : {
201 : 20 : threads[i] = g_thread_create (test_g_static_private_thread,
202 : 20 : GINT_TO_POINTER (i), TRUE, NULL);
203 : : }
204 : :
205 : : /* Busy wait is not nice but that's just a test */
206 [ + + ]: 24 : while (test_g_static_private_ready != THREADS)
207 : 22 : g_usleep (G_USEC_PER_SEC / 5);
208 : :
209 : : /* Reuse the static private */
210 : 2 : g_static_private_free (&test_g_static_private_private2);
211 : 2 : g_static_private_init (&test_g_static_private_private2);
212 : :
213 : 2 : test_g_static_private_ready = 0;
214 : :
215 [ + + ]: 22 : for (i = 0; i < THREADS; i++)
216 : 20 : g_assert_cmpint (GPOINTER_TO_UINT (g_thread_join (threads[i])), ==, i * 3);
217 : :
218 : 2 : g_assert_cmpint (test_g_static_private_counter, ==, 0);
219 : 2 : }
220 : :
221 : : /* GStaticRWLock */
222 : :
223 : : /* -1 = writing; >0 = # of readers */
224 : : static gint test_g_static_rw_lock_state = 0;
225 : : G_LOCK_DEFINE (test_g_static_rw_lock_state);
226 : :
227 : : static gboolean test_g_static_rw_lock_run = TRUE;
228 : : static GStaticRWLock test_g_static_rw_lock_lock = G_STATIC_RW_LOCK_INIT;
229 : :
230 : : static gpointer
231 : 20 : test_g_static_rw_lock_thread (gpointer data)
232 : : {
233 [ + + ]: 25173 : while (test_g_static_rw_lock_run)
234 : : {
235 [ + + ]: 25153 : if (g_random_double() > .2) /* I'm a reader */
236 : : {
237 : :
238 [ + + ]: 20095 : if (g_random_double() > .2) /* I'll block */
239 : 16145 : g_static_rw_lock_reader_lock (&test_g_static_rw_lock_lock);
240 : : else /* I'll only try */
241 [ + + ]: 3950 : if (!g_static_rw_lock_reader_trylock (&test_g_static_rw_lock_lock))
242 : 2547 : continue;
243 : 17548 : G_LOCK (test_g_static_rw_lock_state);
244 : 17548 : g_assert_cmpint (test_g_static_rw_lock_state, >=, 0);
245 : 17548 : test_g_static_rw_lock_state++;
246 : 17548 : G_UNLOCK (test_g_static_rw_lock_state);
247 : :
248 : 17548 : g_usleep (g_random_int_range (20,1000));
249 : :
250 : 17548 : G_LOCK (test_g_static_rw_lock_state);
251 : 17548 : test_g_static_rw_lock_state--;
252 : 17548 : G_UNLOCK (test_g_static_rw_lock_state);
253 : :
254 : 17548 : g_static_rw_lock_reader_unlock (&test_g_static_rw_lock_lock);
255 : : }
256 : : else /* I'm a writer */
257 : : {
258 [ + + ]: 5058 : if (g_random_double () > .2) /* I'll block */
259 : 3994 : g_static_rw_lock_writer_lock (&test_g_static_rw_lock_lock);
260 : : else /* I'll only try */
261 [ + + ]: 1064 : if (!g_static_rw_lock_writer_trylock (&test_g_static_rw_lock_lock))
262 : 854 : continue;
263 : 4204 : G_LOCK (test_g_static_rw_lock_state);
264 : 4204 : g_assert_cmpint (test_g_static_rw_lock_state, ==, 0);
265 : 4204 : test_g_static_rw_lock_state = -1;
266 : 4204 : G_UNLOCK (test_g_static_rw_lock_state);
267 : :
268 : 4204 : g_usleep (g_random_int_range (20,1000));
269 : :
270 : 4204 : G_LOCK (test_g_static_rw_lock_state);
271 : 4204 : test_g_static_rw_lock_state = 0;
272 : 4204 : G_UNLOCK (test_g_static_rw_lock_state);
273 : :
274 : 4204 : g_static_rw_lock_writer_unlock (&test_g_static_rw_lock_lock);
275 : : }
276 : : }
277 : 20 : return NULL;
278 : : }
279 : :
280 : : static void
281 : 2 : test_g_static_rw_lock (void)
282 : : {
283 : : GThread *threads[THREADS];
284 : : guint i;
285 [ + + ]: 22 : for (i = 0; i < THREADS; i++)
286 : : {
287 : 20 : threads[i] = g_thread_create (test_g_static_rw_lock_thread,
288 : : NULL, TRUE, NULL);
289 : : }
290 : 2 : g_usleep (G_USEC_PER_SEC * 5);
291 : 2 : test_g_static_rw_lock_run = FALSE;
292 [ + + ]: 22 : for (i = 0; i < THREADS; i++)
293 : : {
294 : 20 : g_thread_join (threads[i]);
295 : : }
296 : 2 : g_assert_cmpint (test_g_static_rw_lock_state, ==, 0);
297 : 2 : }
298 : :
299 : : #define G_ONCE_SIZE 100
300 : : #define G_ONCE_THREADS 10
301 : :
302 : : G_LOCK_DEFINE (test_g_once);
303 : : static guint test_g_once_guint_array[G_ONCE_SIZE];
304 : : static GOnce test_g_once_array[G_ONCE_SIZE];
305 : :
306 : : static gpointer
307 : 200 : test_g_once_init_func(gpointer arg)
308 : : {
309 : 200 : guint *count = arg;
310 : 200 : g_usleep (g_random_int_range (20,1000));
311 : 200 : (*count)++;
312 : 200 : g_usleep (g_random_int_range (20,1000));
313 : 200 : return arg;
314 : : }
315 : :
316 : : static gpointer
317 : 20 : test_g_once_thread (gpointer ignore)
318 : : {
319 : : guint i;
320 : 20 : G_LOCK (test_g_once);
321 : : /* Don't start before all threads are created */
322 : 20 : G_UNLOCK (test_g_once);
323 [ + + ]: 20020 : for (i = 0; i < 1000; i++)
324 : : {
325 : 20000 : guint pos = g_random_int_range (0, G_ONCE_SIZE);
326 [ + + ]: 20000 : gpointer ret = g_once (test_g_once_array + pos,
327 : : test_g_once_init_func,
328 : : test_g_once_guint_array + pos);
329 : 20000 : g_assert_cmpmem (ret, sizeof (int),
330 : : test_g_once_guint_array + pos, sizeof (int));
331 : : }
332 : :
333 : : /* Make sure, that all counters are touched at least once */
334 [ + + ]: 2020 : for (i = 0; i < G_ONCE_SIZE; i++)
335 : : {
336 [ + - ]: 2000 : gpointer ret = g_once (test_g_once_array + i,
337 : : test_g_once_init_func,
338 : : test_g_once_guint_array + i);
339 : 2000 : g_assert_cmpmem (ret, sizeof (int),
340 : : test_g_once_guint_array + i, sizeof (int));
341 : : }
342 : :
343 : 20 : return NULL;
344 : : }
345 : :
346 : : static void
347 : 2 : test_g_thread_once (void)
348 : : {
349 : : static GOnce once_init = G_ONCE_INIT;
350 : : GThread *threads[G_ONCE_THREADS];
351 : : guint i;
352 [ + + ]: 202 : for (i = 0; i < G_ONCE_SIZE; i++)
353 : : {
354 : 200 : test_g_once_array[i] = once_init;
355 : 200 : test_g_once_guint_array[i] = i;
356 : : }
357 : 2 : G_LOCK (test_g_once);
358 [ + + ]: 22 : for (i = 0; i < G_ONCE_THREADS; i++)
359 : : {
360 : 20 : threads[i] = g_thread_create (test_g_once_thread, GUINT_TO_POINTER (i % 2),
361 : : TRUE, NULL);
362 : : }
363 : 2 : G_UNLOCK (test_g_once);
364 [ + + ]: 22 : for (i = 0; i < G_ONCE_THREADS; i++)
365 : : {
366 : 20 : g_thread_join (threads[i]);
367 : : }
368 : :
369 [ + + ]: 202 : for (i = 0; i < G_ONCE_SIZE; i++)
370 : : {
371 : 200 : g_assert_cmpint (test_g_once_guint_array[i], ==, i + 1);
372 : : }
373 : 2 : }
374 : :
375 : : /* rerun all the tests */
376 : : static void
377 : 1 : test_rerun_all (void)
378 : : {
379 : : /* Now we rerun all tests, but this time we fool the system into
380 : : * thinking, that the available thread system is not native, but
381 : : * userprovided. */
382 : 1 : g_thread_use_default_impl = FALSE;
383 : :
384 : 1 : test_g_mutex ();
385 : 1 : test_g_static_rec_mutex ();
386 : 1 : test_g_static_private ();
387 : 1 : test_g_static_rw_lock ();
388 : 1 : test_g_thread_once ();
389 : :
390 : : /* XXX: And this shows how silly the above non-native tests are */
391 : 1 : g_static_rw_lock_free (&test_g_static_rw_lock_lock);
392 : 1 : g_static_rec_mutex_free (&test_g_static_rec_mutex_mutex);
393 : 1 : g_static_private_free (&test_g_static_private_private2);
394 : 1 : }
395 : :
396 : : int
397 : 1 : main (int argc,
398 : : char *argv[])
399 : : {
400 : 1 : g_test_init (&argc, &argv, NULL);
401 : :
402 : 1 : g_test_add_func ("/thread/mutex", test_g_mutex);
403 : 1 : g_test_add_func ("/thread/static-rec-mutex", test_g_static_rec_mutex);
404 : 1 : g_test_add_func ("/thread/static-private", test_g_static_private);
405 : 1 : g_test_add_func ("/thread/static-rw-lock", test_g_static_rw_lock);
406 : 1 : g_test_add_func ("/thread/once", test_g_thread_once);
407 : 1 : g_test_add_func ("/thread/rerun-all", test_rerun_all);
408 : :
409 : 1 : return g_test_run ();
410 : : }
|