I am learning about the Ruby Fiber
which gives lot of flexibility but I came up with some doubt's in Fiber as well as in Ruby.
require 'fiber'
class MyObj
def call_yield
print "Prepare to Yield"
print "foo bar"
Fiber.yield
print "Resumed"
@fiber = nil
end
def create_fiber
#@fiber = Fiber.new{call_yield}
@fiber = Fiber.new {}
p @fiber
end
def update
p @fiber.resume
end
end
obj = MyObj.new
# obj.call_yield #Fiber error
obj.create_fiber
obj.update
obj.update
When I uncomment the line with obj.call_yield
the Fiber error occurs as expected.Even when I type Fiber.yield
in irb session the same error occurs.
Fiber.Yield
given to Fiber.new
.Notice the line #@fiber = Fiber.new{call_yield}
inside create fiber method is still a valid code.
As fiber's are written in C,I have no other sources to clear my doubt's so please provide minimalistic examples for each questions as possible.
I want to know how
Fiber.yield
behaves when inside block that is provided toFiber.new
vs any other place in program ie)How it produces "root fiber error" elsewhere in program?
Ah, that is actually quite simple. All you need to do is modify a piece of global state when executing resume
. For example, push the current fiber onto a global stack or something like that. Here's a fake Fiber class that exhibits the same behaviour.
class MyFiber
class << self
def stack
@stack ||= []
end
def yield
top = stack.pop
if top.nil?
raise 'root fiber error'
end
puts "running fiber #{top}"
end
end
def initialize(&block)
@block = block
end
def resume
MyFiber.stack.push(@block)
@block.call
end
end