Mercurial > pub > ImplabNet
comparison Implab/PromiseT.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 | 656815cb7147 |
| children | 8c0b95069066 |
comparison
equal
deleted
inserted
replaced
| 137:238e15580926 | 138:f75cfa58e3d4 |
|---|---|
| 37 /// только инициатор обещания иначе могут возникнуть противоречия. | 37 /// только инициатор обещания иначе могут возникнуть противоречия. |
| 38 /// </para> | 38 /// </para> |
| 39 /// </remarks> | 39 /// </remarks> |
| 40 public class Promise<T> : AbstractPromise<IDeferred<T>>, IPromise<T>, IDeferred<T> { | 40 public class Promise<T> : AbstractPromise<IDeferred<T>>, IPromise<T>, IDeferred<T> { |
| 41 | 41 |
| 42 class StubDeferred : IDeferred<T> { | 42 class StubDeferred : IDeferred, IDeferred<T> { |
| 43 public static readonly StubDeferred instance = new StubDeferred(); | 43 public static readonly StubDeferred instance = new StubDeferred(); |
| 44 | 44 |
| 45 StubDeferred() { | 45 StubDeferred() { |
| 46 } | 46 } |
| 47 | 47 |
| 48 #region IDeferred implementation | 48 #region IDeferred implementation |
| 49 | 49 |
| 50 public void Resolve(T value) { | 50 public void Resolve(T value) { |
| 51 } | 51 } |
| 52 | 52 |
| 53 public void Resolve() { | |
| 54 } | |
| 55 | |
| 53 public void Reject(Exception error) { | 56 public void Reject(Exception error) { |
| 54 } | 57 } |
| 55 | 58 |
| 56 #endregion | 59 #endregion |
| 57 | 60 |
| 58 #region ICancellable implementation | 61 #region ICancellable implementation |
| 59 | 62 |
| 60 public void Cancel() { | 63 public void Cancel() { |
| 64 } | |
| 65 | |
| 66 public void Cancel(Exception reason) { | |
| 61 } | 67 } |
| 62 | 68 |
| 63 #endregion | 69 #endregion |
| 64 | 70 |
| 65 | 71 |
| 66 } | 72 } |
| 67 | 73 |
| 68 class RemapDescriptor<T2> : IDeferred<T> { | 74 class RemapDescriptor<T2> : IDeferred<T> { |
| 69 readonly Func<T,T2> m_remap; | 75 readonly Func<T,T2> m_remap; |
| 70 readonly Func<Exception,T2> m_failed; | 76 readonly Func<Exception, T2> m_failed; |
| 71 readonly Func<T2> m_cancel; | 77 readonly Func<Exception, T2> m_cancel; |
| 72 readonly IDeferred<T2> m_deferred; | 78 readonly IDeferred<T2> m_deferred; |
| 73 | 79 |
| 74 public RemapDescriptor(Func<T,T2> remap, Func<Exception,T2> failed, Func<T2> cancel, IDeferred<T2> deferred ) { | 80 public RemapDescriptor(Func<T,T2> remap, Func<Exception,T2> failed, Func<Exception, T2> cancel, IDeferred<T2> deferred ) { |
| 75 Debug.Assert(deferred != null); | 81 Debug.Assert(deferred != null); |
| 76 m_remap = remap; | 82 m_remap = remap; |
| 77 m_failed = failed; | 83 m_failed = failed; |
| 78 m_cancel = cancel; | 84 m_cancel = cancel; |
| 79 m_deferred = deferred; | 85 m_deferred = deferred; |
| 108 | 114 |
| 109 #endregion | 115 #endregion |
| 110 | 116 |
| 111 #region ICancellable implementation | 117 #region ICancellable implementation |
| 112 | 118 |
| 119 public void Cancel(Exception reason) { | |
| 120 if (m_cancel != null) { | |
| 121 try { | |
| 122 m_deferred.Resolve(m_cancel(reason)); | |
| 123 } catch (Exception ex) { | |
| 124 Reject(ex); | |
| 125 } | |
| 126 } else { | |
| 127 m_deferred.Cancel(reason); | |
| 128 } | |
| 129 } | |
| 130 | |
| 113 public void Cancel() { | 131 public void Cancel() { |
| 114 if (m_cancel != null) { | 132 Cancel(null); |
| 115 try { | 133 } |
| 116 m_deferred.Resolve(m_cancel()); | |
| 117 } catch (Exception ex) { | |
| 118 Reject(ex); | |
| 119 } | |
| 120 } else { | |
| 121 m_deferred.Cancel(); | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 #endregion | 134 #endregion |
| 126 } | 135 } |
| 127 | 136 |
| 128 class ListenerDescriptor : IDeferred<T> { | 137 class ListenerDescriptor : IDeferred<T> { |
| 129 readonly Action m_handler; | 138 readonly Action m_handler; |
| 161 #endregion | 170 #endregion |
| 162 | 171 |
| 163 #region ICancellable implementation | 172 #region ICancellable implementation |
| 164 | 173 |
| 165 public void Cancel() { | 174 public void Cancel() { |
| 175 Cancel(null); | |
| 176 } | |
| 177 | |
| 178 public void Cancel(Exception reason) { | |
| 166 if (m_events.HasFlag(PromiseEventType.Cancelled)){ | 179 if (m_events.HasFlag(PromiseEventType.Cancelled)){ |
| 167 try { | 180 try { |
| 168 m_handler(); | 181 m_handler(); |
| 169 // Analysis disable once EmptyGeneralCatchClause | 182 // Analysis disable once EmptyGeneralCatchClause |
| 170 } catch { | 183 } catch { |
| 176 } | 189 } |
| 177 | 190 |
| 178 class ValueEventDescriptor : IDeferred<T> { | 191 class ValueEventDescriptor : IDeferred<T> { |
| 179 readonly Action<T> m_success; | 192 readonly Action<T> m_success; |
| 180 readonly Action<Exception> m_failed; | 193 readonly Action<Exception> m_failed; |
| 181 readonly Action m_cancelled; | 194 readonly Action<Exception> m_cancelled; |
| 182 readonly IDeferred<T> m_deferred; | 195 readonly IDeferred<T> m_deferred; |
| 183 | 196 |
| 184 public ValueEventDescriptor(Action<T> success, Action<Exception> failed, Action cancelled, IDeferred<T> deferred) { | 197 public ValueEventDescriptor(Action<T> success, Action<Exception> failed, Action<Exception> cancelled, IDeferred<T> deferred) { |
| 185 Debug.Assert(deferred != null); | 198 Debug.Assert(deferred != null); |
| 186 | 199 |
| 187 m_success = success; | 200 m_success = success; |
| 188 m_failed = failed; | 201 m_failed = failed; |
| 189 m_cancelled = cancelled; | 202 m_cancelled = cancelled; |
| 218 | 231 |
| 219 #endregion | 232 #endregion |
| 220 | 233 |
| 221 #region ICancellable implementation | 234 #region ICancellable implementation |
| 222 | 235 |
| 236 public void Cancel(Exception reason) { | |
| 237 if (m_cancelled != null) { | |
| 238 try { | |
| 239 m_cancelled(reason); | |
| 240 m_deferred.Resolve(default(T)); | |
| 241 } catch (Exception ex) { | |
| 242 Reject(ex); | |
| 243 } | |
| 244 } else { | |
| 245 m_deferred.Cancel(reason); | |
| 246 } | |
| 247 } | |
| 248 | |
| 223 public void Cancel() { | 249 public void Cancel() { |
| 224 if (m_cancelled != null) { | 250 Cancel(null); |
| 225 try { | |
| 226 m_cancelled(); | |
| 227 m_deferred.Resolve(default(T)); | |
| 228 } catch(Exception ex) { | |
| 229 Reject(ex); | |
| 230 } | |
| 231 } else { | |
| 232 m_deferred.Cancel(); | |
| 233 } | |
| 234 } | 251 } |
| 235 | 252 |
| 236 #endregion | 253 #endregion |
| 237 } | 254 } |
| 238 | 255 |
| 239 public class EventDescriptor : IDeferred<T> { | 256 public class EventDescriptor : IDeferred<T> { |
| 240 readonly Action m_success; | 257 readonly Action m_success; |
| 241 readonly Action<Exception> m_failed; | 258 readonly Action<Exception> m_failed; |
| 242 readonly Action m_cancelled; | 259 readonly Action<Exception> m_cancelled; |
| 243 readonly IDeferred<T> m_deferred; | 260 readonly IDeferred m_deferred; |
| 244 | 261 |
| 245 public EventDescriptor(Action success, Action<Exception> failed, Action cancelled, IDeferred<T> deferred) { | 262 public EventDescriptor(Action success, Action<Exception> failed, Action<Exception> cancelled, IDeferred deferred) { |
| 246 Debug.Assert(deferred != null); | 263 Debug.Assert(deferred != null); |
| 247 | 264 |
| 248 m_success = success; | 265 m_success = success; |
| 249 m_failed = failed; | 266 m_failed = failed; |
| 250 m_cancelled = cancelled; | 267 m_cancelled = cancelled; |
| 255 | 272 |
| 256 public void Resolve(T value) { | 273 public void Resolve(T value) { |
| 257 if (m_success != null) { | 274 if (m_success != null) { |
| 258 try { | 275 try { |
| 259 m_success(); | 276 m_success(); |
| 260 m_deferred.Resolve(value); | 277 m_deferred.Resolve(); |
| 261 } catch (Exception ex) { | 278 } catch (Exception ex) { |
| 262 Reject(ex); | 279 Reject(ex); |
| 263 } | 280 } |
| 264 } | 281 } |
| 265 } | 282 } |
| 266 | 283 |
| 267 public void Reject(Exception error) { | 284 public void Reject(Exception error) { |
| 268 if (m_failed != null) { | 285 if (m_failed != null) { |
| 269 try { | 286 try { |
| 270 m_failed(error); | 287 m_failed(error); |
| 271 m_deferred.Resolve(default(T)); | 288 m_deferred.Resolve(); |
| 272 }catch (Exception ex) | 289 } catch (Exception ex) { |
| 273 { | |
| 274 m_deferred.Reject(ex); | 290 m_deferred.Reject(ex); |
| 275 } | 291 } |
| 276 } else { | 292 } else { |
| 277 m_deferred.Reject(error); | 293 m_deferred.Reject(error); |
| 278 } | 294 } |
| 279 | |
| 280 } | 295 } |
| 281 | 296 |
| 282 #endregion | 297 #endregion |
| 283 | 298 |
| 284 #region ICancellable implementation | 299 #region ICancellable implementation |
| 285 | 300 |
| 301 public void Cancel(Exception reason) { | |
| 302 if (m_cancelled != null) { | |
| 303 try { | |
| 304 m_cancelled(reason); | |
| 305 m_deferred.Resolve(); | |
| 306 } catch (Exception ex) { | |
| 307 Reject(ex); | |
| 308 } | |
| 309 } else { | |
| 310 m_deferred.Cancel(reason); | |
| 311 } | |
| 312 } | |
| 313 | |
| 286 public void Cancel() { | 314 public void Cancel() { |
| 287 if (m_cancelled != null) { | 315 Cancel(null); |
| 288 try { | |
| 289 m_cancelled(); | |
| 290 m_deferred.Resolve(default(T)); | |
| 291 } catch (Exception ex) { | |
| 292 Reject(ex); | |
| 293 } | |
| 294 } else { | |
| 295 m_deferred.Cancel(); | |
| 296 } | |
| 297 } | 316 } |
| 298 | 317 |
| 299 #endregion | 318 #endregion |
| 300 } | 319 } |
| 301 | 320 |
| 325 public new T Join(int timeout) { | 344 public new T Join(int timeout) { |
| 326 WaitResult(timeout); | 345 WaitResult(timeout); |
| 327 return m_result; | 346 return m_result; |
| 328 } | 347 } |
| 329 | 348 |
| 330 public IPromise<T> On(Action<T> success, Action<Exception> error, Action cancel) { | 349 public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) { |
| 331 AddHandler(new ValueEventDescriptor(success, error, cancel, StubDeferred.instance)); | 350 AddHandler(new ValueEventDescriptor(success, error, cancel, StubDeferred.instance)); |
| 332 return this; | 351 return this; |
| 333 } | 352 } |
| 334 | 353 |
| 335 public IPromise<T> On(Action<T> success, Action<Exception> error) { | 354 public IPromise<T> On(Action<T> success, Action<Exception> error) { |
| 345 public IPromise<T> On(Action handler, PromiseEventType events) { | 364 public IPromise<T> On(Action handler, PromiseEventType events) { |
| 346 Listen(events, handler); | 365 Listen(events, handler); |
| 347 return this; | 366 return this; |
| 348 } | 367 } |
| 349 | 368 |
| 350 public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error, Func<T2> cancel) { | 369 public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error, Func<Exception, T2> cancel) { |
| 351 var promise = new Promise<T2>(); | 370 var promise = new Promise<T2>(); |
| 352 if (mapper != null) | 371 if (mapper != null) |
| 353 promise.On(Cancel, PromiseEventType.Cancelled); | 372 promise.On((Action)null, null, Cancel); |
| 354 AddHandler(new RemapDescriptor<T2>(mapper, error, cancel, promise)); | 373 AddHandler(new RemapDescriptor<T2>(mapper, error, cancel, promise)); |
| 355 return promise; | 374 return promise; |
| 356 } | 375 } |
| 357 | 376 |
| 358 public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error) { | 377 public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error) { |
| 359 var promise = new Promise<T2>(); | 378 var promise = new Promise<T2>(); |
| 360 if (mapper != null) | 379 if (mapper != null) |
| 361 promise.On(Cancel, PromiseEventType.Cancelled); | 380 promise.On((Action)null, null, Cancel); |
| 362 AddHandler(new RemapDescriptor<T2>(mapper, error, null, promise)); | 381 AddHandler(new RemapDescriptor<T2>(mapper, error, null, promise)); |
| 363 return promise; | 382 return promise; |
| 364 } | 383 } |
| 365 | 384 |
| 366 public IPromise<T2> Then<T2>(Func<T, T2> mapper) { | 385 public IPromise<T2> Then<T2>(Func<T, T2> mapper) { |
| 367 var promise = new Promise<T2>(); | 386 var promise = new Promise<T2>(); |
| 368 if (mapper != null) | 387 if (mapper != null) |
| 369 promise.On(Cancel, PromiseEventType.Cancelled); | 388 promise.On((Action)null, null, Cancel); |
| 370 AddHandler(new RemapDescriptor<T2>(mapper, null, null, promise)); | 389 AddHandler(new RemapDescriptor<T2>(mapper, null, null, promise)); |
| 371 return promise; | 390 return promise; |
| 372 } | 391 } |
| 373 | 392 |
| 374 public IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error, Func<IPromise<T2>> cancel) { | 393 public IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel) { |
| 375 // this promise will be resolved when an asyc operation is started | 394 // this promise will be resolved when an asyc operation is started |
| 376 var promise = new Promise<IPromise<T2>>(); | 395 var promise = new Promise<IPromise<T2>>(); |
| 377 | 396 |
| 378 AddHandler(new RemapDescriptor<IPromise<T2>>( | 397 AddHandler(new RemapDescriptor<IPromise<T2>>( |
| 379 chained, | 398 chained, |
| 402 static void ConnectPromise<T2>(IPromise<T2> result, Promise<T2> medium) { | 421 static void ConnectPromise<T2>(IPromise<T2> result, Promise<T2> medium) { |
| 403 if (result != null) { | 422 if (result != null) { |
| 404 result.On( | 423 result.On( |
| 405 medium.Resolve, | 424 medium.Resolve, |
| 406 medium.Reject, | 425 medium.Reject, |
| 407 () => medium.Reject(new OperationCanceledException()) | 426 medium.Cancel |
| 408 ); | 427 ); |
| 409 medium.On(result.Cancel, PromiseEventType.Cancelled); | 428 medium.On(result.Cancel, PromiseEventType.Cancelled); |
| 410 } else { | 429 } else { |
| 411 medium.Reject( | 430 medium.Reject( |
| 412 new NullReferenceException( | 431 new NullReferenceException( |
| 423 | 442 |
| 424 public IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained) { | 443 public IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained) { |
| 425 return Chain(chained, null, null); | 444 return Chain(chained, null, null); |
| 426 } | 445 } |
| 427 | 446 |
| 428 public IPromise<T2> Error<T2>(Func<Exception, T2> error) { | 447 public IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel) { |
| 429 var promise = new Promise<T2>(); | 448 var promise = new Promise(); |
| 430 if (error != null) | |
| 431 On( | |
| 432 (Action<T>)null, | |
| 433 ex => { | |
| 434 try { | |
| 435 promise.Resolve(error(ex)); | |
| 436 } catch (Exception ex2) { | |
| 437 promise.Reject(ex2); | |
| 438 } | |
| 439 } | |
| 440 ); | |
| 441 else | |
| 442 Listen(PromiseEventType.Error, () => promise.Resolve(default(T2))); | |
| 443 return promise; | |
| 444 } | |
| 445 | |
| 446 public IPromise<T2> Cancelled<T2>(Func<T2> handler) { | |
| 447 var promise = new Promise<T2>(); | |
| 448 if (handler != null) | |
| 449 On( | |
| 450 (Action<T>)null, | |
| 451 null, | |
| 452 () => { | |
| 453 try { | |
| 454 promise.Resolve(handler()); | |
| 455 } catch (Exception ex) { | |
| 456 promise.Reject(ex); | |
| 457 } | |
| 458 }); | |
| 459 else | |
| 460 Listen(PromiseEventType.Cancelled, () => promise.Resolve(default(T2))); | |
| 461 return promise; | |
| 462 } | |
| 463 | |
| 464 public IPromise Then(Action success, Action<Exception> error, Action cancel) { | |
| 465 var promise = new Promise<T>(); | |
| 466 if (success != null) | 449 if (success != null) |
| 467 promise.On(Cancel, PromiseEventType.Cancelled); | 450 promise.On(null, null, Cancel); |
| 468 | 451 |
| 469 AddHandler(new EventDescriptor(success, error, cancel, promise)); | 452 AddHandler(new EventDescriptor(success, error, cancel, promise)); |
| 470 | 453 |
| 471 return promise; | 454 return promise; |
| 472 } | 455 } |
| 477 | 460 |
| 478 public IPromise Then(Action success) { | 461 public IPromise Then(Action success) { |
| 479 return Then(success, null, null); | 462 return Then(success, null, null); |
| 480 } | 463 } |
| 481 | 464 |
| 482 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<IPromise> cancel) { | 465 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel) { |
| 483 var promise = new Promise<IPromise>(); | 466 var promise = new Promise<IPromise>(); |
| 484 | 467 |
| 485 AddHandler( | 468 AddHandler( |
| 486 new RemapDescriptor<IPromise>( | 469 new RemapDescriptor<IPromise>( |
| 487 x => chained(), | 470 x => chained(), |
| 491 ) | 474 ) |
| 492 ); | 475 ); |
| 493 | 476 |
| 494 var medium = new Promise(); | 477 var medium = new Promise(); |
| 495 if (chained != null) | 478 if (chained != null) |
| 496 medium.On(Cancel, PromiseEventType.Cancelled); | 479 medium.On(null, null, Cancel); |
| 497 | 480 |
| 498 promise.On( | 481 promise.On( |
| 499 result => ConnectPromise(result, medium), | 482 result => ConnectPromise(result, medium), |
| 500 medium.Reject, | 483 medium.Reject, |
| 501 medium.Cancel | 484 medium.Cancel |
| 507 static void ConnectPromise(IPromise result, Promise medium) { | 490 static void ConnectPromise(IPromise result, Promise medium) { |
| 508 if (result != null) { | 491 if (result != null) { |
| 509 result.On( | 492 result.On( |
| 510 medium.Resolve, | 493 medium.Resolve, |
| 511 medium.Reject, | 494 medium.Reject, |
| 512 () => medium.Reject(new OperationCanceledException()) | 495 medium.Cancel |
| 513 ); | 496 ); |
| 514 medium.On(result.Cancel, PromiseEventType.Cancelled); | 497 medium.On(null, null, result.Cancel); |
| 515 } else { | 498 } else { |
| 516 medium.Reject( | 499 medium.Reject( |
| 517 new NullReferenceException( | 500 new NullReferenceException( |
| 518 "The chained asynchronous operation returned" + | 501 "The chained asynchronous operation returned" + |
| 519 " 'null' where the promise instance is expected" | 502 " 'null' where the promise instance is expected" |
| 528 | 511 |
| 529 public IPromise Chain(Func<IPromise> chained) { | 512 public IPromise Chain(Func<IPromise> chained) { |
| 530 return Chain(chained, null, null); | 513 return Chain(chained, null, null); |
| 531 } | 514 } |
| 532 | 515 |
| 533 public IPromise On(Action success, Action<Exception> error, Action cancel) { | 516 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) { |
| 534 AddHandler(new EventDescriptor(success,error,cancel, StubDeferred.instance)); | 517 AddHandler(new EventDescriptor(success,error,cancel, StubDeferred.instance)); |
| 535 return this; | 518 return this; |
| 536 } | 519 } |
| 537 | 520 |
| 538 public IPromise On(Action success, Action<Exception> error) { | 521 public IPromise On(Action success, Action<Exception> error) { |
| 548 IPromise IPromise.On(Action handler, PromiseEventType events) { | 531 IPromise IPromise.On(Action handler, PromiseEventType events) { |
| 549 Listen(events,handler); | 532 Listen(events,handler); |
| 550 return this; | 533 return this; |
| 551 } | 534 } |
| 552 | 535 |
| 553 public IPromise Error(Action<Exception> error) { | |
| 554 var promise = new Promise(); | |
| 555 if (error != null) | |
| 556 On( | |
| 557 (Action<T>)null, | |
| 558 ex => { | |
| 559 try { | |
| 560 error(ex); | |
| 561 promise.Resolve(); | |
| 562 } catch (Exception ex2) { | |
| 563 promise.Reject(ex2); | |
| 564 } | |
| 565 }); | |
| 566 else | |
| 567 Listen(PromiseEventType.Error, promise.Resolve); | |
| 568 return promise; | |
| 569 } | |
| 570 | |
| 571 public IPromise Cancelled(Action handler) { | |
| 572 var promise = new Promise(); | |
| 573 if (handler != null) | |
| 574 On( | |
| 575 (Action<T>)null, | |
| 576 null, | |
| 577 () => { | |
| 578 try { | |
| 579 handler(); | |
| 580 promise.Resolve(); | |
| 581 } catch (Exception ex) { | |
| 582 promise.Reject(ex); | |
| 583 } | |
| 584 }); | |
| 585 else | |
| 586 Listen(PromiseEventType.Cancelled, promise.Resolve); | |
| 587 return promise; | |
| 588 } | |
| 589 | |
| 590 public IPromise<T2> Cast<T2>() { | 536 public IPromise<T2> Cast<T2>() { |
| 591 return (IPromise<T2>)this; | 537 return (IPromise<T2>)this; |
| 592 } | 538 } |
| 593 | 539 |
| 594 #region implemented abstract members of AbstractPromise | 540 #region implemented abstract members of AbstractPromise |
| 599 | 545 |
| 600 protected override void SignalError(IDeferred<T> handler, Exception error) { | 546 protected override void SignalError(IDeferred<T> handler, Exception error) { |
| 601 handler.Reject(error); | 547 handler.Reject(error); |
| 602 } | 548 } |
| 603 | 549 |
| 604 protected override void SignalCancelled(IDeferred<T> handler) { | 550 protected override void SignalCancelled(IDeferred<T> handler, Exception reason) { |
| 605 handler.Cancel(); | 551 handler.Cancel(reason); |
| 606 } | 552 } |
| 607 | 553 |
| 608 protected override void Listen(PromiseEventType events, Action handler) { | 554 protected override void Listen(PromiseEventType events, Action handler) { |
| 609 if (handler != null) | 555 if (handler != null) |
| 610 AddHandler(new ListenerDescriptor(handler, events)); | 556 AddHandler(new ListenerDescriptor(handler, events)); |
