~ubuntu-branches/ubuntu/utopic/glib2.0/utopic

« back to all changes in this revision

Viewing changes to tests/thread-test.c

Tags: upstream-2.12.12
ImportĀ upstreamĀ versionĀ 2.12.12

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#undef G_DISABLE_ASSERT
 
2
#undef G_LOG_DOMAIN
 
3
 
 
4
#include <glib.h>
 
5
 
 
6
/* GMutex */
 
7
 
 
8
static GMutex* test_g_mutex_mutex = NULL;
 
9
static guint test_g_mutex_int = 0;
 
10
static gboolean test_g_mutex_thread_ready;
 
11
G_LOCK_DEFINE_STATIC (test_g_mutex);
 
12
 
 
13
static gpointer
 
14
test_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
 
 
27
static void
 
28
test_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
 
 
51
static GStaticRecMutex test_g_static_rec_mutex_mutex = G_STATIC_REC_MUTEX_INIT;
 
52
static guint test_g_static_rec_mutex_int = 0;
 
53
static gboolean test_g_static_rec_mutex_thread_ready;
 
54
 
 
55
static gpointer
 
56
test_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
 
 
75
static void
 
76
test_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
 
 
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 GStaticMutex test_g_static_private_mutex = G_STATIC_MUTEX_INIT;
 
114
static guint test_g_static_private_counter = 0;
 
115
static guint test_g_static_private_ready = 0;
 
116
 
 
117
static gpointer
 
118
test_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
 
 
126
static void
 
127
test_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
 
 
136
static gpointer
 
137
test_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
 
 
191
static void
 
192
test_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 */
 
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
test_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
 
 
281
static void
 
282
test_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
#define G_ONCE_SIZE 100
 
301
#define G_ONCE_THREADS 10
 
302
 
 
303
G_LOCK_DEFINE (test_g_once);
 
304
static guint test_g_once_guint_array[G_ONCE_SIZE];
 
305
static GOnce test_g_once_array[G_ONCE_SIZE];
 
306
 
 
307
static gpointer
 
308
test_g_once_init_func(gpointer arg)
 
309
{
 
310
  guint *count = arg;
 
311
  g_usleep (g_random_int_range (20,1000));
 
312
  (*count)++;
 
313
  g_usleep (g_random_int_range (20,1000));
 
314
  return arg;
 
315
}
 
316
 
 
317
static gpointer
 
318
test_g_once_thread (gpointer ignore)
 
319
{
 
320
  guint i;
 
321
  G_LOCK (test_g_once);
 
322
  /* Don't start before all threads are created */
 
323
  G_UNLOCK (test_g_once);
 
324
  for (i = 0; i < 1000; i++)
 
325
    {
 
326
      guint pos = g_random_int_range (0, G_ONCE_SIZE);
 
327
      gpointer ret = g_once (test_g_once_array + pos, test_g_once_init_func, 
 
328
                             test_g_once_guint_array + pos);
 
329
      g_assert (ret == test_g_once_guint_array + pos);
 
330
    }
 
331
  
 
332
  /* Make sure, that all counters are touched at least once */
 
333
  for (i = 0; i < G_ONCE_SIZE; i++)
 
334
    {
 
335
      gpointer ret = g_once (test_g_once_array + i, test_g_once_init_func, 
 
336
                             test_g_once_guint_array + i);
 
337
      g_assert (ret == test_g_once_guint_array + i);
 
338
    }
 
339
 
 
340
  return NULL;
 
341
}
 
342
 
 
343
static void
 
344
test_g_thread_once (void)
 
345
{
 
346
  static GOnce once_init = G_ONCE_INIT;
 
347
  GThread *threads[G_ONCE_THREADS];
 
348
  guint i;
 
349
  for (i = 0; i < G_ONCE_SIZE; i++) 
 
350
    {
 
351
      test_g_once_array[i] = once_init;
 
352
      test_g_once_guint_array[i] = i;
 
353
    }
 
354
  G_LOCK (test_g_once);
 
355
  for (i = 0; i < G_ONCE_THREADS; i++)
 
356
    {
 
357
      threads[i] = g_thread_create (test_g_once_thread, GUINT_TO_POINTER(i%2), 
 
358
                                    TRUE, NULL);
 
359
    }
 
360
  G_UNLOCK (test_g_once);
 
361
  for (i = 0; i < G_ONCE_THREADS; i++)
 
362
    {
 
363
      g_thread_join (threads[i]);
 
364
    }
 
365
  
 
366
  for (i = 0; i < G_ONCE_SIZE; i++) 
 
367
    {
 
368
      g_assert (test_g_once_guint_array[i] == i + 1);
 
369
    }
 
370
}
 
371
 
 
372
/* run all the tests */
 
373
void
 
374
run_all_tests()
 
375
{
 
376
  test_g_mutex ();
 
377
  test_g_static_rec_mutex ();
 
378
  test_g_static_private ();
 
379
  test_g_static_rw_lock ();
 
380
  test_g_thread_once ();
 
381
}
 
382
 
 
383
int 
 
384
main (int   argc,
 
385
      char *argv[])
 
386
{
 
387
  /* Only run the test, if threads are enabled and a default thread
 
388
     implementation is available */
 
389
#if defined(G_THREADS_ENABLED) && ! defined(G_THREADS_IMPL_NONE)
 
390
  g_thread_init (NULL);
 
391
  run_all_tests ();
 
392
 
 
393
  /* Now we rerun all tests, but this time we fool the system into
 
394
   * thinking, that the available thread system is not native, but
 
395
   * userprovided. */
 
396
 
 
397
  g_thread_use_default_impl = FALSE;
 
398
  run_all_tests ();
 
399
  
 
400
#endif
 
401
  return 0;
 
402
}