[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]