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


170
171
172
173
174
# File 'thread_sync.c', line 170

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)

401
402
403
404
405
# File 'thread_sync.c', line 401

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)

188
189
190
191
192
193
194
# File 'thread_sync.c', line 188

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

    return mutex->fiber ? Qtrue : Qfalse;
}

#owned?Boolean

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

Returns:

  • (Boolean)

413
414
415
416
417
418
419
420
# File 'thread_sync.c', line 413

VALUE
rb_mutex_owned_p(VALUE self)
{
    rb_fiber_t *fiber = GET_EC()->fiber_ptr;
    rb_mutex_t *mutex = mutex_ptr(self);

    return mutex_owned_p(fiber, 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:


580
581
582
583
584
585
586
587
# File 'thread_sync.c', line 580

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:


611
612
613
614
615
616
617
618
619
# File 'thread_sync.c', line 611

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)

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'thread_sync.c', line 235

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

    if (mutex->fiber == 0) {
	rb_fiber_t *fiber = GET_EC()->fiber_ptr;
	rb_thread_t *th = GET_THREAD();
	mutex->fiber = fiber;

	mutex_locked(th, self);
	return Qtrue;
    }

    return Qfalse;
}

#unlockself

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

Returns:

  • (self)

473
474
475
476
477
478
479
480
481
482
483
484
# File 'thread_sync.c', line 473

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

    err = rb_mutex_unlock_th(mutex, th, GET_EC()->fiber_ptr);
    if (err) rb_raise(rb_eThreadError, "%s", err);

    return self;
}