void ec_lock_reader_lock (ECLock *self) { g_static_rw_lock_reader_lock (self->free_lock); { g_assert (!self->destroyed); g_assert (!have_reader_lock_unprotected (self)); g_mutex_lock (self->state_mutex); while ( self->state == EC_LOCK_STATE_WRITER_LOCKED ) { g_cond_wait (self->state_cv, self->state_mutex); } { // To make sure we haven't screwed up this class, we operate an // actual reader/writer lock. It had better work... gboolean lock_result = g_static_rw_lock_reader_trylock (self->lock); g_assert (lock_result == TRUE); g_assert (self->writer == NULL); g_hash_table_insert (self->readers, g_thread_self (), NULL); maybe_trace (self, "obtained reader lock"); self->state = EC_LOCK_STATE_READER_LOCKED; g_cond_broadcast (self->state_cv); } g_mutex_unlock (self->state_mutex); } g_static_rw_lock_reader_unlock (self->free_lock); }
static gpointer test_g_static_rw_lock_thread (gpointer data) { while (test_g_static_rw_lock_run) { if (g_random_double() > .2) /* I'm a reader */ { if (g_random_double() > .2) /* I'll block */ g_static_rw_lock_reader_lock (&test_g_static_rw_lock_lock); else /* I'll only try */ if (!g_static_rw_lock_reader_trylock (&test_g_static_rw_lock_lock)) continue; G_LOCK (test_g_static_rw_lock_state); g_assert (test_g_static_rw_lock_state >= 0); test_g_static_rw_lock_state++; G_UNLOCK (test_g_static_rw_lock_state); g_usleep (g_random_int_range (20,1000)); G_LOCK (test_g_static_rw_lock_state); test_g_static_rw_lock_state--; G_UNLOCK (test_g_static_rw_lock_state); g_static_rw_lock_reader_unlock (&test_g_static_rw_lock_lock); } else /* I'm a writer */ { if (g_random_double() > .2) /* I'll block */ g_static_rw_lock_writer_lock (&test_g_static_rw_lock_lock); else /* I'll only try */ if (!g_static_rw_lock_writer_trylock (&test_g_static_rw_lock_lock)) continue; G_LOCK (test_g_static_rw_lock_state); g_assert (test_g_static_rw_lock_state == 0); test_g_static_rw_lock_state = -1; G_UNLOCK (test_g_static_rw_lock_state); g_usleep (g_random_int_range (20,1000)); G_LOCK (test_g_static_rw_lock_state); test_g_static_rw_lock_state = 0; G_UNLOCK (test_g_static_rw_lock_state); g_static_rw_lock_writer_unlock (&test_g_static_rw_lock_lock); } } return NULL; }