##// END OF EJS Templates
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin -
r138:f75cfa58e3d4 v2
parent child
Show More
@@ -19,11 +19,11 namespace Implab.Fx {
19 19 base.SignalSuccess(handler);
20 20 }
21 21
22 protected override void SignalCancelled(IDeferred<T> handler) {
22 protected override void SignalCancelled(IDeferred<T> handler, Exception reason) {
23 23 if (m_target.InvokeRequired)
24 m_target.BeginInvoke(new Action<IDeferred<T>>(base.SignalCancelled), handler);
24 m_target.BeginInvoke(new Action<IDeferred<T>,Exception>(base.SignalCancelled), handler, reason);
25 25 else
26 base.SignalCancelled(handler);
26 base.SignalCancelled(handler, reason);
27 27 }
28 28
29 29 protected override void SignalError(IDeferred<T> handler, Exception error) {
@@ -53,7 +53,7 namespace Implab.Test {
53 53 var p = new Promise<bool>();
54 54 p.Cancel();
55 55
56 var p2 = p.Cancelled(() => {
56 var p2 = p.Then(x => x, null, reason => {
57 57 throw new ApplicationException("CANCELLED");
58 58 });
59 59
@@ -72,10 +72,10 namespace Implab.Test {
72 72 p.Cancel();
73 73
74 74 var p2 = p
75 .Cancelled<bool>(() => {
75 .Then<bool>(x => x, null, reason => {
76 76 throw new ApplicationException("CANCELLED");
77 77 })
78 .Error(e => true);
78 .Then(x => x, e => true);
79 79
80 80 Assert.AreEqual(true, p2.Join());
81 81 }
@@ -116,7 +116,7 namespace Implab.Test {
116 116 public void FixErrorTest() {
117 117 var p = new Promise<int>();
118 118
119 var p2 = p.Error(e => 101);
119 var p2 = p.Then(x => x, e => 101);
120 120
121 121 p.Reject(new Exception());
122 122
@@ -760,7 +760,7 namespace Implab.Test {
760 760 });
761 761
762 762 result
763 .Cancelled(() => pSurvive.Resolve(true));
763 .On(() => pSurvive.Resolve(true), PromiseEventType.Cancelled);
764 764
765 765 return result;
766 766 });
@@ -68,9 +68,15 namespace Implab {
68 68 /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception>
69 69 protected void SetError(Exception error) {
70 70 if (BeginTransit()) {
71 m_error = error is PromiseTransientException ? error.InnerException : error;
72 CompleteTransit(REJECTED_STATE);
73 OnError();
71 if (error is OperationCanceledException) {
72 CompleteTransit(CANCELLED_STATE);
73 m_error = error.InnerException;
74 OnCancelled();
75 } else {
76 m_error = error is PromiseTransientException ? error.InnerException : error;
77 CompleteTransit(REJECTED_STATE);
78 OnError();
79 }
74 80 } else {
75 81 WaitTransition();
76 82 if (m_state == SUCCEEDED_STATE)
@@ -82,8 +88,9 namespace Implab {
82 88 /// Отменяет операцию, если это возможно.
83 89 /// </summary>
84 90 /// <remarks>Для определения была ли операция отменена следует использовать свойство <see cref="IsCancelled"/>.</remarks>
85 protected void SetCancelled() {
91 protected void SetCancelled(Exception reason) {
86 92 if (BeginTransit()) {
93 m_error = reason;
87 94 CompleteTransit(CANCELLED_STATE);
88 95 OnCancelled();
89 96 }
@@ -93,7 +100,7 namespace Implab {
93 100
94 101 protected abstract void SignalError(THandler handler, Exception error);
95 102
96 protected abstract void SignalCancelled(THandler handler);
103 protected abstract void SignalCancelled(THandler handler, Exception reason);
97 104
98 105 void OnSuccess() {
99 106 var hp = m_handlerPointer;
@@ -137,7 +144,7 namespace Implab {
137 144 var slot = hp +1 ;
138 145 while (slot < m_handlersCommited) {
139 146 if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) {
140 SignalCancelled(m_handlers[slot]);
147 SignalCancelled(m_handlers[slot], m_error);
141 148 }
142 149 hp = m_handlerPointer;
143 150 slot = hp +1 ;
@@ -146,7 +153,7 namespace Implab {
146 153 if (m_extraHandlers != null) {
147 154 THandler handler;
148 155 while (m_extraHandlers.TryDequeue(out handler))
149 SignalCancelled(handler);
156 SignalCancelled(handler, m_error);
150 157 }
151 158 }
152 159
@@ -241,7 +248,7 namespace Implab {
241 248 SignalSuccess(handler);
242 249 break;
243 250 case CANCELLED_STATE:
244 SignalCancelled(handler);
251 SignalCancelled(handler, m_error);
245 252 break;
246 253 case REJECTED_STATE:
247 254 SignalError(handler, m_error);
@@ -282,10 +289,20 namespace Implab {
282 289 #region ICancellable implementation
283 290
284 291 public void Cancel() {
285 SetCancelled();
292 SetCancelled(null);
293 }
294
295 public void Cancel(Exception reason) {
296 SetCancelled(reason);
286 297 }
287 298
288 299 #endregion
300
301 public Exception Error {
302 get {
303 return m_error;
304 }
305 }
289 306 }
290 307 }
291 308
@@ -17,9 +17,9
17 17 TraceLog.EndLogicalOperation();
18 18 TraceContext.Instance.Leave();
19 19 },
20 () => {
20 reason => {
21 21 TraceContext.Instance.EnterLogicalOperation(op,true);
22 TraceLog.TraceInformation("promise cancelled");
22 TraceLog.TraceInformation("promise cancelled {0}", reason.Message);
23 23 TraceLog.EndLogicalOperation();
24 24 TraceContext.Instance.Leave();
25 25 }
@@ -6,5 +6,6 using System.Text;
6 6 namespace Implab {
7 7 public interface ICancellable {
8 8 void Cancel();
9 void Cancel(Exception reason);
9 10 }
10 11 }
@@ -8,6 +8,16 namespace Implab {
8 8
9 9 void Resolve();
10 10
11 /// <summary>
12 /// Reject the promise with the specified error.
13 /// </summary>
14 /// <param name="error">The reason why the promise is rejected.</param>
15 /// <remarks>
16 /// Some exceptions are treated in a special case:
17 /// <see cref="OperationCanceledException"/> is interpreted as call to <see cref="Cancel()"/> method,
18 /// and <see cref="PromiseTransientException"/> is always unwrapped and its
19 /// <see cref="PromiseTransientException.InnerException"> is used as the reason to reject promise.
20 /// </remarks>
11 21 void Reject(Exception error);
12 22 }
13 23 }
@@ -22,6 +22,11 namespace Implab {
22 22 bool IsCancelled { get; }
23 23
24 24 /// <summary>
25 /// Исключение возникшее в результате выполнения обещания, либо причина отмены.
26 /// </summary>
27 Exception Error { get; }
28
29 /// <summary>
25 30 /// Creates a new promise dependend on the current one and resolved on
26 31 /// executing the specified handlers.
27 32 /// </summary>
@@ -43,19 +48,21 namespace Implab {
43 48 /// exception then the dependant promise will be resolved successfully, otherwise the exception
44 49 /// raised by the handler will be transmitted to the dependent promise. If the handler wants
45 50 /// to passthrough the original exception it needs to wrap the exception with
46 /// the <see cref="PromiseTransientException"/>.
51 /// the <see cref="PromiseTransientException"/>. The handler may raise <see cref="OperationCanceledException"/>
52 /// to cancel the dependant promise, the innner exception specifies the reason why the promise
53 /// is canceled.
47 54 /// </para>
48 55 /// <para>
49 56 /// If the cancelation handler is specified and the current promise is cancelled then the dependent
50 /// promise will be resolved after the handler is executed. If the cancelation hendler raises the
57 /// promise will be resolved after the handler is executed. If the cancelation handler raises the
51 58 /// exception it will be passed to the dependent promise.
52 59 /// </para>
53 60 /// </remarks>
54 IPromise Then(Action success, Action<Exception> error, Action cancel);
61 IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel);
55 62 IPromise Then(Action success, Action<Exception> error);
56 63 IPromise Then(Action success);
57 64
58 IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<IPromise> cancel);
65 IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel);
59 66 IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error);
60 67 IPromise Chain(Func<IPromise> chained);
61 68
@@ -66,7 +73,7 namespace Implab {
66 73 /// <param name="error">The handler is called if an error while completing the promise occurred.</param>
67 74 /// <param name="cancel">The handler is called in case of promise cancellation.</param>
68 75 /// <returns>The current promise.</returns>
69 IPromise On(Action success, Action<Exception> error, Action cancel);
76 IPromise On(Action success, Action<Exception> error, Action<Exception> cancel);
70 77 IPromise On(Action success, Action<Exception> error);
71 78 IPromise On(Action success);
72 79
@@ -80,42 +87,6 namespace Implab {
80 87 IPromise On(Action handler, PromiseEventType events);
81 88
82 89 /// <summary>
83 /// Adds the specified error handler to the current promise
84 /// and creates the new dependant promise.
85 /// </summary>
86 /// <param name="error">
87 /// The error handler. If the error handler returns without
88 /// an error the dependant promise will be successfully resolved.
89 /// </param>
90 /// <returns>
91 /// The new dependant promise which will be resolved after the error
92 /// handler is executed.
93 /// </returns>
94 /// <remarks>
95 /// The successfull result of the current promise will be ignored.
96 /// </remarks>
97 IPromise Error(Action<Exception> error);
98
99 /// <summary>
100 /// Adds the specified cncellation handler to the current promise
101 /// and creates the new dependant promise.
102 /// </summary>
103 /// <returns>
104 /// The new dependant promise which will be resolved after the cancellation
105 /// handler is executed.
106 /// </returns>
107 /// <param name="handler">
108 /// The cancellation handler.
109 /// </param>
110 /// <remarks>
111 /// If the cancellation handler is executed without an error the dependent
112 /// promise will be successfully resolved, otherwise the raised exception
113 /// will be passed to the dependant promise. The successful result of the
114 /// current promise will be ignored.
115 /// </remarks>
116 IPromise Cancelled(Action handler);
117
118 /// <summary>
119 90 /// Преобразует результат обещания к заданному типу и возвращает новое обещание.
120 91 /// </summary>
121 92 IPromise<T> Cast<T>();
@@ -7,7 +7,7 namespace Implab {
7 7
8 8 new T Join(int timeout);
9 9
10 IPromise<T> On(Action<T> success, Action<Exception> error, Action cancel);
10 IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel);
11 11
12 12 IPromise<T> On(Action<T> success, Action<Exception> error);
13 13
@@ -15,20 +15,16 namespace Implab {
15 15
16 16 new IPromise<T> On(Action handler, PromiseEventType events);
17 17
18 IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception,T2> error, Func<T2> cancel);
18 IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error, Func<Exception, T2> cancel);
19 19
20 IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception,T2> error);
20 IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error);
21 21
22 22 IPromise<T2> Then<T2>(Func<T, T2> mapper);
23 23
24 IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception,IPromise<T2>> error, Func<IPromise<T2>> cancel);
24 IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel);
25 25
26 IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception,IPromise<T2>> error);
26 IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error);
27 27
28 28 IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained);
29
30 IPromise<T2> Error<T2>(Func<Exception,T2> error);
31
32 IPromise<T2> Cancelled<T2>(Func<T2> handler);
33 29 }
34 30 }
@@ -7,10 +7,10 namespace Implab {
7 7 public struct HandlerDescriptor {
8 8 readonly Action m_success;
9 9 readonly Action<Exception> m_error;
10 readonly Action m_cancel;
10 readonly Action<Exception> m_cancel;
11 11 readonly IDeferred m_deferred;
12 12
13 public HandlerDescriptor(Action success, Action<Exception> error, Action cancel, IDeferred deferred) {
13 public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel, IDeferred deferred) {
14 14 m_success = success;
15 15 m_error = error;
16 16 m_cancel = cancel;
@@ -45,10 +45,18 namespace Implab {
45 45 }
46 46 }
47 47
48 public void SignalCancel() {
48 public void SignalCancel(Exception reason) {
49 49 if (m_cancel != null) {
50 50 try {
51 m_cancel();
51 m_cancel(reason);
52 if (m_deferred != null)
53 m_deferred.Resolve();
54 } catch (Exception err) {
55 SignalError(err);
56 }
57 } else if (reason != null && m_error != null) {
58 try {
59 m_error(new OperationCanceledException("The operation was canceled.", reason));
52 60 if (m_deferred != null)
53 61 m_deferred.Resolve();
54 62 } catch (Exception err) {
@@ -56,7 +64,7 namespace Implab {
56 64 }
57 65 } else {
58 66 if (m_deferred != null)
59 m_deferred.Cancel();
67 m_deferred.Cancel(reason);
60 68 }
61 69 }
62 70 }
@@ -80,15 +88,15 namespace Implab {
80 88 handler.SignalError(error);
81 89 }
82 90
83 protected override void SignalCancelled(HandlerDescriptor handler) {
84 handler.SignalCancel();
91 protected override void SignalCancelled(HandlerDescriptor handler, Exception reason) {
92 handler.SignalCancel(reason);
85 93 }
86 94
87 95 protected override void Listen(PromiseEventType events, Action handler) {
88 96 AddHandler(new HandlerDescriptor(
89 97 events.HasFlag(PromiseEventType.Success) ? handler : null,
90 98 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null,
91 events.HasFlag(PromiseEventType.Cancelled) ? handler : null,
99 events.HasFlag(PromiseEventType.Cancelled) ? new Action<Exception>(reason => handler()) : null,
92 100 null
93 101 ));
94 102 }
@@ -102,7 +110,7 namespace Implab {
102 110 }
103 111 }
104 112
105 public IPromise Then(Action success, Action<Exception> error, Action cancel) {
113 public IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel) {
106 114 var promise = new Promise();
107 115 if (success != null)
108 116 promise.On(Cancel, PromiseEventType.Cancelled);
@@ -120,7 +128,7 namespace Implab {
120 128 return Then(success, null, null);
121 129 }
122 130
123 public IPromise On(Action success, Action<Exception> error, Action cancel) {
131 public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) {
124 132 AddHandler(new HandlerDescriptor(success, error, cancel, null));
125 133 return this;
126 134 }
@@ -137,7 +145,7 namespace Implab {
137 145 return On(
138 146 events.HasFlag(PromiseEventType.Success) ? handler : null,
139 147 events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null,
140 events.HasFlag(PromiseEventType.Cancelled) ? handler : null
148 events.HasFlag(PromiseEventType.Cancelled) ? new Action<Exception>(reason => handler()) : null
141 149 );
142 150 }
143 151
@@ -145,7 +153,7 namespace Implab {
145 153 throw new InvalidCastException();
146 154 }
147 155
148 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<IPromise> cancel) {
156 public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception,IPromise> cancel) {
149 157 var medium = new Promise();
150 158
151 159 On(
@@ -168,13 +176,13 namespace Implab {
168 176 medium.Reject(ex);
169 177 }
170 178 },
171 () => {
179 reason => {
172 180 if (medium.IsCancelled)
173 181 return;
174 182 if (cancel != null)
175 ConnectPromise(cancel(), medium);
183 ConnectPromise(cancel(reason), medium);
176 184 else
177 medium.Cancel();
185 medium.Cancel(reason);
178 186 }
179 187 );
180 188
@@ -189,9 +197,9 namespace Implab {
189 197 result.On(
190 198 medium.Resolve,
191 199 medium.Reject,
192 () => medium.Reject(new OperationCanceledException())
200 medium.Cancel
193 201 );
194 medium.On(result.Cancel, PromiseEventType.Cancelled);
202 medium.On(null,null,result.Cancel);
195 203 } else {
196 204 medium.Reject(
197 205 new NullReferenceException(
@@ -209,50 +217,6 namespace Implab {
209 217 public IPromise Chain(Func<IPromise> chained) {
210 218 return Chain(chained, null, null);
211 219 }
212
213 public IPromise Error(Action<Exception> error) {
214 var promise = new Promise();
215 On(
216 null,
217 err => {
218 if (error != null)
219 try {
220 error(err);
221 promise.Resolve();
222 } catch (Exception err2) {
223 promise.Reject(err2);
224 }
225 else
226 promise.Reject(err);
227 }
228 );
229
230 return promise;
231 }
232
233 public IPromise Cancelled(Action handler) {
234 var promise = new Promise();
235 On(
236 null,
237 null,
238 () => {
239 if (handler != null) {
240 try {
241 handler();
242 promise.Resolve();
243 } catch (Exception err) {
244 promise.Reject(err);
245 }
246 } else {
247 promise.Cancel();
248 }
249 }
250 );
251
252 return promise;
253 }
254
255
256 220 }
257 221 }
258 222
@@ -56,7 +56,7 namespace Implab {
56 56 Safe.ArgumentNotNull(that, "that");
57 57 Safe.ArgumentNotNull(head, "head");
58 58
59 that.On(null,null,() => head.On(cleanup));
59 that.On(() => head.On(cleanup), PromiseEventType.Cancelled);
60 60
61 61 return that;
62 62 }
@@ -123,9 +123,9 namespace Implab {
123 123 new Exception("The dependency promise is failed", error)
124 124 );
125 125 },
126 () => {
126 reason => {
127 127 if (Interlocked.Increment(ref errors) == 1)
128 medium.Reject(
128 medium.Cancel(
129 129 new Exception("The dependency promise is cancelled")
130 130 );
131 131 }
@@ -162,10 +162,10 namespace Implab {
162 162 new Exception("The dependency promise is failed", error)
163 163 );
164 164 },
165 () => {
165 reason => {
166 166 if (Interlocked.Increment(ref errors) == 1)
167 medium.Reject(
168 new Exception("The dependency promise is cancelled")
167 medium.Cancel(
168 new Exception("The dependency promise is cancelled", reason)
169 169 );
170 170 }
171 171 );
@@ -181,7 +181,7 namespace Implab {
181 181 Safe.ArgumentNotNull(that, "that");
182 182 var tcs = new TaskCompletionSource<T>();
183 183
184 that.On(tcs.SetResult, tcs.SetException, tcs.SetCanceled);
184 that.On(tcs.SetResult, tcs.SetException, r => tcs.SetCanceled());
185 185
186 186 return tcs.Task;
187 187 }
@@ -39,7 +39,7 namespace Implab {
39 39 /// </remarks>
40 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 43 public static readonly StubDeferred instance = new StubDeferred();
44 44
45 45 StubDeferred() {
@@ -50,6 +50,9 namespace Implab {
50 50 public void Resolve(T value) {
51 51 }
52 52
53 public void Resolve() {
54 }
55
53 56 public void Reject(Exception error) {
54 57 }
55 58
@@ -60,6 +63,9 namespace Implab {
60 63 public void Cancel() {
61 64 }
62 65
66 public void Cancel(Exception reason) {
67 }
68
63 69 #endregion
64 70
65 71
@@ -67,11 +73,11 namespace Implab {
67 73
68 74 class RemapDescriptor<T2> : IDeferred<T> {
69 75 readonly Func<T,T2> m_remap;
70 readonly Func<Exception,T2> m_failed;
71 readonly Func<T2> m_cancel;
76 readonly Func<Exception, T2> m_failed;
77 readonly Func<Exception, T2> m_cancel;
72 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 81 Debug.Assert(deferred != null);
76 82 m_remap = remap;
77 83 m_failed = failed;
@@ -110,18 +116,21 namespace Implab {
110 116
111 117 #region ICancellable implementation
112 118
113 public void Cancel() {
119 public void Cancel(Exception reason) {
114 120 if (m_cancel != null) {
115 121 try {
116 m_deferred.Resolve(m_cancel());
122 m_deferred.Resolve(m_cancel(reason));
117 123 } catch (Exception ex) {
118 124 Reject(ex);
119 125 }
120 126 } else {
121 m_deferred.Cancel();
127 m_deferred.Cancel(reason);
122 128 }
123 129 }
124 130
131 public void Cancel() {
132 Cancel(null);
133 }
125 134 #endregion
126 135 }
127 136
@@ -163,6 +172,10 namespace Implab {
163 172 #region ICancellable implementation
164 173
165 174 public void Cancel() {
175 Cancel(null);
176 }
177
178 public void Cancel(Exception reason) {
166 179 if (m_events.HasFlag(PromiseEventType.Cancelled)){
167 180 try {
168 181 m_handler();
@@ -178,10 +191,10 namespace Implab {
178 191 class ValueEventDescriptor : IDeferred<T> {
179 192 readonly Action<T> m_success;
180 193 readonly Action<Exception> m_failed;
181 readonly Action m_cancelled;
194 readonly Action<Exception> m_cancelled;
182 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 198 Debug.Assert(deferred != null);
186 199
187 200 m_success = success;
@@ -220,29 +233,33 namespace Implab {
220 233
221 234 #region ICancellable implementation
222 235
223 public void Cancel() {
236 public void Cancel(Exception reason) {
224 237 if (m_cancelled != null) {
225 238 try {
226 m_cancelled();
239 m_cancelled(reason);
227 240 m_deferred.Resolve(default(T));
228 } catch(Exception ex) {
241 } catch (Exception ex) {
229 242 Reject(ex);
230 243 }
231 244 } else {
232 m_deferred.Cancel();
245 m_deferred.Cancel(reason);
233 246 }
234 247 }
235 248
249 public void Cancel() {
250 Cancel(null);
251 }
252
236 253 #endregion
237 254 }
238 255
239 256 public class EventDescriptor : IDeferred<T> {
240 257 readonly Action m_success;
241 258 readonly Action<Exception> m_failed;
242 readonly Action m_cancelled;
243 readonly IDeferred<T> m_deferred;
259 readonly Action<Exception> m_cancelled;
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 263 Debug.Assert(deferred != null);
247 264
248 265 m_success = success;
@@ -257,7 +274,7 namespace Implab {
257 274 if (m_success != null) {
258 275 try {
259 276 m_success();
260 m_deferred.Resolve(value);
277 m_deferred.Resolve();
261 278 } catch (Exception ex) {
262 279 Reject(ex);
263 280 }
@@ -268,34 +285,36 namespace Implab {
268 285 if (m_failed != null) {
269 286 try {
270 287 m_failed(error);
271 m_deferred.Resolve(default(T));
272 }catch (Exception ex)
273 {
288 m_deferred.Resolve();
289 } catch (Exception ex) {
274 290 m_deferred.Reject(ex);
275 291 }
276 292 } else {
277 293 m_deferred.Reject(error);
278 294 }
279
280 295 }
281 296
282 297 #endregion
283 298
284 299 #region ICancellable implementation
285 300
286 public void Cancel() {
301 public void Cancel(Exception reason) {
287 302 if (m_cancelled != null) {
288 303 try {
289 m_cancelled();
290 m_deferred.Resolve(default(T));
304 m_cancelled(reason);
305 m_deferred.Resolve();
291 306 } catch (Exception ex) {
292 307 Reject(ex);
293 308 }
294 309 } else {
295 m_deferred.Cancel();
310 m_deferred.Cancel(reason);
296 311 }
297 312 }
298 313
314 public void Cancel() {
315 Cancel(null);
316 }
317
299 318 #endregion
300 319 }
301 320
@@ -327,7 +346,7 namespace Implab {
327 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 350 AddHandler(new ValueEventDescriptor(success, error, cancel, StubDeferred.instance));
332 351 return this;
333 352 }
@@ -347,10 +366,10 namespace Implab {
347 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 370 var promise = new Promise<T2>();
352 371 if (mapper != null)
353 promise.On(Cancel, PromiseEventType.Cancelled);
372 promise.On((Action)null, null, Cancel);
354 373 AddHandler(new RemapDescriptor<T2>(mapper, error, cancel, promise));
355 374 return promise;
356 375 }
@@ -358,7 +377,7 namespace Implab {
358 377 public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error) {
359 378 var promise = new Promise<T2>();
360 379 if (mapper != null)
361 promise.On(Cancel, PromiseEventType.Cancelled);
380 promise.On((Action)null, null, Cancel);
362 381 AddHandler(new RemapDescriptor<T2>(mapper, error, null, promise));
363 382 return promise;
364 383 }
@@ -366,12 +385,12 namespace Implab {
366 385 public IPromise<T2> Then<T2>(Func<T, T2> mapper) {
367 386 var promise = new Promise<T2>();
368 387 if (mapper != null)
369 promise.On(Cancel, PromiseEventType.Cancelled);
388 promise.On((Action)null, null, Cancel);
370 389 AddHandler(new RemapDescriptor<T2>(mapper, null, null, promise));
371 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 394 // this promise will be resolved when an asyc operation is started
376 395 var promise = new Promise<IPromise<T2>>();
377 396
@@ -404,7 +423,7 namespace Implab {
404 423 result.On(
405 424 medium.Resolve,
406 425 medium.Reject,
407 () => medium.Reject(new OperationCanceledException())
426 medium.Cancel
408 427 );
409 428 medium.On(result.Cancel, PromiseEventType.Cancelled);
410 429 } else {
@@ -425,46 +444,10 namespace Implab {
425 444 return Chain(chained, null, null);
426 445 }
427 446
428 public IPromise<T2> Error<T2>(Func<Exception, T2> error) {
429 var promise = new Promise<T2>();
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>();
447 public IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel) {
448 var promise = new Promise();
466 449 if (success != null)
467 promise.On(Cancel, PromiseEventType.Cancelled);
450 promise.On(null, null, Cancel);
468 451
469 452 AddHandler(new EventDescriptor(success, error, cancel, promise));
470 453
@@ -479,7 +462,7 namespace Implab {
479 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 466 var promise = new Promise<IPromise>();
484 467
485 468 AddHandler(
@@ -493,7 +476,7 namespace Implab {
493 476
494 477 var medium = new Promise();
495 478 if (chained != null)
496 medium.On(Cancel, PromiseEventType.Cancelled);
479 medium.On(null, null, Cancel);
497 480
498 481 promise.On(
499 482 result => ConnectPromise(result, medium),
@@ -509,9 +492,9 namespace Implab {
509 492 result.On(
510 493 medium.Resolve,
511 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 498 } else {
516 499 medium.Reject(
517 500 new NullReferenceException(
@@ -530,7 +513,7 namespace Implab {
530 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 517 AddHandler(new EventDescriptor(success,error,cancel, StubDeferred.instance));
535 518 return this;
536 519 }
@@ -550,43 +533,6 namespace Implab {
550 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 536 public IPromise<T2> Cast<T2>() {
591 537 return (IPromise<T2>)this;
592 538 }
@@ -601,8 +547,8 namespace Implab {
601 547 handler.Reject(error);
602 548 }
603 549
604 protected override void SignalCancelled(IDeferred<T> handler) {
605 handler.Cancel();
550 protected override void SignalCancelled(IDeferred<T> handler, Exception reason) {
551 handler.Cancel(reason);
606 552 }
607 553
608 554 protected override void Listen(PromiseEventType events, Action handler) {
@@ -1,7 +1,6
1 1 using System;
2 2
3 3 namespace Implab {
4
5 4 [Serializable]
6 5 public class PromiseTransientException : Exception {
7 6 /// <summary>
@@ -1,4 +1,5
1 1 using System.Threading;
2 using System;
2 3
3 4 namespace Implab {
4 5 public class SyncContextPromise<T> : Promise<T> {
@@ -13,12 +14,12 namespace Implab {
13 14 m_context.Post(x => base.SignalSuccess(handler), null);
14 15 }
15 16
16 protected override void SignalError(IDeferred<T> handler, System.Exception error) {
17 protected override void SignalError(IDeferred<T> handler, Exception error) {
17 18 m_context.Post(x => base.SignalError(handler, error), null);
18 19 }
19 20
20 protected override void SignalCancelled(IDeferred<T> handler) {
21 m_context.Post(x => base.SignalCancelled(handler), null);
21 protected override void SignalCancelled(IDeferred<T> handler, Exception reason) {
22 m_context.Post(x => base.SignalCancelled(handler, reason), null);
22 23 }
23 24 }
24 25 }
@@ -99,6 +99,13 namespace Implab
99 99 }
100 100 }
101 101
102 public void Cancel(Exception reason) {
103 lock (m_lock) {
104 if (!m_cancelled)
105 m_cancelled = true;
106 }
107 }
108
102 109 protected virtual void OnCancelled() {
103 110 var temp = Cancelled;
104 111 if (temp != null) {
@@ -69,7 +69,7 namespace MonoPlay {
69 69
70 70 var readers = new IPromise[readThreads];
71 71 for (int i = 0; i < readThreads; i++)
72 readers[i] = AsyncPool.RunThread(reader1);
72 readers[i] = AsyncPool.RunThread(reader2);
73 73
74 74 var writers = new IPromise[writeThreads];
75 75 for (int i = 0; i < writeThreads; i++)
General Comments 0
You need to be logged in to leave comments. Login now