glib/tsrc/BC/tests/thread-test.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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 }