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