Mercurial > pub > ImplabNet
comparison Implab/Promise.cs @ 107:f5220e5472ef v2
minor fixes and optimizations
author | cin |
---|---|
date | Tue, 11 Nov 2014 04:14:21 +0300 |
parents | d4e38929ce36 |
children | 38d6a4db35d7 |
comparison
equal
deleted
inserted
replaced
106:d4e38929ce36 | 107:f5220e5472ef |
---|---|
46 public abstract void Resolve(T result); | 46 public abstract void Resolve(T result); |
47 public abstract void Reject(Exception error); | 47 public abstract void Reject(Exception error); |
48 public abstract void Cancel(); | 48 public abstract void Cancel(); |
49 } | 49 } |
50 | 50 |
51 protected class HandlerDescriptor<T2> : AbstractHandler { | 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 HandlerDescriptor(Func<T,T2> resultHandler, Func<Exception,T2> errorHandler, Action cancelHandler, Promise<T2> medium) { | 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; |
62 m_medium = medium; | 62 m_medium = medium; |
63 } | 63 } |
80 if (m_errorHandler != null) { | 80 if (m_errorHandler != null) { |
81 try { | 81 try { |
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 /*} catch (TransientPromiseException err2) { | |
86 if (medium != null) | |
87 medium.Reject(err2.InnerException);*/ | |
88 } catch (Exception err2) { | 85 } catch (Exception err2) { |
89 if (m_medium != null) | 86 if (m_medium != null) |
90 m_medium.Reject(err2); | 87 m_medium.Reject(err2); |
91 } | 88 } |
92 } else if (m_medium != null) | 89 } else if (m_medium != null) |
105 if (m_medium != null) | 102 if (m_medium != null) |
106 m_medium.Cancel(); | 103 m_medium.Cancel(); |
107 } | 104 } |
108 } | 105 } |
109 | 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)); | |
140 } catch (Exception err2) { | |
141 if (m_medium != null) | |
142 m_medium.Reject(err2); | |
143 } | |
144 } else if (m_medium != null) | |
145 m_medium.Reject(error); | |
146 } | |
147 | |
148 public override void Cancel() { | |
149 if (m_cancellHandler != null) { | |
150 try { | |
151 m_cancellHandler(); | |
152 } catch (Exception err) { | |
153 Reject(err); | |
154 return; | |
155 } | |
156 } | |
157 if (m_medium != null) | |
158 m_medium.Cancel(); | |
159 } | |
160 } | |
161 | |
110 const int UNRESOLVED_SATE = 0; | 162 const int UNRESOLVED_SATE = 0; |
111 const int TRANSITIONAL_STATE = 1; | 163 const int TRANSITIONAL_STATE = 1; |
112 const int SUCCEEDED_STATE = 2; | 164 const int SUCCEEDED_STATE = 2; |
113 const int REJECTED_STATE = 3; | 165 const int REJECTED_STATE = 3; |
114 const int CANCELLED_STATE = 4; | 166 const int CANCELLED_STATE = 4; |
124 public Promise() { | 176 public Promise() { |
125 } | 177 } |
126 | 178 |
127 public Promise(IPromise parent) { | 179 public Promise(IPromise parent) { |
128 if (parent != null) | 180 if (parent != null) |
129 AddHandler<T>( | 181 AddMappers<T>( |
130 null, | 182 null, |
131 null, | 183 null, |
132 () => { | 184 () => { |
133 if (parent.IsExclusive) | 185 if (parent.IsExclusive) |
134 parent.Cancel(); | 186 parent.Cancel(); |
250 /// </remarks> | 302 /// </remarks> |
251 public void On(Action<T> success, Action<Exception> error, Action cancel) { | 303 public void On(Action<T> success, Action<Exception> error, Action cancel) { |
252 if (success == null && error == null && cancel == null) | 304 if (success == null && error == null && cancel == null) |
253 return; | 305 return; |
254 | 306 |
307 AddHandler(success, error, cancel, null, false); | |
308 } | |
309 | |
310 public void On(Action<T> success, Action<Exception> error) { | |
311 AddHandler(success, error, null, null, false); | |
312 } | |
313 | |
314 public void On(Action<T> success) { | |
315 AddHandler(success, null, null, null, false); | |
316 } | |
317 | |
318 public void On(Action handler, PromiseEventType events) { | |
319 Safe.ArgumentNotNull(handler, "handler"); | |
320 | |
321 | |
255 AddHandler( | 322 AddHandler( |
256 success != null ? new Func<T,T>(x => { | 323 events.HasFlag(PromiseEventType.Success) ? new Action<T>(x => handler()) : null, |
257 success(x); | 324 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>( x => handler()) : null, |
258 return x; | 325 events.HasFlag(PromiseEventType.Cancelled) ? handler : null, |
259 }) : null, | |
260 error != null ? new Func<Exception,T>(e => { | |
261 error(e); | |
262 return default(T); | |
263 }) : null, | |
264 cancel, | |
265 null, | 326 null, |
266 false | 327 false |
267 ); | 328 ); |
268 } | 329 } |
269 | 330 |
270 public void On(Action<T> success, Action<Exception> error) { | |
271 On(success, error, null); | |
272 } | |
273 | |
274 public void On(Action<T> success) { | |
275 On(success, null, null); | |
276 } | |
277 | |
278 public void On(Action handler, PromiseEventType events) { | |
279 Safe.ArgumentNotNull(handler, "handler"); | |
280 | |
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 | |
291 AddHandler(success, error, cancel, null, false); | |
292 } | |
293 | |
294 public IPromise Error(Action<Exception> error) { | 331 public IPromise Error(Action<Exception> error) { |
295 if (error == null) | 332 if (error == null) |
296 return this; | 333 return this; |
297 | 334 |
298 var medium = new Promise<T>(this); | 335 var medium = new Promise<T>(this); |
299 | 336 |
300 AddHandler( | 337 AddMappers( |
301 null, | 338 null, |
302 e => { | 339 e => { |
303 error(e); | 340 error(e); |
304 return default(T); | 341 return default(T); |
305 }, | 342 }, |
323 if (handler == null) | 360 if (handler == null) |
324 return this; | 361 return this; |
325 | 362 |
326 var medium = new Promise<T>(this); | 363 var medium = new Promise<T>(this); |
327 | 364 |
328 AddHandler(null, handler, null, medium, true); | 365 AddMappers(null, handler, null, medium, true); |
329 | 366 |
330 return medium; | 367 return medium; |
331 } | 368 } |
332 | 369 |
333 /// <summary> | 370 /// <summary> |
343 Safe.ArgumentNotNull(mapper, "mapper"); | 380 Safe.ArgumentNotNull(mapper, "mapper"); |
344 | 381 |
345 // создаем прицепленное обещание | 382 // создаем прицепленное обещание |
346 var medium = new Promise<TNew>(this); | 383 var medium = new Promise<TNew>(this); |
347 | 384 |
348 AddHandler( | 385 AddMappers( |
349 mapper, | 386 mapper, |
350 error, | 387 error, |
351 cancel, | 388 cancel, |
352 medium, | 389 medium, |
353 true | 390 true |
452 medium.Cancel(); | 489 medium.Cancel(); |
453 }; | 490 }; |
454 else | 491 else |
455 cancelHandler = medium.Cancel; | 492 cancelHandler = medium.Cancel; |
456 | 493 |
457 AddHandler( | 494 AddMappers( |
458 resultHandler, | 495 resultHandler, |
459 errorHandler, | 496 errorHandler, |
460 cancelHandler, | 497 cancelHandler, |
461 null, | 498 null, |
462 true | 499 true |
488 Safe.ArgumentNotNull(handler, "handler"); | 525 Safe.ArgumentNotNull(handler, "handler"); |
489 | 526 |
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); |
500 }, | 534 }, |
501 handler, | 535 handler, |
557 | 591 |
558 public T Join() { | 592 public T Join() { |
559 return Join(Timeout.Infinite); | 593 return Join(Timeout.Infinite); |
560 } | 594 } |
561 | 595 |
562 void AddHandler<T2>(Func<T,T2> success, Func<Exception,T2> error, Action cancel, Promise<T2> medium, bool inc) { | 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 HandlerDescriptor<T2>(success, error, cancel, medium); | 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 |
570 if (!IsResolved) { | 630 if (!IsResolved) { |
571 m_handlers.Enqueue(handler); | 631 m_handlers.Enqueue(handler); |
832 medium.Cancel(); | 892 medium.Cancel(); |
833 }; | 893 }; |
834 else | 894 else |
835 cancelHandler = medium.Cancel; | 895 cancelHandler = medium.Cancel; |
836 | 896 |
837 AddHandler( | 897 AddMappers( |
838 resultHandler, | 898 resultHandler, |
839 errorHandler, | 899 errorHandler, |
840 cancelHandler, | 900 cancelHandler, |
841 null, | 901 null, |
842 true | 902 true |