класс 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 14 puts fiber.resume 18
производит
12 14 FiberError: dead fiber called
Публичные методы класса
static VALUE
rb_fiber_s_current(VALUE klass)
{
return rb_fiber_current();
} Возвращает текущее волокно. Вам необходимо require 'fiber' перед использованием этого метода. Если вы не работаете в контексте волокна, этот метод вернёт корневое волокно.
static VALUE
rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass)
{
return rb_fiber_yield(argc, argv);
} Возвращает управление контексту, который возобновил волокно, передавая любые переданные ему аргументы. Волокно возобновит обработку в этом месте, когда resume будет вызвано в следующий раз. Любые аргументы, переданные в следующий resume, будут значением, к которому оценивается это Fiber.yield выражение.
Публичные методы экземпляра
VALUE
rb_fiber_alive_p(VALUE fibval)
{
return FIBER_TERMINATED_P(fiber_ptr(fibval)) ? Qfalse : Qtrue;
} Возвращает true, если волокно всё ещё может быть возобновлено (или передано). После завершения выполнения блока волокна этот метод всегда возвращает false. Вам необходимо require 'fiber' перед использованием этого метода.
static VALUE
rb_fiber_m_resume(int argc, VALUE *argv, VALUE fib)
{
return rb_fiber_resume(fib, argc, argv);
} Возобновляет волокно с точки, в которой был вызван последний Fiber.yield, или запускает его, если это первый вызов resume. Передаваемые аргументы будут значением Fiber.yield выражения или будут переданы в качестве параметров блока блоку волокна, если это первый resume.
В качестве альтернативы, при вызове resume он оценивается в аргументы, переданные следующей Fiber.yield инструкции внутри блока волокна или в значение блока, если он выполняется до конца без каких-либо Fiber.yield.
static VALUE
fiber_to_s(VALUE fibval)
{
const rb_fiber_t *fib = fiber_ptr(fibval);
const rb_proc_t *proc;
char status_info[0x10];
snprintf(status_info, 0x10, " (%s)", fiber_status_name(fib->status));
if (!rb_obj_is_proc(fib->first_proc)) {
VALUE str = rb_any_to_s(fibval);
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(fib->first_proc, proc);
return rb_block_to_s(fibval, &proc->block, status_info);
} Возвращает строку с информацией о волокне.
static VALUE
rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fibval)
{
rb_fiber_t *fib = fiber_ptr(fibval);
fib->transferred = 1;
return fiber_switch(fib, argc, argv, 0);
} Передает управление другому волокну, возобновляя его с момента последней остановки или запуская его, если он не был возобновлён ранее. Вызывающее волокно приостанавливается, как при вызове Fiber.yield. Вам необходимо require 'fiber' перед использованием этого метода.
Волокно, которое получает вызов передачи, обрабатывает его так же, как вызов возобновления. Передаваемые аргументы обрабатываются как те, которые переданы в resume.
Вы не можете возобновить волокно, которое передало управление другому. Это вызовет ошибку двойного возобновления. Вам необходимо передать управление обратно этому волокну, прежде чем оно сможет уступить и возобновиться.
Пример:
fiber1 = Fiber.new do puts "In Fiber 1" Fiber.yield 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
производит
In fiber 2 In fiber 1 In fiber 3
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.