Spec-Zone.ru › Ruby 2.7

класс Fiber

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

Волокна (Fiber) — это примитивы для реализации лёгкого кооперативного конкурентного программирования в Ruby. По сути, они представляют собой способ создания блоков кода, которые могут приостанавливаться и возобновляться, подобно потокам. Основное отличие заключается в том, что волокна никогда не прерываются, и планирование выполняется программистом, а не виртуальной машиной.

В отличие от других моделей бесклеточного лёгкого параллелизма, каждое волокно имеет свой стек. Это позволяет волокну приостанавливаться из глубоко вложенных вызовов функций внутри блока волокна. Обратитесь к руководству ruby(1) для настройки размера стека волокна.

При создании волокна оно не будет запускаться автоматически. Вместо этого его нужно явно запустить с помощью метода Fiber#resume. Код внутри волокна может уступить управление, вызвав Fiber.yield, в этом случае оно передает управление обратно вызывающей стороне (вызывающей стороне метода Fiber#resume).

При передаче управления или завершении волокно Fiber возвращает значение последнего выполненного выражения

Например:

fiber = Fiber.new do
  Fiber.yield 1
  2
end

puts fiber.resume
puts fiber.resume
puts fiber.resume

дает результат

1
2
FiberError: dead fiber called

Метод Fiber#resume принимает произвольное количество параметров; если это первый вызов resume, они будут переданы как аргументы блока. В противном случае они будут возвращаемым значением вызова Fiber.yield

Пример:

fiber = Fiber.new do |first|
  second = Fiber.yield first + 2
end

puts fiber.resume 10
puts fiber.resume 1_000_000
puts fiber.resume "The fiber will be dead before I can cause trouble"

дает результат

12
1000000
FiberError: dead fiber called

Публичные методы класса

current() → fiber Показать исходный код
static VALUE
rb_fiber_s_current(VALUE klass)
{
    return rb_fiber_current();
}

Возвращает текущее волокно. Вам нужно require 'fiber' перед использованием этого метода. Если вы не работаете в контексте волокна, этот метод вернёт корневое волокно.

yield(args, ...) → obj Показать исходный код
static VALUE
rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass)
{
    return rb_fiber_yield_kw(argc, argv, PASS_KW_SPLAT);
}

Возвращает управление обратно контексту, который возобновил волокно, передавая все аргументы, которые были ему переданы. Волокно возобновит обработку в этом месте, когда следующий раз вызов resume. Любые аргументы, переданные следующему вызову resume, будут значением, которое оценивается выражением Fiber.yield.

Публичные методы экземпляра

alive? → true или false Показать исходный код
VALUE
rb_fiber_alive_p(VALUE fiber_value)
{
    return FIBER_TERMINATED_P(fiber_ptr(fiber_value)) ? Qfalse : Qtrue;
}

Возвращает true, если волокно всё ещё может быть возобновлено (или переведено). После завершения выполнения блока волокна этот метод всегда возвращает false. Вам нужно require 'fiber' перед использованием этого метода.

inspect()
Псевдоним для: to_s
raise → obj Показать исходный код
raise(string) → obj
raise(exception [, string [, array]]) → obj
static VALUE
rb_fiber_raise(int argc, VALUE *argv, VALUE fiber)
{
    VALUE exc = rb_make_exception(argc, argv);
    return rb_fiber_resume_kw(fiber, -1, &exc, RB_NO_KEYWORDS);
}

Вызывает исключение в волокне в точке, в которой был вызван последний Fiber.yield, или в начале, если ни resume , ни raise не были вызваны ранее.

Без аргументов вызывает исключение RuntimeError. С единственным аргументом String вызывает исключение RuntimeError с указанным сообщением. В противном случае первый параметр должен быть именем класса исключения (или объектом, который возвращает объект исключения при отправке сообщения exception). Необязательный второй параметр задает сообщение, связанное с исключением, а третий — массив информации обратного вызова. Исключения перехватываются клаузой rescue блоков begin...end.

resume(args, ...) → obj Показать исходный код
static VALUE
rb_fiber_m_resume(int argc, VALUE *argv, VALUE fiber)
{
    return rb_fiber_resume_kw(fiber, argc, argv, PASS_KW_SPLAT);
}

Возобновляет волокно с точки, в которой был вызван последний Fiber.yield, или начинает его выполнение, если это первый вызов resume. Аргументы, передаваемые в resume, будут значением выражения Fiber.yield или будут переданы как аргументы блока блоку волокна, если это первый вызов resume.

В качестве альтернативы, при вызове resume, он оценивается в аргументы, переданные следующей инструкции Fiber.yield внутри блока волокна или в значение блока, если он выполняется до конца без Fiber.yield

to_s → строка Показать исходный код
static VALUE
fiber_to_s(VALUE fiber_value)
{
    const rb_fiber_t *fiber = fiber_ptr(fiber_value);
    const rb_proc_t *proc;
    char status_info[0x20];

    if (fiber->transferred) {
        snprintf(status_info, 0x20, " (%s, transferred)", fiber_status_name(fiber->status));
    }
    else {
        snprintf(status_info, 0x20, " (%s)", fiber_status_name(fiber->status));
    }

    if (!rb_obj_is_proc(fiber->first_proc)) {
        VALUE str = rb_any_to_s(fiber_value);
        strlcat(status_info, ">", sizeof(status_info));
        rb_str_set_len(str, RSTRING_LEN(str)-1);
        rb_str_cat_cstr(str, status_info);
        return str;
    }
    GetProcPtr(fiber->first_proc, proc);
    return rb_block_to_s(fiber_value, &proc->block, status_info);
}

Возвращает строку с информацией о волокне.

Также алиас для: inspect
transfer(args, ...) → obj Показать исходный код
static VALUE
rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fiber_value)
{
    rb_fiber_t *fiber = fiber_ptr(fiber_value);
    fiber->transferred = 1;
    return fiber_switch(fiber, argc, argv, 0, PASS_KW_SPLAT);
}

Передаёт управление другому волокну, возобновляя его с места, где оно остановилось, или запуская его, если оно не было возобновлено ранее. Вызывающее волокно приостанавливается, как при вызове Fiber.yield. Вам нужно require 'fiber' перед использованием этого метода.

Волокно, которое получает вызов transfer, обрабатывает его как вызов resume. Аргументы, передаваемые в transfer, обрабатываются как аргументы в resume.

Вы не можете вызвать resume на волокне, которому было передано управление. Если вы вызываете transfer на волокне, а затем resume на том же волокне, будет вызвано исключение FiberError. После вызова transfer на волокне, единственный способ возобновить обработку волокна — повторно вызвать transfer на нём.

Пример:

fiber1 = Fiber.new do
  puts "In Fiber 1"
  Fiber.yield
  puts "In Fiber 1 again"
end

fiber2 = Fiber.new do
  puts "In Fiber 2"
  fiber1.transfer
  puts "Never see this message"
end

fiber3 = Fiber.new do
  puts "In Fiber 3"
end

fiber2.resume
fiber3.resume
fiber1.resume rescue (p $!)
fiber1.transfer

дает результат

In Fiber 2
In Fiber 1
In Fiber 3
#<FiberError: cannot resume transferred Fiber>
In Fiber 1 again

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

Spec-Zone.ru

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