digitalmars.D.learn - Coroutines in D
- Andrej Mitrovic (93/93) May 03 2011 I'm trying to figure out how to use coroutines in D.
- Andrej Mitrovic (5/5) May 03 2011 Ok,I've found a post that could be useful:
- Robert Clipsham (32/34) May 03 2011 I'm not entirely sure what it is you want to be able to do (I'm rather
I'm trying to figure out how to use coroutines in D. First, I think I've run into some kind of bug. I've followed this C++ example: http://www.subatomicglue.com/secret/coro/readme.html, and came up with this: import std.stdio; import core.thread; void fiberFunc(size_t arg) { int i = 0; foreach (x; 0 .. 1000) { writefln("fiber waiting (id = %d)", arg); Fiber.yield(); } foreach (x; 0 .. 1000) { writefln("fiber running (iter = %d id = %d)", ++i, arg); Fiber.yield(); } while (1) { writefln("fiber waiting (id = %d)", arg); Fiber.yield(); } } void main() { Fiber[200] fibers; foreach (ref fiber; fibers) { fiber = new Fiber(&fiberFunc); } while (true) { foreach (fiber; fibers) { fiber.call(); } } } Only after I've translated the C++ example to D I've realized that fiberFunc actually takes an argument. But from what I can tell core.thread.Fiber never calls this function with any arguments. I have a hunch that "arg" ends up having an uninitialized garbage value, so it looks like this is a bug? Ok, that put aside what I really want to emulate is this Python example of a coroutine (perhaps bearophile is familiar with this): def coroutine(func): def start(*args,**kwargs): cr = func(*args,**kwargs) cr.next() return cr return start coroutine def unwrap_protocol(header='\x61', footer='\x62', dle='\xAB', after_dle_func=lambda x: x, target=None): """ Simplified framing (protocol unwrapping) co-routine. """ while True: byte = (yield) frame = '' if byte == header: while True: byte = (yield) if byte == footer: target.send(frame) break elif byte == dle: byte = (yield) frame += after_dle_func(byte) else: frame += byte coroutine def frame_receiver(): """ A simple co-routine "sink" for receiving full frames. """ while True: frame = (yield) print 'Got frame:', frame.encode('hex') bytes = ''.join(chr(b) for b in [0x70, 0x24, 0x61, 0x99, 0xAF, 0xD1, 0x62, 0x56, 0x62, 0x61, 0xAB, 0xAB, 0x14, 0x62, 0x7 ]) unwrapper = unwrap_protocol(target=frame_receiver()) for byte in bytes: unwrapper.send(byte) This was taken from Eli's blog: http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/ I'm not seeing any way of yielding a value back from a Fiber or even sending it, so I don't see how I can use fibers to implement coroutines which send or return values. But I'm new to the concept so maybe I'm missing something obvious?
May 03 2011
Ok,I've found a post that could be useful: http://www.digitalmars.com/d/archives/digitalmars/D/yield_C_etc_74821.html and there's a Generator mixin in generators.d, from the libs_d library: http://www.fantascienza.net/leonardo/so/index.html I'll give these a try soon.
May 03 2011
On 03/05/2011 19:06, Andrej Mitrovic wrote:I'm trying to figure out how to use coroutines in D. First, I think I've run into some kind of bug. I've followed this C++ example: http://www.subatomicglue.com/secret/coro/readme.html, and came up with this:I'm not entirely sure what it is you want to be able to do (I'm rather tired and didn't want to read through the whole example, I'll take another look tomorrow unless someone else beats me to it), but from what I can gather you want to pass values to the fiber between calling and yielding? The way to do this is to derive your fiber rather than composing it: class Derived : Fiber { size_t arg; this() { super(&run); } void func() { writefln("val: %s", arg); Fiber.yield(); writefln("val: %s", arg); } } auto fiber = new Derived; fiber.arg = 6; fiber.call(); fiber.arg = 7; fiber.call(); You have, however, encountered a bug - Fiber should not accept a function with parameters, you should file a bug report for this. Hope this helps. -- Robert http://octarineparrot.com/
May 03 2011