Question

Playing round with fibers and I know I'm doing something stupid here. But trying to create a simple enumerable type thing based on fibers (it's obviously trivial using Enumerable). When I run the following I get a dead fiber error after it prints out the first couple of iterations. Does anyone know why?

class SumPow
  def initialize(a)
    sum = a
    pow = a
    @fiber = Fiber.new do
      Fiber.yield sum
      pow = pow * a
      sum = sum + pow
    end
  end

  def next
    @fiber.resume
  end

  def each
    loop do
      yield self.next
    end
  end

end

sp = SumPow.new(3)
sp.each do |sum|
  puts sum
end

output:

3
12
tmp/fiber_enum.rb:96:in `resume': dead fiber called (FiberError)
    from tmp/fiber_enum.rb:96:in `next'
    from tmp/fiber_enum.rb:101:in `block in each'
    from tmp/fiber_enum.rb:100:in `loop'
    from tmp/fiber_enum.rb:100:in `each'
    from tmp/fiber_enum.rb:108:in `<main>'

This code on the other hand works completely fine:

fib = Fiber.new do
  x, y = 0, 1
  loop do
    Fiber.yield y
    x, y = y, x + y
  end
end
7.times { puts fib.resume }

output:

1
1
2
3
5
8
13
Was it helpful?

Solution

The code is calling resume regardless of state of the fiber.

Check whether fiber can resume by calling Fiber#alive?

def each
  while @fiber.alive? do
    yield self.next
  end
end

NOTE You need to do require 'fiber' to use alive? method.


UPDATE accoridng to the question edit.

The original code yields only once. To iterate indefinitely, you need loop.

def initialize(a)
  sum = a
  pow = a
  @fiber = Fiber.new do
    loop do # <-------------
      Fiber.yield sum
      pow = pow * a
      sum = sum + pow
    end # <-----------------
  end
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top