annotate Implab/AbstractPromiseT.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 97fbbf816844
children 86187b01c4e0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
1 using System;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
2 using Implab.Parallels;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
3
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
4 namespace Implab {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
5 public abstract class AbstractPromise<T> : AbstractEvent<AbstractPromise<T>.HandlerDescriptor>, IPromise<T> {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
6 public struct HandlerDescriptor {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
7 readonly Action m_handler;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
8 readonly Action<T> m_success;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
9 readonly Action<Exception> m_error;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
10 readonly Action<Exception> m_cancel;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
11 readonly PromiseEventType m_mask;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
12
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
13 public HandlerDescriptor(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
14 m_success = success;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
15 m_error = error;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
16 m_cancel = cancel;
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
17
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
18 m_handler = null;
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
19 m_mask = 0;
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
20 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
21
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
22 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
23 m_handler = success;
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
24 m_success = null;
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
25 m_error = error;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
26 m_cancel = cancel;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
27 m_mask = PromiseEventType.Success;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
28 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
29
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
30 public HandlerDescriptor(Action handler, PromiseEventType mask) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
31 m_handler = handler;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
32 m_mask = mask;
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
33 m_success = null;
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
34 m_error = null;
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
35 m_cancel = null;
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
36 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
37
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
38 public void SignalSuccess(T result) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
39 if (m_success != null) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
40 try {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
41 m_success(result);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
42 } catch(Exception err) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
43 SignalError(err);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
44 }
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
45 } else if ((m_mask & PromiseEventType.Success) != 0 && m_handler != null) {
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
46 try {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
47 m_handler();
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
48 } catch(Exception err) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
49 // avoid calling handler twice in case of error
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
50 if (m_error != null)
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
51 SignalError(err);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
52 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
53 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
54 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
55
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
56 public void SignalError(Exception err) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
57 if (m_error != null) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
58 try {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
59 m_error(err);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
60 // Analysis disable once EmptyGeneralCatchClause
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
61 } catch {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
62 }
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
63 } else if ((m_mask & PromiseEventType.Error) != 0 && m_handler != null) {
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
64 try {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
65 m_handler();
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
66 // Analysis disable once EmptyGeneralCatchClause
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
67 } catch {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
68 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
69 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
70 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
71
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
72 public void SignalCancel(Exception reason) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
73 if (m_cancel != null) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
74 try {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
75 m_cancel(reason);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
76 } catch (Exception err) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
77 SignalError(err);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
78 }
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
79 } else if ((m_mask & PromiseEventType.Cancelled) != 0 && m_handler != null) {
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
80 try {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
81 m_handler();
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
82 // Analysis disable once EmptyGeneralCatchClause
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
83 } catch {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
84 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
85 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
86 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
87 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
88
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
89 public Type PromiseType {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
90 get {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
91 return typeof(T);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
92 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
93 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
94
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
95 public T Join() {
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
96 WaitResult(-1);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
97 return m_result;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
98 }
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
99 public T Join(int timeout) {
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
100 WaitResult(timeout);
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
101 return m_result;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
102 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
103
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
104 void IPromise.Join() {
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
105 WaitResult(-1);
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
106 }
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
107 void IPromise.Join(int timeout) {
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
108 WaitResult(timeout);
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
109 }
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
110
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
111 public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
112 AddHandler(new HandlerDescriptor(success, error, cancel));
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
113 return this;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
114 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
115
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
116 public IPromise<T> On(Action<T> success, Action<Exception> error) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
117 AddHandler(new HandlerDescriptor(success, error, null));
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
118 return this;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
119 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
120
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
121 public IPromise<T> On(Action<T> success) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
122 AddHandler(new HandlerDescriptor(success, null, null));
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
123 return this;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
124 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
125
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
126 public IPromise<T> On(Action handler, PromiseEventType events) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
127 AddHandler(new HandlerDescriptor(handler, events));
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
128 return this;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
129 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
130
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
131 public IPromise<T> On(Action success, Action<Exception> error, Action<Exception> cancel) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
132 AddHandler(new HandlerDescriptor(success, error, cancel));
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
133 return this;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
134 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
135
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
136 public IPromise<T> On(Action success, Action<Exception> error) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
137 AddHandler(new HandlerDescriptor(success, error, null));
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
138 return this;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
139 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
140
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
141 public IPromise<T> On(Action success) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
142 AddHandler(new HandlerDescriptor(success, null, null));
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
143 return this;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
144 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
145
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
146 IPromise IPromise.On(Action success, Action<Exception> error, Action<Exception> cancel) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
147 AddHandler(new HandlerDescriptor(success, error, cancel));
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
148 return this;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
149 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
150
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
151 IPromise IPromise.On(Action success, Action<Exception> error) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
152 AddHandler(new HandlerDescriptor(success, error, null));
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
153 return this;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
154 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
155
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
156 IPromise IPromise.On(Action success) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
157 AddHandler(new HandlerDescriptor(success, null, null));
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
158 return this;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
159 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
160
145
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
161 IPromise IPromise.On(Action handler, PromiseEventType events) {
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
162 AddHandler(new HandlerDescriptor(handler, events));
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
163 return this;
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
164 }
706fccb85524 RC: cancellation support for promises + tests
cin
parents: 144
diff changeset
165
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
166 public IPromise<T2> Cast<T2>() {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
167 return (IPromise<T2>)this;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
168 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
169
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
170 #region implemented abstract members of AbstractPromise
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
171
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
172 protected override Signal GetResolveSignal() {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
173 var signal = new Signal();
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
174 AddHandler(new HandlerDescriptor(signal.Set, PromiseEventType.All));
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
175 return signal;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
176 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
177
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
178 protected override void SignalHandler(HandlerDescriptor handler, int signal) {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
179 switch (signal) {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
180 case SUCCEEDED_STATE:
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
181 handler.SignalSuccess(m_result);
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
182 break;
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
183 case REJECTED_STATE:
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
184 handler.SignalError(Error);
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
185 break;
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
186 case CANCELLED_STATE:
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
187 handler.SignalCancel(CancellationReason);
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
188 break;
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
189 default:
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
190 throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", signal));
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents: 145
diff changeset
191 }
144
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
192 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
193
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
194 #endregion
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
195
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
196 T m_result;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
197
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
198 protected void SetResult(T value) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
199 if (BeginSetResult()) {
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
200 m_result = value;
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
201 EndSetResult();
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
202 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
203 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
204 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
205 }
8c0b95069066 DRAFT: refactoring
cin
parents:
diff changeset
206