Esempio n. 1
0
gboolean
ec_lock_writer_trylock (ECLock *self)
{
    gboolean result;

    g_static_rw_lock_reader_lock (self->free_lock);
    {
        g_assert (!self->destroyed);

        g_assert (!have_writer_lock_unprotected (self));

        g_mutex_lock (self->state_mutex);
        if ( self->state != EC_LOCK_STATE_UNLOCKED ) {
            // Consistency check: we better not be able to successfully
            // trylock the independent lock either.
            gboolean lock_result = g_static_rw_lock_writer_trylock (self->lock);
            g_assert (lock_result == FALSE);

            maybe_trace (self,
                         "failed to obtain writer lock in writer_trylock method");

            result = FALSE;
        }
        else {
            // 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_writer_trylock (self->lock);
            g_assert (lock_result == TRUE);

            // Also, the table of readers had better be empty.
            g_assert (g_hash_table_size (self->readers) == 0);
            // And there better not be any other writer either.
            g_assert (self->writer == NULL);

            self->writer = g_thread_self ();

            maybe_trace (self, "obtained writer lock in writer_trylock method");

            self->state = EC_LOCK_STATE_WRITER_LOCKED;

            // No need to broadcast the new state here; other threads are
            // only interested when a writer lock is released!

            result = TRUE;
        }
        g_mutex_unlock (self->state_mutex);
    }
    g_static_rw_lock_reader_unlock (self->free_lock);

    return result;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
void
ec_lock_free (ECLock *self)
{
    // We are now going to destroy this instance, so nobody else better
    // be using it.
    gboolean lock_status = g_static_rw_lock_writer_trylock (self->free_lock);
    // As we said in the interface, its an error to free an instance in
    // use by any other method of this class (waiting in lock, being
    // queried for status, whatever -- all those uses are deemed naughty
    // race conditions).
    g_assert (lock_status == TRUE);
    {
        self->destroyed = TRUE;
    }
    g_static_rw_lock_writer_unlock (self->free_lock);

    g_mutex_lock (self->state_mutex);
    {
        g_assert (self->state == EC_LOCK_STATE_UNLOCKED);
        g_assert (g_hash_table_size (self->readers) == 0);
        g_assert (self->writer == NULL);
    }
    g_mutex_unlock (self->state_mutex);

    g_mutex_free (self->state_mutex);

    g_cond_free (self->state_cv);

    g_static_rw_lock_free (self->lock);
    g_free (self->lock);

    g_static_mutex_free (self->trace_lock);
    g_free (self->trace_lock);

    g_hash_table_destroy (self->readers);

    g_hash_table_destroy (self->traced_threads);

    g_hash_table_destroy (self->thread_names);

    g_static_rw_lock_free (self->free_lock);
    // FIIXME: I'm not certain now where I got the idea that we need
    // g_free as well as g_static_rw_lock_free, though I have a hazy
    // idea I may have looked at the source once upon a time to
    // determine this.
    g_free (self->free_lock);

    g_free (self);
}
Esempio n. 4
0
void
ec_lock_writer_lock (ECLock *self)
{
    g_static_rw_lock_reader_lock (self->free_lock);
    {
        g_assert (!self->destroyed);

        if ( have_writer_lock_unprotected (self) ) {
            GString *pts = pid_thread_string ();
            g_error ("%s: erroneous attempt to writer lock a lock already held",
                     pts->str);
        }
        g_assert (!have_writer_lock_unprotected (self));

        g_mutex_lock (self->state_mutex);
        while ( self->state != EC_LOCK_STATE_UNLOCKED ) {
            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_writer_trylock (self->lock);
            g_assert (lock_result == TRUE);

            // Also, the table of readers had better be empty.
            g_assert (g_hash_table_size (self->readers) == 0);
            // And there better not be any other writer either.
            g_assert (self->writer == NULL);

            self->writer = g_thread_self ();

            maybe_trace (self, "obtained writer lock");

            self->state = EC_LOCK_STATE_WRITER_LOCKED;

            // No need to broadcast the new state here; other threads are
            // only interested when a writer lock is released!
        }
        g_mutex_unlock (self->state_mutex);
    }
    g_static_rw_lock_reader_unlock (self->free_lock);
}