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