1 /* g_once_init_*() test
2 * Copyright (C) 2007 Tim Janik
4 * This work is provided "as is"; redistribution and modification
5 * in whole or in part, in any medium, physical or electronic is
6 * permitted without restriction.
8 * This work is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * In no event shall the authors or contributors be liable for any
13 * direct, indirect, incidental, special, exemplary, or consequential
14 * damages (including, but not limited to, procurement of substitute
15 * goods or services; loss of use, data, or profits; or business
16 * interruption) however caused and on any theory of liability, whether
17 * in contract, strict liability, or tort (including negligence or
18 * otherwise) arising in any way out of the use of this software, even
19 * if advised of the possibility of such damage.
24 #define N_THREADS (11)
26 static GMutex *tmutex = NULL;
27 static GCond *tcond = NULL;
28 static volatile int tmain_call_count = 0;
29 static char dummy_value = 'x';
32 assert_singleton_execution1 (void)
34 static volatile int seen_execution = 0;
35 int old_seen_execution = g_atomic_int_exchange_and_add (&seen_execution, 1);
36 if (old_seen_execution != 0)
37 g_error ("%s: function executed more than once", G_STRFUNC);
41 assert_singleton_execution2 (void)
43 static volatile int seen_execution = 0;
44 int old_seen_execution = g_atomic_int_exchange_and_add (&seen_execution, 1);
45 if (old_seen_execution != 0)
46 g_error ("%s: function executed more than once", G_STRFUNC);
50 assert_singleton_execution3 (void)
52 static volatile int seen_execution = 0;
53 int old_seen_execution = g_atomic_int_exchange_and_add (&seen_execution, 1);
54 if (old_seen_execution != 0)
55 g_error ("%s: function executed more than once", G_STRFUNC);
61 static volatile gsize initialized = 0;
62 if (g_once_init_enter (&initialized))
65 assert_singleton_execution1();
66 g_once_init_leave (&initialized, initval);
73 static volatile gsize initialized = 0;
74 if (g_once_init_enter (&initialized))
76 void *pointer_value = &dummy_value;
77 assert_singleton_execution2();
78 g_once_init_leave (&initialized, (gsize) pointer_value);
80 return (void*) initialized;
86 static volatile gsize initialized = 0;
87 if (g_once_init_enter (&initialized))
90 assert_singleton_execution3();
91 g_usleep (25 * 1000); /* waste time for multiple threads to wait */
92 g_once_init_leave (&initialized, initval);
97 tmain_call_initializer3 (gpointer user_data)
99 g_mutex_lock (tmutex);
100 g_cond_wait (tcond, tmutex);
101 g_mutex_unlock (tmutex);
105 g_atomic_int_exchange_and_add (&tmain_call_count, 1);
113 GThread *threads[N_THREADS];
115 /* test simple initializer */
118 /* test pointer initializer */
119 void *p = initializer2();
120 g_assert (p == &dummy_value);
122 g_assert (p == &dummy_value);
124 g_thread_init (NULL);
125 tmutex = g_mutex_new ();
126 tcond = g_cond_new ();
127 /* start multiple threads for initializer3() */
128 g_mutex_lock (tmutex);
129 for (i = 0; i < N_THREADS; i++)
130 threads[i] = g_thread_create (tmain_call_initializer3, 0, FALSE, NULL);
131 g_mutex_unlock (tmutex);
132 /* concurrently call initializer3() */
133 g_cond_broadcast (tcond);
134 /* loop until all threads passed the call to initializer3() */
135 while (g_atomic_int_get (&tmain_call_count) < i)
138 g_thread_yield(); /* concurrent shuffling for single core */
140 g_usleep (1000); /* concurrent shuffling for multi core */
141 g_cond_broadcast (tcond);