##// END OF EJS Templates
Bound promise to CancellationToken...
cin -
r209:a867536c68fc v2
parent child
Show More
@@ -1,24 +1,30
1 namespace Implab.Components {
1 namespace Implab.Components {
2
2
3 public enum ExecutionState {
3 public enum ExecutionState {
4 Undefined = 0,
4 Undefined = 0,
5
5
6 Created,
6 Created,
7
7
8 Initializing,
8 Initializing,
9
9
10 Ready,
10 Ready,
11
11
12 Starting,
12 Starting,
13
13
14 Running,
14 Running,
15
15
16 Suspending,
17
18 Suspended,
19
20 Resuming,
21
16 Stopping,
22 Stopping,
17
23
18 Failed,
24 Failed,
19
25
20 Disposed,
26 Disposed,
21
27
22 Last = Disposed
28 Last = Disposed
23 }
29 }
24 } No newline at end of file
30 }
@@ -1,448 +1,475
1 using System.Threading;
1 using System.Threading;
2 using System;
2 using System;
3 using Implab.Diagnostics;
3 using Implab.Diagnostics;
4 using System.Collections.Generic;
4 using System.Collections.Generic;
5 using System.Linq;
5 using System.Linq;
6
6
7 namespace Implab {
7 namespace Implab {
8 public static class PromiseExtensions {
8 public static class PromiseExtensions {
9 public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) {
9 public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) {
10 Safe.ArgumentNotNull(that, "that");
10 Safe.ArgumentNotNull(that, "that");
11 var context = SynchronizationContext.Current;
11 var context = SynchronizationContext.Current;
12 if (context == null)
12 if (context == null)
13 return that;
13 return that;
14
14
15 var p = new SyncContextPromise<T>(context);
15 var p = new SyncContextPromise<T>(context);
16 p.CancellationRequested(that.Cancel);
16 p.CancellationRequested(that.Cancel);
17
17
18 that.On(
18 that.On(
19 p.Resolve,
19 p.Resolve,
20 p.Reject,
20 p.Reject,
21 p.CancelOperation
21 p.CancelOperation
22 );
22 );
23 return p;
23 return p;
24 }
24 }
25
25
26 public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) {
26 public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) {
27 Safe.ArgumentNotNull(that, "that");
27 Safe.ArgumentNotNull(that, "that");
28 Safe.ArgumentNotNull(context, "context");
28 Safe.ArgumentNotNull(context, "context");
29
29
30 var p = new SyncContextPromise<T>(context);
30 var p = new SyncContextPromise<T>(context);
31 p.CancellationRequested(that.Cancel);
31 p.CancellationRequested(that.Cancel);
32
32
33 that.On(
33 that.On(
34 p.Resolve,
34 p.Resolve,
35 p.Reject,
35 p.Reject,
36 p.CancelOperation
36 p.CancelOperation
37 );
37 );
38 return p;
38 return p;
39 }
39 }
40
40
41 /// <summary>
41 /// <summary>
42 /// Ensures the dispatched.
42 /// Ensures the dispatched.
43 /// </summary>
43 /// </summary>
44 /// <returns>The dispatched.</returns>
44 /// <returns>The dispatched.</returns>
45 /// <param name="that">That.</param>
45 /// <param name="that">That.</param>
46 /// <param name="head">Head.</param>
46 /// <param name="head">Head.</param>
47 /// <param name="cleanup">Cleanup.</param>
47 /// <param name="cleanup">Cleanup.</param>
48 /// <typeparam name="TPromise">The 1st type parameter.</typeparam>
48 /// <typeparam name="TPromise">The 1st type parameter.</typeparam>
49 /// <typeparam name="T">The 2nd type parameter.</typeparam>
49 /// <typeparam name="T">The 2nd type parameter.</typeparam>
50 public static TPromise EnsureDispatched<TPromise, T>(this TPromise that, IPromise<T> head, Action<T> cleanup) where TPromise : IPromise {
50 public static TPromise EnsureDispatched<TPromise, T>(this TPromise that, IPromise<T> head, Action<T> cleanup) where TPromise : IPromise {
51 Safe.ArgumentNotNull(that, "that");
51 Safe.ArgumentNotNull(that, "that");
52 Safe.ArgumentNotNull(head, "head");
52 Safe.ArgumentNotNull(head, "head");
53
53
54 that.On(() => head.On(cleanup), PromiseEventType.Cancelled);
54 that.On(() => head.On(cleanup), PromiseEventType.Cancelled);
55
55
56 return that;
56 return that;
57 }
57 }
58
58
59 /// <summary>
59 /// <summary>
60 /// Adds a cancellation point to the chain of promises. When a cancellation request reaches the cancellation point the operation is
60 /// Adds a cancellation point to the chain of promises. When a cancellation request reaches the cancellation point the operation is
61 /// cancelled immediatelly, and the request is passed towards. If the operation at the higher level can not be cancelled is't result
61 /// cancelled immediatelly, and the request is passed towards. If the operation at the higher level can not be cancelled is't result
62 /// will be collected with <paramref name="cleanup"/> callback.
62 /// will be collected with <paramref name="cleanup"/> callback.
63 /// </summary>
63 /// </summary>
64 /// <typeparam name="T">The type of the promise result.</typeparam>
64 /// <typeparam name="T">The type of the promise result.</typeparam>
65 /// <param name="that">The promise to which the cancellation point should be attached.</param>
65 /// <param name="that">The promise to which the cancellation point should be attached.</param>
66 /// <param name="cleanup">The callback which is used to cleanup the result of the operation if the cancellation point is cancelled already.</param>
66 /// <param name="cleanup">The callback which is used to cleanup the result of the operation if the cancellation point is cancelled already.</param>
67 /// <returns>The promise</returns>
67 /// <returns>The promise</returns>
68 public static IPromise<T> CancellationPoint<T>(this IPromise<T> that, Action<T> cleanup) {
68 public static IPromise<T> CancellationPoint<T>(this IPromise<T> that, Action<T> cleanup) {
69 var meduim = new Promise<T>();
69 var meduim = new Promise<T>();
70
70
71 that.On(meduim.Resolve, meduim.Reject, meduim.CancelOperation);
71 that.On(meduim.Resolve, meduim.Reject, meduim.CancelOperation);
72
72
73 meduim.CancellationRequested(that.Cancel);
73 meduim.CancellationRequested(that.Cancel);
74 meduim.CancellationRequested(meduim.CancelOperation);
74 meduim.CancellationRequested(meduim.CancelOperation);
75
75
76 if (cleanup != null)
76 if (cleanup != null)
77 meduim.On((Action<T>)null, null, (e) => {
77 meduim.On((Action<T>)null, null, (e) => {
78 that.On(cleanup);
78 that.On(cleanup);
79 });
79 });
80
80
81 return meduim;
81 return meduim;
82 }
82 }
83
83
84 public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult, T> callback) {
84 public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult, T> callback) {
85 Safe.ArgumentNotNull(that, "that");
85 Safe.ArgumentNotNull(that, "that");
86 Safe.ArgumentNotNull(callback, "callback");
86 Safe.ArgumentNotNull(callback, "callback");
87 var op = TraceContext.Instance.CurrentOperation;
87 var op = TraceContext.Instance.CurrentOperation;
88 return ar => {
88 return ar => {
89 TraceContext.Instance.EnterLogicalOperation(op, false);
89 TraceContext.Instance.EnterLogicalOperation(op, false);
90 try {
90 try {
91 that.Resolve(callback(ar));
91 that.Resolve(callback(ar));
92 } catch (Exception err) {
92 } catch (Exception err) {
93 that.Reject(err);
93 that.Reject(err);
94 } finally {
94 } finally {
95 TraceContext.Instance.Leave();
95 TraceContext.Instance.Leave();
96 }
96 }
97 };
97 };
98 }
98 }
99
99
100 static void CancelByTimeoutCallback(object cookie) {
100 static void CancelByTimeoutCallback(object cookie) {
101 ((ICancellable)cookie).Cancel(new TimeoutException());
101 ((ICancellable)cookie).Cancel(new TimeoutException());
102 }
102 }
103
103
104 /// <summary>
104 /// <summary>
105 /// Cancells promise after the specified timeout is elapsed.
105 /// Cancells promise after the specified timeout is elapsed.
106 /// </summary>
106 /// </summary>
107 /// <param name="that">The promise to cancel on timeout.</param>
107 /// <param name="that">The promise to cancel on timeout.</param>
108 /// <param name="milliseconds">The timeout in milliseconds.</param>
108 /// <param name="milliseconds">The timeout in milliseconds.</param>
109 /// <typeparam name="TPromise">The 1st type parameter.</typeparam>
109 /// <typeparam name="TPromise">The 1st type parameter.</typeparam>
110 public static TPromise Timeout<TPromise>(this TPromise that, int milliseconds) where TPromise : IPromise {
110 public static TPromise Timeout<TPromise>(this TPromise that, int milliseconds) where TPromise : IPromise {
111 Safe.ArgumentNotNull(that, "that");
111 Safe.ArgumentNotNull(that, "that");
112 var timer = new Timer(CancelByTimeoutCallback, that, milliseconds, -1);
112 var timer = new Timer(CancelByTimeoutCallback, that, milliseconds, -1);
113 that.On(timer.Dispose, PromiseEventType.All);
113 that.On(timer.Dispose, PromiseEventType.All);
114 return that;
114 return that;
115 }
115 }
116
116
117 public static IPromise PromiseAll(this IEnumerable<IPromise> that) {
117 public static IPromise PromiseAll(this IEnumerable<IPromise> that) {
118 Safe.ArgumentNotNull(that, "that");
118 Safe.ArgumentNotNull(that, "that");
119 return PromiseAll(that.ToList());
119 return PromiseAll(that.ToList());
120 }
120 }
121
121
122 public static IPromise<T[]> PromiseAll<T>(this IEnumerable<IPromise<T>> that) {
122 public static IPromise<T[]> PromiseAll<T>(this IEnumerable<IPromise<T>> that) {
123 return PromiseAll(that, null);
123 return PromiseAll(that, null);
124 }
124 }
125
125
126 public static IPromise<T[]> PromiseAll<T>(this IEnumerable<IPromise<T>> that, Action<T> cleanup) {
126 public static IPromise<T[]> PromiseAll<T>(this IEnumerable<IPromise<T>> that, Action<T> cleanup) {
127 Safe.ArgumentNotNull(that, "that");
127 Safe.ArgumentNotNull(that, "that");
128 return PromiseAll(that.ToList(), cleanup);
128 return PromiseAll(that.ToList(), cleanup);
129 }
129 }
130
130
131 public static IPromise PromiseAll(this ICollection<IPromise> that) {
131 public static IPromise PromiseAll(this ICollection<IPromise> that) {
132 Safe.ArgumentNotNull(that, "that");
132 Safe.ArgumentNotNull(that, "that");
133
133
134 int count = that.Count;
134 int count = that.Count;
135 int errors = 0;
135 int errors = 0;
136 var medium = new Promise();
136 var medium = new Promise();
137
137
138 if (count == 0) {
138 if (count == 0) {
139 medium.Resolve();
139 medium.Resolve();
140 return medium;
140 return medium;
141 }
141 }
142
142
143 medium.On(() => {
143 medium.On(() => {
144 foreach (var p2 in that)
144 foreach (var p2 in that)
145 p2.Cancel();
145 p2.Cancel();
146 }, PromiseEventType.ErrorOrCancel);
146 }, PromiseEventType.ErrorOrCancel);
147
147
148 foreach (var p in that)
148 foreach (var p in that)
149 p.On(
149 p.On(
150 () => {
150 () => {
151 if (Interlocked.Decrement(ref count) == 0)
151 if (Interlocked.Decrement(ref count) == 0)
152 medium.Resolve();
152 medium.Resolve();
153 },
153 },
154 error => {
154 error => {
155 if (Interlocked.Increment(ref errors) == 1)
155 if (Interlocked.Increment(ref errors) == 1)
156 medium.Reject(
156 medium.Reject(
157 new Exception("The dependency promise is failed", error)
157 new Exception("The dependency promise is failed", error)
158 );
158 );
159 },
159 },
160 reason => {
160 reason => {
161 if (Interlocked.Increment(ref errors) == 1)
161 if (Interlocked.Increment(ref errors) == 1)
162 medium.Cancel(
162 medium.Cancel(
163 new Exception("The dependency promise is cancelled")
163 new Exception("The dependency promise is cancelled")
164 );
164 );
165 }
165 }
166 );
166 );
167
167
168 return medium;
168 return medium;
169 }
169 }
170
170
171 public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that) {
171 public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that) {
172 return PromiseAll(that, null);
172 return PromiseAll(that, null);
173 }
173 }
174
174
175 /// <summary>
175 /// <summary>
176 /// Creates a new promise which will be satisfied when all promises are satisfied.
176 /// Creates a new promise which will be satisfied when all promises are satisfied.
177 /// </summary>
177 /// </summary>
178 /// <typeparam name="T"></typeparam>
178 /// <typeparam name="T"></typeparam>
179 /// <param name="that"></param>
179 /// <param name="that"></param>
180 /// <param name="cleanup">A callback used to cleanup already resolved promises in case of an error</param>
180 /// <param name="cleanup">A callback used to cleanup already resolved promises in case of an error</param>
181 /// <returns></returns>
181 /// <returns></returns>
182 public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that, Action<T> cleanup) {
182 public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that, Action<T> cleanup) {
183 Safe.ArgumentNotNull(that, "that");
183 Safe.ArgumentNotNull(that, "that");
184
184
185 int count = that.Count;
185 int count = that.Count;
186
186
187 if (count == 0)
187 if (count == 0)
188 return Promise<T[]>.FromResult(new T[0]);
188 return Promise<T[]>.FromResult(new T[0]);
189
189
190 int errors = 0;
190 int errors = 0;
191 var medium = new Promise<T[]>();
191 var medium = new Promise<T[]>();
192 var results = new T[that.Count];
192 var results = new T[that.Count];
193
193
194 medium.On(() => {
194 medium.On(() => {
195 foreach (var p2 in that) {
195 foreach (var p2 in that) {
196 p2.Cancel();
196 p2.Cancel();
197 if (cleanup != null)
197 if (cleanup != null)
198 p2.On(cleanup);
198 p2.On(cleanup);
199 }
199 }
200 }, PromiseEventType.ErrorOrCancel);
200 }, PromiseEventType.ErrorOrCancel);
201
201
202 int i = 0;
202 int i = 0;
203 foreach (var p in that) {
203 foreach (var p in that) {
204 var idx = i;
204 var idx = i;
205 p.On(
205 p.On(
206 x => {
206 x => {
207 results[idx] = x;
207 results[idx] = x;
208 if (Interlocked.Decrement(ref count) == 0)
208 if (Interlocked.Decrement(ref count) == 0)
209 medium.Resolve(results);
209 medium.Resolve(results);
210 },
210 },
211 error => {
211 error => {
212 if (Interlocked.Increment(ref errors) == 1)
212 if (Interlocked.Increment(ref errors) == 1)
213 medium.Reject(
213 medium.Reject(
214 new Exception("The dependency promise is failed", error)
214 new Exception("The dependency promise is failed", error)
215 );
215 );
216 },
216 },
217 reason => {
217 reason => {
218 if (Interlocked.Increment(ref errors) == 1)
218 if (Interlocked.Increment(ref errors) == 1)
219 medium.Cancel(
219 medium.Cancel(
220 new Exception("The dependency promise is cancelled", reason)
220 new Exception("The dependency promise is cancelled", reason)
221 );
221 );
222 }
222 }
223 );
223 );
224 i++;
224 i++;
225 }
225 }
226
226
227 return medium;
227 return medium;
228 }
228 }
229
229
230 public static IPromise Then(this IPromise that, Action success, Action<Exception> error, Action<Exception> cancel) {
230 public static IPromise Then(this IPromise that, Action success, Action<Exception> error, Action<Exception> cancel) {
231 Safe.ArgumentNotNull(that, "that");
231 Safe.ArgumentNotNull(that, "that");
232
232
233 var d = new ActionTask(success, error, cancel, false);
233 var d = new ActionTask(success, error, cancel, false);
234 that.On(d.Resolve, d.Reject, d.CancelOperation);
234 that.On(d.Resolve, d.Reject, d.CancelOperation);
235 d.CancellationRequested(that.Cancel);
235 d.CancellationRequested(that.Cancel);
236 return d;
236 return d;
237 }
237 }
238
238
239 public static IPromise Then(this IPromise that, Action success, Action<Exception> error) {
239 public static IPromise Then(this IPromise that, Action success, Action<Exception> error) {
240 return Then(that, success, error, null);
240 return Then(that, success, error, null);
241 }
241 }
242
242
243 public static IPromise Then(this IPromise that, Action success) {
243 public static IPromise Then(this IPromise that, Action success) {
244 return Then(that, success, null, null);
244 return Then(that, success, null, null);
245 }
245 }
246
246
247 public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error, Func<Exception, T> cancel) {
247 public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error, Func<Exception, T> cancel) {
248 Safe.ArgumentNotNull(that, "that");
248 Safe.ArgumentNotNull(that, "that");
249
249
250 var d = new FuncTask<T>(success, error, cancel, false);
250 var d = new FuncTask<T>(success, error, cancel, false);
251 that.On(d.Resolve, d.Reject, d.CancelOperation);
251 that.On(d.Resolve, d.Reject, d.CancelOperation);
252 d.CancellationRequested(that.Cancel);
252 d.CancellationRequested(that.Cancel);
253 return d;
253 return d;
254 }
254 }
255
255
256 public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error) {
256 public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error) {
257 return Then(that, success, error, null);
257 return Then(that, success, error, null);
258 }
258 }
259
259
260 public static IPromise<T> Then<T>(this IPromise that, Func<T> success) {
260 public static IPromise<T> Then<T>(this IPromise that, Func<T> success) {
261 return Then(that, success, null, null);
261 return Then(that, success, null, null);
262 }
262 }
263
263
264 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error, Func<Exception, T2> cancel) {
264 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error, Func<Exception, T2> cancel) {
265 Safe.ArgumentNotNull(that, "that");
265 Safe.ArgumentNotNull(that, "that");
266 Safe.ArgumentNotNull(success, "success");
267
266 var d = new FuncTask<T, T2>(success, error, cancel, false);
268 var d = new FuncTask<T, T2>(success, error, cancel, false);
267 that.On(d.Resolve, d.Reject, d.CancelOperation);
269 that.On(d.Resolve, d.Reject, d.CancelOperation);
268 d.CancellationRequested(that.Cancel);
270 d.CancellationRequested(that.Cancel);
269 return d;
271 return d;
270 }
272 }
271
273
272 public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success, Func<Exception, T> error, Func<Exception, T> cancel) {
274 public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success, Func<Exception, T> error, Func<Exception, T> cancel) {
273 Safe.ArgumentNotNull(that, "that");
275 Safe.ArgumentNotNull(that, "that");
274 var d = new FuncTask<T, T>(
276 var d = new FuncTask<T, T>(
275 x => {
277 x => {
276 success(x);
278 success(x);
277 return x;
279 return x;
278 },
280 },
279 error,
281 error,
280 cancel,
282 cancel,
281 false
283 false
282 );
284 );
283 that.On(d.Resolve, d.Reject, d.CancelOperation);
285 that.On(d.Resolve, d.Reject, d.CancelOperation);
284 d.CancellationRequested(that.Cancel);
286 d.CancellationRequested(that.Cancel);
285 return d;
287 return d;
286 }
288 }
287
289
288 public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success, Func<Exception, T> error) {
290 public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success, Func<Exception, T> error) {
289 return Then(that, success, error, null);
291 return Then(that, success, error, null);
290 }
292 }
291
293
292 public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success) {
294 public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success) {
293 return Then(that, success, null, null);
295 return Then(that, success, null, null);
294 }
296 }
295
297
296 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error) {
298 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error) {
297 return Then(that, success, error, null);
299 return Then(that, success, error, null);
298 }
300 }
299
301
300 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success) {
302 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success) {
301 return Then(that, success, null, null);
303 return Then(that, success, null, null);
302 }
304 }
303
305
304 public static IPromise<T> Always<T>(this IPromise<T> that, Action handler) {
306 public static IPromise<T> Always<T>(this IPromise<T> that, Action handler) {
305 Func<Exception, T> errorOrCancel;
307 Func<Exception, T> errorOrCancel;
306 if (handler != null)
308 if (handler != null)
307 errorOrCancel = e => {
309 errorOrCancel = e => {
308 handler();
310 handler();
309 throw new PromiseTransientException(e);
311 throw new PromiseTransientException(e);
310 };
312 };
311 else
313 else
312 errorOrCancel = null;
314 errorOrCancel = null;
313
315
314 return Then(
316 return Then(
315 that,
317 that,
316 x => {
318 x => {
317 handler();
319 handler();
318 return x;
320 return x;
319 },
321 },
320 errorOrCancel,
322 errorOrCancel,
321 errorOrCancel);
323 errorOrCancel);
322 }
324 }
323
325
324 public static IPromise Always(this IPromise that, Action handler) {
326 public static IPromise Always(this IPromise that, Action handler) {
325 Action<Exception> errorOrCancel;
327 Action<Exception> errorOrCancel;
326 if (handler != null)
328 if (handler != null)
327 errorOrCancel = e => {
329 errorOrCancel = e => {
328 handler();
330 handler();
329 throw new PromiseTransientException(e);
331 throw new PromiseTransientException(e);
330 };
332 };
331 else
333 else
332 errorOrCancel = null;
334 errorOrCancel = null;
333
335
334 return Then(
336 return Then(
335 that,
337 that,
336 handler,
338 handler,
337 errorOrCancel,
339 errorOrCancel,
338 errorOrCancel);
340 errorOrCancel);
339 }
341 }
340
342
341 public static IPromise Error(this IPromise that, Action<Exception> handler, bool handleCancellation) {
343 public static IPromise Error(this IPromise that, Action<Exception> handler, bool handleCancellation) {
342 Action<Exception> errorOrCancel;
344 Action<Exception> errorOrCancel;
343 if (handler != null)
345 if (handler != null)
344 errorOrCancel = e => {
346 errorOrCancel = e => {
345 handler(e);
347 handler(e);
346 throw new PromiseTransientException(e);
348 throw new PromiseTransientException(e);
347 };
349 };
348 else
350 else
349 errorOrCancel = null;
351 errorOrCancel = null;
350
352
351 return Then(that, null, errorOrCancel, handleCancellation ? errorOrCancel : null);
353 return Then(that, null, errorOrCancel, handleCancellation ? errorOrCancel : null);
352 }
354 }
353
355
354 public static IPromise Error(this IPromise that, Action<Exception> handler) {
356 public static IPromise Error(this IPromise that, Action<Exception> handler) {
355 return Error(that, handler, false);
357 return Error(that, handler, false);
356 }
358 }
357
359
358 public static IPromise<T> Error<T>(this IPromise<T> that, Action<Exception> handler, bool handleCancellation) {
360 public static IPromise<T> Error<T>(this IPromise<T> that, Action<Exception> handler, bool handleCancellation) {
359 Func<Exception, T> errorOrCancel;
361 Func<Exception, T> errorOrCancel;
360 if (handler != null)
362 if (handler != null)
361 errorOrCancel = e => {
363 errorOrCancel = e => {
362 handler(e);
364 handler(e);
363 throw new PromiseTransientException(e);
365 throw new PromiseTransientException(e);
364 };
366 };
365 else
367 else
366 errorOrCancel = null;
368 errorOrCancel = null;
367
369
368 return Then(that, null, errorOrCancel, handleCancellation ? errorOrCancel : null);
370 return Then(that, null, errorOrCancel, handleCancellation ? errorOrCancel : null);
369 }
371 }
370
372
371 public static IPromise<T> Error<T>(this IPromise<T> that, Action<Exception> handler) {
373 public static IPromise<T> Error<T>(this IPromise<T> that, Action<Exception> handler) {
372 return Error(that, handler, false);
374 return Error(that, handler, false);
373 }
375 }
374
376
375 #region chain traits
377 #region chain traits
376 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel) {
378 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel) {
377 Safe.ArgumentNotNull(that, "that");
379 Safe.ArgumentNotNull(that, "that");
378
380
379 var d = new ActionChainTask(success, error, cancel, false);
381 var d = new ActionChainTask(success, error, cancel, false);
380 that.On(d.Resolve, d.Reject, d.CancelOperation);
382 that.On(d.Resolve, d.Reject, d.CancelOperation);
381 d.CancellationRequested(that.Cancel);
383 d.CancellationRequested(that.Cancel);
382 return d;
384 return d;
383 }
385 }
384
386
385 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception, IPromise> error) {
387 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception, IPromise> error) {
386 return Chain(that, success, error, null);
388 return Chain(that, success, error, null);
387 }
389 }
388
390
389 public static IPromise Chain(this IPromise that, Func<IPromise> success) {
391 public static IPromise Chain(this IPromise that, Func<IPromise> success) {
390 return Chain(that, success, null, null);
392 return Chain(that, success, null, null);
391 }
393 }
392
394
393 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error, Func<Exception, IPromise<T>> cancel) {
395 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error, Func<Exception, IPromise<T>> cancel) {
394 Safe.ArgumentNotNull(that, "that");
396 Safe.ArgumentNotNull(that, "that");
395
397
396 var d = new FuncChainTask<T>(success, error, cancel, false);
398 var d = new FuncChainTask<T>(success, error, cancel, false);
397 that.On(d.Resolve, d.Reject, d.CancelOperation);
399 that.On(d.Resolve, d.Reject, d.CancelOperation);
398 if (success != null)
400 if (success != null)
399 d.CancellationRequested(that.Cancel);
401 d.CancellationRequested(that.Cancel);
400 return d;
402 return d;
401 }
403 }
402
404
403 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error) {
405 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error) {
404 return Chain(that, success, error, null);
406 return Chain(that, success, error, null);
405 }
407 }
406
408
407 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success) {
409 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success) {
408 return Chain(that, success, null, null);
410 return Chain(that, success, null, null);
409 }
411 }
410
412
411 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel) {
413 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel) {
412 Safe.ArgumentNotNull(that, "that");
414 Safe.ArgumentNotNull(that, "that");
413 var d = new FuncChainTask<T, T2>(success, error, cancel, false);
415 var d = new FuncChainTask<T, T2>(success, error, cancel, false);
414 that.On(d.Resolve, d.Reject, d.CancelOperation);
416 that.On(d.Resolve, d.Reject, d.CancelOperation);
415 if (success != null)
417 if (success != null)
416 d.CancellationRequested(that.Cancel);
418 d.CancellationRequested(that.Cancel);
417 return d;
419 return d;
418 }
420 }
419
421
420 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error) {
422 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error) {
421 return Chain(that, success, error, null);
423 return Chain(that, success, error, null);
422 }
424 }
423
425
424 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success) {
426 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success) {
425 return Chain(that, success, null, null);
427 return Chain(that, success, null, null);
426 }
428 }
427
429
428 #endregion
430 #endregion
429
431
432 public static IPromise<T2> Guard<T, T2>(this IPromise<T> that, Func<IPromise<T>, IPromise<T2>> continuation, Action<T> cleanup) {
433 Safe.ArgumentNotNull(that, "that");
434 Safe.ArgumentNotNull(continuation, "continuation");
435 return continuation(that).Error((err) => {
436 that.On(cleanup);
437 }, true);
438 }
430
439
431 #if NET_4_5
440 #if NET_4_5
432
441
433 public static PromiseAwaiter<T> GetAwaiter<T>(this IPromise<T> that) {
442 public static PromiseAwaiter<T> GetAwaiter<T>(this IPromise<T> that) {
434 Safe.ArgumentNotNull(that, "that");
443 Safe.ArgumentNotNull(that, "that");
435
444
436 return new PromiseAwaiter<T>(that);
445 return new PromiseAwaiter<T>(that);
437 }
446 }
438
447
439 public static PromiseAwaiter GetAwaiter(this IPromise that) {
448 public static PromiseAwaiter GetAwaiter(this IPromise that) {
440 Safe.ArgumentNotNull(that, "that");
449 Safe.ArgumentNotNull(that, "that");
441
450
442 return new PromiseAwaiter(that);
451 return new PromiseAwaiter(that);
443 }
452 }
444
453
454 public static IPromise BoundCancellationToken(this IPromise that, CancellationToken ct) {
455 Safe.ArgumentNotNull(that, "that");
456 ct.Register(that.Cancel);
457 return that.Then(null, null, (err) => {
458 ct.ThrowIfCancellationRequested();
459 throw new PromiseTransientException(err);
460 });
461 }
462
463 public static IPromise<T> BoundCancellationToken<T>(this IPromise<T> that, CancellationToken ct) {
464 Safe.ArgumentNotNull(that, "that");
465 ct.Register(that.Cancel);
466 return that.Then(null, null, (err) => {
467 ct.ThrowIfCancellationRequested();
468 throw new PromiseTransientException(err);
469 });
470 }
471
445 #endif
472 #endif
446 }
473 }
447 }
474 }
448
475
@@ -1,131 +1,132
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5 using System.Text.RegularExpressions;
5 using System.Text.RegularExpressions;
6 using System.Diagnostics;
6 using System.Diagnostics;
7 using System.Collections;
7 using System.Collections;
8
8
9 namespace Implab
9 namespace Implab
10 {
10 {
11 public static class Safe
11 public static class Safe
12 {
12 {
13 public static void ArgumentAssert(bool condition, string paramName) {
13 public static void ArgumentAssert(bool condition, string paramName) {
14 if (!condition)
14 if (!condition)
15 throw new ArgumentException("The parameter is invalid", paramName);
15 throw new ArgumentException("The parameter is invalid", paramName);
16 }
16 }
17
17
18 public static void ArgumentMatch(string value, string paramName, Regex rx) {
18 public static void ArgumentMatch(string value, string paramName, Regex rx) {
19 if (rx == null)
19 if (rx == null)
20 throw new ArgumentNullException("rx");
20 throw new ArgumentNullException("rx");
21 if (!rx.IsMatch(value))
21 if (!rx.IsMatch(value))
22 throw new ArgumentException(String.Format("The prameter value must match {0}", rx), paramName);
22 throw new ArgumentException(String.Format("The prameter value must match {0}", rx), paramName);
23 }
23 }
24
24
25 public static void ArgumentNotEmpty(string value, string paramName) {
25 public static void ArgumentNotEmpty(string value, string paramName) {
26 if (String.IsNullOrEmpty(value))
26 if (String.IsNullOrEmpty(value))
27 throw new ArgumentException("The parameter can't be empty", paramName);
27 throw new ArgumentException("The parameter can't be empty", paramName);
28 }
28 }
29
29
30 public static void ArgumentNotEmpty<T>(T[] value, string paramName) {
30 public static void ArgumentNotEmpty<T>(T[] value, string paramName) {
31 if (value == null || value.Length == 0)
31 if (value == null || value.Length == 0)
32 throw new ArgumentException("The array must be not emty", paramName);
32 throw new ArgumentException("The array must be not emty", paramName);
33 }
33 }
34
34
35 public static void ArgumentNotNull(object value, string paramName) {
35 public static void ArgumentNotNull(object value, string paramName) {
36 if (value == null)
36 if (value == null)
37 throw new ArgumentNullException(paramName);
37 throw new ArgumentNullException(paramName);
38 }
38 }
39
39
40 public static void ArgumentInRange(int value, int min, int max, string paramName) {
40 public static void ArgumentInRange(int value, int min, int max, string paramName) {
41 if (value < min || value > max)
41 if (value < min || value > max)
42 throw new ArgumentOutOfRangeException(paramName);
42 throw new ArgumentOutOfRangeException(paramName);
43 }
43 }
44
44
45 public static void ArgumentOfType(object value, Type type, string paramName) {
45 public static void ArgumentOfType(object value, Type type, string paramName) {
46 if (!type.IsInstanceOfType(value))
46 if (!type.IsInstanceOfType(value))
47 throw new ArgumentException(String.Format("The parameter must be of type {0}", type), paramName);
47 throw new ArgumentException(String.Format("The parameter must be of type {0}", type), paramName);
48 }
48 }
49
49
50 public static void Dispose(params IDisposable[] objects) {
50 public static void Dispose(params IDisposable[] objects) {
51 foreach (var d in objects)
51 foreach (var d in objects)
52 if (d != null)
52 if (d != null)
53 d.Dispose();
53 d.Dispose();
54 }
54 }
55
55
56 public static void Dispose(params object[] objects) {
56 public static void Dispose(params object[] objects) {
57 foreach (var obj in objects) {
57 foreach (var obj in objects) {
58 var d = obj as IDisposable;
58 var d = obj as IDisposable;
59 if (d != null)
59 if (d != null)
60 d.Dispose();
60 d.Dispose();
61 }
61 }
62 }
62 }
63
63
64 public static void Dispose(IEnumerable<IDisposable> objects) {
64 public static void Dispose(IEnumerable<IDisposable> objects) {
65 foreach (var d in objects)
65 foreach (var d in objects)
66 if (d != null)
66 if (d != null)
67 d.Dispose();
67 d.Dispose();
68 }
68 }
69
69
70 public static void Dispose(object obj) {
70 public static void Dispose(object obj) {
71 var d = obj as IDisposable;
71 var d = obj as IDisposable;
72 if (d != null)
72 if (d != null)
73 d.Dispose();
73 d.Dispose();
74 }
74 }
75
75
76 public static void DispatchEvent<T>(this EventHandler<T> handler, object sender, T args) {
76 public static void DispatchEvent<T>(this EventHandler<T> handler, object sender, T args) {
77 if (handler != null)
77 if (handler != null)
78 handler(sender, args);
78 handler(sender, args);
79 }
79 }
80
80
81 public static void DispatchEvent(this EventHandler handler, object sender, EventArgs args) {
81 public static void DispatchEvent(this EventHandler handler, object sender, EventArgs args) {
82 if (handler != null)
82 if (handler != null)
83 handler(sender, args);
83 handler(sender, args);
84 }
84 }
85
85
86 [DebuggerStepThrough]
86 [DebuggerStepThrough]
87 public static IPromise<T> Run<T>(Func<T> action) {
87 public static IPromise<T> Run<T>(Func<T> action) {
88 ArgumentNotNull(action, "action");
88 ArgumentNotNull(action, "action");
89
89
90 try {
90 try {
91 return Promise<T>.FromResult(action());
91 return Promise<T>.FromResult(action());
92 } catch (Exception err) {
92 } catch (Exception err) {
93 return Promise<T>.FromException(err);
93 return Promise<T>.FromException(err);
94 }
94 }
95 }
95 }
96
96
97 [DebuggerStepThrough]
97 [DebuggerStepThrough]
98 public static IPromise Run(Action action) {
98 public static IPromise Run(Action action) {
99 ArgumentNotNull(action, "action");
99 ArgumentNotNull(action, "action");
100
100
101 try {
101 try {
102 action();
102 action();
103 return Promise.Success;
103 return Promise.Success;
104 } catch (Exception err) {
104 } catch (Exception err) {
105 return new FailedPromise(err);
105 return new FailedPromise(err);
106 }
106 }
107 }
107 }
108
108
109 [DebuggerStepThrough]
109 [DebuggerStepThrough]
110 public static IPromise Run(Func<IPromise> action) {
110 public static IPromise Run(Func<IPromise> action) {
111 ArgumentNotNull(action, "action");
111 ArgumentNotNull(action, "action");
112
112
113 try {
113 try {
114 return action() ?? new FailedPromise(new Exception("The action returned null"));
114 return action() ?? new FailedPromise(new Exception("The action returned null"));
115 } catch (Exception err) {
115 } catch (Exception err) {
116 return new FailedPromise(err);
116 return new FailedPromise(err);
117 }
117 }
118 }
118 }
119
119
120 [DebuggerStepThrough]
120 [DebuggerStepThrough]
121 public static IPromise<T> Run<T>(Func<IPromise<T>> action) {
121 public static IPromise<T> Run<T>(Func<IPromise<T>> action) {
122 ArgumentNotNull(action, "action");
122 ArgumentNotNull(action, "action");
123
123
124 try {
124 try {
125 return action() ?? Promise<T>.FromException(new Exception("The action returned null"));
125 return action() ?? Promise<T>.FromException(new Exception("The action returned null"));
126 } catch (Exception err) {
126 } catch (Exception err) {
127 return Promise<T>.FromException(err);
127 return Promise<T>.FromException(err);
128 }
128 }
129 }
129 }
130
130 }
131 }
131 }
132 }
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

ok, latest stable version should be in default

You need to be logged in to leave comments. Login now