As a followup to the post below, here is some example code using fibers to implement co-routines. This works in today's snapshot build, but it uses brand-new stuff, so it probably won't work if your build is more than a day old. Similarly, the API may change again, so it might not work if your snapshot is too new, either. svn.ruby-lang.org seems to be down (for me at least) right now, so I got my snapshot here: http://www.mirrorservice.org/sites/ftp.ruby-lang.org/pub/ruby/snapshot.tar.gz The code works for me on Linux, but I haven't tested it elsewhere:
f = g = nil
f = Fiber::Core.new { |x|
puts "F1: #{x}"
x = g.transfer(x+1)
puts "F2: #{x}"
x = g.transfer(x+1)
puts "F3: #{x}"
}
g = Fiber::Core.new { |x|
puts "G1: #{x}"
x = f.transfer(x+1)
puts "G2: #{x}"
x = f.transfer(x+1)
}
f.transfer(100)
This code prints the following
F1: 100 G1: 101 F2: 102 G2: 103 F3: 104
Notice that the code uses the class Fiber::Core, and its instance method transfer. There is also a Fiber class, with a slightly higher-level API involving the instance method resume and the class method yield. I'm not sure exactly how these are intended to be used, but I was able to produce the same output as above using Fiber (instead of Fiber::Core) as follows:
g = Fiber.new { |x|
puts "G1: #{x}"
x = Fiber.yield(x+1) # Can't use resume here: double resume error
puts "G2: #{x}"
x = Fiber.yield(x+1)
}
f = Fiber.new { |x|
puts "F1: #{x}"
x = g.resume(x+1)
puts "F2: #{x}"
x = g.resume(x+1)
puts "F3: #{x}"
}
f.resume(100)
Update: Koichi SASADA notes on ruby-core:
Fiber::Core and Fiber::Core#transfer is black magic. So I'm planning to rename this class and method to Fiber::DangerousCore::__unsafe_transfer__I_cant_promise_your_program_run_correctly__!
He also says that the Fiber class is a "semi-coroutine" like Python's generator and that the method names Fiber.resume and Fiber::yield are taken from the language Lua. Time to go read up on Lua, I suppose



