fibers/transferring.rb
tests/_examples/fibers/transferring.rb in the metorex repository.
# A fiber reached by a transfer from the top level hands what it answered
# back to the top level.
first = Fiber.new { :first }
second = Fiber.new { first.transfer(); :second }
p(second.transfer())
p(second.transfer())
# One reached by a transfer inside a resumed fiber hands it to that fiber.
finisher = Fiber.new { :finisher }
starter = Fiber.new { Fiber.yield(finisher.transfer()); :unreached }
p(starter.resume())
# A fiber waiting in Fiber.yield takes no transfer.
begin
starter.transfer()
rescue FiberError => error
p(error.message)
end
# Transferring to the fiber running now leaves it there.
p(Fiber.current.transfer(1, 2))
root = Fiber.current
p(Fiber.new { root.transfer(:back) }.transfer())
# A dead fiber takes no transfer.
done = Fiber.new { 1 }
done.transfer()
begin
done.transfer()
rescue FiberError => error
p(error.message)
end
# A fiber part-way through resuming another takes no transfer.
outer = nil
inner = Fiber.new { outer.transfer() }
outer = Fiber.new { inner.resume() }
begin
outer.resume()
rescue FiberError => error
p(error.message)
end
begin
Fiber.new { root.transfer() }.resume()
rescue FiberError => error
p(error.message)
end
# A fiber made on one thread takes no transfer from another.
here = Fiber.new { 42 }
Thread.new do
begin
here.transfer()
rescue FiberError => error
p(error.message)
end
end.join()
p(here.transfer())
# A thread's own fiber and one it made hand control back and forth.
Thread.new do
helper = Fiber.new { |calling| calling.transfer(:from_helper); :helper_done }
p(helper.transfer(Fiber.current))
p(helper.transfer())
end.join()
# A fiber resumed inside another can transfer to the top level, and a
# transfer back to it later finishes both.
low = Fiber.new { answer = root.transfer(:up); [answer, :low_done] }
high = Fiber.new { [low.resume(), :high_done] }
p(high.transfer())
p([low.alive?(), high.alive?()])
begin
high.transfer()
rescue FiberError => error
p(error.message)
end
p(low.transfer(:down))
p([low.alive?(), high.alive?()])
Output:
:first
:second
:finisher
"attempt to transfer to a yielding fiber"
[1, 2]
:back
"dead fiber called"
"attempt to transfer to a resuming fiber"
"attempt to transfer to a resuming fiber"
"fiber called across threads"
42
:from_helper
:helper_done
:up
[true, true]
"attempt to transfer to a resuming fiber"
[[:down, :low_done], :high_done]
[false, false]