(root)/
glib-2.79.0/
glib/
tests/
rwlock.c
       1  /* Unit tests for GRWLock
       2   * Copyright (C) 2011 Red Hat, Inc
       3   * Author: Matthias Clasen
       4   *
       5   * SPDX-License-Identifier: LicenseRef-old-glib-tests
       6   *
       7   * This work is provided "as is"; redistribution and modification
       8   * in whole or in part, in any medium, physical or electronic is
       9   * permitted without restriction.
      10   *
      11   * This work is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      14   *
      15   * In no event shall the authors or contributors be liable for any
      16   * direct, indirect, incidental, special, exemplary, or consequential
      17   * damages (including, but not limited to, procurement of substitute
      18   * goods or services; loss of use, data, or profits; or business
      19   * interruption) however caused and on any theory of liability, whether
      20   * in contract, strict liability, or tort (including negligence or
      21   * otherwise) arising in any way out of the use of this software, even
      22   * if advised of the possibility of such damage.
      23   */
      24  
      25  /* We are testing some deprecated APIs here */
      26  #ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
      27  #define GLIB_DISABLE_DEPRECATION_WARNINGS
      28  #endif
      29  
      30  #include <glib.h>
      31  
      32  static void
      33  test_rwlock1 (void)
      34  {
      35    GRWLock lock;
      36  
      37    g_rw_lock_init (&lock);
      38    g_rw_lock_writer_lock (&lock);
      39    g_rw_lock_writer_unlock (&lock);
      40    g_rw_lock_writer_lock (&lock);
      41    g_rw_lock_writer_unlock (&lock);
      42    g_rw_lock_clear (&lock);
      43  }
      44  
      45  static void
      46  test_rwlock2 (void)
      47  {
      48    static GRWLock lock;
      49  
      50    g_rw_lock_writer_lock (&lock);
      51    g_rw_lock_writer_unlock (&lock);
      52    g_rw_lock_writer_lock (&lock);
      53    g_rw_lock_writer_unlock (&lock);
      54  }
      55  
      56  static void
      57  test_rwlock3 (void)
      58  {
      59    static GRWLock lock;
      60    gboolean ret;
      61  
      62    ret = g_rw_lock_writer_trylock (&lock);
      63    g_assert (ret);
      64    ret = g_rw_lock_writer_trylock (&lock);
      65    g_assert (!ret);
      66  
      67    g_rw_lock_writer_unlock (&lock);
      68  }
      69  
      70  static void
      71  test_rwlock4 (void)
      72  {
      73    static GRWLock lock;
      74  
      75    g_rw_lock_reader_lock (&lock);
      76    g_rw_lock_reader_unlock (&lock);
      77    g_rw_lock_reader_lock (&lock);
      78    g_rw_lock_reader_unlock (&lock);
      79  }
      80  
      81  static void
      82  test_rwlock5 (void)
      83  {
      84    static GRWLock lock;
      85    gboolean ret;
      86  
      87    ret = g_rw_lock_reader_trylock (&lock);
      88    g_assert (ret);
      89    ret = g_rw_lock_reader_trylock (&lock);
      90    g_assert (ret);
      91  
      92    g_rw_lock_reader_unlock (&lock);
      93    g_rw_lock_reader_unlock (&lock);
      94  }
      95  
      96  static void
      97  test_rwlock6 (void)
      98  {
      99    static GRWLock lock;
     100    gboolean ret;
     101  
     102    g_rw_lock_writer_lock (&lock);
     103    ret = g_rw_lock_reader_trylock (&lock);
     104    g_assert (!ret);
     105    g_rw_lock_writer_unlock (&lock);
     106  
     107    g_rw_lock_reader_lock (&lock);
     108    ret = g_rw_lock_writer_trylock (&lock);
     109    g_assert (!ret);
     110    g_rw_lock_reader_unlock (&lock);
     111  }
     112  
     113  
     114  #define LOCKS      48
     115  #define ITERATIONS 10000
     116  #define THREADS    100
     117  
     118  
     119  GThread *owners[LOCKS];
     120  GRWLock  locks[LOCKS];
     121  
     122  static void
     123  acquire (gint nr)
     124  {
     125    GThread *self;
     126  
     127    self = g_thread_self ();
     128  
     129    if (!g_rw_lock_writer_trylock (&locks[nr]))
     130      {
     131        if (g_test_verbose ())
     132          g_printerr ("thread %p going to block on lock %d\n", self, nr);
     133  
     134        g_rw_lock_writer_lock (&locks[nr]);
     135      }
     136  
     137    g_assert (owners[nr] == NULL);   /* hopefully nobody else is here */
     138    owners[nr] = self;
     139  
     140    /* let some other threads try to ruin our day */
     141    g_thread_yield ();
     142    g_thread_yield ();
     143    g_thread_yield ();
     144  
     145    g_assert (owners[nr] == self);   /* hopefully this is still us... */
     146    owners[nr] = NULL;               /* make way for the next guy */
     147  
     148    g_rw_lock_writer_unlock (&locks[nr]);
     149  }
     150  
     151  static gpointer
     152  thread_func (gpointer data)
     153  {
     154    gint i;
     155    GRand *rand;
     156  
     157    rand = g_rand_new ();
     158  
     159    for (i = 0; i < ITERATIONS; i++)
     160      acquire (g_rand_int_range (rand, 0, LOCKS));
     161  
     162    g_rand_free (rand);
     163  
     164    return NULL;
     165  }
     166  
     167  static void
     168  test_rwlock7 (void)
     169  {
     170    gint i;
     171    GThread *threads[THREADS];
     172  
     173    for (i = 0; i < LOCKS; i++)
     174      g_rw_lock_init (&locks[i]);
     175  
     176    for (i = 0; i < THREADS; i++)
     177      threads[i] = g_thread_new ("test", thread_func, NULL);
     178  
     179    for (i = 0; i < THREADS; i++)
     180      g_thread_join (threads[i]);
     181  
     182    for (i = 0; i < LOCKS; i++)
     183      g_rw_lock_clear (&locks[i]);
     184  
     185    for (i = 0; i < LOCKS; i++)
     186      g_assert (owners[i] == NULL);
     187  }
     188  
     189  static gint even;
     190  static GRWLock even_lock;
     191  GThread *writers[2];
     192  GThread *readers[10];
     193  
     194  static void
     195  change_even (gpointer data)
     196  {
     197    g_rw_lock_writer_lock (&even_lock);
     198  
     199    g_assert (even % 2 == 0);
     200  
     201    even += 1;
     202  
     203    if (GPOINTER_TO_INT (data) == 0)
     204      even += 1;
     205    else
     206      even -= 1;
     207  
     208    g_assert (even % 2 == 0);
     209  
     210    g_rw_lock_writer_unlock (&even_lock);
     211  }
     212  
     213  static void
     214  verify_even (gpointer data)
     215  {
     216    g_rw_lock_reader_lock (&even_lock);
     217  
     218    g_assert (even % 2 == 0);
     219  
     220    g_rw_lock_reader_unlock (&even_lock);
     221  }
     222  
     223  static gpointer
     224  writer_func (gpointer data)
     225  {
     226    gint i;
     227  
     228    for (i = 0; i < 100000; i++)
     229      change_even (data);
     230  
     231    return NULL;
     232  }
     233  
     234  static gpointer
     235  reader_func (gpointer data)
     236  {
     237    gint i;
     238  
     239    for (i = 0; i < 100000; i++)
     240      verify_even (data);
     241  
     242    return NULL;
     243  }
     244  
     245  /* This test has 2 writers and 10 readers.
     246   * The writers modify an integer multiple times,
     247   * but always leave it with an even value.
     248   * The readers verify that they can only observe
     249   * even values
     250   */
     251  static void
     252  test_rwlock8 (void)
     253  {
     254    gint i;
     255  
     256    even = 0;
     257    g_rw_lock_init (&even_lock);
     258  
     259    for (i = 0; i < 2; i++)
     260      writers[i] = g_thread_new ("a", writer_func, GINT_TO_POINTER (i));
     261  
     262    for (i = 0; i < 10; i++)
     263      readers[i] = g_thread_new ("b", reader_func, NULL);
     264  
     265    for (i = 0; i < 2; i++)
     266      g_thread_join (writers[i]);
     267  
     268    for (i = 0; i < 10; i++)
     269      g_thread_join (readers[i]);
     270  
     271    g_assert (even % 2 == 0);
     272  
     273    g_rw_lock_clear (&even_lock);
     274  }
     275  
     276  int
     277  main (int argc, char *argv[])
     278  {
     279    g_test_init (&argc, &argv, NULL);
     280  
     281    g_test_add_func ("/thread/rwlock1", test_rwlock1);
     282    g_test_add_func ("/thread/rwlock2", test_rwlock2);
     283    g_test_add_func ("/thread/rwlock3", test_rwlock3);
     284    g_test_add_func ("/thread/rwlock4", test_rwlock4);
     285    g_test_add_func ("/thread/rwlock5", test_rwlock5);
     286    g_test_add_func ("/thread/rwlock6", test_rwlock6);
     287    g_test_add_func ("/thread/rwlock7", test_rwlock7);
     288    g_test_add_func ("/thread/rwlock8", test_rwlock8);
     289  
     290    return g_test_run ();
     291  }