Coroutines (Was: FasterGenerator (#66))

R

Ross Bamford

Hi,

Well, I've snapped a string on my guitar and my computer won't play MP3s
today for some reason, so inevitably boredom started to creep in. I
started playing around with the generator stuff, specifically about the
coroutine discussion earlier in this thread. Just wanted to see if I
could *really* get my head around continuations and all that.

It starts with some private methods on Kernel, which are then used to
implement the generator, but can be used elsewhere too:

module Kernel
private
def coreset(blk)
Thread.current[:"#{blk.inspect.hash}_codone"] = nil
end

def coyield?(blk)
Thread.current[:"#{blk.inspect.hash}_codone"] ? false : true
end

def coyield(blk, *args)
raise "Coroutine exhausted" if Thread.current[:"#{blk.inspect.hash}_codone"]

catch :coreturn do
next_item = (Thread.current[:coreturn] ||= []).pop

if next_item
next_item.call
else
final = blk.call(*args)
Thread.current[:"#{blk.inspect.hash}_codone"] = true
throw :coreturn, final
end
end
end

def coreturn(val)
callcc do |return_cc|
(Thread.current[:coreturn] ||= []) << return_cc
throw :coreturn, val
end
end
end

class CoGenerator
def initialize(enum = nil, &blk)
@blk, @pos = blk, 0

if enum
@blk = lambda { enum.each { |e| coreturn e } }
end
end

def rewind
@pos = 0
coreset @blk
end

def next
@pos += 1
@current = coyield(@blk)
end

def current
@current
end

def next?
coyield? @blk
end

def end?
!self.next?
end

def each
rewind
yield coyield(@blk) while coyield?(@blk)
end

def pos
@pos
end
end

It would be used like:

g = CoGenerator.new do
coreturn 6
# Some work
coreturn 7
# More work
coreturn 8
# Yet more work
9
end

p g.next while g.next?
# ->
# 6
# 7
# 8
# 9

Obviously this isn't for the quiz (it'd be dead last, being based on
continuations, and it doesn't actually have the Generator API) but just,
well, for fun. And something to do. It was fun to write, but it's a toy.
I dread to think what it mightn't do properly, or at all :) It's
behaviour in multithreaded code could well be a bit counter-intuitive
too, I'm afraid I don't know much about how coroutines work in other
languages.

It times a bit faster than the old callcc generator, because it's using
less continuations (just the one) but really I guess it's just a test of
the coyield/coreturn stuff.

Anyway, enough about that... Music shop will be open now :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,610
Members
45,255
Latest member
TopCryptoTwitterChannels

Latest Threads

Top