1 module test_fiber;
2 
3 import core.thread.fiber;
4 import std.stdio;
5 import std.algorithm;
6 
7 import auxil.model;
8 
9 import test_data;
10 import common;
11 
12 struct MyVisitor
13 {
14 	import auxil.model : TreePath;
15 
16 	enum treePathNGEnabled = true;
17 	enum treePathEnabled = false;
18 	enum sizeEnabled = false;
19 
20 	TreePath tree_path;
21 
22 	TreePath[] log;
23 
24 	TreePath path;
25 	private bool _complete;
26 
27 	bool complete() @trusted @nogc
28 	{
29 		return _complete;
30 	}
31 
32 	void enterTree(alias order, Data, Model)(auto ref const(Data) data, ref Model model)
33 	{
34 	}
35 
36 	auto enterNode(alias order, Data, Model)(ref const(Data) data, ref Model model)
37 	{
38 		log ~= tree_path;
39 		Fiber.yield();
40 		{
41 			_complete = !path.value.empty && tree_path.value[] == path.value[];
42 		}
43 
44 		return false;
45 	}
46 
47 	void leaveNode(alias order, Data, Model)(ref const(Data) data, ref Model model)
48 	{
49 		Fiber.yield();
50 	}
51 
52 	void processLeaf(alias order, Data, Model)(ref const(Data) data, ref Model model)
53 	{
54 
55 		log ~= tree_path;
56 		Fiber.yield();
57 		{
58 			_complete = !path.value.empty && tree_path.value[] == path.value[];
59 		}
60 	}
61 }
62 
63 // a fiber traverses to the specific tree path in forward direction
64 void testRunningFiberInLoop()
65 {
66 	auto model = makeModel(m.a2);
67 	
68 	MyVisitor visitor;
69 	
70 	scope fiberVisitor = new Fiber(()
71 	{
72 		model.visitForward(m.a2, visitor);
73 	});
74 
75 	TreePath[] fiberLog;
76 	foreach(_; 0..3)
77 	{
78 		fiberLog = null;
79 		visitor.log = null;
80 		visitor.path.value = [1, 0];
81 		visitor.tree_path.value.clear;
82 		visitor._complete = false;
83 		fiberVisitor.reset;
84 		while(fiberVisitor.state != Fiber.State.TERM)
85 		{
86 			fiberVisitor.call();
87 			if (!visitor.complete)
88 			{
89 				fiberLog ~= visitor.tree_path;
90 			}
91 		}
92 
93 		fiberLog.each!writeln;
94 		assert(visitor.log.equal(fiberLog));
95 
96 		writeln("\n---");
97 		writeln(visitor.log);
98 		assert(visitor.log.equal([
99 			[],     // a2
100 			[1],    // a2.b
101 					// a2.b.f skipped
102 			[1, 0], // a2.b.i
103 		]));
104 	}
105 }
106 
107 // a fiber traverses to the specific tree path in forward direction
108 void testFiberRange()
109 {
110 	auto model = makeModel(m.a2);
111 	
112 	MyVisitor visitor;
113 
114 	TreePath[] fiberLog;
115 	{
116 		fiberLog = null;
117 		visitor.log = null;
118 		visitor.path.value = [1, 0];
119 		visitor.tree_path.value.clear;
120 		visitor._complete = false;
121 		auto r = visitor.makeRange(()
122 		{
123 			model.visitForward(m.a2, visitor);
124 		});
125 		r.each!((ref a)=>writeln(a));
126 		writeln("---");
127 		visitor = MyVisitor();
128 		visitor.path.value = [1, 0];
129 		r = visitor.makeRange(()
130 		{
131 			model.visitForward(m.a2, visitor);
132 		});
133 		r.each!((ref a)=>writeln(a));
134 	}
135 }