##// END OF EJS Templates
DRAFT: refactoring
cin -
r144:8c0b95069066 v2
parent child
Show More
@@ -0,0 +1,350
1 using System;
2 using Implab.Parallels;
3 using System.Threading;
4 using System.Reflection;
5
6 namespace Implab {
7 public abstract class AbstractEvent<THandler> : ICancelationToken, ICancellable {
8
9 const int UNRESOLVED_SATE = 0;
10 const int TRANSITIONAL_STATE = 1;
11 const int SUCCEEDED_STATE = 2;
12 const int REJECTED_STATE = 3;
13 const int CANCELLED_STATE = 4;
14
15 const int CANCEL_NOT_REQUESTED = 0;
16 const int CANCEL_REQUESTING = 1;
17 const int CANCEL_REQUESTED = 2;
18
19 const int RESERVED_HANDLERS_COUNT = 4;
20
21 int m_state;
22 Exception m_error;
23 int m_handlersCount;
24
25 readonly THandler[] m_handlers = new THandler[RESERVED_HANDLERS_COUNT];
26 MTQueue<THandler> m_extraHandlers;
27 int m_handlerPointer = -1;
28 int m_handlersCommited;
29
30 int m_cancelRequest;
31 Exception m_cancelationReason;
32 MTQueue<Action<Exception>> m_cancelationHandlers;
33
34
35 #region state managment
36 bool BeginTransit() {
37 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
38 }
39
40 void CompleteTransit(int state) {
41 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
42 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
43 }
44
45 void WaitTransition() {
46 while (m_state == TRANSITIONAL_STATE) {
47 Thread.MemoryBarrier();
48 }
49 }
50
51 protected bool BeginSetResult() {
52 if (!BeginTransit()) {
53 WaitTransition();
54 if (m_state != CANCELLED_STATE)
55 throw new InvalidOperationException("The promise is already resolved");
56 return false;
57 }
58 return true;
59 }
60
61 protected void EndSetResult() {
62 CompleteTransit(SUCCEEDED_STATE);
63 OnSuccess();
64 }
65
66
67
68 /// <summary>
69 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
70 /// </summary>
71 /// <remarks>
72 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
73 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
74 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
75 /// </remarks>
76 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
77 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
78 protected void SetError(Exception error) {
79 if (BeginTransit()) {
80 if (error is OperationCanceledException) {
81 CompleteTransit(CANCELLED_STATE);
82 m_error = error.InnerException;
83 OnCancelled();
84 } else {
85 m_error = error is PromiseTransientException ? error.InnerException : error;
86 CompleteTransit(REJECTED_STATE);
87 OnError();
88 }
89 } else {
90 WaitTransition();
91 if (m_state == SUCCEEDED_STATE)
92 throw new InvalidOperationException("The promise is already resolved");
93 }
94 }
95
96 /// <summary>
97 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
98 /// </summary>
99 /// <remarks>Для опрСдСлСния Π±Ρ‹Π»Π° Π»ΠΈ опСрация ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π° слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свойство <see cref="IsCancelled"/>.</remarks>
100 protected void SetCancelled(Exception reason) {
101 if (BeginTransit()) {
102 m_error = reason;
103 CompleteTransit(CANCELLED_STATE);
104 OnCancelled();
105 }
106 }
107
108 protected abstract void SignalSuccess(THandler handler);
109
110 protected abstract void SignalError(THandler handler, Exception error);
111
112 protected abstract void SignalCancelled(THandler handler, Exception reason);
113
114 void OnSuccess() {
115 var hp = m_handlerPointer;
116 var slot = hp +1 ;
117 while (slot < m_handlersCommited) {
118 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
119 SignalSuccess(m_handlers[slot]);
120 }
121 hp = m_handlerPointer;
122 slot = hp +1 ;
123 }
124
125
126 if (m_extraHandlers != null) {
127 THandler handler;
128 while (m_extraHandlers.TryDequeue(out handler))
129 SignalSuccess(handler);
130 }
131 }
132
133 void OnError() {
134 var hp = m_handlerPointer;
135 var slot = hp +1 ;
136 while (slot < m_handlersCommited) {
137 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
138 SignalError(m_handlers[slot],m_error);
139 }
140 hp = m_handlerPointer;
141 slot = hp +1 ;
142 }
143
144 if (m_extraHandlers != null) {
145 THandler handler;
146 while (m_extraHandlers.TryDequeue(out handler))
147 SignalError(handler, m_error);
148 }
149 }
150
151 void OnCancelled() {
152 var hp = m_handlerPointer;
153 var slot = hp +1 ;
154 while (slot < m_handlersCommited) {
155 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
156 SignalCancelled(m_handlers[slot], m_error);
157 }
158 hp = m_handlerPointer;
159 slot = hp +1 ;
160 }
161
162 if (m_extraHandlers != null) {
163 THandler handler;
164 while (m_extraHandlers.TryDequeue(out handler))
165 SignalCancelled(handler, m_error);
166 }
167 }
168
169 #endregion
170
171 protected abstract Signal GetResolveSignal();
172
173 #region synchronization traits
174 protected void WaitResult(int timeout) {
175 if (!IsResolved)
176 GetResolveSignal().Wait(timeout);
177
178 switch (m_state) {
179 case SUCCEEDED_STATE:
180 return;
181 case CANCELLED_STATE:
182 throw new OperationCanceledException();
183 case REJECTED_STATE:
184 throw new TargetInvocationException(m_error);
185 default:
186 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
187 }
188 }
189 #endregion
190
191 #region handlers managment
192
193 protected void AddHandler(THandler handler) {
194
195 if (m_state > 1) {
196 // the promise is in the resolved state, just invoke the handler
197 InvokeHandler(handler);
198 } else {
199 var slot = Interlocked.Increment(ref m_handlersCount) - 1;
200
201 if (slot < RESERVED_HANDLERS_COUNT) {
202
203 m_handlers[slot] = handler;
204
205 while (slot != Interlocked.CompareExchange(ref m_handlersCommited, slot + 1, slot)) {
206 }
207
208 if (m_state > 1) {
209 do {
210 var hp = m_handlerPointer;
211 slot = hp + 1;
212 if (slot < m_handlersCommited) {
213 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) != hp)
214 continue;
215 InvokeHandler(m_handlers[slot]);
216 }
217 break;
218 } while(true);
219 }
220 } else {
221 if (slot == RESERVED_HANDLERS_COUNT) {
222 m_extraHandlers = new MTQueue<THandler>();
223 } else {
224 while (m_extraHandlers == null)
225 Thread.MemoryBarrier();
226 }
227
228 m_extraHandlers.Enqueue(handler);
229
230 if (m_state > 1 && m_extraHandlers.TryDequeue(out handler))
231 // if the promise have been resolved while we was adding the handler to the queue
232 // we can't guarantee that someone is still processing it
233 // therefore we need to fetch a handler from the queue and execute it
234 // note that fetched handler may be not the one that we have added
235 // even we can fetch no handlers at all :)
236 InvokeHandler(handler);
237 }
238 }
239 }
240
241 protected void InvokeHandler(THandler handler) {
242 switch (m_state) {
243 case SUCCEEDED_STATE:
244 SignalSuccess(handler);
245 break;
246 case CANCELLED_STATE:
247 SignalCancelled(handler, m_error);
248 break;
249 case REJECTED_STATE:
250 SignalError(handler, m_error);
251 break;
252 default:
253 throw new Exception(String.Format("Invalid promise state {0}", m_state));
254 }
255 }
256
257 #endregion
258
259 #region IPromise implementation
260
261 public bool IsResolved {
262 get {
263 Thread.MemoryBarrier();
264 return m_state > 1;
265 }
266 }
267
268 public bool IsCancelled {
269 get {
270 Thread.MemoryBarrier();
271 return m_state == CANCELLED_STATE;
272 }
273 }
274
275 #endregion
276
277 public Exception Error {
278 get {
279 return m_error;
280 }
281 }
282
283 public bool AcceptIfRequested() {
284 if (IsCancelRequested)
285 CancelOperation(CancelReason);
286 }
287
288 public virtual void CancelOperation(Exception reason) {
289 SetCancelled(reason);
290 }
291
292 public void CancelationRequested(Action<Exception> handler) {
293 Safe.ArgumentNotNull(handler, "handler");
294 if (IsCancelRequested)
295 handler(CancelReason);
296
297 if (m_cancelationHandlers == null)
298 Interlocked.CompareExchange(ref m_cancelationHandlers, new MTQueue<Action<Exception>>(), null);
299
300 m_cancelationHandlers.Enqueue(handler);
301
302 if (IsCancelRequested && m_cancelationHandlers.TryDequeue(out handler))
303 // TryDeque implies MemoryBarrier()
304 handler(m_cancelationReason);
305 }
306
307 public bool IsCancelRequested {
308 get {
309 do {
310 if (m_cancelRequest == CANCEL_NOT_REQUESTED)
311 return false;
312 if (m_cancelRequest == CANCEL_REQUESTED)
313 return true;
314 Thread.MemoryBarrier();
315 } while(true);
316 }
317 }
318
319 public Exception CancelReason {
320 get {
321 do {
322 Thread.MemoryBarrier();
323 } while(m_cancelRequest == CANCEL_REQUESTING);
324
325 return m_cancelationReason;
326 }
327 }
328
329 #region ICancellable implementation
330
331 public void Cancel() {
332 Cancel(null);
333 }
334
335 public void Cancel(Exception reason) {
336 if (CANCEL_NOT_REQUESTED == Interlocked.CompareExchange(ref m_cancelRequest, CANCEL_REQUESTING)) {
337 m_cancelationReason = reason;
338 m_cancelRequest = CANCEL_REQUESTED;
339 if (m_cancelationHandlers != null) {
340 Action<Exception> handler;
341 while (m_cancelationHandlers.TryDequeue(out handler))
342 handler(m_cancelationReason);
343 }
344 }
345 }
346
347 #endregion
348 }
349 }
350
@@ -0,0 +1,185
1 using System;
2 using Implab.Parallels;
3
4 namespace Implab {
5 public abstract class AbstractPromise<T> : AbstractEvent<AbstractPromise<T>.HandlerDescriptor>, IPromise<T> {
6 public struct HandlerDescriptor {
7 readonly Action m_handler;
8 readonly Action<T> m_success;
9 readonly Action<Exception> m_error;
10 readonly Action<Exception> m_cancel;
11 readonly PromiseEventType m_mask;
12
13 public HandlerDescriptor(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
14 m_success = success;
15 m_error = error;
16 m_cancel = cancel;
17 }
18
19 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) {
20 m_handler = success;
21 m_error = error;
22 m_cancel = cancel;
23 m_mask = PromiseEventType.Success;
24 }
25
26 public HandlerDescriptor(Action handler, PromiseEventType mask) {
27 m_handler = handler;
28 m_mask = mask;
29 }
30
31 public void SignalSuccess(T result) {
32 if (m_success != null) {
33 try {
34 m_success(result);
35 } catch(Exception err) {
36 SignalError(err);
37 }
38 } else if (m_mask & PromiseEventType.Success && m_handler != null) {
39 try {
40 m_handler();
41 } catch(Exception err) {
42 // avoid calling handler twice in case of error
43 if (m_error != null)
44 SignalError(err);
45 }
46 }
47 }
48
49 public void SignalError(Exception err) {
50 if (m_error != null) {
51 try {
52 m_error(err);
53 // Analysis disable once EmptyGeneralCatchClause
54 } catch {
55 }
56 } else if (m_mask & PromiseEventType.Error && m_handler != null) {
57 try {
58 m_handler();
59 // Analysis disable once EmptyGeneralCatchClause
60 } catch {
61 }
62 }
63 }
64
65 public void SignalCancel(Exception reason) {
66 if (m_cancel != null) {
67 try {
68 m_cancel(reason);
69 } catch (Exception err) {
70 SignalError(err);
71 }
72 } else if (m_mask & PromiseEventType.Cancelled && m_handler != null) {
73 try {
74 m_handler();
75 // Analysis disable once EmptyGeneralCatchClause
76 } catch {
77 }
78 }
79 }
80 }
81
82
83
84 public Type PromiseType {
85 get {
86 return typeof(T);
87 }
88 }
89
90 public new T Join() {
91 WaitResult(-1);
92 return m_result;
93 }
94 public new T Join(int timeout) {
95 WaitResult(timeout);
96 return m_result;
97 }
98
99 public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
100 AddHandler(new HandlerDescriptor(success, error, cancel));
101 return this;
102 }
103
104 public IPromise<T> On(Action<T> success, Action<Exception> error) {
105 AddHandler(new HandlerDescriptor(success, error, null));
106 return this;
107 }
108
109 public IPromise<T> On(Action<T> success) {
110 AddHandler(new HandlerDescriptor(success, null, null));
111 return this;
112 }
113
114 public IPromise<T> On(Action handler, PromiseEventType events) {
115 AddHandler(new HandlerDescriptor(handler, events));
116 return this;
117 }
118
119 public IPromise<T> On(Action success, Action<Exception> error, Action<Exception> cancel) {
120 AddHandler(new HandlerDescriptor(success, error, cancel));
121 return this;
122 }
123
124 public IPromise<T> On(Action success, Action<Exception> error) {
125 AddHandler(new HandlerDescriptor(success, error, null));
126 return this;
127 }
128
129 public IPromise<T> On(Action success) {
130 AddHandler(new HandlerDescriptor(success, null, null));
131 return this;
132 }
133
134 IPromise IPromise.On(Action success, Action<Exception> error, Action<Exception> cancel) {
135 AddHandler(new HandlerDescriptor(success, error, cancel));
136 return this;
137 }
138
139 IPromise IPromise.On(Action success, Action<Exception> error) {
140 AddHandler(new HandlerDescriptor(success, error, null));
141 return this;
142 }
143
144 IPromise IPromise.On(Action success) {
145 AddHandler(new HandlerDescriptor(success, null, null));
146 return this;
147 }
148
149 public IPromise<T2> Cast<T2>() {
150 return (IPromise<T2>)this;
151 }
152
153 #region implemented abstract members of AbstractPromise
154
155 protected override Signal GetResolveSignal() {
156 var signal = new Signal();
157 AddHandler(new HandlerDescriptor(signal.Set, PromiseEventType.All));
158 return signal;
159 }
160
161 protected override void SignalSuccess(HandlerDescriptor handler) {
162 handler.SignalSuccess(m_result);
163 }
164
165 protected override void SignalError(HandlerDescriptor handler, Exception error) {
166 handler.SignalError(error);
167 }
168
169 protected override void SignalCancelled(HandlerDescriptor handler, Exception reason) {
170 handler.SignalCancel(reason);
171 }
172
173 #endregion
174
175 T m_result;
176
177 protected void SetResult(T value) {
178 if (BeginSetResult()) {
179 m_result = value;
180 EndSetResult();
181 }
182 }
183 }
184 }
185
@@ -0,0 +1,54
1 using System;
2 using System.Threading;
3
4 namespace Implab {
5 public class ChainTask : AbstractPromise, IDeferred {
6 readonly Func<IPromise> m_task;
7 readonly Action<Exception> m_error;
8 readonly Action<Exception> m_cancel;
9
10 int m_cancelationLock;
11
12 public ChainTask(Func<IPromise> task, Func<Exception> error, Func<Exception> cancel) {
13 m_task = task;
14 }
15
16 public void Resolve() {
17 if (m_task != null && LockCancelation()) {
18 try {
19 var operation = m_task();
20 if (operation == null)
21 throw new NullReferenceException("The task returned null promise");
22
23 operation.On(SetResult, SetError, SetCancelled);
24
25 CancelationRequested(operation.Cancel);
26 } catch(Exception err) {
27 HandleErrorInternal(err);
28 }
29 }
30 }
31
32 public void Reject(Exception error) {
33 throw new NotImplementedException();
34 }
35
36 protected void HandleErrorInternal(Exception error) {
37 if (m_error != null) {
38 try {
39 m_error(error);
40 SetResult();
41 } catch(Exception err) {
42 SetError(err);
43 }
44 } else {
45 SetError(error);
46 }
47 }
48
49 protected bool LockCancelation() {
50 return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0);
51 }
52 }
53 }
54
@@ -0,0 +1,23
1 using System;
2 using System.Threading;
3
4 namespace Implab {
5 public class FuncTask<T> : FuncTaskBase<T>, IDeferred {
6 readonly Func<T> m_task;
7
8 public FuncTask(Func<T> task, Func<Exception, T> error, Func<Exception, T> cancel) : base(error,cancel) {
9 m_task = task;
10 }
11
12 public void Resolve() {
13 if (m_task != null && LockCancelation()) {
14 try {
15 SetResult(m_task());
16 } catch(Exception err) {
17 HandleErrorInternal(err);
18 }
19 }
20 }
21 }
22 }
23
@@ -0,0 +1,53
1 using System;
2 using System.Threading;
3
4 namespace Implab {
5 public class FuncTaskBase<TResult> : AbstractPromise<TResult> {
6 readonly Func<Exception, TResult> m_cancel;
7 readonly Func<Exception, TResult> m_error;
8
9 int m_cancelationLock;
10
11 protected FuncTaskBase( Func<Exception, TResult> error, Func<Exception, TResult> cancel) {
12 m_error = error;
13 m_cancel = cancel;
14 }
15
16 public void Reject(Exception error) {
17 Safe.ArgumentNotNull(error, "error");
18 if (LockCancelation())
19 HandleErrorInternal(error);
20 }
21
22 protected void HandleErrorInternal(Exception error) {
23 if (m_error != null) {
24 try {
25 SetResult(m_error(error));
26 } catch(Exception err) {
27 SetError(err);
28 }
29 } else {
30 SetError(error);
31 }
32 }
33
34 public override void CancelOperation(Exception reason) {
35 if (LockCancelation()) {
36 if (m_cancel != null) {
37 try {
38 SetResult(m_cancel(reason));
39 } catch (Exception err) {
40 HandleErrorInternal(err);
41 }
42 } else {
43 SetCancelled(reason);
44 }
45 }
46 }
47
48 protected bool LockCancelation() {
49 return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0);
50 }
51 }
52 }
53
@@ -0,0 +1,22
1 using System;
2
3 namespace Implab {
4 public class FuncTask<TArg, TResult> : FuncTaskBase<TResult>, IDeferred<TArg> {
5 readonly Func<TArg, TResult> m_task;
6
7 public FuncTask(Func<TArg, TResult> task, Func<Exception, TResult> error,Func<Exception, TResult> cancel) : base(error,cancel) {
8 m_task = task;
9 }
10
11 public void Resolve(TArg value) {
12 if (m_task != null && LockCancelation()) {
13 try {
14 SetResult(m_task(value));
15 } catch (Exception err) {
16 HandleErrorInternal(err);
17 }
18 }
19 }
20 }
21 }
22
@@ -1,295 +1,135
1 using System;
1 using System;
2 using Implab.Parallels;
2 using Implab.Parallels;
3 using System.Threading;
4 using System.Reflection;
5
3
6 namespace Implab {
4 namespace Implab {
7 public abstract class AbstractPromise<THandler> {
5 public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise {
6 public struct HandlerDescriptor {
7 readonly Action m_handler;
8 readonly Action<Exception> m_error;
9 readonly Action<Exception> m_cancel;
10 readonly PromiseEventType m_mask;
8
11
9 const int UNRESOLVED_SATE = 0;
12 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) {
10 const int TRANSITIONAL_STATE = 1;
13 m_handler = success;
11 const int SUCCEEDED_STATE = 2;
14 m_error = error;
12 const int REJECTED_STATE = 3;
15 m_cancel = cancel;
13 const int CANCELLED_STATE = 4;
16 m_mask = PromiseEventType.Success;
14
17 }
15 const int RESERVED_HANDLERS_COUNT = 4;
16
18
17 int m_state;
19 public HandlerDescriptor(Action handler, PromiseEventType mask) {
18 Exception m_error;
20 m_handler = handler;
19 int m_handlersCount;
21 m_mask = mask;
22 }
20
23
21 readonly THandler[] m_handlers = new THandler[RESERVED_HANDLERS_COUNT];
24 public void SignalSuccess() {
22 MTQueue<THandler> m_extraHandlers;
25 if (m_mask & PromiseEventType.Success && m_handler != null) {
23 int m_handlerPointer = -1;
26 try {
24 int m_handlersCommited;
27 m_handler();
25
28 } catch (Exception err) {
26 #region state managment
29 // avoid calling handler twice in case of error
27 bool BeginTransit() {
30 if (m_error != null)
28 return UNRESOLVED_SATE == Interlocked.CompareExchange(ref m_state, TRANSITIONAL_STATE, UNRESOLVED_SATE);
31 SignalError(err);
29 }
32 }
33 }
34 }
30
35
31 void CompleteTransit(int state) {
36 public void SignalError(Exception err) {
32 if (TRANSITIONAL_STATE != Interlocked.CompareExchange(ref m_state, state, TRANSITIONAL_STATE))
37 if (m_error != null) {
33 throw new InvalidOperationException("Can't complete transition when the object isn't in the transitional state");
38 try {
34 }
39 m_error(err);
35
40 // Analysis disable once EmptyGeneralCatchClause
36 void WaitTransition() {
41 } catch {
37 while (m_state == TRANSITIONAL_STATE) {
42 }
38 Thread.MemoryBarrier();
43 } else if (m_mask & PromiseEventType.Error && m_handler != null) {
44 try {
45 m_handler();
46 // Analysis disable once EmptyGeneralCatchClause
47 } catch {
48 }
49 }
39 }
50 }
40 }
41
51
42 protected bool BeginSetResult() {
52 public void SignalCancel(Exception reason) {
43 if (!BeginTransit()) {
53 if (m_cancel != null) {
44 WaitTransition();
54 try {
45 if (m_state != CANCELLED_STATE)
55 m_cancel(reason);
46 throw new InvalidOperationException("The promise is already resolved");
56 } catch (Exception err) {
47 return false;
57 SignalError(err);
58 }
59 } else if (m_mask & PromiseEventType.Cancelled && m_handler != null) {
60 try {
61 m_handler();
62 // Analysis disable once EmptyGeneralCatchClause
63 } catch {
64 }
65 }
48 }
66 }
49 return true;
50 }
51
52 protected void EndSetResult() {
53 CompleteTransit(SUCCEEDED_STATE);
54 OnSuccess();
55 }
67 }
56
68
57
69
70 #region implemented abstract members of AbstractPromise
58
71
59 /// <summary>
72 protected override void SignalSuccess(HandlerDescriptor handler) {
60 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
73 handler.SignalSuccess();
61 /// </summary>
62 /// <remarks>
63 /// ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠ½ΠΎΠ³ΠΎΠΏΡ‚ΠΎΡ‡Π½ΠΎΠΉ срСдС, ΠΏΡ€ΠΈ Π΅Π³ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²
64 /// ΠΌΠΎΠ³Ρƒ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΏΡ€ΠΈ этом Ρ‚ΠΎΠ»ΡŒΠΊΠΎ пСрвая Π±ΡƒΠ΄Π΅Ρ‚ использована Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅
65 /// Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹.
66 /// </remarks>
67 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
68 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
69 protected void SetError(Exception error) {
70 if (BeginTransit()) {
71 if (error is OperationCanceledException) {
72 CompleteTransit(CANCELLED_STATE);
73 m_error = error.InnerException;
74 OnCancelled();
75 } else {
76 m_error = error is PromiseTransientException ? error.InnerException : error;
77 CompleteTransit(REJECTED_STATE);
78 OnError();
79 }
80 } else {
81 WaitTransition();
82 if (m_state == SUCCEEDED_STATE)
83 throw new InvalidOperationException("The promise is already resolved");
84 }
85 }
86
87 /// <summary>
88 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
89 /// </summary>
90 /// <remarks>Для опрСдСлСния Π±Ρ‹Π»Π° Π»ΠΈ опСрация ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π° слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ свойство <see cref="IsCancelled"/>.</remarks>
91 protected void SetCancelled(Exception reason) {
92 if (BeginTransit()) {
93 m_error = reason;
94 CompleteTransit(CANCELLED_STATE);
95 OnCancelled();
96 }
97 }
74 }
98
75
99 protected abstract void SignalSuccess(THandler handler);
76 protected override void SignalError(HandlerDescriptor handler, Exception error) {
100
77 handler.SignalError(error);
101 protected abstract void SignalError(THandler handler, Exception error);
102
103 protected abstract void SignalCancelled(THandler handler, Exception reason);
104
105 void OnSuccess() {
106 var hp = m_handlerPointer;
107 var slot = hp +1 ;
108 while (slot < m_handlersCommited) {
109 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
110 SignalSuccess(m_handlers[slot]);
111 }
112 hp = m_handlerPointer;
113 slot = hp +1 ;
114 }
115
116
117 if (m_extraHandlers != null) {
118 THandler handler;
119 while (m_extraHandlers.TryDequeue(out handler))
120 SignalSuccess(handler);
121 }
122 }
78 }
123
79
124 void OnError() {
80 protected override void SignalCancelled(HandlerDescriptor handler, Exception reason) {
125 var hp = m_handlerPointer;
81 handler.SignalCancel(reason);
126 var slot = hp +1 ;
127 while (slot < m_handlersCommited) {
128 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
129 SignalError(m_handlers[slot],m_error);
130 }
131 hp = m_handlerPointer;
132 slot = hp +1 ;
133 }
134
135 if (m_extraHandlers != null) {
136 THandler handler;
137 while (m_extraHandlers.TryDequeue(out handler))
138 SignalError(handler, m_error);
139 }
140 }
82 }
141
83
142 void OnCancelled() {
84 protected override Signal GetResolveSignal() {
143 var hp = m_handlerPointer;
85 var signal = new Signal();
144 var slot = hp +1 ;
86 On(signal.Set, PromiseEventType.All);
145 while (slot < m_handlersCommited) {
146 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
147 SignalCancelled(m_handlers[slot], m_error);
148 }
149 hp = m_handlerPointer;
150 slot = hp +1 ;
151 }
152
153 if (m_extraHandlers != null) {
154 THandler handler;
155 while (m_extraHandlers.TryDequeue(out handler))
156 SignalCancelled(handler, m_error);
157 }
158 }
87 }
159
88
160 #endregion
89 #endregion
161
90
162 protected abstract void Listen(PromiseEventType events, Action handler);
163
91
164 #region synchronization traits
92 public Type PromiseType {
165 protected void WaitResult(int timeout) {
93 get {
166 if (!IsResolved) {
94 return typeof(void);
167 var lk = new object();
168
169 Listen(PromiseEventType.All, () => {
170 lock(lk) {
171 Monitor.Pulse(lk);
172 }
173 });
174
175 lock (lk) {
176 while(!IsResolved) {
177 if(!Monitor.Wait(lk,timeout))
178 throw new TimeoutException();
179 }
180 }
181
182 }
183 switch (m_state) {
184 case SUCCEEDED_STATE:
185 return;
186 case CANCELLED_STATE:
187 throw new OperationCanceledException();
188 case REJECTED_STATE:
189 throw new TargetInvocationException(m_error);
190 default:
191 throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
192 }
193 }
194 #endregion
195
196 #region handlers managment
197
198 protected void AddHandler(THandler handler) {
199
200 if (m_state > 1) {
201 // the promise is in the resolved state, just invoke the handler
202 InvokeHandler(handler);
203 } else {
204 var slot = Interlocked.Increment(ref m_handlersCount) - 1;
205
206 if (slot < RESERVED_HANDLERS_COUNT) {
207 m_handlers[slot] = handler;
208
209 while (slot != Interlocked.CompareExchange(ref m_handlersCommited, slot + 1, slot)) {
210 }
211
212 if (m_state > 1) {
213 do {
214 var hp = m_handlerPointer;
215 slot = hp + 1;
216 if (slot < m_handlersCommited) {
217 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) != hp)
218 continue;
219 InvokeHandler(m_handlers[slot]);
220 }
221 break;
222 } while(true);
223 }
224 } else {
225 if (slot == RESERVED_HANDLERS_COUNT) {
226 m_extraHandlers = new MTQueue<THandler>();
227 } else {
228 while (m_extraHandlers == null)
229 Thread.MemoryBarrier();
230 }
231
232 m_extraHandlers.Enqueue(handler);
233
234 if (m_state > 1 && m_extraHandlers.TryDequeue(out handler))
235 // if the promise have been resolved while we was adding the handler to the queue
236 // we can't guarantee that someone is still processing it
237 // therefore we need to fetch a handler from the queue and execute it
238 // note that fetched handler may be not the one that we have added
239 // even we can fetch no handlers at all :)
240 InvokeHandler(handler);
241 }
242 }
95 }
243 }
96 }
244
97
245 protected void InvokeHandler(THandler handler) {
98 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
246 switch (m_state) {
99 AddHandler(new HandlerDescriptor(success, error, cancel));
247 case SUCCEEDED_STATE:
100 return this;
248 SignalSuccess(handler);
101 }
249 break;
102
250 case CANCELLED_STATE:
103 public IPromise On(Action success, Action<Exception> error) {
251 SignalCancelled(handler, m_error);
104 AddHandler(new HandlerDescriptor(success, error, null));
252 break;
105 return this;
253 case REJECTED_STATE:
254 SignalError(handler, m_error);
255 break;
256 default:
257 throw new Exception(String.Format("Invalid promise state {0}", m_state));
258 }
259 }
106 }
260
107
261 #endregion
108 public IPromise On(Action success) {
109 AddHandler(new HandlerDescriptor(success, null, null));
110 return this;
111 }
262
112
263 #region IPromise implementation
113 public IPromise On(Action handler, PromiseEventType events) {
114 AddHandler(new HandlerDescriptor(handler,events));
115 return this;
116 }
264
117
265 public void Join(int timeout) {
118 public IPromise<T> Cast<T>() {
266 WaitResult(timeout);
119 throw new InvalidCastException();
267 }
120 }
268
121
269 public void Join() {
122 public void Join() {
270 WaitResult(-1);
123 WaitResult(-1);
271 }
124 }
272
125
273 public bool IsResolved {
126 public void Join(int timeout) {
274 get {
127 WaitResult(timeout);
275 Thread.MemoryBarrier();
276 return m_state > 1;
277 }
278 }
128 }
279
129
280 public bool IsCancelled {
130 protected void SetResult() {
281 get {
131 BeginSetResult();
282 Thread.MemoryBarrier();
132 EndSetResult();
283 return m_state == CANCELLED_STATE;
284 }
285 }
286
287 #endregion
288
289 public Exception Error {
290 get {
291 return m_error;
292 }
293 }
133 }
294 }
134 }
295 }
135 }
@@ -22,14 +22,14 namespace Implab {
22 /// Sets the token to cancelled state.
22 /// Sets the token to cancelled state.
23 /// </summary>
23 /// </summary>
24 /// <param name="reason">The reason why the operation was cancelled.</param>
24 /// <param name="reason">The reason why the operation was cancelled.</param>
25 void SetCancelled(Exception reason);
25 void CancelOperation(Exception reason);
26
26
27 /// <summary>
27 /// <summary>
28 /// Adds the listener for the cancellation request, is the cancellation was requested the <paramref name="handler"/>
28 /// Adds the listener for the cancellation request, is the cancellation was requested the <paramref name="handler"/>
29 /// is executed immediatelly.
29 /// is executed immediatelly.
30 /// </summary>
30 /// </summary>
31 /// <param name="handler">The handler which will be executed if the cancel occurs.</param>
31 /// <param name="handler">The handler which will be executed if the cancel occurs.</param>
32 void CancellationRequested(Action<Exception> handler);
32 void CancelationRequested(Action<Exception> handler);
33
33
34 }
34 }
35 }
35 }
@@ -58,13 +58,13 namespace Implab {
58 /// exception it will be passed to the dependent promise.
58 /// exception it will be passed to the dependent promise.
59 /// </para>
59 /// </para>
60 /// </remarks>
60 /// </remarks>
61 IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel);
61 /* IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel);
62 IPromise Then(Action success, Action<Exception> error);
62 IPromise Then(Action success, Action<Exception> error);
63 IPromise Then(Action success);
63 IPromise Then(Action success);
64
64
65 IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel);
65 IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel);
66 IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error);
66 IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error);
67 IPromise Chain(Func<IPromise> chained);
67 IPromise Chain(Func<IPromise> chained);*/
68
68
69 /// <summary>
69 /// <summary>
70 /// Adds specified listeners to the current promise.
70 /// Adds specified listeners to the current promise.
@@ -3,28 +3,23
3 namespace Implab {
3 namespace Implab {
4 public interface IPromise<out T> : IPromise {
4 public interface IPromise<out T> : IPromise {
5
5
6 new T Join();
7
8 new T Join(int timeout);
9
10 IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel);
6 IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel);
11
7
12 IPromise<T> On(Action<T> success, Action<Exception> error);
8 IPromise<T> On(Action<T> success, Action<Exception> error);
13
9
14 IPromise<T> On(Action<T> success);
10 IPromise<T> On(Action<T> success);
15
11
12 new T Join();
13
14 new T Join(int timeout);
15
16 new IPromise<T> On(Action success, Action<Exception> error, Action<Exception> cancel);
17
18 new IPromise<T> On(Action success, Action<Exception> error);
19
20 new IPromise<T> On(Action success);
21
16 new IPromise<T> On(Action handler, PromiseEventType events);
22 new IPromise<T> On(Action handler, PromiseEventType events);
17
23
18 IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error, Func<Exception, T2> cancel);
19
20 IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error);
21
22 IPromise<T2> Then<T2>(Func<T, T2> mapper);
23
24 IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel);
25
26 IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error);
27
28 IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained);
29 }
24 }
30 }
25 }
@@ -150,7 +150,6
150 <Compile Include="PromiseT.cs" />
150 <Compile Include="PromiseT.cs" />
151 <Compile Include="IDeferred.cs" />
151 <Compile Include="IDeferred.cs" />
152 <Compile Include="IDeferredT.cs" />
152 <Compile Include="IDeferredT.cs" />
153 <Compile Include="AbstractPromise.cs" />
154 <Compile Include="Promise.cs" />
153 <Compile Include="Promise.cs" />
155 <Compile Include="PromiseTransientException.cs" />
154 <Compile Include="PromiseTransientException.cs" />
156 <Compile Include="Parallels\Signal.cs" />
155 <Compile Include="Parallels\Signal.cs" />
@@ -159,6 +158,13
159 <Compile Include="Diagnostics\ListenerBase.cs" />
158 <Compile Include="Diagnostics\ListenerBase.cs" />
160 <Compile Include="Parallels\BlockingQueue.cs" />
159 <Compile Include="Parallels\BlockingQueue.cs" />
161 <Compile Include="ICancelationToken.cs" />
160 <Compile Include="ICancelationToken.cs" />
161 <Compile Include="AbstractEvent.cs" />
162 <Compile Include="AbstractPromise.cs" />
163 <Compile Include="AbstractPromiseT.cs" />
164 <Compile Include="FuncTask.cs" />
165 <Compile Include="FuncTaskBase.cs" />
166 <Compile Include="FuncTaskT.cs" />
167 <Compile Include="ChainTask.cs" />
162 </ItemGroup>
168 </ItemGroup>
163 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
169 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
164 <ItemGroup />
170 <ItemGroup />
@@ -1,222 +1,22
1 using System;
1 using System;
2 using System.Diagnostics;
2 using Implab.Parallels;
3
3
4 namespace Implab {
4 namespace Implab {
5 public class Promise : AbstractPromise<Promise.HandlerDescriptor>, IPromise, IDeferred {
5 public class Promise : AbstractPromise, IDeferred {
6
6 public static readonly Promise SUCCESS;
7 public struct HandlerDescriptor {
8 readonly Action m_success;
9 readonly Action<Exception> m_error;
10 readonly Action<Exception> m_cancel;
11 readonly IDeferred m_deferred;
12
13 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel, IDeferred deferred) {
14 m_success = success;
15 m_error = error;
16 m_cancel = cancel;
17 m_deferred = deferred;
18 }
19
20 public void SignalSuccess() {
21 if (m_success != null) {
22 try {
23 m_success();
24 if (m_deferred != null)
25 m_deferred.Resolve();
26 } catch (Exception err) {
27 SignalError(err);
28 }
29 }
30 }
31
7
32 public void SignalError(Exception err) {
8 static Promise() {
33 if (m_error != null) {
9 SUCCESS = new Promise();
34 try {
10 SUCCESS.Resolve();
35 m_error(err);
36 if (m_deferred != null)
37 m_deferred.Resolve();
38 } catch (Exception err2) {
39 if (m_deferred != null)
40 m_deferred.Reject(err2);
41 }
42 } else {
43 if (m_deferred != null)
44 m_deferred.Reject(err);
45 }
46 }
47
48 public void SignalCancel(Exception reason) {
49 if (m_cancel != null) {
50 try {
51 m_cancel(reason);
52 if (m_deferred != null)
53 m_deferred.Resolve();
54 } catch (Exception err) {
55 SignalError(err);
56 }
57 } else if (reason != null && m_error != null) {
58 try {
59 m_error(new OperationCanceledException("The operation was canceled.", reason));
60 if (m_deferred != null)
61 m_deferred.Resolve();
62 } catch (Exception err) {
63 SignalError(err);
64 }
65 } else {
66 if (m_deferred != null)
67 m_deferred.Cancel(reason);
68 }
69 }
70 }
11 }
71
12
72 public void Resolve() {
13 public void Resolve() {
73 BeginSetResult();
14 SetResult();
74 EndSetResult();
75 }
15 }
76
16
77 public void Reject(Exception error) {
17 public void Reject(Exception error) {
78 SetError(error);
18 SetError(error);
79 }
19 }
80
81 #region implemented abstract members of AbstractPromise
82
83 protected override void SignalSuccess(HandlerDescriptor handler) {
84 handler.SignalSuccess();
85 }
86
87 protected override void SignalError(HandlerDescriptor handler, Exception error) {
88 handler.SignalError(error);
89 }
90
91 protected override void SignalCancelled(HandlerDescriptor handler, Exception reason) {
92 handler.SignalCancel(reason);
93 }
94
95 protected override void Listen(PromiseEventType events, Action handler) {
96 AddHandler(new HandlerDescriptor(
97 events.HasFlag(PromiseEventType.Success) ? handler : null,
98 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null,
99 events.HasFlag(PromiseEventType.Cancelled) ? new Action<Exception>(reason => handler()) : null,
100 null
101 ));
102 }
103
104 #endregion
105
106
107 public Type PromiseType {
108 get {
109 return typeof(void);
110 }
111 }
112
113 public IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel) {
114 var promise = new Promise();
115 if (success != null)
116 promise.On(Cancel, PromiseEventType.Cancelled);
117
118 AddHandler(new HandlerDescriptor(success, error, cancel, promise));
119
120 return promise;
121 }
122
123 public IPromise Then(Action success, Action<Exception> error) {
124 return Then(success, error, null);
125 }
126
127 public IPromise Then(Action success) {
128 return Then(success, null, null);
129 }
130
131 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
132 AddHandler(new HandlerDescriptor(success, error, cancel, null));
133 return this;
134 }
135
136 public IPromise On(Action success, Action<Exception> error) {
137 return On(success, error, null);
138 }
139
140 public IPromise On(Action success) {
141 return On(success, null, null);
142 }
143
144 public IPromise On(Action handler, PromiseEventType events) {
145 return On(
146 events.HasFlag(PromiseEventType.Success) ? handler : null,
147 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null,
148 events.HasFlag(PromiseEventType.Cancelled) ? new Action<Exception>(reason => handler()) : null
149 );
150 }
151
152 public IPromise<T> Cast<T>() {
153 throw new InvalidCastException();
154 }
155
156 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception,IPromise> cancel) {
157 var medium = new Promise();
158
159 On(
160 () => {
161 if (medium.IsCancelled)
162 return;
163 if (chained != null)
164 ConnectPromise(chained(), medium);
165 },
166 ex => {
167 if (medium.IsCancelled)
168 return;
169 if (error != null) {
170 try {
171 ConnectPromise(error(ex), medium);
172 } catch (Exception ex2) {
173 medium.Reject(ex2);
174 }
175 } else {
176 medium.Reject(ex);
177 }
178 },
179 reason => {
180 if (medium.IsCancelled)
181 return;
182 if (cancel != null)
183 ConnectPromise(cancel(reason), medium);
184 else
185 medium.Cancel(reason);
186 }
187 );
188
189 if (chained != null)
190 medium.On(Cancel, PromiseEventType.Cancelled);
191
192 return medium;
193 }
194
195 static void ConnectPromise(IPromise result, Promise medium) {
196 if (result != null) {
197 result.On(
198 medium.Resolve,
199 medium.Reject,
200 medium.Cancel
201 );
202 medium.On(null,null,result.Cancel);
203 } else {
204 medium.Reject(
205 new NullReferenceException(
206 "The chained asynchronous operation returned" +
207 " 'null' where the promise instance is expected"
208 )
209 );
210 }
211 }
212
213 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error) {
214 return Chain(chained, error, null);
215 }
216
217 public IPromise Chain(Func<IPromise> chained) {
218 return Chain(chained, null, null);
219 }
220 }
20 }
221 }
21 }
222
22
This diff has been collapsed as it changes many lines, (533 lines changed) Show them Hide them
@@ -1,5 +1,6
1 using System;
1 using System;
2 using System.Diagnostics;
2 using System.Diagnostics;
3 using Implab.Parallels;
3
4
4 namespace Implab {
5 namespace Implab {
5
6
@@ -37,538 +38,26 namespace Implab {
37 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
38 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
38 /// </para>
39 /// </para>
39 /// </remarks>
40 /// </remarks>
40 public class Promise<T> : AbstractPromise<IDeferred<T>>, IPromise<T>, IDeferred<T> {
41 public class Promise<T> : AbstractPromise<T>, IDeferred<T> {
41
42 class StubDeferred : IDeferred, IDeferred<T> {
43 public static readonly StubDeferred instance = new StubDeferred();
44
45 StubDeferred() {
46 }
47
48 #region IDeferred implementation
49
50 public void Resolve(T value) {
51 }
52
53 public void Resolve() {
54 }
55
56 public void Reject(Exception error) {
57 }
58
59 #endregion
60
61 #region ICancellable implementation
62
63 public void Cancel() {
64 }
65
66 public void Cancel(Exception reason) {
67 }
68
69 #endregion
70
71
72 }
73
74 class RemapDescriptor<T2> : IDeferred<T> {
75 readonly Func<T,T2> m_remap;
76 readonly Func<Exception, T2> m_failed;
77 readonly Func<Exception, T2> m_cancel;
78 readonly IDeferred<T2> m_deferred;
79
80 public RemapDescriptor(Func<T,T2> remap, Func<Exception,T2> failed, Func<Exception, T2> cancel, IDeferred<T2> deferred ) {
81 Debug.Assert(deferred != null);
82 m_remap = remap;
83 m_failed = failed;
84 m_cancel = cancel;
85 m_deferred = deferred;
86 }
87
42
88
43 public static IPromise<T> FromResult(T value) {
89
44 var p = new Promise<T>();
90 #region IDeferred implementation
45 p.Resolve(value);
91
46 return p;
92 public void Resolve(T value) {
93 if (m_remap != null) {
94 try {
95 m_deferred.Resolve(m_remap(value));
96 } catch (Exception ex) {
97 Reject(ex);
98 }
99 }
100 }
101
102 public void Reject(Exception error) {
103 if (m_failed != null) {
104 try {
105 m_deferred.Resolve(m_failed(error));
106 } catch (Exception ex) {
107 m_deferred.Reject(ex);
108 }
109 } else {
110 m_deferred.Reject(error);
111 }
112 }
113
114
115 #endregion
116
117 #region ICancellable implementation
118
119 public void Cancel(Exception reason) {
120 if (m_cancel != null) {
121 try {
122 m_deferred.Resolve(m_cancel(reason));
123 } catch (Exception ex) {
124 Reject(ex);
125 }
126 } else {
127 m_deferred.Cancel(reason);
128 }
129 }
130
131 public void Cancel() {
132 Cancel(null);
133 }
134 #endregion
135 }
47 }
136
48
137 class ListenerDescriptor : IDeferred<T> {
49 public static IPromise<T> FromException(Exception error) {
138 readonly Action m_handler;
50 var p = new Promise<T>();
139 readonly PromiseEventType m_events;
51 p.Reject(error);
140
52 return p;
141 public ListenerDescriptor(Action handler, PromiseEventType events) {
142 Debug.Assert(handler != null);
143
144 m_handler = handler;
145 m_events = events;
146 }
147
148 #region IDeferred implementation
149
150 public void Resolve(T value) {
151 if (m_events.HasFlag(PromiseEventType.Success)) {
152 try {
153 m_handler();
154 // Analysis disable once EmptyGeneralCatchClause
155 } catch {
156 }
157 }
158 }
159
160 public void Reject(Exception error) {
161 if (m_events.HasFlag(PromiseEventType.Error)){
162 try {
163 m_handler();
164 // Analysis disable once EmptyGeneralCatchClause
165 } catch {
166 }
167 }
168 }
169
170 #endregion
171
172 #region ICancellable implementation
173
174 public void Cancel() {
175 Cancel(null);
176 }
177
178 public void Cancel(Exception reason) {
179 if (m_events.HasFlag(PromiseEventType.Cancelled)){
180 try {
181 m_handler();
182 // Analysis disable once EmptyGeneralCatchClause
183 } catch {
184 }
185 }
186 }
187
188 #endregion
189 }
53 }
190
54
191 class ValueEventDescriptor : IDeferred<T> {
192 readonly Action<T> m_success;
193 readonly Action<Exception> m_failed;
194 readonly Action<Exception> m_cancelled;
195 readonly IDeferred<T> m_deferred;
196
197 public ValueEventDescriptor(Action<T> success, Action<Exception> failed, Action<Exception> cancelled, IDeferred<T> deferred) {
198 Debug.Assert(deferred != null);
199
200 m_success = success;
201 m_failed = failed;
202 m_cancelled = cancelled;
203 m_deferred = deferred;
204 }
205
206 #region IDeferred implementation
207
208 public void Resolve(T value) {
209 if (m_success != null) {
210 try {
211 m_success(value);
212 m_deferred.Resolve(value);
213 } catch (Exception ex) {
214 Reject(ex);
215 }
216 }
217 }
218
219 public void Reject(Exception error) {
220 if (m_failed != null) {
221 try {
222 m_failed(error);
223 m_deferred.Resolve(default(T));
224 } catch(Exception ex) {
225 m_deferred.Reject(ex);
226 }
227 } else {
228 m_deferred.Reject(error);
229 }
230 }
231
232 #endregion
233
234 #region ICancellable implementation
235
236 public void Cancel(Exception reason) {
237 if (m_cancelled != null) {
238 try {
239 m_cancelled(reason);
240 m_deferred.Resolve(default(T));
241 } catch (Exception ex) {
242 Reject(ex);
243 }
244 } else {
245 m_deferred.Cancel(reason);
246 }
247 }
248
249 public void Cancel() {
250 Cancel(null);
251 }
252
253 #endregion
254 }
255
256 public class EventDescriptor : IDeferred<T> {
257 readonly Action m_success;
258 readonly Action<Exception> m_failed;
259 readonly Action<Exception> m_cancelled;
260 readonly IDeferred m_deferred;
261
262 public EventDescriptor(Action success, Action<Exception> failed, Action<Exception> cancelled, IDeferred deferred) {
263 Debug.Assert(deferred != null);
264
265 m_success = success;
266 m_failed = failed;
267 m_cancelled = cancelled;
268 m_deferred = deferred;
269 }
270
271 #region IDeferred implementation
272
273 public void Resolve(T value) {
274 if (m_success != null) {
275 try {
276 m_success();
277 m_deferred.Resolve();
278 } catch (Exception ex) {
279 Reject(ex);
280 }
281 }
282 }
283
284 public void Reject(Exception error) {
285 if (m_failed != null) {
286 try {
287 m_failed(error);
288 m_deferred.Resolve();
289 } catch (Exception ex) {
290 m_deferred.Reject(ex);
291 }
292 } else {
293 m_deferred.Reject(error);
294 }
295 }
296
297 #endregion
298
299 #region ICancellable implementation
300
301 public void Cancel(Exception reason) {
302 if (m_cancelled != null) {
303 try {
304 m_cancelled(reason);
305 m_deferred.Resolve();
306 } catch (Exception ex) {
307 Reject(ex);
308 }
309 } else {
310 m_deferred.Cancel(reason);
311 }
312 }
313
314 public void Cancel() {
315 Cancel(null);
316 }
317
318 #endregion
319 }
320
321 T m_result;
322
323 public virtual void Resolve(T value) {
55 public virtual void Resolve(T value) {
324 if (BeginSetResult()) {
56 SetResult(value);
325 m_result = value;
326 EndSetResult();
327 }
328 }
57 }
329
58
330 public void Reject(Exception error) {
59 public void Reject(Exception error) {
331 SetError(error);
60 SetError(error);
332 }
61 }
333
334 public Type PromiseType {
335 get {
336 return typeof(T);
337 }
338 }
339
340 public new T Join() {
341 WaitResult(-1);
342 return m_result;
343 }
344 public new T Join(int timeout) {
345 WaitResult(timeout);
346 return m_result;
347 }
348
349 public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
350 AddHandler(new ValueEventDescriptor(success, error, cancel, StubDeferred.instance));
351 return this;
352 }
353
354 public IPromise<T> On(Action<T> success, Action<Exception> error) {
355 AddHandler(new ValueEventDescriptor(success, error, null, StubDeferred.instance));
356 return this;
357 }
358
359 public IPromise<T> On(Action<T> success) {
360 AddHandler(new ValueEventDescriptor(success, null, null, StubDeferred.instance));
361 return this;
362 }
363
364 public IPromise<T> On(Action handler, PromiseEventType events) {
365 Listen(events, handler);
366 return this;
367 }
368
369 public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error, Func<Exception, T2> cancel) {
370 var promise = new Promise<T2>();
371 if (mapper != null)
372 promise.On((Action)null, null, Cancel);
373 AddHandler(new RemapDescriptor<T2>(mapper, error, cancel, promise));
374 return promise;
375 }
376
377 public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error) {
378 var promise = new Promise<T2>();
379 if (mapper != null)
380 promise.On((Action)null, null, Cancel);
381 AddHandler(new RemapDescriptor<T2>(mapper, error, null, promise));
382 return promise;
383 }
384
385 public IPromise<T2> Then<T2>(Func<T, T2> mapper) {
386 var promise = new Promise<T2>();
387 if (mapper != null)
388 promise.On((Action)null, null, Cancel);
389 AddHandler(new RemapDescriptor<T2>(mapper, null, null, promise));
390 return promise;
391 }
392
393 public IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel) {
394 // this promise will be resolved when an asyc operation is started
395 var promise = new Promise<IPromise<T2>>();
396
397 AddHandler(new RemapDescriptor<IPromise<T2>>(
398 chained,
399 error,
400 cancel,
401 promise
402 ));
403
404 var medium = new Promise<T2>();
405
406 if (chained != null)
407 medium.On(Cancel, PromiseEventType.Cancelled);
408
409 // we need to connect started async operation with the medium
410 // if the async operation hasn't been started by the some reason
411 // report is to the medium
412 promise.On(
413 result => ConnectPromise<T2>(result, medium),
414 medium.Reject,
415 medium.Cancel
416 );
417
418 return medium;
419 }
420
421 static void ConnectPromise<T2>(IPromise<T2> result, Promise<T2> medium) {
422 if (result != null) {
423 result.On(
424 medium.Resolve,
425 medium.Reject,
426 medium.Cancel
427 );
428 medium.On(result.Cancel, PromiseEventType.Cancelled);
429 } else {
430 medium.Reject(
431 new NullReferenceException(
432 "The chained asynchronous operation returned" +
433 " 'null' where the promise instance is expected"
434 )
435 );
436 }
437 }
438
439 public IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error) {
440 return Chain(chained, error, null);
441 }
442
443 public IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained) {
444 return Chain(chained, null, null);
445 }
446
447 public IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel) {
448 var promise = new Promise();
449 if (success != null)
450 promise.On(null, null, Cancel);
451
452 AddHandler(new EventDescriptor(success, error, cancel, promise));
453
454 return promise;
455 }
456
457 public IPromise Then(Action success, Action<Exception> error) {
458 return Then(success, error, null);
459 }
460
461 public IPromise Then(Action success) {
462 return Then(success, null, null);
463 }
464
465 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel) {
466 var promise = new Promise<IPromise>();
467
468 AddHandler(
469 new RemapDescriptor<IPromise>(
470 x => chained(),
471 error,
472 cancel,
473 promise
474 )
475 );
476
477 var medium = new Promise();
478 if (chained != null)
479 medium.On(null, null, Cancel);
480
481 promise.On(
482 result => ConnectPromise(result, medium),
483 medium.Reject,
484 medium.Cancel
485 );
486
487 return medium;
488 }
489
490 static void ConnectPromise(IPromise result, Promise medium) {
491 if (result != null) {
492 result.On(
493 medium.Resolve,
494 medium.Reject,
495 medium.Cancel
496 );
497 medium.On(null, null, result.Cancel);
498 } else {
499 medium.Reject(
500 new NullReferenceException(
501 "The chained asynchronous operation returned" +
502 " 'null' where the promise instance is expected"
503 )
504 );
505 }
506 }
507
508 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error) {
509 return Chain(chained, error, null);
510 }
511
512 public IPromise Chain(Func<IPromise> chained) {
513 return Chain(chained, null, null);
514 }
515
516 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
517 AddHandler(new EventDescriptor(success,error,cancel, StubDeferred.instance));
518 return this;
519 }
520
521 public IPromise On(Action success, Action<Exception> error) {
522 AddHandler(new EventDescriptor(success, error, null, StubDeferred.instance));
523 return this;
524 }
525
526 public IPromise On(Action success) {
527 Listen(PromiseEventType.Success, success);
528 return this;
529 }
530
531 IPromise IPromise.On(Action handler, PromiseEventType events) {
532 Listen(events,handler);
533 return this;
534 }
535
536 public IPromise<T2> Cast<T2>() {
537 return (IPromise<T2>)this;
538 }
539
540 #region implemented abstract members of AbstractPromise
541
542 protected override void SignalSuccess(IDeferred<T> handler) {
543 handler.Resolve(m_result);
544 }
545
546 protected override void SignalError(IDeferred<T> handler, Exception error) {
547 handler.Reject(error);
548 }
549
550 protected override void SignalCancelled(IDeferred<T> handler, Exception reason) {
551 handler.Cancel(reason);
552 }
553
554 protected override void Listen(PromiseEventType events, Action handler) {
555 if (handler != null)
556 AddHandler(new ListenerDescriptor(handler, events));
557 }
558
559 #endregion
560
561 public static IPromise<T> ResultToPromise(T value) {
562 var p = new Promise<T>();
563 p.Resolve(value);
564 return p;
565 }
566
567 public static IPromise<T> ExceptionToPromise(Exception error) {
568 var p = new Promise<T>();
569 p.Reject(error);
570 return p;
571 }
572
573 }
62 }
574 }
63 }
General Comments 0
You need to be logged in to leave comments. Login now