comparison Implab/Promise.cs @ 106:d4e38929ce36 v2

promises refactoring
author cin
date Mon, 10 Nov 2014 18:00:28 +0300
parents 4d308952fd5e
children f5220e5472ef
comparison
equal deleted inserted replaced
105:4d308952fd5e 106:d4e38929ce36
40 /// только инициатор обещания иначе могут возникнуть противоречия. 40 /// только инициатор обещания иначе могут возникнуть противоречия.
41 /// </para> 41 /// </para>
42 /// </remarks> 42 /// </remarks>
43 public class Promise<T> : IPromise<T> { 43 public class Promise<T> : IPromise<T> {
44 44
45 protected struct HandlerDescriptor { 45 protected abstract class AbstractHandler : MTCustomQueueNode<AbstractHandler> {
46 public Action<T> resultHandler; 46 public abstract void Resolve(T result);
47 public Func<Exception,T> errorHandler; 47 public abstract void Reject(Exception error);
48 public Action cancellHandler; 48 public abstract void Cancel();
49 public Promise<T> medium; 49 }
50 50
51 public void Resolve(T result) { 51 protected class HandlerDescriptor<T2> : AbstractHandler {
52 if (resultHandler != null) { 52
53 readonly Func<T,T2> m_resultHandler;
54 readonly Func<Exception,T2> m_errorHandler;
55 readonly Action m_cancellHandler;
56 readonly Promise<T2> m_medium;
57
58 public HandlerDescriptor(Func<T,T2> resultHandler, Func<Exception,T2> errorHandler, Action cancelHandler, Promise<T2> medium) {
59 m_resultHandler = resultHandler;
60 m_errorHandler = errorHandler;
61 m_cancellHandler = cancelHandler;
62 m_medium = medium;
63 }
64
65 public override void Resolve(T result) {
66 if (m_resultHandler != null) {
53 try { 67 try {
54 resultHandler(result); 68 if (m_medium != null)
69 m_medium.Resolve(m_resultHandler(result));
70 else
71 m_resultHandler(result);
55 } catch (Exception e) { 72 } catch (Exception e) {
56 Reject(e); 73 Reject(e);
57 return;
58 } 74 }
59 } 75 } else if(m_medium != null)
60 if (medium != null) 76 m_medium.Resolve(default(T2));
61 medium.Resolve(result); 77 }
62 } 78
63 79 public override void Reject(Exception error) {
64 public void Reject(Exception err) { 80 if (m_errorHandler != null) {
65 if (errorHandler != null) {
66 try { 81 try {
67 var res = errorHandler(err); 82 var res = m_errorHandler(error);
68 if (medium != null) 83 if (m_medium != null)
69 medium.Resolve(res); 84 m_medium.Resolve(res);
70 /*} catch (TransientPromiseException err2) { 85 /*} catch (TransientPromiseException err2) {
71 if (medium != null) 86 if (medium != null)
72 medium.Reject(err2.InnerException);*/ 87 medium.Reject(err2.InnerException);*/
73 } catch (Exception err2) { 88 } catch (Exception err2) {
74 if (medium != null) 89 if (m_medium != null)
75 medium.Reject(err2); 90 m_medium.Reject(err2);
76 } 91 }
77 } else if (medium != null) 92 } else if (m_medium != null)
78 medium.Reject(err); 93 m_medium.Reject(error);
79 } 94 }
80 95
81 public void Cancel() { 96 public override void Cancel() {
82 if (cancellHandler != null) { 97 if (m_cancellHandler != null) {
83 try { 98 try {
84 cancellHandler(); 99 m_cancellHandler();
85 } catch (Exception err) { 100 } catch (Exception err) {
86 Reject(err); 101 Reject(err);
87 return; 102 return;
88 } 103 }
89 } 104 }
90 if (medium != null) 105 if (m_medium != null)
91 medium.Cancel(); 106 m_medium.Cancel();
92 } 107 }
93 } 108 }
94 109
95 const int UNRESOLVED_SATE = 0; 110 const int UNRESOLVED_SATE = 0;
96 const int TRANSITIONAL_STATE = 1; 111 const int TRANSITIONAL_STATE = 1;
101 int m_childrenCount; 116 int m_childrenCount;
102 int m_state; 117 int m_state;
103 T m_result; 118 T m_result;
104 Exception m_error; 119 Exception m_error;
105 120
106 readonly MTQueue<HandlerDescriptor> m_handlers = new MTQueue<HandlerDescriptor>(); 121 readonly MTCustomQueue<AbstractHandler> m_handlers = new MTCustomQueue<AbstractHandler>();
122 //readonly MTQueue<AbstractHandler> m_handlers = new MTQueue<AbstractHandler>();
107 123
108 public Promise() { 124 public Promise() {
109 } 125 }
110 126
111 public Promise(IPromise parent) { 127 public Promise(IPromise parent) {
112 if (parent != null) 128 if (parent != null)
113 AddHandler( 129 AddHandler<T>(
114 null, 130 null,
115 null, 131 null,
116 () => { 132 () => {
117 if (parent.IsExclusive) 133 if (parent.IsExclusive)
118 parent.Cancel(); 134 parent.Cancel();
211 public void Cancel() { 227 public void Cancel() {
212 if (BeginTransit()) { 228 if (BeginTransit()) {
213 CompleteTransit(CANCELLED_STATE); 229 CompleteTransit(CANCELLED_STATE);
214 OnStateChanged(); 230 OnStateChanged();
215 } 231 }
216 }
217
218 public IPromise<T> Then(Action<T> success, Func<Exception,T> error, Action cancel) {
219 if (success == null && error == null && cancel == null)
220 return this;
221
222 var medium = new Promise<T>(this);
223
224 AddHandler(success, error, cancel, medium, true);
225
226 return medium;
227 }
228
229 /// <summary>
230 /// Adds new handlers to this promise.
231 /// </summary>
232 /// <param name="success">The handler of the successfully completed operation.
233 /// This handler will recieve an operation result as a parameter.</param>
234 /// <param name="error">Handles an exception that may occur during the operation and returns the value which will be used as the result of the operation.</param>
235 /// <returns>The new promise chained to this one.</returns>
236 public IPromise<T> Then(Action<T> success, Func<Exception,T> error) {
237 if (success == null && error == null)
238 return this;
239
240 var medium = new Promise<T>(this);
241
242 AddHandler(success, error, null, medium, true);
243
244 return medium;
245 }
246
247
248
249
250 public IPromise<T> Then(Action<T> success) {
251 if (success == null)
252 return this;
253
254 var medium = new Promise<T>(this);
255
256 AddHandler(success, null, null, medium, true);
257
258 return medium;
259 } 232 }
260 233
261 /// <summary> 234 /// <summary>
262 /// Последний обработчик в цепочки обещаний. 235 /// Последний обработчик в цепочки обещаний.
263 /// </summary> 236 /// </summary>
277 /// </remarks> 250 /// </remarks>
278 public void On(Action<T> success, Action<Exception> error, Action cancel) { 251 public void On(Action<T> success, Action<Exception> error, Action cancel) {
279 if (success == null && error == null && cancel == null) 252 if (success == null && error == null && cancel == null)
280 return; 253 return;
281 254
282 Func<Exception,T> errorHandler = null; 255 AddHandler(
283 if (error != null) 256 success != null ? new Func<T,T>(x => {
284 errorHandler = err => { 257 success(x);
285 error(err); 258 return x;
286 return default(T); 259 }) : null,
287 }; 260 error != null ? new Func<Exception,T>(e => {
288 AddHandler(success, errorHandler, cancel, null, false); 261 error(e);
262 return default(T);
263 }) : null,
264 cancel,
265 null,
266 false
267 );
289 } 268 }
290 269
291 public void On(Action<T> success, Action<Exception> error) { 270 public void On(Action<T> success, Action<Exception> error) {
292 On(success, error, null); 271 On(success, error, null);
293 } 272 }
297 } 276 }
298 277
299 public void On(Action handler, PromiseEventType events) { 278 public void On(Action handler, PromiseEventType events) {
300 Safe.ArgumentNotNull(handler, "handler"); 279 Safe.ArgumentNotNull(handler, "handler");
301 280
302 Action<T> success = events.HasFlag(PromiseEventType.Success) ? new Action<T>(x => handler()) : null; 281 Func<T,T> success = events.HasFlag(PromiseEventType.Success) ? new Func<T,T>(x => {
282 handler();
283 return x;
284 }) : null;
303 Func<Exception,T> error = events.HasFlag(PromiseEventType.Error) ? new Func<Exception,T>(e => { 285 Func<Exception,T> error = events.HasFlag(PromiseEventType.Error) ? new Func<Exception,T>(e => {
304 handler(); 286 handler();
305 return default(T); 287 return default(T);
306 }) : null; 288 }) : null;
307 Action cancel = events.HasFlag(PromiseEventType.Cancelled) ? handler : null; 289 Action cancel = events.HasFlag(PromiseEventType.Cancelled) ? handler : null;
361 Safe.ArgumentNotNull(mapper, "mapper"); 343 Safe.ArgumentNotNull(mapper, "mapper");
362 344
363 // создаем прицепленное обещание 345 // создаем прицепленное обещание
364 var medium = new Promise<TNew>(this); 346 var medium = new Promise<TNew>(this);
365 347
366 Action<T> resultHandler = result => medium.Resolve(mapper(result));
367 Func<Exception,T> errorHandler;
368 if (error != null)
369 errorHandler = e => {
370 try {
371 medium.Resolve(error(e));
372 } catch (Exception e2) {
373 // в случае ошибки нужно передать исключение дальше по цепочке
374 medium.Reject(e2);
375 }
376 return default(T);
377 };
378 else
379 errorHandler = e => {
380 medium.Reject(e);
381 return default(T);
382 };
383
384 Action cancelHandler;
385 if (cancel != null)
386 cancelHandler = () => {
387 cancel();
388 medium.Cancel();
389 };
390 else
391 cancelHandler = medium.Cancel;
392
393
394 AddHandler( 348 AddHandler(
395 resultHandler, 349 mapper,
396 errorHandler, 350 error,
397 cancelHandler, 351 cancel,
398 null, 352 medium,
399 true 353 true
400 ); 354 );
401 355
402 return medium; 356 return medium;
403 } 357 }
429 // создать посредника, к которому будут подвызяваться следующие обработчики. 383 // создать посредника, к которому будут подвызяваться следующие обработчики.
430 // когда будет выполнена реальная асинхронная операция, она обратиться к посреднику, чтобы 384 // когда будет выполнена реальная асинхронная операция, она обратиться к посреднику, чтобы
431 // передать через него результаты работы. 385 // передать через него результаты работы.
432 var medium = new Promise<TNew>(this); 386 var medium = new Promise<TNew>(this);
433 387
434 Action<T> resultHandler = delegate(T result) { 388 Func<T,T> resultHandler = delegate(T result) {
435 if (medium.IsCancelled) 389 if (medium.IsCancelled)
436 return; 390 return default(T);
437 391
438 var promise = chained(result); 392 var promise = chained(result);
439 393
440 promise.On( 394 promise.On(
441 medium.Resolve, 395 medium.Resolve,
452 () => { 406 () => {
453 if (promise.IsExclusive) 407 if (promise.IsExclusive)
454 promise.Cancel(); 408 promise.Cancel();
455 } 409 }
456 ); 410 );
411
412 return default(T);
457 }; 413 };
458 414
459 Func<Exception,T> errorHandler; 415 Func<Exception,T> errorHandler;
460 416
461 if (error != null) 417 if (error != null)
532 Safe.ArgumentNotNull(handler, "handler"); 488 Safe.ArgumentNotNull(handler, "handler");
533 489
534 var medium = new Promise<T>(this); 490 var medium = new Promise<T>(this);
535 491
536 AddHandler( 492 AddHandler(
537 x => handler(), 493 x => {
494 handler();
495 return x;
496 },
538 e => { 497 e => {
539 handler(); 498 handler();
540 throw new TransientPromiseException(e); 499 throw new TransientPromiseException(e);
541 }, 500 },
542 handler, 501 handler,
598 557
599 public T Join() { 558 public T Join() {
600 return Join(Timeout.Infinite); 559 return Join(Timeout.Infinite);
601 } 560 }
602 561
603 void AddHandler(Action<T> success, Func<Exception,T> error, Action cancel, Promise<T> medium, bool inc) { 562 void AddHandler<T2>(Func<T,T2> success, Func<Exception,T2> error, Action cancel, Promise<T2> medium, bool inc) {
604 if (inc) 563 if (inc)
605 Interlocked.Increment(ref m_childrenCount); 564 Interlocked.Increment(ref m_childrenCount);
606 565
607 var handler = new HandlerDescriptor { 566 AbstractHandler handler = new HandlerDescriptor<T2>(success, error, cancel, medium);
608 resultHandler = success,
609 errorHandler = error,
610 cancellHandler = cancel,
611 medium = medium
612 };
613 567
614 bool queued; 568 bool queued;
615 569
616 if (!IsResolved) { 570 if (!IsResolved) {
617 m_handlers.Enqueue(handler); 571 m_handlers.Enqueue(handler);
629 // note that fetched handler may be not the one that we have added 583 // note that fetched handler may be not the one that we have added
630 // even we can fetch no handlers at all :) 584 // even we can fetch no handlers at all :)
631 InvokeHandler(handler); 585 InvokeHandler(handler);
632 } 586 }
633 587
634 protected virtual void InvokeHandler(HandlerDescriptor handler) { 588 protected virtual void InvokeHandler(AbstractHandler handler) {
635 switch (m_state) { 589 switch (m_state) {
636 case SUCCEEDED_STATE: 590 case SUCCEEDED_STATE:
637 handler.Resolve(m_result); 591 handler.Resolve(m_result);
638 break; 592 break;
639 case REJECTED_STATE: 593 case REJECTED_STATE:
647 return; 601 return;
648 } 602 }
649 } 603 }
650 604
651 void OnStateChanged() { 605 void OnStateChanged() {
652 HandlerDescriptor handler; 606 AbstractHandler handler;
653 while (m_handlers.TryDequeue(out handler)) 607 while (m_handlers.TryDequeue(out handler))
654 InvokeHandler(handler); 608 InvokeHandler(handler);
655 } 609 }
656 610
657 public bool IsExclusive { 611 public bool IsExclusive {
686 640
687 for (int i = 0; i < promises.Count; i++) { 641 for (int i = 0; i < promises.Count; i++) {
688 var dest = i; 642 var dest = i;
689 643
690 if (promises[i] != null) { 644 if (promises[i] != null) {
691 promises[i].Then( 645 promises[i].On(
692 x => { 646 x => {
693 result[dest] = x; 647 result[dest] = x;
694 if (Interlocked.Decrement(ref pending) == 0) 648 if (Interlocked.Decrement(ref pending) == 0)
695 promise.Resolve(result); 649 promise.Resolve(result);
696 }, 650 },
697 e => { 651 promise.Reject
698 promise.Reject(e);
699 return default(T);
700 }
701 ); 652 );
702 } else { 653 } else {
703 if (Interlocked.Decrement(ref pending) == 0) 654 if (Interlocked.Decrement(ref pending) == 0)
704 promise.Resolve(result); 655 promise.Resolve(result);
705 } 656 }
774 725
775 #region IPromiseBase explicit implementation 726 #region IPromiseBase explicit implementation
776 727
777 IPromise IPromise.Then(Action success, Action<Exception> error, Action cancel) { 728 IPromise IPromise.Then(Action success, Action<Exception> error, Action cancel) {
778 return Then( 729 return Then(
779 success != null ? new Action<T>(x => success()) : null, 730 success != null ? new Func<T,T>(x => {
731 success();
732 return x;
733 }) : null,
780 error != null ? new Func<Exception,T>(e => { 734 error != null ? new Func<Exception,T>(e => {
781 error(e); 735 error(e);
782 return default(T); 736 return default(T);
783 }) : null, 737 }) : null,
784 cancel 738 cancel
785 ); 739 );
786 } 740 }
787 741
788 IPromise IPromise.Then(Action success, Action<Exception> error) { 742 IPromise IPromise.Then(Action success, Action<Exception> error) {
789 return Then( 743 return Then(
790 success != null ? new Action<T>(x => success()) : null, 744 success != null ? new Func<T,T>(x => {
745 success();
746 return x;
747 }) : null,
791 error != null ? new Func<Exception,T>(e => { 748 error != null ? new Func<Exception,T>(e => {
792 error(e); 749 error(e);
793 return default(T); 750 return default(T);
794 }) : null 751 }) : null
795 ); 752 );
796 } 753 }
797 754
798 IPromise IPromise.Then(Action success) { 755 IPromise IPromise.Then(Action success) {
799 Safe.ArgumentNotNull(success, "success"); 756 Safe.ArgumentNotNull(success, "success");
800 return Then(x => success()); 757 return Then(x => {
758 success();
759 return x;
760 });
801 } 761 }
802 762
803 IPromise IPromise.Chain(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) { 763 IPromise IPromise.Chain(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) {
804 return ChainNoResult(chained, error, cancel); 764 return ChainNoResult(chained, error, cancel);
805 } 765 }
807 IPromise ChainNoResult(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) { 767 IPromise ChainNoResult(Func<IPromise> chained, Func<Exception,IPromise> error, Action cancel) {
808 Safe.ArgumentNotNull(chained, "chained"); 768 Safe.ArgumentNotNull(chained, "chained");
809 769
810 var medium = new Promise<object>(this); 770 var medium = new Promise<object>(this);
811 771
812 Action<T> resultHandler = delegate { 772 Func<T,T> resultHandler = delegate {
813 if (medium.IsCancelled) 773 if (medium.IsCancelled)
814 return; 774 return default(T);
815 775
816 var promise = chained(); 776 var promise = chained();
817 777
818 promise.On( 778 promise.On(
819 medium.Resolve, 779 medium.Resolve,
826 // зависит IsExclusive 786 // зависит IsExclusive
827 medium.Cancelled(() => { 787 medium.Cancelled(() => {
828 if (promise.IsExclusive) 788 if (promise.IsExclusive)
829 promise.Cancel(); 789 promise.Cancel();
830 }); 790 });
791
792 return default(T);
831 }; 793 };
832 794
833 Func<Exception,T> errorHandler; 795 Func<Exception,T> errorHandler;
834 796
835 if (error != null) 797 if (error != null)