@@ -48,14 +48,14 namespace Implab { | |||
|
48 | 48 | public abstract void Cancel(); |
|
49 | 49 | } |
|
50 | 50 | |
|
51 |
protected class |
|
|
51 | protected class RemapDescriptor<T2> : AbstractHandler { | |
|
52 | 52 | |
|
53 | 53 | readonly Func<T,T2> m_resultHandler; |
|
54 | 54 | readonly Func<Exception,T2> m_errorHandler; |
|
55 | 55 | readonly Action m_cancellHandler; |
|
56 | 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 | 59 | m_resultHandler = resultHandler; |
|
60 | 60 | m_errorHandler = errorHandler; |
|
61 | 61 | m_cancellHandler = cancelHandler; |
@@ -82,9 +82,61 namespace Implab { | |||
|
82 | 82 | var res = m_errorHandler(error); |
|
83 | 83 | if (m_medium != null) |
|
84 | 84 | m_medium.Resolve(res); |
|
85 |
|
|
|
86 | if (medium != null) | |
|
87 |
|
|
|
85 | } catch (Exception err2) { | |
|
86 | if (m_medium != null) | |
|
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 | 140 | } catch (Exception err2) { |
|
89 | 141 | if (m_medium != null) |
|
90 | 142 | m_medium.Reject(err2); |
@@ -126,7 +178,7 namespace Implab { | |||
|
126 | 178 | |
|
127 | 179 | public Promise(IPromise parent) { |
|
128 | 180 | if (parent != null) |
|
129 |
Add |
|
|
181 | AddMappers<T>( | |
|
130 | 182 | null, |
|
131 | 183 | null, |
|
132 | 184 | () => { |
@@ -252,43 +304,28 namespace Implab { | |||
|
252 | 304 | if (success == null && error == null && cancel == null) |
|
253 | 305 | return; |
|
254 | 306 | |
|
255 | AddHandler( | |
|
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 | ); | |
|
307 | AddHandler(success, error, cancel, null, false); | |
|
268 | 308 | } |
|
269 | 309 | |
|
270 | 310 | public void On(Action<T> success, Action<Exception> error) { |
|
271 |
|
|
|
311 | AddHandler(success, error, null, null, false); | |
|
272 | 312 | } |
|
273 | 313 | |
|
274 | 314 | public void On(Action<T> success) { |
|
275 |
|
|
|
315 | AddHandler(success, null, null, null, false); | |
|
276 | 316 | } |
|
277 | 317 | |
|
278 | 318 | public void On(Action handler, PromiseEventType events) { |
|
279 | 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 | 331 | public IPromise Error(Action<Exception> error) { |
@@ -297,7 +334,7 namespace Implab { | |||
|
297 | 334 | |
|
298 | 335 | var medium = new Promise<T>(this); |
|
299 | 336 | |
|
300 |
Add |
|
|
337 | AddMappers( | |
|
301 | 338 | null, |
|
302 | 339 | e => { |
|
303 | 340 | error(e); |
@@ -325,7 +362,7 namespace Implab { | |||
|
325 | 362 | |
|
326 | 363 | var medium = new Promise<T>(this); |
|
327 | 364 | |
|
328 |
Add |
|
|
365 | AddMappers(null, handler, null, medium, true); | |
|
329 | 366 | |
|
330 | 367 | return medium; |
|
331 | 368 | } |
@@ -345,7 +382,7 namespace Implab { | |||
|
345 | 382 | // ΡΠΎΠ·Π΄Π°Π΅ΠΌ ΠΏΡΠΈΡΠ΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠ΅ |
|
346 | 383 | var medium = new Promise<TNew>(this); |
|
347 | 384 | |
|
348 |
Add |
|
|
385 | AddMappers( | |
|
349 | 386 | mapper, |
|
350 | 387 | error, |
|
351 | 388 | cancel, |
@@ -454,7 +491,7 namespace Implab { | |||
|
454 | 491 | else |
|
455 | 492 | cancelHandler = medium.Cancel; |
|
456 | 493 | |
|
457 |
Add |
|
|
494 | AddMappers( | |
|
458 | 495 | resultHandler, |
|
459 | 496 | errorHandler, |
|
460 | 497 | cancelHandler, |
@@ -490,10 +527,7 namespace Implab { | |||
|
490 | 527 | var medium = new Promise<T>(this); |
|
491 | 528 | |
|
492 | 529 | AddHandler( |
|
493 |
x => |
|
|
494 | handler(); | |
|
495 | return x; | |
|
496 | }, | |
|
530 | x => handler(), | |
|
497 | 531 | e => { |
|
498 | 532 | handler(); |
|
499 | 533 | throw new TransientPromiseException(e); |
@@ -559,11 +593,37 namespace Implab { | |||
|
559 | 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 | 597 | if (inc) |
|
564 | 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 | 628 | bool queued; |
|
569 | 629 | |
@@ -834,7 +894,7 namespace Implab { | |||
|
834 | 894 | else |
|
835 | 895 | cancelHandler = medium.Cancel; |
|
836 | 896 | |
|
837 |
Add |
|
|
897 | AddMappers( | |
|
838 | 898 | resultHandler, |
|
839 | 899 | errorHandler, |
|
840 | 900 | cancelHandler, |
General Comments 0
You need to be logged in to leave comments.
Login now