ruby-changes:64544
From: zverok <ko1@a...>
Date: Thu, 24 Dec 2020 14:37:22 +0900 (JST)
Subject: [ruby-changes:64544] 5696c69354 (master): Redocument Fiber#transfer
https://git.ruby-lang.org/ruby.git/commit/?id=5696c69354 From 5696c693540a06c01bf6172d33aff731ad61f871 Mon Sep 17 00:00:00 2001 From: zverok <zverok.offline@g...> Date: Tue, 22 Dec 2020 23:23:14 +0200 Subject: Redocument Fiber#transfer diff --git a/cont.c b/cont.c index 4a9e757..956f58e 100644 --- a/cont.c +++ b/cont.c @@ -2460,42 +2460,68 @@ rb_fiber_backtrace_locations(int argc, VALUE *argv, VALUE fiber) https://github.com/ruby/ruby/blob/trunk/cont.c#L2460 * a resume call. Arguments passed to transfer are treated like those * passed to resume. * - * You cannot call +resume+ on a fiber that has been transferred to. - * If you call +transfer+ on a fiber, and later call +resume+ on the - * the fiber, a +FiberError+ will be raised. Once you call +transfer+ on - * a fiber, the only way to resume processing the fiber is to - * call +transfer+ on it again. + * The two style of control passing to and from fiber (one is #resume and + * Fiber::yield, another is #transfer to and from fiber) can't be freely + * mixed. + * + * * If the Fiber's lifecycle had started with transfer, it will never + * be able to participate in yield/resume control passing, only + * finish or transfer back. + * * If the Fiber's lifecycle had started with resume, it can yield + * or transfer to another Fiber, but can receive control back only + * the way compatible with the way it was given away: if it had + * transferred, it only can be transferred back, and if it had + * yielded, it only can be resumed back. After that, it again can + * transfer or yield + * + * If those rules are broken FiberError is raised. + * * * Example: * - * fiber1 = Fiber.new do - * puts "In Fiber 1" - * Fiber.yield - * puts "In Fiber 1 again" - * end + * require 'fiber' * - * fiber2 = Fiber.new do - * puts "In Fiber 2" - * fiber1.transfer - * puts "Never see this message" - * end + * manager = nil # For local var to be visible inside worker block * - * fiber3 = Fiber.new do - * puts "In Fiber 3" - * end + * # This fiber would be started with transfer + * # It can't yield, and can't be resumed + * worker = Fiber.new { |work| + * puts "Worker: starts" + * puts "Worker: Performed #{work.inspect}, transferring back" + * # Fiber.yield # this would raise FiberError: attempt to yield on a not resumed fiber + * # manager.resume # this would raise FiberError: attempt to resume a resumed fiber (double resume) + * manager.transfer(work.capitalize) + * } + * + * # This fiber would be started with resume + * # It can yield or transfer, and can be transferred + * # back or resumed + * manager = Fiber.new { + * puts "Manager: starts" + * puts "Manager: transferring 'something' to worker" + * result = worker.transfer('something') + * puts "Manager: worker returned #{result.inspect}" + * # worker.resume # this would raise FiberError: attempt to resume a transferring fiber + * Fiber.yield # this is OK, the fiber transferred from and to, now it can yield + * puts "Manager: finished" + * } * - * fiber2.resume - * fiber3.resume - * fiber1.resume rescue (p $!) - * fiber1.transfer + * puts "Starting the manager" + * manager.resume + * puts "Resuming the manager" + * # manager.transfer # this would raise FiberError: attempt to transfer to a yielding fiber + * manager.resume * * <em>produces</em> * - * In Fiber 2 - * In Fiber 1 - * In Fiber 3 - * #<FiberError: cannot resume transferred Fiber> - * In Fiber 1 again + * Starting the manager + * Manager: starts + * Manager: transferring 'something' to worker + * Worker: starts + * Worker: Performed "something", transferring back + * Manager: worker returned "Something" + * Resuming the manager + * Manager: finished * */ static VALUE -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/