digitalmars.D.learn - fibers and ranges: what's wrong here?
- zeljkog (43/43) Dec 13 2014 import std.stdio, core.thread;
- Tobias Pankrath (19/19) Dec 13 2014 When you assigning the worker in TreeRange, you create a delegate
- zeljkog (18/29) Dec 13 2014 Sorry, this works:
- Tobias Pankrath (2/34) Dec 13 2014 Have a look at @disable.
import std.stdio, core.thread; struct Tree{ int val; Tree[] tree; } struct TreeRange{ Tree curtree; bool empty; Fiber worker; this(Tree t){ worker = new Fiber(&fiberFunc); curtree = t; popFront(); } void fiberFunc(){ Tree t = curtree; Fiber.yield(); foreach(child; t.tree){ curtree = child; fiberFunc(); } } int front(){ return curtree.val; }; void popFront() { worker.call(); empty = worker.state == Fiber.State.TERM; } } void main() { auto tt = Tree(5, [Tree(7,[Tree(11), Tree(4)]), Tree(10)]); auto tr1 = TreeRange(tt); foreach(v; tr1){ writef("%2d, ", v); } writeln(); for(auto r = TreeRange(tt); !r.empty; r.popFront()) writef("%2d, ", r.front); writeln(); } output: 5, 5, 5, 5, 5, 5, 7, 11, 4, 10, Is it supposed to work?
Dec 13 2014
When you assigning the worker in TreeRange, you create a delegate that captures the current TreeRange or 'this'. --- worker = new Fiber(&fiberFunc); --- foreach is defined as (http://dlang.org/statement.html#ForeachStatement): --- for (auto __r = range; !__r.empty; __r.popFront()) { auto e = __r.front; ... } --- __r is a copy of your range that still refers to the original worker which in turn refers to your original range. So when you popFront, the worker will advance the original range and if you call front you get the element from __r - unadvanced. That's my best guess.
Dec 13 2014
On 13.12.14 13:01, zeljkog wrote:void main() { auto tt = Tree(5, [Tree(7,[Tree(11), Tree(4)]), Tree(10)]); auto tr1 = TreeRange(tt); foreach(v; tr1){ writef("%2d, ", v); } writeln(); for(auto r = TreeRange(tt); !r.empty; r.popFront()) writef("%2d, ", r.front); writeln(); }Sorry, this works: void main() { auto tt = Tree(5, [Tree(7,[Tree(11), Tree(4)]), Tree(10)]); foreach(v; TreeRange(tt)){ writef("%2d, ", v); } writeln(); for(auto r = TreeRange(tt); !r.empty; r.popFront()) writef("%2d, ", r.front); writeln(); } I needed this: struct TreeRange{ this (this){ throw new Exception("TreeRange is noncopyable!"); } ... } Or use class :)
Dec 13 2014
On Saturday, 13 December 2014 at 12:26:49 UTC, zeljkog wrote:On 13.12.14 13:01, zeljkog wrote:Have a look at disable.void main() { auto tt = Tree(5, [Tree(7,[Tree(11), Tree(4)]), Tree(10)]); auto tr1 = TreeRange(tt); foreach(v; tr1){ writef("%2d, ", v); } writeln(); for(auto r = TreeRange(tt); !r.empty; r.popFront()) writef("%2d, ", r.front); writeln(); }Sorry, this works: void main() { auto tt = Tree(5, [Tree(7,[Tree(11), Tree(4)]), Tree(10)]); foreach(v; TreeRange(tt)){ writef("%2d, ", v); } writeln(); for(auto r = TreeRange(tt); !r.empty; r.popFront()) writef("%2d, ", r.front); writeln(); } I needed this: struct TreeRange{ this (this){ throw new Exception("TreeRange is noncopyable!"); } ... } Or use class :)
Dec 13 2014