(root)/
glib-2.79.0/
glib/
tests/
thread-deprecated.c
       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  test_g_mutex_thread (gpointer data)
      16  {
      17    g_assert_cmpint (GPOINTER_TO_INT (data), ==, 42);
      18    g_assert_false (g_mutex_trylock (&test_g_mutex_mutex));
      19    g_assert_false (G_TRYLOCK (test_g_mutex));
      20    test_g_mutex_thread_ready = TRUE;
      21    g_mutex_lock (&test_g_mutex_mutex);
      22    g_assert_cmpint (test_g_mutex_int, ==, 42);
      23    g_mutex_unlock (&test_g_mutex_mutex);
      24  
      25    return GINT_TO_POINTER (41);
      26  }
      27  
      28  static void
      29  test_g_mutex (void)
      30  {
      31    GThread *thread;
      32  
      33    g_assert_true (g_mutex_trylock (&test_g_mutex_mutex));
      34    g_assert_true (G_TRYLOCK (test_g_mutex));
      35    test_g_mutex_thread_ready = FALSE;
      36    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    while (!test_g_mutex_thread_ready)
      41      g_usleep (G_USEC_PER_SEC / 5);
      42    test_g_mutex_int = 42;
      43    G_UNLOCK (test_g_mutex);
      44    g_mutex_unlock (&test_g_mutex_mutex);
      45    g_assert_cmpint (GPOINTER_TO_INT (g_thread_join (thread)), ==, 41);
      46  }
      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  test_g_static_rec_mutex_thread (gpointer data)
      56  {
      57    g_assert_cmpint (GPOINTER_TO_INT (data), ==, 42);
      58    g_assert_false (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
      59  
      60    test_g_static_rec_mutex_thread_ready = TRUE;
      61    g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
      62    g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
      63    g_assert_cmpint (test_g_static_rec_mutex_int, ==, 42);
      64  
      65    test_g_static_rec_mutex_thread_ready = FALSE;
      66    g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
      67    g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
      68  
      69    g_thread_exit (GINT_TO_POINTER (43));
      70  
      71    g_assert_not_reached ();
      72    return NULL;
      73  }
      74  
      75  static void
      76  test_g_static_rec_mutex (void)
      77  {
      78    GThread *thread;
      79  
      80    g_assert_true (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
      81    test_g_static_rec_mutex_thread_ready = FALSE;
      82    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    while (!test_g_static_rec_mutex_thread_ready)
      87      g_usleep (G_USEC_PER_SEC / 5);
      88  
      89    g_assert_true (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
      90    test_g_static_rec_mutex_int = 41;
      91    g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
      92    test_g_static_rec_mutex_int = 42;
      93    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    while (test_g_static_rec_mutex_thread_ready)
      98      g_usleep (G_USEC_PER_SEC / 5);
      99  
     100    g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
     101    test_g_static_rec_mutex_int = 0;
     102    g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
     103  
     104    g_assert_cmpint (GPOINTER_TO_INT (g_thread_join (thread)), ==, 43);
     105  }
     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  test_g_static_private_constructor (void)
     119  {
     120    g_mutex_lock (&test_g_static_private_mutex);
     121    test_g_static_private_counter++;
     122    g_mutex_unlock (&test_g_static_private_mutex);
     123    return g_new (guint,1);
     124  }
     125  
     126  static void
     127  test_g_static_private_destructor (gpointer data)
     128  {
     129    g_mutex_lock (&test_g_static_private_mutex);
     130    test_g_static_private_counter--;
     131    g_mutex_unlock (&test_g_static_private_mutex);
     132    g_free (data);
     133  }
     134  
     135  
     136  static gpointer
     137  test_g_static_private_thread (gpointer data)
     138  {
     139    guint number = GPOINTER_TO_INT (data);
     140    guint i;
     141    guint *private1, *private2;
     142    for (i = 0; i < 10; i++)
     143      {
     144        number = number * 11 + 1; /* A very simple and bad RNG ;-) */
     145        private1 = g_static_private_get (&test_g_static_private_private1);
     146        if (!private1 || number % 7 > 3)
     147  	{
     148  	  private1 = test_g_static_private_constructor ();
     149  	  g_static_private_set (&test_g_static_private_private1, private1,
     150  				test_g_static_private_destructor);
     151  	}
     152        *private1 = number;
     153        private2 = g_static_private_get (&test_g_static_private_private2);
     154        if (!private2 || number % 13 > 5)
     155  	{
     156  	  private2 = test_g_static_private_constructor ();
     157  	  g_static_private_set (&test_g_static_private_private2, private2,
     158  				test_g_static_private_destructor);
     159  	}
     160        *private2 = number * 2;
     161        g_usleep (G_USEC_PER_SEC / 5);
     162        g_assert_cmpint (number, ==, *private1);
     163        g_assert_cmpint (number * 2, ==, *private2);
     164      }
     165    g_mutex_lock (&test_g_static_private_mutex);
     166    test_g_static_private_ready++;
     167    g_mutex_unlock (&test_g_static_private_mutex);
     168  
     169    /* Busy wait is not nice but that's just a test */
     170    while (test_g_static_private_ready != 0)
     171      g_usleep (G_USEC_PER_SEC / 5);
     172  
     173    for (i = 0; i < 10; i++)
     174      {
     175        private2 = g_static_private_get (&test_g_static_private_private2);
     176        number = number * 11 + 1; /* A very simple and bad RNG ;-) */
     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_cmpint (number * 2, ==, *private2);
     186      }
     187  
     188    return GINT_TO_POINTER (GPOINTER_TO_INT (data) * 3);
     189  }
     190  
     191  static void
     192  test_g_static_private (void)
     193  {
     194    GThread *threads[THREADS];
     195    guint i;
     196  
     197    test_g_static_private_ready = 0;
     198  
     199    for (i = 0; i < THREADS; i++)
     200      {
     201        threads[i] = g_thread_create (test_g_static_private_thread,
     202                                      GINT_TO_POINTER (i), TRUE, NULL);
     203      }
     204  
     205    /* Busy wait is not nice but that's just a test */
     206    while (test_g_static_private_ready != THREADS)
     207      g_usleep (G_USEC_PER_SEC / 5);
     208  
     209    /* Reuse the static private */
     210    g_static_private_free (&test_g_static_private_private2);
     211    g_static_private_init (&test_g_static_private_private2);
     212  
     213    test_g_static_private_ready = 0;
     214  
     215    for (i = 0; i < THREADS; i++)
     216      g_assert_cmpint (GPOINTER_TO_UINT (g_thread_join (threads[i])), ==, i * 3);
     217  
     218    g_assert_cmpint (test_g_static_private_counter, ==, 0);
     219  }
     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  test_g_static_rw_lock_thread (gpointer data)
     232  {
     233    while (test_g_static_rw_lock_run)
     234      {
     235        if (g_random_double() > .2) /* I'm a reader */
     236  	{
     237  
     238            if (g_random_double() > .2) /* I'll block */
     239  	    g_static_rw_lock_reader_lock (&test_g_static_rw_lock_lock);
     240  	  else /* I'll only try */
     241  	    if (!g_static_rw_lock_reader_trylock (&test_g_static_rw_lock_lock))
     242  	      continue;
     243  	  G_LOCK (test_g_static_rw_lock_state);
     244            g_assert_cmpint (test_g_static_rw_lock_state, >=, 0);
     245            test_g_static_rw_lock_state++;
     246  	  G_UNLOCK (test_g_static_rw_lock_state);
     247  
     248  	  g_usleep (g_random_int_range (20,1000));
     249  
     250  	  G_LOCK (test_g_static_rw_lock_state);
     251  	  test_g_static_rw_lock_state--;
     252  	  G_UNLOCK (test_g_static_rw_lock_state);
     253  
     254  	  g_static_rw_lock_reader_unlock (&test_g_static_rw_lock_lock);
     255  	}
     256        else /* I'm a writer */
     257  	{
     258            if (g_random_double () > .2) /* I'll block */
     259              g_static_rw_lock_writer_lock (&test_g_static_rw_lock_lock);
     260  	  else /* I'll only try */
     261  	    if (!g_static_rw_lock_writer_trylock (&test_g_static_rw_lock_lock))
     262  	      continue;
     263  	  G_LOCK (test_g_static_rw_lock_state);
     264            g_assert_cmpint (test_g_static_rw_lock_state, ==, 0);
     265            test_g_static_rw_lock_state = -1;
     266  	  G_UNLOCK (test_g_static_rw_lock_state);
     267  
     268  	  g_usleep (g_random_int_range (20,1000));
     269  
     270  	  G_LOCK (test_g_static_rw_lock_state);
     271  	  test_g_static_rw_lock_state = 0;
     272  	  G_UNLOCK (test_g_static_rw_lock_state);
     273  
     274  	  g_static_rw_lock_writer_unlock (&test_g_static_rw_lock_lock);
     275  	}
     276      }
     277    return NULL;
     278  }
     279  
     280  static void
     281  test_g_static_rw_lock (void)
     282  {
     283    GThread *threads[THREADS];
     284    guint i;
     285    for (i = 0; i < THREADS; i++)
     286      {
     287        threads[i] = g_thread_create (test_g_static_rw_lock_thread,
     288                                      NULL, TRUE, NULL);
     289      }
     290    g_usleep (G_USEC_PER_SEC * 5);
     291    test_g_static_rw_lock_run = FALSE;
     292    for (i = 0; i < THREADS; i++)
     293      {
     294        g_thread_join (threads[i]);
     295      }
     296    g_assert_cmpint (test_g_static_rw_lock_state, ==, 0);
     297  }
     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  test_g_once_init_func(gpointer arg)
     308  {
     309    guint *count = arg;
     310    g_usleep (g_random_int_range (20,1000));
     311    (*count)++;
     312    g_usleep (g_random_int_range (20,1000));
     313    return arg;
     314  }
     315  
     316  static gpointer
     317  test_g_once_thread (gpointer ignore)
     318  {
     319    guint i;
     320    G_LOCK (test_g_once);
     321    /* Don't start before all threads are created */
     322    G_UNLOCK (test_g_once);
     323    for (i = 0; i < 1000; i++)
     324      {
     325        guint pos = g_random_int_range (0, G_ONCE_SIZE);
     326        gpointer ret = g_once (test_g_once_array + pos,
     327                               test_g_once_init_func,
     328                               test_g_once_guint_array + pos);
     329        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    for (i = 0; i < G_ONCE_SIZE; i++)
     335      {
     336        gpointer ret = g_once (test_g_once_array + i,
     337                               test_g_once_init_func,
     338                               test_g_once_guint_array + i);
     339        g_assert_cmpmem (ret, sizeof (int),
     340                         test_g_once_guint_array + i, sizeof (int));
     341      }
     342  
     343    return NULL;
     344  }
     345  
     346  static void
     347  test_g_thread_once (void)
     348  {
     349    static GOnce once_init = G_ONCE_INIT;
     350    GThread *threads[G_ONCE_THREADS];
     351    guint i;
     352    for (i = 0; i < G_ONCE_SIZE; i++)
     353      {
     354        test_g_once_array[i] = once_init;
     355        test_g_once_guint_array[i] = i;
     356      }
     357    G_LOCK (test_g_once);
     358    for (i = 0; i < G_ONCE_THREADS; i++)
     359      {
     360        threads[i] = g_thread_create (test_g_once_thread, GUINT_TO_POINTER (i % 2),
     361                                      TRUE, NULL);
     362      }
     363    G_UNLOCK (test_g_once);
     364    for (i = 0; i < G_ONCE_THREADS; i++)
     365      {
     366        g_thread_join (threads[i]);
     367      }
     368  
     369    for (i = 0; i < G_ONCE_SIZE; i++)
     370      {
     371        g_assert_cmpint (test_g_once_guint_array[i], ==, i + 1);
     372      }
     373  }
     374  
     375  /* rerun all the tests */
     376  static void
     377  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    g_thread_use_default_impl = FALSE;
     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    /* XXX: And this shows how silly the above non-native tests are */
     391    g_static_rw_lock_free (&test_g_static_rw_lock_lock);
     392    g_static_rec_mutex_free (&test_g_static_rec_mutex_mutex);
     393    g_static_private_free (&test_g_static_private_private2);
     394  }
     395  
     396  int
     397  main (int argc,
     398        char *argv[])
     399  {
     400    g_test_init (&argc, &argv, NULL);
     401  
     402    g_test_add_func ("/thread/mutex", test_g_mutex);
     403    g_test_add_func ("/thread/static-rec-mutex", test_g_static_rec_mutex);
     404    g_test_add_func ("/thread/static-private", test_g_static_private);
     405    g_test_add_func ("/thread/static-rw-lock", test_g_static_rw_lock);
     406    g_test_add_func ("/thread/once", test_g_thread_once);
     407    g_test_add_func ("/thread/rerun-all", test_rerun_all);
     408  
     409    return g_test_run ();
     410  }