@@ -48,14 +48,14 namespace Implab { | |||||
48 | public abstract void Cancel(); |
|
48 | public abstract void Cancel(); | |
49 | } |
|
49 | } | |
50 |
|
50 | |||
51 |
protected class |
|
51 | protected class RemapDescriptor<T2> : AbstractHandler { | |
52 |
|
52 | |||
53 | readonly Func<T,T2> m_resultHandler; |
|
53 | readonly Func<T,T2> m_resultHandler; | |
54 | readonly Func<Exception,T2> m_errorHandler; |
|
54 | readonly Func<Exception,T2> m_errorHandler; | |
55 | readonly Action m_cancellHandler; |
|
55 | readonly Action m_cancellHandler; | |
56 | readonly Promise<T2> m_medium; |
|
56 | readonly Promise<T2> m_medium; | |
57 |
|
57 | |||
58 |
public |
|
58 | public RemapDescriptor(Func<T,T2> resultHandler, Func<Exception,T2> errorHandler, Action cancelHandler, Promise<T2> medium) { | |
59 | m_resultHandler = resultHandler; |
|
59 | m_resultHandler = resultHandler; | |
60 | m_errorHandler = errorHandler; |
|
60 | m_errorHandler = errorHandler; | |
61 | m_cancellHandler = cancelHandler; |
|
61 | m_cancellHandler = cancelHandler; | |
@@ -82,9 +82,61 namespace Implab { | |||||
82 | var res = m_errorHandler(error); |
|
82 | var res = m_errorHandler(error); | |
83 | if (m_medium != null) |
|
83 | if (m_medium != null) | |
84 | m_medium.Resolve(res); |
|
84 | m_medium.Resolve(res); | |
85 |
|
|
85 | } catch (Exception err2) { | |
86 | if (medium != null) |
|
86 | if (m_medium != null) | |
87 |
|
|
87 | m_medium.Reject(err2); | |
|
88 | } | |||
|
89 | } else if (m_medium != null) | |||
|
90 | m_medium.Reject(error); | |||
|
91 | } | |||
|
92 | ||||
|
93 | public override void Cancel() { | |||
|
94 | if (m_cancellHandler != null) { | |||
|
95 | try { | |||
|
96 | m_cancellHandler(); | |||
|
97 | } catch (Exception err) { | |||
|
98 | Reject(err); | |||
|
99 | return; | |||
|
100 | } | |||
|
101 | } | |||
|
102 | if (m_medium != null) | |||
|
103 | m_medium.Cancel(); | |||
|
104 | } | |||
|
105 | } | |||
|
106 | ||||
|
107 | protected class HandlerDescriptor : AbstractHandler { | |||
|
108 | ||||
|
109 | readonly Action<T> m_resultHandler; | |||
|
110 | readonly Action<Exception> m_errorHandler; | |||
|
111 | readonly Action m_cancellHandler; | |||
|
112 | readonly Promise<T> m_medium; | |||
|
113 | ||||
|
114 | public HandlerDescriptor(Action<T> resultHandler, Action<Exception> errorHandler, Action cancelHandler, Promise<T> medium) { | |||
|
115 | m_resultHandler = resultHandler; | |||
|
116 | m_errorHandler = errorHandler; | |||
|
117 | m_cancellHandler = cancelHandler; | |||
|
118 | m_medium = medium; | |||
|
119 | } | |||
|
120 | ||||
|
121 | public override void Resolve(T result) { | |||
|
122 | if (m_resultHandler != null) { | |||
|
123 | try { | |||
|
124 | m_resultHandler(result); | |||
|
125 | } catch (Exception e) { | |||
|
126 | Reject(e); | |||
|
127 | return; | |||
|
128 | } | |||
|
129 | } | |||
|
130 | if(m_medium != null) | |||
|
131 | m_medium.Resolve(result); | |||
|
132 | } | |||
|
133 | ||||
|
134 | public override void Reject(Exception error) { | |||
|
135 | if (m_errorHandler != null) { | |||
|
136 | try { | |||
|
137 | m_errorHandler(error); | |||
|
138 | if (m_medium != null) | |||
|
139 | m_medium.Resolve(default(T)); | |||
88 | } catch (Exception err2) { |
|
140 | } catch (Exception err2) { | |
89 | if (m_medium != null) |
|
141 | if (m_medium != null) | |
90 | m_medium.Reject(err2); |
|
142 | m_medium.Reject(err2); | |
@@ -126,7 +178,7 namespace Implab { | |||||
126 |
|
178 | |||
127 | public Promise(IPromise parent) { |
|
179 | public Promise(IPromise parent) { | |
128 | if (parent != null) |
|
180 | if (parent != null) | |
129 |
Add |
|
181 | AddMappers<T>( | |
130 | null, |
|
182 | null, | |
131 | null, |
|
183 | null, | |
132 | () => { |
|
184 | () => { | |
@@ -252,43 +304,28 namespace Implab { | |||||
252 | if (success == null && error == null && cancel == null) |
|
304 | if (success == null && error == null && cancel == null) | |
253 | return; |
|
305 | return; | |
254 |
|
306 | |||
255 | AddHandler( |
|
307 | AddHandler(success, error, cancel, null, false); | |
256 | success != null ? new Func<T,T>(x => { |
|
|||
257 | success(x); |
|
|||
258 | return x; |
|
|||
259 | }) : null, |
|
|||
260 | error != null ? new Func<Exception,T>(e => { |
|
|||
261 | error(e); |
|
|||
262 | return default(T); |
|
|||
263 | }) : null, |
|
|||
264 | cancel, |
|
|||
265 | null, |
|
|||
266 | false |
|
|||
267 | ); |
|
|||
268 | } |
|
308 | } | |
269 |
|
309 | |||
270 | public void On(Action<T> success, Action<Exception> error) { |
|
310 | public void On(Action<T> success, Action<Exception> error) { | |
271 |
|
|
311 | AddHandler(success, error, null, null, false); | |
272 | } |
|
312 | } | |
273 |
|
313 | |||
274 | public void On(Action<T> success) { |
|
314 | public void On(Action<T> success) { | |
275 |
|
|
315 | AddHandler(success, null, null, null, false); | |
276 | } |
|
316 | } | |
277 |
|
317 | |||
278 | public void On(Action handler, PromiseEventType events) { |
|
318 | public void On(Action handler, PromiseEventType events) { | |
279 | Safe.ArgumentNotNull(handler, "handler"); |
|
319 | Safe.ArgumentNotNull(handler, "handler"); | |
280 |
|
320 | |||
281 | Func<T,T> success = events.HasFlag(PromiseEventType.Success) ? new Func<T,T>(x => { |
|
|||
282 | handler(); |
|
|||
283 | return x; |
|
|||
284 | }) : null; |
|
|||
285 | Func<Exception,T> error = events.HasFlag(PromiseEventType.Error) ? new Func<Exception,T>(e => { |
|
|||
286 | handler(); |
|
|||
287 | return default(T); |
|
|||
288 | }) : null; |
|
|||
289 | Action cancel = events.HasFlag(PromiseEventType.Cancelled) ? handler : null; |
|
|||
290 |
|
321 | |||
291 | AddHandler(success, error, cancel, null, false); |
|
322 | AddHandler( | |
|
323 | events.HasFlag(PromiseEventType.Success) ? new Action<T>(x => handler()) : null, | |||
|
324 | events.HasFlag(PromiseEventType.Error) ? new Action<Exception>( x => handler()) : null, | |||
|
325 | events.HasFlag(PromiseEventType.Cancelled) ? handler : null, | |||
|
326 | null, | |||
|
327 | false | |||
|
328 | ); | |||
292 | } |
|
329 | } | |
293 |
|
330 | |||
294 | public IPromise Error(Action<Exception> error) { |
|
331 | public IPromise Error(Action<Exception> error) { | |
@@ -297,7 +334,7 namespace Implab { | |||||
297 |
|
334 | |||
298 | var medium = new Promise<T>(this); |
|
335 | var medium = new Promise<T>(this); | |
299 |
|
336 | |||
300 |
Add |
|
337 | AddMappers( | |
301 | null, |
|
338 | null, | |
302 | e => { |
|
339 | e => { | |
303 | error(e); |
|
340 | error(e); | |
@@ -325,7 +362,7 namespace Implab { | |||||
325 |
|
362 | |||
326 | var medium = new Promise<T>(this); |
|
363 | var medium = new Promise<T>(this); | |
327 |
|
364 | |||
328 |
Add |
|
365 | AddMappers(null, handler, null, medium, true); | |
329 |
|
366 | |||
330 | return medium; |
|
367 | return medium; | |
331 | } |
|
368 | } | |
@@ -345,7 +382,7 namespace Implab { | |||||
345 | // ΡΠΎΠ·Π΄Π°Π΅ΠΌ ΠΏΡΠΈΡΠ΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ |
|
382 | // ΡΠΎΠ·Π΄Π°Π΅ΠΌ ΠΏΡΠΈΡΠ΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ | |
346 | var medium = new Promise<TNew>(this); |
|
383 | var medium = new Promise<TNew>(this); | |
347 |
|
384 | |||
348 |
Add |
|
385 | AddMappers( | |
349 | mapper, |
|
386 | mapper, | |
350 | error, |
|
387 | error, | |
351 | cancel, |
|
388 | cancel, | |
@@ -454,7 +491,7 namespace Implab { | |||||
454 | else |
|
491 | else | |
455 | cancelHandler = medium.Cancel; |
|
492 | cancelHandler = medium.Cancel; | |
456 |
|
493 | |||
457 |
Add |
|
494 | AddMappers( | |
458 | resultHandler, |
|
495 | resultHandler, | |
459 | errorHandler, |
|
496 | errorHandler, | |
460 | cancelHandler, |
|
497 | cancelHandler, | |
@@ -490,10 +527,7 namespace Implab { | |||||
490 | var medium = new Promise<T>(this); |
|
527 | var medium = new Promise<T>(this); | |
491 |
|
528 | |||
492 | AddHandler( |
|
529 | AddHandler( | |
493 |
x => |
|
530 | x => handler(), | |
494 | handler(); |
|
|||
495 | return x; |
|
|||
496 | }, |
|
|||
497 | e => { |
|
531 | e => { | |
498 | handler(); |
|
532 | handler(); | |
499 | throw new TransientPromiseException(e); |
|
533 | throw new TransientPromiseException(e); | |
@@ -559,11 +593,37 namespace Implab { | |||||
559 | return Join(Timeout.Infinite); |
|
593 | return Join(Timeout.Infinite); | |
560 | } |
|
594 | } | |
561 |
|
595 | |||
562 |
void Add |
|
596 | void AddMappers<T2>(Func<T,T2> success, Func<Exception,T2> error, Action cancel, Promise<T2> medium, bool inc) { | |
563 | if (inc) |
|
597 | if (inc) | |
564 | Interlocked.Increment(ref m_childrenCount); |
|
598 | Interlocked.Increment(ref m_childrenCount); | |
565 |
|
599 | |||
566 |
AbstractHandler handler = new |
|
600 | AbstractHandler handler = new RemapDescriptor<T2>(success, error, cancel, medium); | |
|
601 | ||||
|
602 | bool queued; | |||
|
603 | ||||
|
604 | if (!IsResolved) { | |||
|
605 | m_handlers.Enqueue(handler); | |||
|
606 | queued = true; | |||
|
607 | } else { | |||
|
608 | // the promise is in resolved state, just invoke the handled with minimum overhead | |||
|
609 | queued = false; | |||
|
610 | InvokeHandler(handler); | |||
|
611 | } | |||
|
612 | ||||
|
613 | if (queued && IsResolved && m_handlers.TryDequeue(out handler)) | |||
|
614 | // if the promise have been resolved while we was adding handler to the queue | |||
|
615 | // we can't guarantee that someone is still processing it | |||
|
616 | // therefore we will fetch a handler from the queue and execute it | |||
|
617 | // note that fetched handler may be not the one that we have added | |||
|
618 | // even we can fetch no handlers at all :) | |||
|
619 | InvokeHandler(handler); | |||
|
620 | } | |||
|
621 | ||||
|
622 | void AddHandler(Action<T> success, Action<Exception> error, Action cancel, Promise<T> medium, bool inc) { | |||
|
623 | if (inc) | |||
|
624 | Interlocked.Increment(ref m_childrenCount); | |||
|
625 | ||||
|
626 | AbstractHandler handler = new HandlerDescriptor(success, error, cancel, medium); | |||
567 |
|
627 | |||
568 | bool queued; |
|
628 | bool queued; | |
569 |
|
629 | |||
@@ -834,7 +894,7 namespace Implab { | |||||
834 | else |
|
894 | else | |
835 | cancelHandler = medium.Cancel; |
|
895 | cancelHandler = medium.Cancel; | |
836 |
|
896 | |||
837 |
Add |
|
897 | AddMappers( | |
838 | resultHandler, |
|
898 | resultHandler, | |
839 | errorHandler, |
|
899 | errorHandler, | |
840 | cancelHandler, |
|
900 | cancelHandler, |
General Comments 0
You need to be logged in to leave comments.
Login now