Class: Mutex

Inherits:
Object show all
Defined in:
thread_sync.c,
thread_sync.c

Overview

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
  }
}

Instance Method Summary collapse

Constructor Details

#newObject

Creates a new Mutex



158
159
160
161
162
# File 'thread_sync.c', line 158

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

Instance Method Details

#lockself

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

Returns:

  • (self)


332
333
334
335
336
# File 'thread_sync.c', line 332

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

#locked?Boolean

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

Returns:

  • (Boolean)


176
177
178
179
180
181
182
# File 'thread_sync.c', line 176

VALUE
rb_mutex_locked_p(VALUE self)
{
    rb_mutex_t *mutex = mutex_ptr(self);

    return mutex->th ? Qtrue : Qfalse;
}

#owned?Boolean

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

Returns:

  • (Boolean)


344
345
346
347
348
349
350
351
# File 'thread_sync.c', line 344

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

    return mutex_owned_p(th, mutex);
}

#sleep(timeout = nil) ⇒ Numeric

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.

Returns:



504
505
506
507
508
509
510
511
# File 'thread_sync.c', line 504

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

    timeout = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
    return rb_mutex_sleep(self, timeout);
}

#synchronize { ... } ⇒ Object

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

Yields:



535
536
537
538
539
540
541
542
543
# File 'thread_sync.c', line 535

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

    return rb_mutex_synchronize(self, rb_yield, Qundef);
}

#try_lockBoolean

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

Returns:

  • (Boolean)


202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'thread_sync.c', line 202

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

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

	mutex_locked(th, self);
    }

    return locked;
}

#unlockself

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

Returns:

  • (self)


402
403
404
405
406
407
408
409
410
411
412
# File 'thread_sync.c', line 402

VALUE
rb_mutex_unlock(VALUE self)
{
    const char *err;
    rb_mutex_t *mutex = mutex_ptr(self);

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

    return self;
}