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

ruby-changes:63031

From: Samuel <ko1@a...>
Date: Mon, 21 Sep 2020 12:28:28 +0900 (JST)
Subject: [ruby-changes:63031] f7aa51b2b8 (master): Update NEWS & documentation relating to scheduler.

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

From f7aa51b2b8fe576f33d15cbcbb28723116fb0885 Mon Sep 17 00:00:00 2001
From: Samuel Williams <samuel.williams@o...>
Date: Mon, 21 Sep 2020 13:36:34 +1200
Subject: Update NEWS & documentation relating to scheduler.


diff --git a/NEWS.md b/NEWS.md
index 5a43a7a..e6c77e0 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -161,11 +161,51 @@ Outstanding ones only. https://github.com/ruby/ruby/blob/trunk/NEWS.md#L161
             p C.ancestors #=> [C, M1, M2, Object, Kernel, BasicObject]
             ```
 
+* Thread
+
+    * Introduce `Thread#scheduler` for intercepting blocking operations and
+      `Thread.scheduler` for accessing the current scheduler. See
+      doc/scheduler.md for more details. [[Feature #16786]]
+    * `Thread#blocking?` tells whether the current execution context is
+      blocking. [[Feature #16786]]
+    * `Thread#join` invokes the scheduler hooks `block`/`unblock` in a
+      non-blocking execution context. [[Feature #16786]]
+
 * Mutex
 
-    * Mutex is now acquired per-Fiber instead of per-Thread. This change should
-      be compatible for essentially all usages and avoids blocking when using
-      a Fiber Scheduler. [[Feature #16792]]
+    * `Mutex` is now acquired per-`Fiber` instead of per-`Thread`. This change
+      should be compatible for essentially all usages and avoids blocking when
+      using a scheduler. [[Feature #16792]]
+
+* Fiber
+
+    * `Fiber.new(blocking: true/false)` allows you to create non-blocking
+      execution contexts. [[Feature #16786]]
+    * `Fiber#blocking?` tells whether the fiber is non-blocking. [[Feature #16786]]
+
+* Kernel
+
+    * `Kernel.sleep(...)` invokes the scheduler hook `#kernel_sleep(...)` in a
+      non-blocking execution context. [[Feature #16786]]
+
+* IO
+
+    * `IO#nonblock?` now defaults to `true`. [[Feature #16786]]
+    * `IO#wait_readable`, `IO#wait_writable`, `IO#read`, `IO#write` and other
+      related methods (e.g. `#puts`, `#gets`) may invoke the scheduler hook
+      `#io_wait(io, events, timeout)` in a non-blocking execution context.
+      [[Feature #16786]]
+
+* ConditionVariable
+
+    * `ConditionVariable#wait` may now invoke the `block`/`unblock` scheduler
+      hooks in a non-blocking context. [[Feature #16786]]
+
+* Queue / SizedQueue
+
+    * `Queue#pop`, `SizedQueue#push` and related methods may now invoke the
+      `block`/`unblock` scheduler hooks in a non-blocking context.
+      [[Feature #16786]]
 
 * Ractor
 
@@ -381,6 +421,7 @@ Excluding feature bug fixes. https://github.com/ruby/ruby/blob/trunk/NEWS.md#L421
 [Feature #16686]: https://bugs.ruby-lang.org/issues/16686
 [Feature #16746]: https://bugs.ruby-lang.org/issues/16746
 [Feature #16754]: https://bugs.ruby-lang.org/issues/16754
+[Feature #16786]: https://bugs.ruby-lang.org/issues/16786
 [Feature #16792]: https://bugs.ruby-lang.org/issues/16792
 [Feature #16828]: https://bugs.ruby-lang.org/issues/16828
 [Misc #16961]:    https://bugs.ruby-lang.org/issues/16961
diff --git a/doc/fiber.rdoc b/doc/fiber.rdoc
deleted file mode 100644
index 584e67f..0000000
--- a/doc/fiber.rdoc
+++ /dev/null
@@ -1,137 +0,0 @@ https://github.com/ruby/ruby/blob/trunk/NEWS.md#L0
-= Fiber
-
-Fiber is a flow-control primitive which enable cooperative scheduling. This is
-in contrast to threads which can be preemptively scheduled at any time. While
-having a similar memory profiles, the cost of context switching fibers can be
-significantly less than threads as it does not involve a system call.
-
-== Design
-
-=== Scheduler
-
-The per-thread fiber scheduler interface is used to intercept blocking
-operations. A typical implementation would be a wrapper for a gem like
-EventMachine or Async. This design provides separation of concerns between the
-event loop implementation and application code. It also allows for layered
-schedulers which can perform instrumentation.
-
-  class Scheduler
-    # Wait for the given file descriptor to become readable.
-    def wait_readable(io)
-    end
-
-    # Wait for the given file descriptor to become writable.
-    def wait_writable(io)
-    end
-
-    # Wait for the given file descriptor to match the specified events within
-    # the specified timeout.
-    # @param event [Integer] a bit mask of +IO::WAIT_READABLE+,
-    #   `IO::WAIT_WRITABLE` and `IO::WAIT_PRIORITY`.
-    # @param timeout [#to_f] the amount of time to wait for the event.
-    def wait_any(io, events, timeout)
-    end
-
-    # Sleep the current task for the specified duration, or forever if not
-    # specified.
-    # @param duration [#to_f] the amount of time to sleep.
-    def wait_sleep(duration = nil)
-    end
-
-    # The Ruby virtual machine is going to enter a system level blocking
-    # operation.
-    def enter_blocking_region
-    end
-
-    # The Ruby virtual machine has completed the system level blocking
-    # operation.
-    def exit_blocking_region
-    end
-
-    # Intercept the creation of a non-blocking fiber.
-    def fiber(&block)
-      Fiber.new(blocking: false, &block)
-    end
-
-    # Invoked when the thread exits.
-    def run
-      # Implement event loop here.
-    end
-  end
-
-On CRuby, the following extra methods need to be implemented to handle the
-public C interface:
-
-  class Scheduler
-    # Wrapper for rb_wait_readable(int) C function.
-    def wait_readable_fd(fd)
-      wait_readable(::IO.for_fd(fd, autoclose: false))
-    end
-
-    # Wrapper for rb_wait_readable(int) C function.
-    def wait_writable_fd(fd)
-      wait_writable(::IO.for_fd(fd, autoclose: false))
-    end
-
-    # Wrapper for rb_wait_for_single_fd(int) C function.
-    def wait_for_single_fd(fd, events, duration)
-      wait_any(::IO.for_fd(fd, autoclose: false), events, duration)
-    end
-  end
-
-=== Non-blocking Fibers
-
-By default fibers are blocking. Non-blocking fibers may invoke specific
-scheduler hooks when a blocking operation occurs, and these hooks may introduce
-context switching points.
-
-  Fiber.new(blocking: false) do
-    puts Fiber.current.blocking? # false
-
-    # May invoke `Thread.current.scheduler&.wait_readable`.
-    io.read(...)
-
-    # May invoke `Thread.current.scheduler&.wait_writable`.
-    io.write(...)
-
-    # Will invoke `Thread.current.scheduler&.wait_sleep`.
-    sleep(n)
-  end.resume
-
-We also introduce a new method which simplifies the creation of these
-non-blocking fibers:
-
-  Fiber.schedule do
-    puts Fiber.current.blocking? # false
-  end
-
-The purpose of this method is to allow the scheduler to internally decide the
-policy for when to start the fiber, and whether to use symmetric or asymmetric
-fibers.
-
-=== Mutex
-
-Locking a mutex causes the +Thread#scheduler+ to not be used while the mutex
-is held by that thread. On +Mutex#lock+, fiber switching via the scheduler
-is disabled and operations become blocking for all fibers of the same +Thread+.
-On +Mutex#unlock+, the scheduler is enabled again.
-
-  mutex = Mutex.new
-
-  puts Thread.current.blocking? # 1 (true)
-
-  Fiber.new(blocking: false) do
-    puts Thread.current.blocking? # false
-    mutex.synchronize do
-      puts Thread.current.blocking? # (1) true
-    end
-
-    puts Thread.current.blocking? # false
-  end.resume
-
-=== Non-blocking I/O
-
-By default, I/O is non-blocking. Not all operating systems support non-blocking
-I/O. Windows is a notable example where socket I/O can be non-blocking but pipe
-I/O is blocking. Provided that there *is* a scheduler and the current thread *is
-non-blocking*, the operation will invoke the scheduler.
diff --git a/doc/scheduler.md b/doc/scheduler.md
new file mode 100644
index 0000000..e641dab
--- /dev/null
+++ b/doc/scheduler.md
@@ -0,0 +1,127 @@ https://github.com/ruby/ruby/blob/trunk/doc/scheduler.md#L1
+# Scheduler
+
+The scheduler interface is used to intercept blocking operations. A typical
+implementation would be a wrapper for a gem like `EventMachine` or `Async`. This
+design provides separation of concerns between the event loop implementation
+and application code. It also allows for layered schedulers which can perform
+instrumentation.
+
+## Interface
+
+This is the interface you need to implement.
+
+~~~ ruby
+class Scheduler
+  # Wait for the given file descriptor to match the specified events within
+  # the specified timeout.
+  # @parameter event [Integer] A bit mask of `IO::READABLE`,
+  #   `IO::WRITABLE` and `IO::PRIORITY`.
+  # @parameter timeout [Numeric] The amount of time to wait for the event in seconds.
+  # @returns [Integer] The subset of events that are ready.
+  def io_wait(io, events, timeout)
+  end
+
+  # Sleep the current task for the specified duration, or forever if not
+  # specified.
+  # @param duration [Numeric] The amount of time to sleep in seconds.
+  def kernel_sleep(duration = nil)
+  end
+
+  # Block the calling fiber.
+  # @parameter blocker [Object] What we are waiting on, informational only.
+  # @parameter timeout [Numeric | Nil] The amount of time to wait for in seconds.
+  # @returns [Boolean] Whether the blocking operation was successful or not.
+  def block(blocker, timeout = nil)
+  end
+
+  # Unblock the specified fiber.
+  # @parameter blocker [Object] What we are waiting on, informational only.
+  # @parameter fiber [Fiber] The fiber to unblock.
+  # @reentrant Thread safe.
+  def unblock(blocker, fiber)
+  end
+
+  # Intercept the creation of a non-blocking fiber.
+  # @returns [Fiber]
+  def fiber(&block)
+    Fiber.new(blocking: false, &block)
+  end
+
+  # Invoked when the thread exits.
+  def close
+    self.run
+  end
+
+  def run
+    # Implement event loop here.
+  end
+end
+~~~
+
+Additional hooks may be introduced in the future, we will use feature detection
+in order to enable these hooks.
+
+## Non-blocking Execution
+
+The scheduler hooks will only be used in special non-blocking execution
+contexts. Non-blocking execution contexts introduce non-determinism because the
+execution of scheduler hooks may introduce context switching (... truncated)

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

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