annotate Implab/AbstractPromise.cs @ 196:40d7fed4a09e

fixed promise chaining behavior, the error handler doesn't handle result or cancellation handlers exceptions these exceptions are propagated to the next handlers.
author cin
date Mon, 29 Aug 2016 23:15:51 +0300
parents 75103928da09
children 86187b01c4e0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
1 using System;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
2 using Implab.Parallels;
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
3
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
4 namespace Implab {
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
5 public abstract class AbstractPromise : AbstractEvent<AbstractPromise.HandlerDescriptor>, IPromise {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
6 public struct HandlerDescriptor {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
7 readonly Action m_handler;
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
8 readonly Action<Exception> m_error;
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
9 readonly Action<Exception> m_cancel;
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
10 readonly PromiseEventType m_mask;
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
11
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
12 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
13 m_handler = success;
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
14 m_error = error;
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
15 m_cancel = cancel;
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
16 m_mask = PromiseEventType.Success;
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
17 }
125
f803565868a4 improved performance of promises
cin
parents: 119
diff changeset
18
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
19 public HandlerDescriptor(Action handler, PromiseEventType mask) {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
20 m_handler = handler;
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
21 m_error = null;
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
22 m_cancel = null;
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
23 m_mask = mask;
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
24 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
25
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
26 public void SignalSuccess() {
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
27 if ((m_mask & PromiseEventType.Success) != 0 && m_handler != null) {
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
28 try {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
29 m_handler();
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
30 } catch (Exception err) {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
31 // avoid calling handler twice in case of error
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
32 if (m_error != null)
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
33 SignalError(err);
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
34 }
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
35 }
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
36 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
37
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
38 public void SignalError(Exception err) {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
39 if (m_error != null) {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
40 try {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
41 m_error(err);
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
42 // Analysis disable once EmptyGeneralCatchClause
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
43 } catch {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
44 }
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
45 } else if ((m_mask & PromiseEventType.Error ) != 0 && m_handler != null) {
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
46 try {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
47 m_handler();
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
48 // Analysis disable once EmptyGeneralCatchClause
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
49 } catch {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
50 }
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
51 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
52 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
53
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
54 public void SignalCancel(Exception reason) {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
55 if (m_cancel != null) {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
56 try {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
57 m_cancel(reason);
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
58 } catch (Exception err) {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
59 SignalError(err);
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
60 }
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
61 } else if ( (m_mask & PromiseEventType.Cancelled) != 0 && m_handler != null) {
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
62 try {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
63 m_handler();
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
64 // Analysis disable once EmptyGeneralCatchClause
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
65 } catch {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
66 }
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
67 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
68 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
69 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
70
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
71
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
72 #region implemented abstract members of AbstractPromise
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
73
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
74 protected override void SignalHandler(HandlerDescriptor handler, int signal) {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
75 switch (signal) {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
76 case SUCCEEDED_STATE:
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
77 handler.SignalSuccess();
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
78 break;
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
79 case REJECTED_STATE:
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
80 handler.SignalError(Error);
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
81 break;
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
82 case CANCELLED_STATE:
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
83 handler.SignalCancel(CancellationReason);
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
84 break;
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
85 default:
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
86 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", signal));
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
87 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
88 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
89
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
90 protected override Signal GetResolveSignal() {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
91 var signal = new Signal();
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
92 On(signal.Set, PromiseEventType.All);
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
93 return signal;
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
94 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
95
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
96 #endregion
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
97
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
98 public Type PromiseType {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
99 get {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
100 return typeof(void);
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
101 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
102 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
103
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
104 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
105 AddHandler(new HandlerDescriptor(success, error, cancel));
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
106 return this;
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
107 }
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
108
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
109 public IPromise On(Action success, Action<Exception> error) {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
110 AddHandler(new HandlerDescriptor(success, error, null));
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
111 return this;
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
112 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
113
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
114 public IPromise On(Action success) {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
115 AddHandler(new HandlerDescriptor(success, null, null));
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
116 return this;
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
117 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
118
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
119 public IPromise On(Action handler, PromiseEventType events) {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
120 AddHandler(new HandlerDescriptor(handler,events));
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
121 return this;
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
122 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
123
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
124 public IPromise<T> Cast<T>() {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
125 throw new InvalidCastException();
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
126 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
127
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
128 public void Join() {
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
129 WaitResult(-1);
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
130 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
131
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
132 public void Join(int timeout) {
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
133 WaitResult(timeout);
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
134 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
135
144
8c0b95069066 DRAFT: refactoring
cin
parents: 143
diff changeset
136 protected void SetResult() {
186
75103928da09 working on cancelation and error handling
cin
parents: 156
diff changeset
137 if(BeginSetResult())
75103928da09 working on cancelation and error handling
cin
parents: 156
diff changeset
138 EndSetResult();
138
f75cfa58e3d4 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents: 130
diff changeset
139 }
119
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
140 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
141 }
2573b562e328 Promises rewritten, added improved version of AsyncQueue
cin
parents:
diff changeset
142