source: trunk/third/glib2/tests/thread-test.c @ 18159

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