Spec-Zone.ru › Ruby 3

класс Fiber::SchedulerInterface

Родитель:
Объект

Это не существующий класс, а документация интерфейса, которому должен соответствовать объект Scheduler, чтобы быть использованным как Fiber.scheduler и обрабатывать неблокирующие волокна. См. также раздел «Неблокирующие волокна» в документации класса Fiber для объяснений некоторых концепций.

Ожидается, что поведение и использование планировщика будут следующими:

  • Когда выполнение в неблокирующем Fiber достигает некоторой блокирующей операции (например, sleep, ожидание процесса или неподготовленного ввода-вывода), оно вызывает некоторые методы-обработчики планировщика, перечисленные ниже.

  • Планировщик каким-то образом регистрирует, чего ждёт текущее волокно, и уступает управление другим волокнам с помощью Fiber.yield (чтобы волокно было приостановлено, ожидая окончания ожидания, и другие волокна в том же потоке могли работать).

  • В конце выполнения текущего потока вызывается метод планировщика close

  • Планировщик попадает в цикл ожидания, проверяя все заблокированные волокна (которые он зарегистрировал при вызовах обработчиков) и возобновляя их, когда ожидаемый ресурс готов (ввод-вывод готов, время сна прошло).

Типичная реализация, вероятно, будет полагаться для этого цикла закрытия на такой gem, как EventMachine или Async.

Таким образом, одновременное выполнение будет достигнуто прозрачно для каждого отдельного кода волокна.

Методы-обработчики:

  • io_wait

  • process_wait

  • kernel_sleep

  • block и unblock

  • (список расширяется по мере того, как разработчики Ruby создают больше методов с неблокирующими вызовами)

Если не указано иное, реализации обработчиков обязательны: если они не реализованы, методы, пытающиеся вызвать обработчик, завершатся ошибкой. Для обеспечения обратной совместимости в будущем обработчики будут необязательными (если они не реализованы из-за того, что планировщик создан для более старой версии Ruby, код, которому нужен этот обработчик, не завершится ошибкой, а просто будет вести себя блокирующим образом).

Также настоятельно рекомендуется, чтобы планировщик реализовал метод fiber, которому делегируется Fiber.schedule.

Пример игрушечной реализации планировщика можно найти в коде Ruby в test/fiber/scheduler.rb

Общедоступные методы экземпляра

block(blocker, timeout = nil) Показать исходный код
static VALUE
rb_fiber_scheduler_interface_block(VALUE self)
{
}

Вызывается методами, такими как Thread.join, и Mutex, чтобы указать, что текущее Fiber заблокировано до дальнейших указаний (например, unblock) или до того, как timeout пройдёт.

blocker — то, на чём мы ждём, только информационная информация (для отладки и ведения журнала). Гарантий о его значении нет.

Ожидается, что вернёт булево значение, указывающее, была ли блокирующая операция успешной или нет.

close() Показать исходный код
static VALUE
rb_fiber_scheduler_interface_close(VALUE self)
{
}

Вызывается при выходе текущего потока. Планировщик должен реализовать этот метод, чтобы разрешить всем ожидающим волокнам завершить выполнение.

Рекомендуемый шаблон — реализовать основной цикл обработки событий в методе close.

fiber(&block) Показать исходный код
static VALUE
rb_fiber_scheduler_interface_fiber(VALUE self)
{
}

Реализация Fiber.schedule. Метод должен немедленно запустить переданный блок кода в отдельном неблокирующем волокне и вернуть это Fiber.

Минимальная рекомендуемая реализация:

def fiber(&block)
  Fiber.new(blocking: false, &block).tap(&:resume)
end
io_wait(io, events, timeout) Показать исходный код
static VALUE
rb_fiber_scheduler_interface_io_wait(VALUE self)
{
}

Вызывается IO#wait, IO#wait_readable, IO#wait_writable, чтобы узнать, готов ли указанный дескриптор для указанных событий в течение заданного timeout.

events — битовая маска IO::READABLE, IO::WRITABLE, и IO::PRIORITY.

Рекомендуемая реализация должна регистрировать, какое Fiber ждёт какие ресурсы и немедленно вызывать Fiber.yield, чтобы передать управление другим волокнам. Затем в методе close планировщик может распределить все ресурсы ввода-вывода ожидающим их волокнам.

Ожидается, что вернёт подмножество событий, которые готовы немедленно.

kernel_sleep(duration = nil) Показать исходный код
static VALUE
rb_fiber_scheduler_interface_kernel_sleep(VALUE self)
{
}

Вызывается Kernel#sleep и Mutex#sleep и ожидается, что обеспечит реализацию сна в неблокирующем режиме. Реализация может зарегистрировать текущее волокно в некотором списке «какое волокно ждёт до какого момента», вызвать Fiber.yield для передачи управления, а затем в close возобновить волокна, чьё время ожидания истекло.

process_wait(pid, flags) Показать исходный код
static VALUE
rb_fiber_scheduler_interface_process_wait(VALUE self)
{
}

Вызывается Process::Status.wait для ожидания указанного процесса. См. описание этого метода для описания аргументов.

Рекомендуемая минимальная реализация:

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

Этот обработчик необязателен: если он отсутствует в текущем планировщике, Process::Status.wait будет вести себя как блокирующий метод.

Ожидается, что вернёт экземпляр Process::Status.

unblock(blocker, fiber) Показать исходный код
static VALUE
rb_fiber_scheduler_interface_unblock(VALUE self)
{
}

Вызывается для разблокировки Fiber, предварительно заблокированного с помощью block (например, Mutex#lock вызывает block, а Mutex#unlock вызывает unblock). Планировщик должен использовать параметр fiber, чтобы понять, какое волокно разблокировано.

blocker — то, на чём ждали, но это только информационная информация (для отладки и ведения журнала), и не гарантируется, что это будет то же значение, что и blocker для block.

Ruby Core © 1993–2020 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API