class Fiber::SchedulerInterface

This is not an existing class, but documentation of the interface that Scheduler object should comply to in order to be used as argument to Fiber.scheduler and handle non-blocking fibers. See also the “Non-blocking fibers” section in Fiber class docs for explanations of some concepts.

Scheduler's behavior and usage are expected to be as follows:

A typical implementation would probably rely for this closing loop on a gem like EventMachine or Async.

This way concurrent execution will be achieved transparently for every individual Fiber's code.

Hook methods are:

When not specified otherwise, the hook implementations are mandatory: if they are not implemented, the methods trying to call hook will fail. To provide backward compatibility, in the future hooks will be optional (if they are not implemented, due to the scheduler being created for the older Ruby version, the code which needs this hook will not fail, and will just behave in a blocking fashion).

It is also strongly recommended that the scheduler implements the fiber method, which is delegated to by Fiber.schedule.

Sample toy implementation of the scheduler can be found in Ruby's code, in test/fiber/scheduler.rb

Public Instance Methods

block(blocker, timeout = nil) click to toggle source

Invoked by methods like Thread.join, and by Mutex, to signify that current Fiber is blocked until further notice (e.g. unblock) or until timeout has elapsed.

blocker is what we are waiting on, informational only (for debugging and logging). There are no guarantee about its value.

Expected to return boolean, specifying whether the blocking operation was successful or not.

static VALUE
rb_fiber_scheduler_interface_block(VALUE self)
{
}
close() click to toggle source

Called when the current thread exits. The scheduler is expected to implement this method in order to allow all waiting fibers to finalize their execution.

The suggested pattern is to implement the main event loop in the close method.

static VALUE
rb_fiber_scheduler_interface_close(VALUE self)
{
}
fiber(&block) click to toggle source

Implementation of the Fiber.schedule. The method is expected to immediately run the given block of code in a separate non-blocking fiber, and to return that Fiber.

Minimal suggested implementation is:

def fiber(&block)
  fiber = Fiber.new(blocking: false, &block)
  fiber.resume
  fiber
end
static VALUE
rb_fiber_scheduler_interface_fiber(VALUE self)
{
}
io_wait(io, events, timeout) click to toggle source

Invoked by IO#wait, IO#wait_readable, IO#wait_writable to ask whether the specified descriptor is ready for specified events within the specified timeout.

events is a bit mask of IO::READABLE, IO::WRITABLE, and IO::PRIORITY.

Suggested implementation should register which Fiber is waiting for which resources and immediately calling Fiber.yield to pass control to other fibers. Then, in the close method, the scheduler might dispatch all the I/O resources to fibers waiting for it.

Expected to return the subset of events that are ready immediately.

static VALUE
rb_fiber_scheduler_interface_io_wait(VALUE self)
{
}
kernel_sleep(duration = nil) click to toggle source

Invoked by Kernel#sleep and Mutex#sleep and is expected to provide an implementation of sleeping in a non-blocking way. Implementation might register the current fiber in some list of “which fiber wait until what moment”, call Fiber.yield to pass control, and then in close resume the fibers whose wait period has elapsed.

static VALUE
rb_fiber_scheduler_interface_kernel_sleep(VALUE self)
{
}
process_wait(pid, flags) click to toggle source

Invoked by Process::Status.wait in order to wait for a specified process. See that method description for arguments description.

Suggested minimal implementation:

Thread.new do
  Process::Status.wait(pid, flags)
end.value

This hook is optional: if it is not present in the current scheduler, Process::Status.wait will behave as a blocking method.

Expected to return a Process::Status instance.

static VALUE
rb_fiber_scheduler_interface_process_wait(VALUE self)
{
}
unblock(blocker, fiber) click to toggle source

Invoked to wake up Fiber previously blocked with block (for example, Mutex#lock calls block and Mutex#unlock calls unblock). The scheduler should use the fiber parameter to understand which fiber is unblocked.

blocker is what was awaited for, but it is informational only (for debugging and logging), and it is not guaranteed to be the same value as the blocker for block.

static VALUE
rb_fiber_scheduler_interface_unblock(VALUE self)
{
}