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