www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - fibers and ranges: what's wrong here?

reply zeljkog <zeljkog home.com> writes:
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
next sibling parent "Tobias Pankrath" <tobias pankrath.net> writes:
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
prev sibling parent reply zeljkog <zeljkog home.com> writes:
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
parent "Tobias Pankrath" <tobias pankrath.net> writes:
On Saturday, 13 December 2014 at 12:26:49 UTC, zeljkog wrote:
 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 :)
Have a look at disable.
Dec 13 2014