1 module ws.thread.awaiter;
2 
3 import
4 	core.thread,
5 	std.parallelism,
6 	ws.list,
7 	ws.exception,
8 	ws.io;
9 
10 __gshared:
11 
12 
13 class Awaiter {
14 	
15 	this(){
16 		fibers = new List!Fiber;
17 	}
18 
19 	/++
20 		Creates a Fiber (coroutine) and puts it into 'fibers'.
21 		To complete the work, call 'tick' from a repeating function.
22 	+/
23 	void spawn(void delegate() f){
24 		fibers ~= new Fiber(f);
25 	}
26 
27 	/++
28 		Creates a Fiber (coroutine) and puts it into 'fibers'.
29 		After that, it waits until the fiber has been processed.
30 		This is supposed to be called from worker threads that were started with $(D async).
31 	+/
32 	void process(void delegate() func){
33 		assert(!thread_isMainThread(), "Cannot run 'process' from main thread, deadlock");
34 		auto f = new Fiber(func);
35 		fibers ~= f;
36 		while(f.state != Fiber.State.TERM)
37 			Thread.yield();
38 	}
39 	
40 	/// Creates a new Thread from inside a Fiber and waits until it completed its work.
41 	T async(T)(T delegate() func){
42 		if(!Fiber.getThis())
43 			exception("Cannot call \"async\" from non-fiber. Use it in a spawn({ .. here .. })");
44 		T result;
45 		auto t = new Task({
46 			try
47 				result = func();
48 			catch(Exception e)
49 				writeln("THREAD ERROR:\n", e);
50 		});
51 		TaskPool.taskPool().put(t);
52 		while(!t.done)
53 			Fiber.getThis().yield();
54 		return result;
55 	}
56 
57 	/// Creates a new Thread from inside a Fiber and waits until it completed its work.
58 	void async(T: void)(T delegate() func){
59 		if(!Fiber.getThis())
60 			exception("Cannot call \"async\" from non-fiber. Use it in a spawn({ .. here .. })");
61 		auto t = new Thread({
62 			try
63 				func();
64 			catch(Exception e)
65 				writeln("THREAD ERROR:\n", e);
66 		});
67 		t.start();
68 		while(t.isRunning)
69 			Fiber.getThis().yield();
70 			
71 	}
72 	
73 	void tick(){
74 		foreach(f; fibers){
75 			f.call();
76 			if(f.state == Fiber.State.TERM)
77 				fibers.remove(f);
78 		}
79 	}
80 	
81 	List!Fiber fibers;
82 	
83 }
84