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

ruby-changes:62993

From: Benoit <ko1@a...>
Date: Thu, 17 Sep 2020 22:04:17 +0900 (JST)
Subject: [ruby-changes:62993] 9472d16061 (master): Call scheduler.block instead of scheduler.kernel_sleep for blocking Queue/SizedQueue operations

https://git.ruby-lang.org/ruby.git/commit/?id=9472d16061

From 9472d160619861201bad91560c06248fef8362dc Mon Sep 17 00:00:00 2001
From: Benoit Daloze <eregontp@g...>
Date: Thu, 17 Sep 2020 14:45:44 +0200
Subject: Call scheduler.block instead of scheduler.kernel_sleep for blocking
 Queue/SizedQueue operations

* scheduler.unblock was already already called before but with no corresponding scheduler.block
* add test that Queue#pop makes the scheduler wait until it gets an element.

diff --git a/test/fiber/scheduler.rb b/test/fiber/scheduler.rb
index 1e7f60c..f7a773a 100644
--- a/test/fiber/scheduler.rb
+++ b/test/fiber/scheduler.rb
@@ -93,6 +93,7 @@ class Scheduler https://github.com/ruby/ruby/blob/trunk/test/fiber/scheduler.rb#L93
     end
   ensure
     @urgent.each(&:close)
+    @urgent = nil
   end
 
   def current_time
@@ -139,7 +140,7 @@ class Scheduler https://github.com/ruby/ruby/blob/trunk/test/fiber/scheduler.rb#L140
     end
 
     if io = @urgent&.last
-      @urgent.last.write_nonblock('.')
+      io.write_nonblock('.')
     end
   end
 
diff --git a/test/fiber/test_mutex.rb b/test/fiber/test_mutex.rb
index 1f53ae1..baec559 100644
--- a/test/fiber/test_mutex.rb
+++ b/test/fiber/test_mutex.rb
@@ -115,6 +115,31 @@ class TestFiberMutex < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/fiber/test_mutex.rb#L115
     assert processed == 3
   end
 
+  def test_queue_pop_waits
+    queue = Queue.new
+    running = false
+
+    thread = Thread.new do
+      scheduler = Scheduler.new
+      Thread.current.scheduler = scheduler
+
+      result = nil
+      Fiber.schedule do
+        result = queue.pop
+      end
+
+      running = true
+      scheduler.run
+      result
+    end
+
+    Thread.pass until running
+    sleep 0.1
+
+    queue << :done
+    assert_equal :done, thread.value
+  end
+
   def test_mutex_deadlock
     err = /No live threads left. Deadlock\?/
     assert_in_out_err %W[-I#{__dir__} -], <<-RUBY, ['in synchronize'], err, success: false
diff --git a/thread.c b/thread.c
index 6b20716..b3b7a69 100644
--- a/thread.c
+++ b/thread.c
@@ -134,7 +134,7 @@ rb_thread_local_storage(VALUE thread) https://github.com/ruby/ruby/blob/trunk/thread.c#L134
 
 static void sleep_hrtime(rb_thread_t *, rb_hrtime_t, unsigned int fl);
 static void sleep_forever(rb_thread_t *th, unsigned int fl);
-static void rb_thread_sleep_deadly_allow_spurious_wakeup(void);
+static void rb_thread_sleep_deadly_allow_spurious_wakeup(VALUE blocker);
 static int rb_threadptr_dead(rb_thread_t *th);
 static void rb_check_deadlock(rb_ractor_t *r);
 static int rb_threadptr_pending_interrupt_empty_p(const rb_thread_t *th);
@@ -1485,11 +1485,11 @@ rb_thread_sleep_interruptible(void) https://github.com/ruby/ruby/blob/trunk/thread.c#L1485
 }
 
 static void
-rb_thread_sleep_deadly_allow_spurious_wakeup(void)
+rb_thread_sleep_deadly_allow_spurious_wakeup(VALUE blocker)
 {
     VALUE scheduler = rb_thread_current_scheduler();
     if (scheduler != Qnil) {
-        rb_scheduler_kernel_sleepv(scheduler, 0, NULL);
+        rb_scheduler_block(scheduler, blocker);
     } else {
         thread_debug("rb_thread_sleep_deadly_allow_spurious_wakeup\n");
         sleep_forever(GET_THREAD(), SLEEP_DEADLOCKABLE);
diff --git a/thread_sync.c b/thread_sync.c
index 5b1e4f2..741bff6 100644
--- a/thread_sync.c
+++ b/thread_sync.c
@@ -483,9 +483,9 @@ rb_mutex_abandon_all(rb_mutex_t *mutexes) https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L483
 #endif
 
 static VALUE
-rb_mutex_sleep_forever(VALUE time)
+rb_mutex_sleep_forever(VALUE self)
 {
-    rb_thread_sleep_deadly_allow_spurious_wakeup();
+    rb_thread_sleep_deadly_allow_spurious_wakeup(self);
     return Qnil;
 }
 
@@ -516,7 +516,7 @@ rb_mutex_sleep(VALUE self, VALUE timeout) https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L516
         mutex_lock_uninterruptible(self);
     } else {
         if (NIL_P(timeout)) {
-            rb_ensure(rb_mutex_sleep_forever, Qnil, mutex_lock_uninterruptible, self);
+            rb_ensure(rb_mutex_sleep_forever, self, mutex_lock_uninterruptible, self);
         } else {
             rb_hrtime_t rel = rb_timeval2hrtime(&t);
             rb_ensure(rb_mutex_wait_for, (VALUE)&rel, mutex_lock_uninterruptible, self);
@@ -904,9 +904,9 @@ rb_queue_push(VALUE self, VALUE obj) https://github.com/ruby/ruby/blob/trunk/thread_sync.c#L904
 }
 
 static VALUE
-queue_sleep(VALUE arg)
+queue_sleep(VALUE self)
 {
-    rb_thread_sleep_deadly_allow_spurious_wakeup();
+    rb_thread_sleep_deadly_allow_spurious_wakeup(self);
     return Qnil;
 }
 
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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