class Thread::ConditionVariable

ConditionVariable objects augment class Mutex. Using condition variables, it is possible to suspend while in the middle of a critical section until a resource becomes available.

Example:

mutex = Thread::Mutex.new
resource = Thread::ConditionVariable.new

a = Thread.new {
   mutex.synchronize {
     # Thread 'a' now needs the resource
     resource.wait(mutex)
     # 'a' can now have the resource
   }
}

b = Thread.new {
   mutex.synchronize {
     # Thread 'b' has finished using the resource
     resource.signal
   }
}

Public Class Methods

new ()

Creates a new condition variable instance.

static VALUE
rb_condvar_initialize(VALUE self)
{
    struct rb_condvar *cv = condvar_ptr(self);
    ccan_list_head_init(&cv->waitq);
    return self;
}

Public Instance Methods

broadcast ()

Wakes up all threads waiting for this lock.

static VALUE
rb_condvar_broadcast(VALUE self)
{
    struct rb_condvar *cv = condvar_ptr(self);
    wakeup_all(&cv->waitq);
    return self;
}
signal ()

Wakes up the first thread in line waiting for this lock.

static VALUE
rb_condvar_signal(VALUE self)
{
    struct rb_condvar *cv = condvar_ptr(self);
    wakeup_one(&cv->waitq);
    return self;
}
wait(mutex, timeout=nil)

Releases the lock held in mutex and waits; reacquires the lock on wakeup.

If timeout is given, this method returns after timeout seconds passed, even if no other thread doesn’t signal.

Returns the slept result on mutex.

static VALUE
rb_condvar_wait(int argc, VALUE *argv, VALUE self)
{
    rb_execution_context_t *ec = GET_EC();

    struct rb_condvar *cv = condvar_ptr(self);
    struct sleep_call args;

    rb_scan_args(argc, argv, "11", &args.mutex, &args.timeout);

    struct sync_waiter sync_waiter = {
        .self = args.mutex,
        .th = ec->thread_ptr,
        .fiber = nonblocking_fiber(ec->fiber_ptr)
    };

    ccan_list_add_tail(&cv->waitq, &sync_waiter.node);
    return rb_ensure(do_sleep, (VALUE)&args, delete_from_waitq, (VALUE)&sync_waiter);
}