mirror of
https://github.com/ruby/ruby.git
synced 2026-01-26 12:14:51 +00:00
Define Thread::ConditionVariable in thread_sync.rb
It's more consistent with Mutex, but also the `#wait` method benefits from receiving the execution context instead of having to call `GET_EC`.
This commit is contained in:
parent
cf97a14c78
commit
7e7a1db579
Notes:
git
2025-12-12 09:08:06 +00:00
@ -1560,21 +1560,8 @@ condvar_alloc(VALUE klass)
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* Document-method: ConditionVariable::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;
|
||||
}
|
||||
|
||||
struct sleep_call {
|
||||
rb_execution_context_t *ec;
|
||||
VALUE mutex;
|
||||
VALUE timeout;
|
||||
};
|
||||
@ -1585,65 +1572,44 @@ static VALUE
|
||||
do_sleep(VALUE args)
|
||||
{
|
||||
struct sleep_call *p = (struct sleep_call *)args;
|
||||
return rb_funcallv(p->mutex, id_sleep, 1, &p->timeout);
|
||||
if (CLASS_OF(p->mutex) == rb_cMutex) {
|
||||
return rb_mut_sleep(p->ec, p->mutex, p->timeout);
|
||||
}
|
||||
else {
|
||||
return rb_funcallv(p->mutex, id_sleep, 1, &p->timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Document-method: Thread::ConditionVariable#wait
|
||||
* call-seq: 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.
|
||||
*
|
||||
* This method may wake up spuriously due to underlying implementation details.
|
||||
*
|
||||
* Returns the slept result on +mutex+.
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
rb_condvar_wait(int argc, VALUE *argv, VALUE self)
|
||||
rb_condvar_wait(rb_execution_context_t *ec, VALUE self, VALUE mutex, VALUE timeout)
|
||||
{
|
||||
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 sleep_call args = {
|
||||
.ec = ec,
|
||||
.mutex = mutex,
|
||||
.timeout = timeout,
|
||||
};
|
||||
|
||||
struct sync_waiter sync_waiter = {
|
||||
.self = args.mutex,
|
||||
.self = 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);
|
||||
return rb_ec_ensure(ec, do_sleep, (VALUE)&args, delete_from_waitq, (VALUE)&sync_waiter);
|
||||
}
|
||||
|
||||
/*
|
||||
* Document-method: Thread::ConditionVariable#signal
|
||||
*
|
||||
* Wakes up the first thread in line waiting for this lock.
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
rb_condvar_signal(VALUE self)
|
||||
rb_condvar_signal(rb_execution_context_t *ec, VALUE self)
|
||||
{
|
||||
struct rb_condvar *cv = condvar_ptr(self);
|
||||
wakeup_one(&cv->waitq);
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* Document-method: Thread::ConditionVariable#broadcast
|
||||
*
|
||||
* Wakes up all threads waiting for this lock.
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
rb_condvar_broadcast(VALUE self)
|
||||
rb_condvar_broadcast(rb_execution_context_t *ec, VALUE self)
|
||||
{
|
||||
struct rb_condvar *cv = condvar_ptr(self);
|
||||
wakeup_all(&cv->waitq);
|
||||
@ -1726,13 +1692,6 @@ Init_thread_sync(void)
|
||||
|
||||
id_sleep = rb_intern("sleep");
|
||||
|
||||
rb_define_method(rb_cConditionVariable, "initialize", rb_condvar_initialize, 0);
|
||||
rb_undef_method(rb_cConditionVariable, "initialize_copy");
|
||||
rb_define_method(rb_cConditionVariable, "marshal_dump", undumpable, 0);
|
||||
rb_define_method(rb_cConditionVariable, "wait", rb_condvar_wait, -1);
|
||||
rb_define_method(rb_cConditionVariable, "signal", rb_condvar_signal, 0);
|
||||
rb_define_method(rb_cConditionVariable, "broadcast", rb_condvar_broadcast, 0);
|
||||
|
||||
rb_provide("thread.rb");
|
||||
}
|
||||
|
||||
|
||||
@ -148,4 +148,48 @@ class Thread
|
||||
Primitive.rb_mut_sleep(timeout)
|
||||
end
|
||||
end
|
||||
|
||||
class ConditionVariable
|
||||
# Document-method: ConditionVariable::new
|
||||
#
|
||||
# Creates a new condition variable instance.
|
||||
def initialize
|
||||
end
|
||||
|
||||
undef_method :initialize_copy
|
||||
|
||||
# :nodoc:
|
||||
def marshal_dump
|
||||
raise TypeError, "can't dump #{self.class}"
|
||||
end
|
||||
|
||||
# Document-method: Thread::ConditionVariable#signal
|
||||
#
|
||||
# Wakes up the first thread in line waiting for this lock.
|
||||
def signal
|
||||
Primitive.rb_condvar_signal
|
||||
end
|
||||
|
||||
# Document-method: Thread::ConditionVariable#broadcast
|
||||
#
|
||||
# Wakes up all threads waiting for this lock.
|
||||
def broadcast
|
||||
Primitive.rb_condvar_broadcast
|
||||
end
|
||||
|
||||
# Document-method: Thread::ConditionVariable#wait
|
||||
# call-seq: 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.
|
||||
#
|
||||
# This method may wake up spuriously due to underlying implementation details.
|
||||
#
|
||||
# Returns the slept result on +mutex+.
|
||||
def wait(mutex, timeout=nil)
|
||||
Primitive.rb_condvar_wait(mutex, timeout)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user