1 /*
2  * Hunt - A refined core library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.concurrency.FuturePromise;
13 
14 import hunt.concurrency.Future;
15 import hunt.concurrency.Promise;
16 
17 import hunt.Exceptions;
18 import std.format;
19 import std.datetime;
20 
21 import core.thread;
22 import hunt.logging;
23 
24 /**
25 */
26 class FuturePromise(T) : Future!T, Promise!T {
27 	private __gshared Exception COMPLETED;
28     private bool _done;	
29     private Exception _cause;
30 	private T _result;
31 	private string _id;
32 
33     shared static this() {
34         COMPLETED = new Exception("");
35     }
36 
37     this() {
38     }
39 
40     string id() { return _id; }
41 	void id(string id) { _id = id; }
42     
43 	void succeeded(T result) {
44 		if (!_done) {
45             _done = true;
46 			_result = result;
47 			_cause = COMPLETED;
48 		}
49 	}
50 
51 	
52 	void failed(Exception cause) {
53         if (!_done) {
54             _done = true;
55 			_cause = cause;
56 		}
57 	}
58 	
59 	bool cancel(bool mayInterruptIfRunning) {
60         if (!_done) {
61             _done = true;
62 			_result = T.init;
63 			_cause = new CancellationException("");
64 			return true;
65 		}
66 		return false;
67 	}
68 
69 	
70 	bool isCancelled() {
71 		if (_done) {
72 			try {
73 				// _latch.await();
74 			} catch (InterruptedException e) {
75 				throw new RuntimeException(e.msg);
76 			}
77 			return typeid(_cause) == typeid(CancellationException);
78 		}
79 		return false;
80 	}
81 	
82 	bool isDone() {
83 		return _done; 
84 	}
85 
86     T get() {
87 		// if(!_done)
88 		// 	throw new ExecutionException("Not done yet.");
89 		while(!_done) {
90 			version(HUNT_DEBUG) warning("Waiting for a promise...");
91 			// FIXME: Needing refactor or cleanup -@zxp at 9/10/2018, 2:11:03 PM
92 			// 
93 			Thread.sleep(20.msecs);
94 		}
95 		version(HUNT_DEBUG) info("Got a promise");
96 		
97 		if(_cause is null) {
98 			warning("no cause!");
99 			new ExecutionException("no cause!");
100 		}
101 
102 		if (_cause is COMPLETED)
103 			return _result;
104 		CancellationException c = cast(CancellationException) _cause;
105 		if (c !is null)
106 			throw c;
107 		throw new ExecutionException(_cause.msg);
108 	}
109 
110     T get(Duration timeout) {
111 		MonoTime before = MonoTime.currTime;
112 		while(!_done) {
113 			version(HUNT_DEBUG) warning("Waiting for a promise...");
114 			// FIXME: Needing refactor or cleanup -@zxp at 9/10/2018, 2:15:52 PM
115 			// 
116 			Thread.sleep(20.msecs);
117 			Duration timeElapsed = MonoTime.currTime - before;
118 			if(timeElapsed > timeout)
119 				break;
120 		}
121 		version(HUNT_DEBUG) infof("promise status: isDone=%s", _done);
122 		if(!_done)
123 			throw new TimeoutException();
124 
125 		if (_cause == COMPLETED)
126 			return _result;
127 		
128 		TimeoutException t = cast(TimeoutException) _cause;
129 		if (t !is null)
130 			throw t;
131 			
132 		CancellationException c = cast(CancellationException) _cause;
133 		if (c !is null)
134 			throw c;
135 
136 		throw new ExecutionException(_cause.msg);        
137     }
138 	
139     override
140 	string toString() {
141 		return format("FutureCallback@%x{%b,%b,%s}", toHash(), _done, _cause == COMPLETED, _result);
142 	}
143 }