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)); |