LCOV - code coverage report
Current view: top level - glib/glib/tests - thread-deprecated.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 196 196 100.0 %
Date: 2024-04-30 05:17:35 Functions: 15 15 100.0 %
Branches: 61 62 98.4 %

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

Generated by: LCOV version 1.14