Fibers for Ruby 1.8 in 42 lines feat. call/cc
Actually, stripped of comments and stuff, it's even less than 42 lines.Fibersare a big new thing with Ruby 1.9. The name is supposed to suggest that they're the thinner things inside a thread. You create them with a block to execute but they won't run in parallel. Instead they are explicitly entered and left via resume and yield. The first call to resume enters at the top of the block. Calling yield from inside the block jumps back out and the next resume jumps back inside. Repeat as often as you like.
f = Fiber.new {
    ...
    Fiber.yield 23  # returns 5
    ...
}
f.resume            # start it up; returns 23
...                 # control transfers back here after "yield"
f.resume 5          # run the rest
doesmeans it starts the job in the background, registers an event handler, and immediately yields back to the GUI event loop. When the job finishes, the handler resumes the fiber and it goes on to the next step. Ruby 1.9 adds fibers as a primitive, but they are also easily implemented in terms of call/cc -
call with current continuation, which Ruby has had for no idea how long. So here goes, a drop-in substitute for 1.9's Fiber class:
class Fibr
    @@fs = []   # a stack of fibers corresponding to calls of 'resume'
    def initialize(&block)
        @k = lambda(&block)         # lambda makes 'return' work as expected
    end
    def resume(*xs)
        @@fs.push(self)
        jump(xs)                    # jumping into fiber
    end
    def self.current
        @@fs.last
    end
    def self.yield(*xs)
        f = @@fs.pop
        f && f.send(:jump, xs)      # jumping out of fiber
    end
    private
    def jump(xs)
        callcc { |k|
            destination = @k
            @k = k
            destination.call(*xs)
            @@fs.pop
            @k.call                 # return from the last 'resume'
        }
    end
end
Fiber = Fibr if RUBY_VERSION<"1.9"
(1 comment…)