os/ossrv/glib/tsrc/BC/tests/thread-test.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* Portion Copyright © 2008-09 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.*/
sl@0
     2
#undef G_DISABLE_ASSERT
sl@0
     3
#undef G_LOG_DOMAIN
sl@0
     4
sl@0
     5
#include <glib.h>
sl@0
     6
#include <stdio.h>
sl@0
     7
sl@0
     8
#ifdef SYMBIAN
sl@0
     9
#include <glib_global.h>
sl@0
    10
#include "mrt2_glib2_test.h"
sl@0
    11
#endif /*SYMBIAN*/
sl@0
    12
sl@0
    13
sl@0
    14
/* GMutex */
sl@0
    15
sl@0
    16
static GMutex* test_g_mutex_mutex = NULL;
sl@0
    17
static guint test_g_mutex_int = 0;
sl@0
    18
static gboolean test_g_mutex_thread_ready;
sl@0
    19
G_LOCK_DEFINE_STATIC (test_g_mutex);
sl@0
    20
sl@0
    21
static gpointer
sl@0
    22
test_g_mutex_thread (gpointer data)
sl@0
    23
{
sl@0
    24
  g_assert (GPOINTER_TO_INT (data) == 42);
sl@0
    25
  g_assert (g_mutex_trylock (test_g_mutex_mutex) == FALSE);
sl@0
    26
  g_assert (G_TRYLOCK (test_g_mutex) == FALSE);
sl@0
    27
  test_g_mutex_thread_ready = TRUE;
sl@0
    28
  g_mutex_lock (test_g_mutex_mutex);
sl@0
    29
  g_assert (test_g_mutex_int == 42);
sl@0
    30
  g_mutex_unlock (test_g_mutex_mutex);
sl@0
    31
sl@0
    32
  return GINT_TO_POINTER (41);
sl@0
    33
}
sl@0
    34
sl@0
    35
static void
sl@0
    36
test_g_mutex (void)
sl@0
    37
{
sl@0
    38
  GThread *thread;
sl@0
    39
  test_g_mutex_mutex = g_mutex_new ();
sl@0
    40
sl@0
    41
  g_assert (g_mutex_trylock (test_g_mutex_mutex));
sl@0
    42
  g_assert (G_TRYLOCK (test_g_mutex));
sl@0
    43
  test_g_mutex_thread_ready = FALSE;
sl@0
    44
  thread = g_thread_create (test_g_mutex_thread, GINT_TO_POINTER (42),
sl@0
    45
			    TRUE, NULL);
sl@0
    46
  /* This busy wait is only for testing purposes and not an example of
sl@0
    47
   * good code!*/
sl@0
    48
  while (!test_g_mutex_thread_ready)
sl@0
    49
    g_usleep (G_USEC_PER_SEC / 5);
sl@0
    50
  test_g_mutex_int = 42;
sl@0
    51
  G_UNLOCK (test_g_mutex);
sl@0
    52
  g_mutex_unlock (test_g_mutex_mutex);
sl@0
    53
  g_assert (GPOINTER_TO_INT (g_thread_join (thread)) == 41);
sl@0
    54
  g_mutex_free (test_g_mutex_mutex);
sl@0
    55
}
sl@0
    56
sl@0
    57
/* GStaticRecMutex */
sl@0
    58
sl@0
    59
static GStaticRecMutex test_g_static_rec_mutex_mutex = G_STATIC_REC_MUTEX_INIT;
sl@0
    60
static guint test_g_static_rec_mutex_int = 0;
sl@0
    61
static gboolean test_g_static_rec_mutex_thread_ready;
sl@0
    62
sl@0
    63
static gpointer
sl@0
    64
test_g_static_rec_mutex_thread (gpointer data)
sl@0
    65
{
sl@0
    66
  g_assert (GPOINTER_TO_INT (data) == 42);
sl@0
    67
  g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex) 
sl@0
    68
	    == FALSE);
sl@0
    69
  test_g_static_rec_mutex_thread_ready = TRUE;
sl@0
    70
  g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
sl@0
    71
  g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
sl@0
    72
  g_assert (test_g_static_rec_mutex_int == 42);
sl@0
    73
  test_g_static_rec_mutex_thread_ready = FALSE;
sl@0
    74
  g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
sl@0
    75
  g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
sl@0
    76
sl@0
    77
  g_thread_exit (GINT_TO_POINTER (43));
sl@0
    78
  
sl@0
    79
  g_assert_not_reached ();
sl@0
    80
  return NULL;
sl@0
    81
}
sl@0
    82
sl@0
    83
static void
sl@0
    84
test_g_static_rec_mutex (void)
sl@0
    85
{
sl@0
    86
  GThread *thread;
sl@0
    87
sl@0
    88
  g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
sl@0
    89
  test_g_static_rec_mutex_thread_ready = FALSE;
sl@0
    90
  thread = g_thread_create (test_g_static_rec_mutex_thread, 
sl@0
    91
			    GINT_TO_POINTER (42), TRUE, NULL);
sl@0
    92
  /* This busy wait is only for testing purposes and not an example of
sl@0
    93
   * good code!*/
sl@0
    94
  while (!test_g_static_rec_mutex_thread_ready)
sl@0
    95
    g_usleep (G_USEC_PER_SEC / 5);
sl@0
    96
sl@0
    97
  g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
sl@0
    98
  test_g_static_rec_mutex_int = 41;
sl@0
    99
  g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
sl@0
   100
  test_g_static_rec_mutex_int = 42;  
sl@0
   101
  g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
sl@0
   102
sl@0
   103
  /* This busy wait is only for testing purposes and not an example of
sl@0
   104
   * good code!*/
sl@0
   105
  while (test_g_static_rec_mutex_thread_ready)
sl@0
   106
    g_usleep (G_USEC_PER_SEC / 5);
sl@0
   107
sl@0
   108
  g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
sl@0
   109
  test_g_static_rec_mutex_int = 0;  
sl@0
   110
  g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
sl@0
   111
sl@0
   112
  g_assert (GPOINTER_TO_INT (g_thread_join (thread)) == 43);
sl@0
   113
}
sl@0
   114
sl@0
   115
/* GStaticPrivate */
sl@0
   116
sl@0
   117
#define THREADS 10
sl@0
   118
sl@0
   119
static GStaticPrivate test_g_static_private_private1 = G_STATIC_PRIVATE_INIT;
sl@0
   120
static GStaticPrivate test_g_static_private_private2 = G_STATIC_PRIVATE_INIT;
sl@0
   121
static GStaticMutex test_g_static_private_mutex = G_STATIC_MUTEX_INIT;
sl@0
   122
static guint test_g_static_private_counter = 0;
sl@0
   123
static guint test_g_static_private_ready = 0;
sl@0
   124
sl@0
   125
static gpointer
sl@0
   126
test_g_static_private_constructor (void)
sl@0
   127
{
sl@0
   128
  g_static_mutex_lock (&test_g_static_private_mutex);
sl@0
   129
  test_g_static_private_counter++;
sl@0
   130
  g_static_mutex_unlock (&test_g_static_private_mutex);  
sl@0
   131
  return g_new (guint,1);
sl@0
   132
}
sl@0
   133
sl@0
   134
static void
sl@0
   135
test_g_static_private_destructor (gpointer data)
sl@0
   136
{
sl@0
   137
  g_static_mutex_lock (&test_g_static_private_mutex);
sl@0
   138
  test_g_static_private_counter--;
sl@0
   139
  g_static_mutex_unlock (&test_g_static_private_mutex);  
sl@0
   140
  g_free (data);
sl@0
   141
}
sl@0
   142
sl@0
   143
sl@0
   144
static gpointer
sl@0
   145
test_g_static_private_thread (gpointer data)
sl@0
   146
{
sl@0
   147
  guint number = GPOINTER_TO_INT (data);
sl@0
   148
  guint i;
sl@0
   149
  guint *private1, *private2;
sl@0
   150
  for (i = 0; i < 10; i++)
sl@0
   151
    {
sl@0
   152
      number = number * 11 + 1; /* A very simple and bad RNG ;-) */
sl@0
   153
      private1 = g_static_private_get (&test_g_static_private_private1);
sl@0
   154
      if (!private1 || number % 7 > 3)
sl@0
   155
	{
sl@0
   156
	  private1 = test_g_static_private_constructor ();
sl@0
   157
	  g_static_private_set (&test_g_static_private_private1, private1,
sl@0
   158
				test_g_static_private_destructor);
sl@0
   159
	}
sl@0
   160
      *private1 = number;
sl@0
   161
      private2 = g_static_private_get (&test_g_static_private_private2);
sl@0
   162
      if (!private2 || number % 13 > 5)
sl@0
   163
	{
sl@0
   164
	  private2 = test_g_static_private_constructor ();
sl@0
   165
	  g_static_private_set (&test_g_static_private_private2, private2,
sl@0
   166
				test_g_static_private_destructor);
sl@0
   167
	}
sl@0
   168
      *private2 = number * 2;
sl@0
   169
      g_usleep (G_USEC_PER_SEC / 5);
sl@0
   170
      g_assert (number == *private1);
sl@0
   171
      g_assert (number * 2 == *private2);      
sl@0
   172
    }
sl@0
   173
  g_static_mutex_lock (&test_g_static_private_mutex);
sl@0
   174
  test_g_static_private_ready++;
sl@0
   175
  g_static_mutex_unlock (&test_g_static_private_mutex);  
sl@0
   176
sl@0
   177
  /* Busy wait is not nice but that's just a test */
sl@0
   178
  while (test_g_static_private_ready != 0)
sl@0
   179
    g_usleep (G_USEC_PER_SEC / 5);  
sl@0
   180
sl@0
   181
  for (i = 0; i < 10; i++)
sl@0
   182
    {
sl@0
   183
      private2 = g_static_private_get (&test_g_static_private_private2);
sl@0
   184
      number = number * 11 + 1; /* A very simple and bad RNG ;-) */
sl@0
   185
      if (!private2 || number % 13 > 5)
sl@0
   186
	{
sl@0
   187
	  private2 = test_g_static_private_constructor ();
sl@0
   188
	  g_static_private_set (&test_g_static_private_private2, private2,
sl@0
   189
				test_g_static_private_destructor);
sl@0
   190
	}      
sl@0
   191
      *private2 = number * 2;
sl@0
   192
      g_usleep (G_USEC_PER_SEC / 5);
sl@0
   193
      g_assert (number * 2 == *private2);      
sl@0
   194
    }
sl@0
   195
sl@0
   196
  return GINT_TO_POINTER (GPOINTER_TO_INT (data) * 3);
sl@0
   197
}
sl@0
   198
sl@0
   199
static void
sl@0
   200
test_g_static_private (void)
sl@0
   201
{
sl@0
   202
  GThread *threads[THREADS];
sl@0
   203
  guint i;
sl@0
   204
sl@0
   205
  test_g_static_private_ready = 0;
sl@0
   206
sl@0
   207
  for (i = 0; i < THREADS; i++)
sl@0
   208
    {
sl@0
   209
      threads[i] = g_thread_create (test_g_static_private_thread, 
sl@0
   210
				    GINT_TO_POINTER (i), TRUE, NULL);      
sl@0
   211
    }
sl@0
   212
sl@0
   213
  /* Busy wait is not nice but that's just a test */
sl@0
   214
  while (test_g_static_private_ready != THREADS)
sl@0
   215
    g_usleep (G_USEC_PER_SEC / 5);
sl@0
   216
sl@0
   217
  /* Reuse the static private */
sl@0
   218
  g_static_private_free (&test_g_static_private_private2);
sl@0
   219
  g_static_private_init (&test_g_static_private_private2);
sl@0
   220
  
sl@0
   221
  test_g_static_private_ready = 0;
sl@0
   222
sl@0
   223
  for (i = 0; i < THREADS; i++)
sl@0
   224
    g_assert (GPOINTER_TO_INT (g_thread_join (threads[i])) == i * 3);
sl@0
   225
    
sl@0
   226
  g_assert (test_g_static_private_counter == 0); 
sl@0
   227
}
sl@0
   228
sl@0
   229
/* GStaticRWLock */
sl@0
   230
sl@0
   231
/* -1 = writing; >0 = # of readers */
sl@0
   232
static gint test_g_static_rw_lock_state = 0; 
sl@0
   233
G_LOCK_DEFINE (test_g_static_rw_lock_state);
sl@0
   234
sl@0
   235
static gboolean test_g_static_rw_lock_run = TRUE; 
sl@0
   236
static GStaticRWLock test_g_static_rw_lock_lock = G_STATIC_RW_LOCK_INIT;
sl@0
   237
sl@0
   238
static gpointer
sl@0
   239
test_g_static_rw_lock_thread (gpointer data)
sl@0
   240
{
sl@0
   241
  while (test_g_static_rw_lock_run)
sl@0
   242
    {
sl@0
   243
      if (g_random_double() > .2) /* I'm a reader */
sl@0
   244
	{
sl@0
   245
	  
sl@0
   246
	  if (g_random_double() > .2) /* I'll block */
sl@0
   247
	    g_static_rw_lock_reader_lock (&test_g_static_rw_lock_lock);
sl@0
   248
	  else /* I'll only try */
sl@0
   249
	    if (!g_static_rw_lock_reader_trylock (&test_g_static_rw_lock_lock))
sl@0
   250
	      continue;
sl@0
   251
	  G_LOCK (test_g_static_rw_lock_state);
sl@0
   252
	  g_assert (test_g_static_rw_lock_state >= 0);
sl@0
   253
	  test_g_static_rw_lock_state++;
sl@0
   254
	  G_UNLOCK (test_g_static_rw_lock_state);
sl@0
   255
sl@0
   256
	  g_usleep (g_random_int_range (20,1000));
sl@0
   257
sl@0
   258
	  G_LOCK (test_g_static_rw_lock_state);
sl@0
   259
	  test_g_static_rw_lock_state--;
sl@0
   260
	  G_UNLOCK (test_g_static_rw_lock_state);
sl@0
   261
sl@0
   262
	  g_static_rw_lock_reader_unlock (&test_g_static_rw_lock_lock);
sl@0
   263
	}
sl@0
   264
      else /* I'm a writer */
sl@0
   265
	{
sl@0
   266
	  
sl@0
   267
	  if (g_random_double() > .2) /* I'll block */ 
sl@0
   268
	    g_static_rw_lock_writer_lock (&test_g_static_rw_lock_lock);
sl@0
   269
	  else /* I'll only try */
sl@0
   270
	    if (!g_static_rw_lock_writer_trylock (&test_g_static_rw_lock_lock))
sl@0
   271
	      continue;
sl@0
   272
	  G_LOCK (test_g_static_rw_lock_state);
sl@0
   273
	  g_assert (test_g_static_rw_lock_state == 0);
sl@0
   274
	  test_g_static_rw_lock_state = -1;
sl@0
   275
	  G_UNLOCK (test_g_static_rw_lock_state);
sl@0
   276
sl@0
   277
	  g_usleep (g_random_int_range (20,1000));
sl@0
   278
sl@0
   279
	  G_LOCK (test_g_static_rw_lock_state);
sl@0
   280
	  test_g_static_rw_lock_state = 0;
sl@0
   281
	  G_UNLOCK (test_g_static_rw_lock_state);
sl@0
   282
sl@0
   283
	  g_static_rw_lock_writer_unlock (&test_g_static_rw_lock_lock);
sl@0
   284
	}
sl@0
   285
    }
sl@0
   286
  return NULL;
sl@0
   287
}
sl@0
   288
sl@0
   289
static void
sl@0
   290
test_g_static_rw_lock ()
sl@0
   291
{
sl@0
   292
  GThread *threads[THREADS];
sl@0
   293
  guint i;
sl@0
   294
  for (i = 0; i < THREADS; i++)
sl@0
   295
    {
sl@0
   296
      threads[i] = g_thread_create (test_g_static_rw_lock_thread, 
sl@0
   297
				    NULL, TRUE, NULL);      
sl@0
   298
    }
sl@0
   299
  g_usleep (G_USEC_PER_SEC * 5);
sl@0
   300
  test_g_static_rw_lock_run = FALSE;
sl@0
   301
  for (i = 0; i < THREADS; i++)
sl@0
   302
    {
sl@0
   303
      g_thread_join (threads[i]);
sl@0
   304
    }
sl@0
   305
  g_assert (test_g_static_rw_lock_state == 0);
sl@0
   306
}
sl@0
   307
sl@0
   308
#define G_ONCE_SIZE 100
sl@0
   309
#define G_ONCE_THREADS 10
sl@0
   310
sl@0
   311
G_LOCK_DEFINE (test_g_once);
sl@0
   312
static guint test_g_once_guint_array[G_ONCE_SIZE];
sl@0
   313
static GOnce test_g_once_array[G_ONCE_SIZE];
sl@0
   314
sl@0
   315
static gpointer
sl@0
   316
test_g_once_init_func(gpointer arg)
sl@0
   317
{
sl@0
   318
  guint *count = arg;
sl@0
   319
  g_usleep (g_random_int_range (20,1000));
sl@0
   320
  (*count)++;
sl@0
   321
  g_usleep (g_random_int_range (20,1000));
sl@0
   322
  return arg;
sl@0
   323
}
sl@0
   324
sl@0
   325
static gpointer
sl@0
   326
test_g_once_thread (gpointer ignore)
sl@0
   327
{
sl@0
   328
  guint i;
sl@0
   329
  G_LOCK (test_g_once);
sl@0
   330
  /* Don't start before all threads are created */
sl@0
   331
  G_UNLOCK (test_g_once);
sl@0
   332
  for (i = 0; i < 1000; i++)
sl@0
   333
    {
sl@0
   334
      guint pos = g_random_int_range (0, G_ONCE_SIZE);
sl@0
   335
      gpointer ret = g_once (test_g_once_array + pos, test_g_once_init_func, 
sl@0
   336
			     test_g_once_guint_array + pos);
sl@0
   337
      g_assert (ret == test_g_once_guint_array + pos);
sl@0
   338
    }
sl@0
   339
  
sl@0
   340
  /* Make sure, that all counters are touched at least once */
sl@0
   341
  for (i = 0; i < G_ONCE_SIZE; i++)
sl@0
   342
    {
sl@0
   343
      gpointer ret = g_once (test_g_once_array + i, test_g_once_init_func, 
sl@0
   344
			     test_g_once_guint_array + i);
sl@0
   345
      g_assert (ret == test_g_once_guint_array + i);
sl@0
   346
    }
sl@0
   347
sl@0
   348
  return NULL;
sl@0
   349
}
sl@0
   350
sl@0
   351
static void
sl@0
   352
test_g_thread_once (void)
sl@0
   353
{
sl@0
   354
  static GOnce once_init = G_ONCE_INIT;
sl@0
   355
  GThread *threads[G_ONCE_THREADS];
sl@0
   356
  guint i;
sl@0
   357
  for (i = 0; i < G_ONCE_SIZE; i++) 
sl@0
   358
    {
sl@0
   359
      test_g_once_array[i] = once_init;
sl@0
   360
      test_g_once_guint_array[i] = i;
sl@0
   361
    }
sl@0
   362
  G_LOCK (test_g_once);
sl@0
   363
  for (i = 0; i < G_ONCE_THREADS; i++)
sl@0
   364
    {
sl@0
   365
      threads[i] = g_thread_create (test_g_once_thread, GUINT_TO_POINTER(i%2), 
sl@0
   366
				    TRUE, NULL);
sl@0
   367
    }
sl@0
   368
  G_UNLOCK (test_g_once);
sl@0
   369
  for (i = 0; i < G_ONCE_THREADS; i++)
sl@0
   370
    {
sl@0
   371
      g_thread_join (threads[i]);
sl@0
   372
    }
sl@0
   373
  
sl@0
   374
  for (i = 0; i < G_ONCE_SIZE; i++) 
sl@0
   375
    {
sl@0
   376
      g_assert (test_g_once_guint_array[i] == i + 1);
sl@0
   377
    }
sl@0
   378
}
sl@0
   379
sl@0
   380
/* run all the tests */
sl@0
   381
void
sl@0
   382
run_all_tests()
sl@0
   383
{
sl@0
   384
  test_g_mutex ();
sl@0
   385
  test_g_static_rec_mutex ();
sl@0
   386
  test_g_static_private ();
sl@0
   387
  test_g_static_rw_lock ();
sl@0
   388
  test_g_thread_once ();
sl@0
   389
}
sl@0
   390
sl@0
   391
int 
sl@0
   392
main (int   argc,
sl@0
   393
      char *argv[])
sl@0
   394
{
sl@0
   395
  #ifdef SYMBIAN
sl@0
   396
  
sl@0
   397
  g_log_set_handler (NULL,  G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG, &mrtLogHandler, NULL);
sl@0
   398
  g_set_print_handler(mrtPrintHandler);
sl@0
   399
  #endif /*SYMBIAN*/
sl@0
   400
	  
sl@0
   401
sl@0
   402
  /* Only run the test, if threads are enabled and a default thread
sl@0
   403
     implementation is available */
sl@0
   404
#if defined(G_THREADS_ENABLED) && ! defined(G_THREADS_IMPL_NONE)
sl@0
   405
  g_thread_init (NULL);
sl@0
   406
  run_all_tests ();
sl@0
   407
sl@0
   408
  /* Now we rerun all tests, but this time we fool the system into
sl@0
   409
   * thinking, that the available thread system is not native, but
sl@0
   410
   * userprovided. */
sl@0
   411
sl@0
   412
  g_thread_use_default_impl = FALSE;
sl@0
   413
  run_all_tests ();
sl@0
   414
  
sl@0
   415
#endif
sl@0
   416
sl@0
   417
#ifdef SYMBIAN
sl@0
   418
  testResultXml("thread-test");
sl@0
   419
#endif /* EMULATOR */
sl@0
   420
  return 0;
sl@0
   421
}