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
30 static volatile gint next;
33 push_value (gint value)
35 g_mutex_lock (&mutex);
37 if (g_test_verbose ())
38 g_print ("Thread %p producing next value: %d\n", g_thread_self (), value);
40 g_cond_broadcast (&cond);
42 g_cond_signal (&cond);
43 g_mutex_unlock (&mutex);
51 g_mutex_lock (&mutex);
54 if (g_test_verbose ())
55 g_print ("Thread %p waiting for cond\n", g_thread_self ());
56 g_cond_wait (&cond, &mutex);
60 if (g_test_verbose ())
61 g_print ("Thread %p consuming value %d\n", g_thread_self (), value);
62 g_mutex_unlock (&mutex);
68 produce_values (gpointer data)
75 for (i = 1; i < 100; i++)
86 if (g_test_verbose ())
87 g_print ("Thread %p produced %d altogether\n", g_thread_self (), total);
89 return GINT_TO_POINTER (total);
93 consume_values (gpointer data)
100 value = pop_value ();
107 if (g_test_verbose ())
108 g_print ("Thread %p accumulated %d\n", g_thread_self (), accum);
110 return GINT_TO_POINTER (accum);
113 static GThread *producer, *consumer1, *consumer2;
118 gint total, acc1, acc2;
120 producer = g_thread_create (produce_values, NULL, TRUE, NULL);
121 consumer1 = g_thread_create (consume_values, NULL, TRUE, NULL);
122 consumer2 = g_thread_create (consume_values, NULL, TRUE, NULL);
124 total = GPOINTER_TO_INT (g_thread_join (producer));
125 acc1 = GPOINTER_TO_INT (g_thread_join (consumer1));
126 acc2 = GPOINTER_TO_INT (g_thread_join (consumer2));
128 g_assert_cmpint (total, ==, acc1 + acc2);
140 barrier_init (Barrier *barrier,
143 g_mutex_init (&barrier->mutex);
144 g_cond_init (&barrier->cond);
145 barrier->limit = limit;
146 barrier->count = limit;
150 barrier_wait (Barrier *barrier)
154 g_mutex_lock (&barrier->mutex);
156 if (barrier->count == 0)
159 barrier->count = barrier->limit;
160 g_cond_broadcast (&barrier->cond);
165 while (barrier->count != barrier->limit)
166 g_cond_wait (&barrier->cond, &barrier->mutex);
168 g_mutex_unlock (&barrier->mutex);
177 cond2_func (gpointer data)
179 gint value = GPOINTER_TO_INT (data);
182 g_atomic_int_inc (&check);
184 if (g_test_verbose ())
185 g_print ("thread %d starting, check %d\n", value, g_atomic_int_get (&check));
187 g_usleep (10000 * value);
189 g_atomic_int_inc (&check);
191 if (g_test_verbose ())
192 g_print ("thread %d reaching barrier, check %d\n", value, g_atomic_int_get (&check));
194 ret = barrier_wait (&b);
196 g_assert_cmpint (g_atomic_int_get (&check), ==, 10);
198 if (g_test_verbose ())
199 g_print ("thread %d leaving barrier (%d), check %d\n", value, ret, g_atomic_int_get (&check));
204 /* this test demonstrates how to use a condition variable
205 * to implement a barrier
213 g_atomic_int_set (&check, 0);
215 barrier_init (&b, 5);
216 for (i = 0; i < 5; i++)
217 threads[i] = g_thread_create (cond2_func, GINT_TO_POINTER (i), TRUE, NULL);
219 for (i = 0; i < 5; i++)
220 g_thread_join (threads[i]);
222 g_assert_cmpint (g_atomic_int_get (&check), ==, 10);
226 main (int argc, char *argv[])
228 g_test_init (&argc, &argv, NULL);
230 g_test_add_func ("/thread/cond1", test_cond1);
231 g_test_add_func ("/thread/cond2", test_cond2);
233 return g_test_run ();