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