ruby-changes:58323
From: Koichi <ko1@a...>
Date: Sun, 20 Oct 2019 15:49:12 +0900 (JST)
Subject: [ruby-changes:58323] a236eaa762 (master): Native MonitorMixin::ConditionVariable#wait
https://git.ruby-lang.org/ruby.git/commit/?id=a236eaa762 From a236eaa762137d7cb32b8311e0ef9a74bbb0f385 Mon Sep 17 00:00:00 2001 From: Koichi Sasada <ko1@a...> Date: Sun, 20 Oct 2019 15:45:30 +0900 Subject: Native MonitorMixin::ConditionVariable#wait MonitorMixin::ConditionVariable#wait can be interrupted just after Monitor#exit_for_cond. So implementation in C. diff --git a/ext/monitor/lib/monitor.rb b/ext/monitor/lib/monitor.rb index f6b3023..b9ae036 100644 --- a/ext/monitor/lib/monitor.rb +++ b/ext/monitor/lib/monitor.rb @@ -105,13 +105,7 @@ module MonitorMixin https://github.com/ruby/ruby/blob/trunk/ext/monitor/lib/monitor.rb#L105 # def wait(timeout = nil) @monitor.mon_check_owner - count = @monitor.__send__(:exit_for_cond) - begin - @cond.wait(@monitor.__send__(:mutex_for_cond), timeout) - return true - ensure - @monitor.__send__(:enter_for_cond, count) - end + @monitor.wait_for_cond(@cond, timeout) end # diff --git a/ext/monitor/monitor.c b/ext/monitor/monitor.c index cf9e7fe..2d39976 100644 --- a/ext/monitor/monitor.c +++ b/ext/monitor/monitor.c @@ -122,15 +122,6 @@ monitor_check_owner(VALUE monitor) https://github.com/ruby/ruby/blob/trunk/ext/monitor/monitor.c#L122 } static VALUE -monitor_enter_for_cond(VALUE monitor, VALUE count) -{ - struct rb_monitor *mc = monitor_ptr(monitor); - RB_OBJ_WRITE(monitor, &mc->owner, rb_thread_current()); - mc->count = NUM2LONG(count); - return Qnil; -} - -static VALUE monitor_exit_for_cond(VALUE monitor) { struct rb_monitor *mc = monitor_ptr(monitor); @@ -140,11 +131,49 @@ monitor_exit_for_cond(VALUE monitor) https://github.com/ruby/ruby/blob/trunk/ext/monitor/monitor.c#L131 return LONG2NUM(cnt); } +struct wait_for_cond_data { + VALUE monitor; + VALUE cond; + VALUE timeout; + VALUE count; +}; + static VALUE -monitor_mutex_for_cond(VALUE monitor) +monitor_wait_for_cond_body(VALUE v) { - struct rb_monitor *mc = monitor_ptr(monitor); - return mc->mutex; + struct wait_for_cond_data *data = (struct wait_for_cond_data *)v; + struct rb_monitor *mc = monitor_ptr(data->monitor); + // cond.wait(monitor.mutex, timeout) + rb_funcall(data->cond, rb_intern("wait"), 2, mc->mutex, data->timeout); + return Qtrue; +} + +static VALUE +monitor_enter_for_cond(VALUE v) +{ + // assert(rb_mutex_owned_p(mc->mutex) == Qtrue) + // but rb_mutex_owned_p is not exported... + + struct wait_for_cond_data *data = (struct wait_for_cond_data *)v; + struct rb_monitor *mc = monitor_ptr(data->monitor); + RB_OBJ_WRITE(data->monitor, &mc->owner, rb_thread_current()); + mc->count = NUM2LONG(data->count); + return Qnil; +} + +static VALUE +monitor_wait_for_cond(VALUE monitor, VALUE cond, VALUE timeout) +{ + VALUE count = monitor_exit_for_cond(monitor); + struct wait_for_cond_data data = { + monitor, + cond, + timeout, + count, + }; + + return rb_ensure(monitor_wait_for_cond_body, (VALUE)&data, + monitor_enter_for_cond, (VALUE)&data); } static VALUE @@ -183,7 +212,5 @@ Init_monitor(void) https://github.com/ruby/ruby/blob/trunk/ext/monitor/monitor.c#L212 rb_define_method(rb_cMonitor, "mon_owned?", monitor_owned_p, 0); /* internal methods for MonitorMixin::ConditionalVariable */ - rb_define_private_method(rb_cMonitor, "enter_for_cond", monitor_enter_for_cond, 1); - rb_define_private_method(rb_cMonitor, "exit_for_cond", monitor_exit_for_cond, 0); - rb_define_private_method(rb_cMonitor, "mutex_for_cond", monitor_mutex_for_cond, 0); + rb_define_method(rb_cMonitor, "wait_for_cond", monitor_wait_for_cond, 2); } -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/