Mercurial > pub > ImplabNet
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) |
