1 /++
2 Copyright (C) 2012 Nick Sabalausky <http://semitwist.com/contact>
3 
4 This program is free software. It comes without any warranty, to
5 the extent permitted by applicable law. You can redistribute it
6 and/or modify it under the terms of the Do What The Fuck You Want
7 To Public License, Version 2, as published by Sam Hocevar. See
8 http://www.wtfpl.net/ for more details.
9 
10 	DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11 				Version 2, December 2004
12 
13 Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
14 
15 Everyone is permitted to copy and distribute verbatim or modified
16 copies of this license document, and changing it is allowed as long
17 as the name is changed.
18 
19 		DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
20 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
21 
22 0. You just DO WHAT THE FUCK YOU WANT TO.
23 +/
24 
25 /++
26 Should work with DMD 2.059 and up
27 
28 For more info on this, see:
29 http://semitwist.com/articles/article/view/combine-coroutines-and-input-ranges-for-dead-simple-d-iteration
30 +/
31 module gfx.decl.sdlang.libInputVisitor;
32 
33 import core.thread;
34 
35 class InputVisitor(Obj, Elem) : Fiber
36 {
37 	bool started = false;
38 	Obj obj;
39 	this(Obj obj)
40 	{
41 		this.obj = obj;
42 
43 		version(Windows) // Issue #1
44 		{
45 			import core.sys.windows.windows : SYSTEM_INFO, GetSystemInfo;
46 			SYSTEM_INFO info;
47 			GetSystemInfo(&info);
48 			auto PAGESIZE = info.dwPageSize;
49 
50 			super(&run, PAGESIZE * 16);
51 		}
52 		else
53 			super(&run);
54 	}
55 
56 	this(Obj obj, size_t stackSize)
57 	{
58 		this.obj = obj;
59 		super(&run, stackSize);
60 	}
61 
62 	private void run()
63 	{
64 		obj.visit(this);
65 	}
66 
67 	private void ensureStarted()
68 	{
69 		if(!started)
70 		{
71 			call();
72 			started = true;
73 		}
74 	}
75 
76 	// Member 'front' must be a function due to DMD Issue #5403
77 	private Elem _front = Elem.init; // Default initing here avoids "Error: field _front must be initialized in constructor"
78 	@property Elem front()
79 	{
80 		ensureStarted();
81 		return _front;
82 	}
83 
84 	void popFront()
85 	{
86 		ensureStarted();
87 		call();
88 	}
89 
90 	@property bool empty()
91 	{
92 		ensureStarted();
93 		return state == Fiber.State.TERM;
94 	}
95 
96 	void yield(Elem elem)
97 	{
98 		_front = elem;
99 		Fiber.yield();
100 	}
101 }
102 
103 template inputVisitor(Elem)
104 {
105 	@property InputVisitor!(Obj, Elem) inputVisitor(Obj)(Obj obj)
106 	{
107 		return new InputVisitor!(Obj, Elem)(obj);
108 	}
109 
110 	@property InputVisitor!(Obj, Elem) inputVisitor(Obj)(Obj obj, size_t stackSize)
111 	{
112 		return new InputVisitor!(Obj, Elem)(obj, stackSize);
113 	}
114 }