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