Add a non-trivial GRWLock test
authorMatthias Clasen <mclasen@redhat.com>
Fri, 23 Sep 2011 11:21:53 +0000 (07:21 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Fri, 23 Sep 2011 11:25:07 +0000 (07:25 -0400)
This one tests that the writer lock behaves like a mutex.
Adapted from the corresponding test in GMutex.

glib/tests/rwlock.c

index 17869ca..c69dd94 100644 (file)
@@ -111,6 +111,82 @@ test_rwlock6 (void)
   g_rw_lock_clear (&lock);
 }
 
+
+#define LOCKS      48
+#define ITERATIONS 10000
+#define THREADS    100
+
+
+GThread *owners[LOCKS];
+GRWLock  locks[LOCKS];
+
+static void
+acquire (gint nr)
+{
+  GThread *self;
+
+  self = g_thread_self ();
+
+  if (!g_rw_lock_writer_trylock (&locks[nr]))
+    {
+      if (g_test_verbose ())
+        g_print ("thread %p going to block on lock %d\n", self, nr);
+
+      g_rw_lock_writer_lock (&locks[nr]);
+    }
+
+  g_assert (owners[nr] == NULL);   /* hopefully nobody else is here */
+  owners[nr] = self;
+
+  /* let some other threads try to ruin our day */
+  g_thread_yield ();
+  g_thread_yield ();
+  g_thread_yield ();
+
+  g_assert (owners[nr] == self);   /* hopefully this is still us... */
+  owners[nr] = NULL;               /* make way for the next guy */
+
+  g_rw_lock_writer_unlock (&locks[nr]);
+}
+
+static gpointer
+thread_func (gpointer data)
+{
+  gint i;
+  GRand *rand;
+
+  rand = g_rand_new ();
+
+  for (i = 0; i < ITERATIONS; i++)
+    acquire (g_rand_int_range (rand, 0, LOCKS));
+
+  g_rand_free (rand);
+
+  return NULL;
+}
+
+static void
+test_rwlock7 (void)
+{
+  gint i;
+  GThread *threads[THREADS];
+
+  for (i = 0; i < LOCKS; i++)
+    g_rw_lock_init (&locks[i]);
+
+  for (i = 0; i < THREADS; i++)
+    threads[i] = g_thread_create (thread_func, NULL, TRUE, NULL);
+
+  for (i = 0; i < THREADS; i++)
+    g_thread_join (threads[i]);
+
+  for (i = 0; i < LOCKS; i++)
+    g_rw_lock_clear (&locks[i]);
+
+  for (i = 0; i < LOCKS; i++)
+    g_assert (owners[i] == NULL);
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -122,6 +198,7 @@ main (int argc, char *argv[])
   g_test_add_func ("/thread/rwlock4", test_rwlock4);
   g_test_add_func ("/thread/rwlock5", test_rwlock5);
   g_test_add_func ("/thread/rwlock6", test_rwlock6);
+  g_test_add_func ("/thread/rwlock7", test_rwlock7);
 
   return g_test_run ();
 }