Merge branch '976-disable-assert-checks' into 'master'
[glib.git] / glib / tests / cond.c
blob0987f01e0fb795f547743570478d08968cd748f2
1 /* Unit tests for GCond
2 * Copyright (C) 2011 Red Hat, Inc
3 * Author: Matthias Clasen
5 * This work is provided "as is"; redistribution and modification
6 * in whole or in part, in any medium, physical or electronic is
7 * permitted without restriction.
9 * This work is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * In no event shall the authors or contributors be liable for any
14 * direct, indirect, incidental, special, exemplary, or consequential
15 * damages (including, but not limited to, procurement of substitute
16 * goods or services; loss of use, data, or profits; or business
17 * interruption) however caused and on any theory of liability, whether
18 * in contract, strict liability, or tort (including negligence or
19 * otherwise) arising in any way out of the use of this software, even
20 * if advised of the possibility of such damage.
23 /* We are testing some deprecated APIs here */
24 #define GLIB_DISABLE_DEPRECATION_WARNINGS
26 #include <glib.h>
28 static GCond cond;
29 static GMutex mutex;
30 static volatile gint next;
32 static void
33 push_value (gint value)
35 g_mutex_lock (&mutex);
36 while (next != 0)
37 g_cond_wait (&cond, &mutex);
38 next = value;
39 if (g_test_verbose ())
40 g_printerr ("Thread %p producing next value: %d\n", g_thread_self (), value);
41 if (value % 10 == 0)
42 g_cond_broadcast (&cond);
43 else
44 g_cond_signal (&cond);
45 g_mutex_unlock (&mutex);
48 static gint
49 pop_value (void)
51 gint value;
53 g_mutex_lock (&mutex);
54 while (next == 0)
56 if (g_test_verbose ())
57 g_printerr ("Thread %p waiting for cond\n", g_thread_self ());
58 g_cond_wait (&cond, &mutex);
60 value = next;
61 next = 0;
62 g_cond_broadcast (&cond);
63 if (g_test_verbose ())
64 g_printerr ("Thread %p consuming value %d\n", g_thread_self (), value);
65 g_mutex_unlock (&mutex);
67 return value;
70 static gpointer
71 produce_values (gpointer data)
73 gint total;
74 gint i;
76 total = 0;
78 for (i = 1; i < 100; i++)
80 total += i;
81 push_value (i);
84 push_value (-1);
85 push_value (-1);
87 if (g_test_verbose ())
88 g_printerr ("Thread %p produced %d altogether\n", g_thread_self (), total);
90 return GINT_TO_POINTER (total);
93 static gpointer
94 consume_values (gpointer data)
96 gint accum = 0;
97 gint value;
99 while (TRUE)
101 value = pop_value ();
102 if (value == -1)
103 break;
105 accum += value;
108 if (g_test_verbose ())
109 g_printerr ("Thread %p accumulated %d\n", g_thread_self (), accum);
111 return GINT_TO_POINTER (accum);
114 static GThread *producer, *consumer1, *consumer2;
116 static void
117 test_cond1 (void)
119 gint total, acc1, acc2;
121 producer = g_thread_create (produce_values, NULL, TRUE, NULL);
122 consumer1 = g_thread_create (consume_values, NULL, TRUE, NULL);
123 consumer2 = g_thread_create (consume_values, NULL, TRUE, NULL);
125 total = GPOINTER_TO_INT (g_thread_join (producer));
126 acc1 = GPOINTER_TO_INT (g_thread_join (consumer1));
127 acc2 = GPOINTER_TO_INT (g_thread_join (consumer2));
129 g_assert_cmpint (total, ==, acc1 + acc2);
132 typedef struct
134 GMutex mutex;
135 GCond cond;
136 gint limit;
137 gint count;
138 } Barrier;
140 static void
141 barrier_init (Barrier *barrier,
142 gint limit)
144 g_mutex_init (&barrier->mutex);
145 g_cond_init (&barrier->cond);
146 barrier->limit = limit;
147 barrier->count = limit;
150 static gint
151 barrier_wait (Barrier *barrier)
153 gint ret;
155 g_mutex_lock (&barrier->mutex);
156 barrier->count--;
157 if (barrier->count == 0)
159 ret = -1;
160 barrier->count = barrier->limit;
161 g_cond_broadcast (&barrier->cond);
163 else
165 ret = 0;
166 while (barrier->count != barrier->limit)
167 g_cond_wait (&barrier->cond, &barrier->mutex);
169 g_mutex_unlock (&barrier->mutex);
171 return ret;
174 static void
175 barrier_clear (Barrier *barrier)
177 g_mutex_clear (&barrier->mutex);
178 g_cond_clear (&barrier->cond);
181 static Barrier b;
182 static gint check;
184 static gpointer
185 cond2_func (gpointer data)
187 gint value = GPOINTER_TO_INT (data);
188 gint ret;
190 g_atomic_int_inc (&check);
192 if (g_test_verbose ())
193 g_printerr ("thread %d starting, check %d\n", value, g_atomic_int_get (&check));
195 g_usleep (10000 * value);
197 g_atomic_int_inc (&check);
199 if (g_test_verbose ())
200 g_printerr ("thread %d reaching barrier, check %d\n", value, g_atomic_int_get (&check));
202 ret = barrier_wait (&b);
204 g_assert_cmpint (g_atomic_int_get (&check), ==, 10);
206 if (g_test_verbose ())
207 g_printerr ("thread %d leaving barrier (%d), check %d\n", value, ret, g_atomic_int_get (&check));
209 return NULL;
212 /* this test demonstrates how to use a condition variable
213 * to implement a barrier
215 static void
216 test_cond2 (void)
218 gint i;
219 GThread *threads[5];
221 g_atomic_int_set (&check, 0);
223 barrier_init (&b, 5);
224 for (i = 0; i < 5; i++)
225 threads[i] = g_thread_create (cond2_func, GINT_TO_POINTER (i), TRUE, NULL);
227 for (i = 0; i < 5; i++)
228 g_thread_join (threads[i]);
230 g_assert_cmpint (g_atomic_int_get (&check), ==, 10);
232 barrier_clear (&b);
235 static void
236 test_wait_until (void)
238 gint64 until;
239 GMutex lock;
240 GCond cond;
242 /* This test will make sure we don't wait too much or too little.
244 * We check the 'too long' with a timeout of 60 seconds.
246 * We check the 'too short' by verifying a guarantee of the API: we
247 * should not wake up until the specified time has passed.
249 g_mutex_init (&lock);
250 g_cond_init (&cond);
252 until = g_get_monotonic_time () + G_TIME_SPAN_SECOND;
254 /* Could still have spurious wakeups, so we must loop... */
255 g_mutex_lock (&lock);
256 while (g_cond_wait_until (&cond, &lock, until))
258 g_mutex_unlock (&lock);
260 /* Make sure it's after the until time */
261 g_assert_cmpint (until, <=, g_get_monotonic_time ());
263 /* Make sure it returns FALSE on timeout */
264 until = g_get_monotonic_time () + G_TIME_SPAN_SECOND / 50;
265 g_mutex_lock (&lock);
266 g_assert (g_cond_wait_until (&cond, &lock, until) == FALSE);
267 g_mutex_unlock (&lock);
269 g_mutex_clear (&lock);
270 g_cond_clear (&cond);
274 main (int argc, char *argv[])
276 g_test_init (&argc, &argv, NULL);
278 g_test_add_func ("/thread/cond1", test_cond1);
279 g_test_add_func ("/thread/cond2", test_cond2);
280 g_test_add_func ("/thread/cond/wait-until", test_wait_until);
282 return g_test_run ();