# class Mutex

Mutex implements a simple semaphore that can be used to coordinate access to shared data from multiple concurrent threads.

Example:

    semaphore = Mutex.new

    a = Thread.new {
      semaphore.synchronize {
        # access shared resource
      }
    }

    b = Thread.new {
      semaphore.synchronize {
        # access shared resource
      }
    }

### Public Class Methods

new → mutex click to toggle source

Creates a new Mutex

    static VALUE
    mutex_initialize(VALUE self)
    {
        return self;
    }

### Public Instance Methods

lock → self click to toggle source

Attempts to grab the lock and waits if it isn't available. Raises `ThreadError` if `mutex` was locked by the current thread.

    VALUE
    rb_mutex_lock(VALUE self)
    {
        return do_mutex_lock(self, 1);
    }

locked? → true or false click to toggle source

Returns `true` if this lock is currently held by some thread.

    VALUE
    rb_mutex_locked_p(VALUE self)
    {
        rb_mutex_t *mutex;
        GetMutexPtr(self, mutex);
        return mutex->th ? Qtrue : Qfalse;
    }

owned? → true or false click to toggle source

Returns `true` if this lock is currently held by current thread.

    VALUE
    rb_mutex_owned_p(VALUE self)
    {
        VALUE owned = Qfalse;
        rb_thread_t *th = GET_THREAD();
        rb_mutex_t *mutex;

        GetMutexPtr(self, mutex);

        if (mutex->th == th)
            owned = Qtrue;

        return owned;
    }

sleep(timeout = nil) → number click to toggle source

Releases the lock and sleeps `timeout` seconds if it is given and non-nil or forever. Raises `ThreadError` if `mutex` wasn't locked by the current thread.

When the thread is next woken up, it will attempt to reacquire the lock.

Note that this method can wakeup without explicit Thread#wakeup call. For example, receiving signal and so on.

    static VALUE
    mutex_sleep(int argc, VALUE *argv, VALUE self)
    {
        VALUE timeout;

        rb_scan_args(argc, argv, "01", &timeout);
        return rb_mutex_sleep(self, timeout);
    }

synchronize { ... } → result of the block click to toggle source

Obtains a lock, runs the block, and releases the lock when the block completes. See the example under `Mutex`.

    static VALUE
    rb_mutex_synchronize_m(VALUE self, VALUE args)
    {
        if (!rb_block_given_p()) {
            rb_raise(rb_eThreadError, "must be called with a block");
        }

        return rb_mutex_synchronize(self, rb_yield, Qundef);
    }

try_lock → true or false click to toggle source

Attempts to obtain the lock and returns immediately. Returns `true` if the lock was granted.

    VALUE
    rb_mutex_trylock(VALUE self)
    {
        rb_mutex_t *mutex;
        VALUE locked = Qfalse;
        GetMutexPtr(self, mutex);

        if (mutex->th == 0) {
            rb_thread_t *th = GET_THREAD();
            mutex->th = th;
            locked = Qtrue;

            mutex_locked(th, self);
        }

        return locked;
    }

unlock → self click to toggle source

Releases the lock. Raises `ThreadError` if `mutex` wasn't locked by the current thread.

    VALUE
    rb_mutex_unlock(VALUE self)
    {
        const char *err;
        rb_mutex_t *mutex;
        GetMutexPtr(self, mutex);

        err = rb_mutex_unlock_th(mutex, GET_THREAD());
        if (err) rb_raise(rb_eThreadError, "%s", err);

        return self;
    }