Mercurial > pub > ImplabNet
comparison Implab/AbstractPromise.cs @ 243:b1e0ffdf3451 v3
working on promises
| author | cin |
|---|---|
| date | Wed, 24 Jan 2018 19:24:10 +0300 |
| parents | cbe10ac0731e |
| children | eee3e49dd1ff |
comparison
equal
deleted
inserted
replaced
| 242:cbe10ac0731e | 243:b1e0ffdf3451 |
|---|---|
| 1 using System; | 1 using System; |
| 2 using System.Diagnostics; | |
| 3 using System.Reflection; | |
| 2 using Implab.Parallels; | 4 using Implab.Parallels; |
| 3 | 5 |
| 4 namespace Implab { | 6 namespace Implab { |
| 5 public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise { | 7 public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise { |
| 6 public class HandlerDescriptor { | 8 public class HandlerDescriptor { |
| 7 readonly Action m_handler; | 9 readonly Action m_resolve; |
| 8 readonly Action<Exception> m_error; | 10 readonly Action<Exception> m_reject; |
| 11 | |
| 12 readonly IDeferred m_deferred; | |
| 9 public HandlerDescriptor(Action success, Action<Exception> error) { | 13 public HandlerDescriptor(Action success, Action<Exception> error) { |
| 10 m_handler = success; | 14 m_resolve = success; |
| 11 m_error = error; | 15 m_reject = error; |
| 12 } | 16 } |
| 13 | 17 |
| 14 public void SignalSuccess() { | 18 public void SignalSuccess() { |
| 15 if (m_handler != null) { | 19 try { |
| 16 try { | 20 if (m_resolve != null) |
| 17 m_handler(); | 21 m_resolve(); |
| 18 // Analysis disable once EmptyGeneralCatchClause | 22 m_deferred.Resolve(); |
| 19 } catch { | 23 } catch (Exception ex) { |
| 20 } | 24 m_deferred.Reject(ex); |
| 21 } | 25 } |
| 22 } | 26 } |
| 23 | 27 |
| 24 public void SignalError(Exception err) { | 28 public void SignalError(Exception err) { |
| 25 if (m_error != null) { | 29 if (m_reject != null) { |
| 26 try { | 30 try { |
| 27 m_error(err); | 31 m_reject(err); |
| 28 // Analysis disable once EmptyGeneralCatchClause | 32 m_deferred.Resolve(); |
| 29 } catch { | 33 } catch (Exception ex) { |
| 34 m_deferred.Reject(ex); | |
| 30 } | 35 } |
| 31 } | 36 } |
| 37 } | |
| 38 } | |
| 39 | |
| 40 PromiseState m_state; | |
| 41 | |
| 42 Exception m_error; | |
| 43 | |
| 44 public bool IsRejected { | |
| 45 get { | |
| 46 return m_state == PromiseState.Rejected; | |
| 47 } | |
| 48 } | |
| 49 | |
| 50 public bool IsResolved { | |
| 51 get { | |
| 52 return m_state == PromiseState.Resolved; | |
| 53 } | |
| 54 } | |
| 55 | |
| 56 public Exception RejectReason { | |
| 57 get { | |
| 58 return m_error; | |
| 32 } | 59 } |
| 33 } | 60 } |
| 34 | 61 |
| 35 | 62 |
| 36 #region implemented abstract members of AbstractPromise | 63 #region implemented abstract members of AbstractPromise |
| 37 | 64 |
| 38 protected override void SignalHandler(HandlerDescriptor handler, int signal) { | 65 protected override void SignalHandler(HandlerDescriptor handler) { |
| 39 switch (signal) { | 66 switch (m_state) { |
| 40 case SUCCEEDED_STATE: | 67 case PromiseState.Resolved: |
| 41 handler.SignalSuccess(); | 68 handler.SignalSuccess(); |
| 42 break; | 69 break; |
| 43 case REJECTED_STATE: | 70 case PromiseState.Rejected: |
| 44 handler.SignalError(RejectReason); | 71 handler.SignalError(RejectReason); |
| 45 break; | 72 break; |
| 46 default: | 73 default: |
| 47 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", signal)); | 74 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state)); |
| 48 } | 75 } |
| 49 } | 76 } |
| 50 | 77 |
| 51 protected override Signal GetFulfillSignal() { | 78 protected override Signal GetFulfillSignal() { |
| 52 var signal = new Signal(); | 79 var signal = new Signal(); |
| 54 return signal; | 81 return signal; |
| 55 } | 82 } |
| 56 | 83 |
| 57 #endregion | 84 #endregion |
| 58 | 85 |
| 86 protected void CompleteResolve() { | |
| 87 m_state = PromiseState.Resolved; | |
| 88 CompleteTransit(); | |
| 89 } | |
| 90 | |
| 59 public Type ResultType { | 91 public Type ResultType { |
| 60 get { | 92 get { |
| 61 return typeof(void); | 93 return typeof(void); |
| 62 } | 94 } |
| 95 } | |
| 96 | |
| 97 /// <summary> | |
| 98 /// Выполняет обещание, сообщая об ошибке | |
| 99 /// </summary> | |
| 100 /// <remarks> | |
| 101 /// Поскольку обещание должно работать в многопточной среде, при его выполнении сразу несколько потоков | |
| 102 /// могу вернуть ошибку, при этом только первая будет использована в качестве результата, остальные | |
| 103 /// будут проигнорированы. | |
| 104 /// </remarks> | |
| 105 /// <param name="error">Исключение возникшее при выполнении операции</param> | |
| 106 /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception> | |
| 107 protected void SetError(Exception error) { | |
| 108 if (BeginTransit()) { | |
| 109 m_error = error; | |
| 110 m_state = PromiseState.Rejected; | |
| 111 CompleteTransit(); | |
| 112 } else { | |
| 113 WaitTransition(); | |
| 114 if (m_state == PromiseState.Resolved) | |
| 115 throw new InvalidOperationException("The promise is already resolved"); | |
| 116 } | |
| 117 } | |
| 118 | |
| 119 protected void Rethrow() { | |
| 120 Debug.Assert(m_error != null); | |
| 121 if (m_error is OperationCanceledException) | |
| 122 throw new OperationCanceledException("Operation cancelled", m_error); | |
| 123 else | |
| 124 throw new TargetInvocationException(m_error); | |
| 63 } | 125 } |
| 64 | 126 |
| 65 public void On(Action success, Action<Exception> error) { | 127 public void On(Action success, Action<Exception> error) { |
| 66 AddHandler(new HandlerDescriptor(success, error)); | 128 AddHandler(new HandlerDescriptor(success, error)); |
| 67 } | 129 } |
| 70 throw new InvalidCastException(); | 132 throw new InvalidCastException(); |
| 71 } | 133 } |
| 72 | 134 |
| 73 public void Join() { | 135 public void Join() { |
| 74 WaitResult(-1); | 136 WaitResult(-1); |
| 137 if (IsRejected) | |
| 138 Rethrow(); | |
| 75 } | 139 } |
| 76 | 140 |
| 77 public void Join(int timeout) { | 141 public void Join(int timeout) { |
| 78 WaitResult(timeout); | 142 WaitResult(timeout); |
| 79 } | 143 } |
| 80 | |
| 81 protected void SetResult() { | |
| 82 if(BeginSetResult()) | |
| 83 EndSetResult(); | |
| 84 } | |
| 85 } | 144 } |
| 86 } | 145 } |
| 87 | 146 |
