Mercurial > pub > ImplabNet
comparison Implab/Promise.cs @ 138:f75cfa58e3d4 v2
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
| author | cin |
|---|---|
| date | Tue, 17 Feb 2015 18:16:26 +0300 |
| parents | 2573b562e328 |
| children | 8c0b95069066 |
comparison
equal
deleted
inserted
replaced
| 137:238e15580926 | 138:f75cfa58e3d4 |
|---|---|
| 5 public class Promise : AbstractPromise<Promise.HandlerDescriptor>, IPromise, IDeferred { | 5 public class Promise : AbstractPromise<Promise.HandlerDescriptor>, IPromise, IDeferred { |
| 6 | 6 |
| 7 public struct HandlerDescriptor { | 7 public struct HandlerDescriptor { |
| 8 readonly Action m_success; | 8 readonly Action m_success; |
| 9 readonly Action<Exception> m_error; | 9 readonly Action<Exception> m_error; |
| 10 readonly Action m_cancel; | 10 readonly Action<Exception> m_cancel; |
| 11 readonly IDeferred m_deferred; | 11 readonly IDeferred m_deferred; |
| 12 | 12 |
| 13 public HandlerDescriptor(Action success, Action<Exception> error, Action cancel, IDeferred deferred) { | 13 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel, IDeferred deferred) { |
| 14 m_success = success; | 14 m_success = success; |
| 15 m_error = error; | 15 m_error = error; |
| 16 m_cancel = cancel; | 16 m_cancel = cancel; |
| 17 m_deferred = deferred; | 17 m_deferred = deferred; |
| 18 } | 18 } |
| 43 if (m_deferred != null) | 43 if (m_deferred != null) |
| 44 m_deferred.Reject(err); | 44 m_deferred.Reject(err); |
| 45 } | 45 } |
| 46 } | 46 } |
| 47 | 47 |
| 48 public void SignalCancel() { | 48 public void SignalCancel(Exception reason) { |
| 49 if (m_cancel != null) { | 49 if (m_cancel != null) { |
| 50 try { | 50 try { |
| 51 m_cancel(); | 51 m_cancel(reason); |
| 52 if (m_deferred != null) | 52 if (m_deferred != null) |
| 53 m_deferred.Resolve(); | 53 m_deferred.Resolve(); |
| 54 } catch (Exception err) { | 54 } catch (Exception err) { |
| 55 SignalError(err); | 55 SignalError(err); |
| 56 } | 56 } |
| 57 } else if (reason != null && m_error != null) { | |
| 58 try { | |
| 59 m_error(new OperationCanceledException("The operation was canceled.", reason)); | |
| 60 if (m_deferred != null) | |
| 61 m_deferred.Resolve(); | |
| 62 } catch (Exception err) { | |
| 63 SignalError(err); | |
| 64 } | |
| 57 } else { | 65 } else { |
| 58 if (m_deferred != null) | 66 if (m_deferred != null) |
| 59 m_deferred.Cancel(); | 67 m_deferred.Cancel(reason); |
| 60 } | 68 } |
| 61 } | 69 } |
| 62 } | 70 } |
| 63 | 71 |
| 64 public void Resolve() { | 72 public void Resolve() { |
| 78 | 86 |
| 79 protected override void SignalError(HandlerDescriptor handler, Exception error) { | 87 protected override void SignalError(HandlerDescriptor handler, Exception error) { |
| 80 handler.SignalError(error); | 88 handler.SignalError(error); |
| 81 } | 89 } |
| 82 | 90 |
| 83 protected override void SignalCancelled(HandlerDescriptor handler) { | 91 protected override void SignalCancelled(HandlerDescriptor handler, Exception reason) { |
| 84 handler.SignalCancel(); | 92 handler.SignalCancel(reason); |
| 85 } | 93 } |
| 86 | 94 |
| 87 protected override void Listen(PromiseEventType events, Action handler) { | 95 protected override void Listen(PromiseEventType events, Action handler) { |
| 88 AddHandler(new HandlerDescriptor( | 96 AddHandler(new HandlerDescriptor( |
| 89 events.HasFlag(PromiseEventType.Success) ? handler : null, | 97 events.HasFlag(PromiseEventType.Success) ? handler : null, |
| 90 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null, | 98 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null, |
| 91 events.HasFlag(PromiseEventType.Cancelled) ? handler : null, | 99 events.HasFlag(PromiseEventType.Cancelled) ? new Action<Exception>(reason => handler()) : null, |
| 92 null | 100 null |
| 93 )); | 101 )); |
| 94 } | 102 } |
| 95 | 103 |
| 96 #endregion | 104 #endregion |
| 100 get { | 108 get { |
| 101 return typeof(void); | 109 return typeof(void); |
| 102 } | 110 } |
| 103 } | 111 } |
| 104 | 112 |
| 105 public IPromise Then(Action success, Action<Exception> error, Action cancel) { | 113 public IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel) { |
| 106 var promise = new Promise(); | 114 var promise = new Promise(); |
| 107 if (success != null) | 115 if (success != null) |
| 108 promise.On(Cancel, PromiseEventType.Cancelled); | 116 promise.On(Cancel, PromiseEventType.Cancelled); |
| 109 | 117 |
| 110 AddHandler(new HandlerDescriptor(success, error, cancel, promise)); | 118 AddHandler(new HandlerDescriptor(success, error, cancel, promise)); |
| 118 | 126 |
| 119 public IPromise Then(Action success) { | 127 public IPromise Then(Action success) { |
| 120 return Then(success, null, null); | 128 return Then(success, null, null); |
| 121 } | 129 } |
| 122 | 130 |
| 123 public IPromise On(Action success, Action<Exception> error, Action cancel) { | 131 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) { |
| 124 AddHandler(new HandlerDescriptor(success, error, cancel, null)); | 132 AddHandler(new HandlerDescriptor(success, error, cancel, null)); |
| 125 return this; | 133 return this; |
| 126 } | 134 } |
| 127 | 135 |
| 128 public IPromise On(Action success, Action<Exception> error) { | 136 public IPromise On(Action success, Action<Exception> error) { |
| 135 | 143 |
| 136 public IPromise On(Action handler, PromiseEventType events) { | 144 public IPromise On(Action handler, PromiseEventType events) { |
| 137 return On( | 145 return On( |
| 138 events.HasFlag(PromiseEventType.Success) ? handler : null, | 146 events.HasFlag(PromiseEventType.Success) ? handler : null, |
| 139 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null, | 147 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null, |
| 140 events.HasFlag(PromiseEventType.Cancelled) ? handler : null | 148 events.HasFlag(PromiseEventType.Cancelled) ? new Action<Exception>(reason => handler()) : null |
| 141 ); | 149 ); |
| 142 } | 150 } |
| 143 | 151 |
| 144 public IPromise<T> Cast<T>() { | 152 public IPromise<T> Cast<T>() { |
| 145 throw new InvalidCastException(); | 153 throw new InvalidCastException(); |
| 146 } | 154 } |
| 147 | 155 |
| 148 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<IPromise> cancel) { | 156 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception,IPromise> cancel) { |
| 149 var medium = new Promise(); | 157 var medium = new Promise(); |
| 150 | 158 |
| 151 On( | 159 On( |
| 152 () => { | 160 () => { |
| 153 if (medium.IsCancelled) | 161 if (medium.IsCancelled) |
| 166 } | 174 } |
| 167 } else { | 175 } else { |
| 168 medium.Reject(ex); | 176 medium.Reject(ex); |
| 169 } | 177 } |
| 170 }, | 178 }, |
| 171 () => { | 179 reason => { |
| 172 if (medium.IsCancelled) | 180 if (medium.IsCancelled) |
| 173 return; | 181 return; |
| 174 if (cancel != null) | 182 if (cancel != null) |
| 175 ConnectPromise(cancel(), medium); | 183 ConnectPromise(cancel(reason), medium); |
| 176 else | 184 else |
| 177 medium.Cancel(); | 185 medium.Cancel(reason); |
| 178 } | 186 } |
| 179 ); | 187 ); |
| 180 | 188 |
| 181 if (chained != null) | 189 if (chained != null) |
| 182 medium.On(Cancel, PromiseEventType.Cancelled); | 190 medium.On(Cancel, PromiseEventType.Cancelled); |
| 187 static void ConnectPromise(IPromise result, Promise medium) { | 195 static void ConnectPromise(IPromise result, Promise medium) { |
| 188 if (result != null) { | 196 if (result != null) { |
| 189 result.On( | 197 result.On( |
| 190 medium.Resolve, | 198 medium.Resolve, |
| 191 medium.Reject, | 199 medium.Reject, |
| 192 () => medium.Reject(new OperationCanceledException()) | 200 medium.Cancel |
| 193 ); | 201 ); |
| 194 medium.On(result.Cancel, PromiseEventType.Cancelled); | 202 medium.On(null,null,result.Cancel); |
| 195 } else { | 203 } else { |
| 196 medium.Reject( | 204 medium.Reject( |
| 197 new NullReferenceException( | 205 new NullReferenceException( |
| 198 "The chained asynchronous operation returned" + | 206 "The chained asynchronous operation returned" + |
| 199 " 'null' where the promise instance is expected" | 207 " 'null' where the promise instance is expected" |
| 207 } | 215 } |
| 208 | 216 |
| 209 public IPromise Chain(Func<IPromise> chained) { | 217 public IPromise Chain(Func<IPromise> chained) { |
| 210 return Chain(chained, null, null); | 218 return Chain(chained, null, null); |
| 211 } | 219 } |
| 212 | |
| 213 public IPromise Error(Action<Exception> error) { | |
| 214 var promise = new Promise(); | |
| 215 On( | |
| 216 null, | |
| 217 err => { | |
| 218 if (error != null) | |
| 219 try { | |
| 220 error(err); | |
| 221 promise.Resolve(); | |
| 222 } catch (Exception err2) { | |
| 223 promise.Reject(err2); | |
| 224 } | |
| 225 else | |
| 226 promise.Reject(err); | |
| 227 } | |
| 228 ); | |
| 229 | |
| 230 return promise; | |
| 231 } | |
| 232 | |
| 233 public IPromise Cancelled(Action handler) { | |
| 234 var promise = new Promise(); | |
| 235 On( | |
| 236 null, | |
| 237 null, | |
| 238 () => { | |
| 239 if (handler != null) { | |
| 240 try { | |
| 241 handler(); | |
| 242 promise.Resolve(); | |
| 243 } catch (Exception err) { | |
| 244 promise.Reject(err); | |
| 245 } | |
| 246 } else { | |
| 247 promise.Cancel(); | |
| 248 } | |
| 249 } | |
| 250 ); | |
| 251 | |
| 252 return promise; | |
| 253 } | |
| 254 | |
| 255 | |
| 256 } | 220 } |
| 257 } | 221 } |
| 258 | 222 |
