comparison Implab/PromiseExtensions.cs @ 192:f1da3afc3521 release v2.1

Слияние с v2
author cin
date Fri, 22 Apr 2016 13:10:34 +0300
parents 822aab37b107
children 8200ab154c8a
comparison
equal deleted inserted replaced
71:1714fd8678ef 192:f1da3afc3521
1 using System.Threading;
2 using System;
3 using Implab.Diagnostics;
4 using System.Collections.Generic;
5
6 namespace Implab {
7 public static class PromiseExtensions {
8 public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) {
9 Safe.ArgumentNotNull(that, "that");
10 var context = SynchronizationContext.Current;
11 if (context == null)
12 return that;
13
14 var p = new SyncContextPromise<T>(context);
15 p.CancellationRequested(that.Cancel);
16
17 that.On(
18 p.Resolve,
19 p.Reject,
20 p.CancelOperation
21 );
22 return p;
23 }
24
25 public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) {
26 Safe.ArgumentNotNull(that, "that");
27 Safe.ArgumentNotNull(context, "context");
28
29 var p = new SyncContextPromise<T>(context);
30 p.CancellationRequested(that.Cancel);
31
32 that.On(
33 p.Resolve,
34 p.Reject,
35 p.CancelOperation
36 );
37 return p;
38 }
39
40 /// <summary>
41 /// Ensures the dispatched.
42 /// </summary>
43 /// <returns>The dispatched.</returns>
44 /// <param name="that">That.</param>
45 /// <param name="head">Head.</param>
46 /// <param name="cleanup">Cleanup.</param>
47 /// <typeparam name="TPromise">The 1st type parameter.</typeparam>
48 /// <typeparam name="T">The 2nd type parameter.</typeparam>
49 public static TPromise EnsureDispatched<TPromise,T>(this TPromise that, IPromise<T> head, Action<T> cleanup) where TPromise : IPromise{
50 Safe.ArgumentNotNull(that, "that");
51 Safe.ArgumentNotNull(head, "head");
52
53 that.On(() => head.On(cleanup), PromiseEventType.Cancelled);
54
55 return that;
56 }
57
58 public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult,T> callback) {
59 Safe.ArgumentNotNull(that, "that");
60 Safe.ArgumentNotNull(callback, "callback");
61 var op = TraceContext.Instance.CurrentOperation;
62 return ar => {
63 TraceContext.Instance.EnterLogicalOperation(op,false);
64 try {
65 that.Resolve(callback(ar));
66 } catch (Exception err) {
67 that.Reject(err);
68 } finally {
69 TraceContext.Instance.Leave();
70 }
71 };
72 }
73
74 static void CancelByTimeoutCallback(object cookie) {
75 ((ICancellable)cookie).Cancel(new TimeoutException());
76 }
77
78 /// <summary>
79 /// Cancells promise after the specified timeout is elapsed.
80 /// </summary>
81 /// <param name="that">The promise to cancel on timeout.</param>
82 /// <param name="milliseconds">The timeout in milliseconds.</param>
83 /// <typeparam name="TPromise">The 1st type parameter.</typeparam>
84 public static TPromise Timeout<TPromise>(this TPromise that, int milliseconds) where TPromise : IPromise {
85 Safe.ArgumentNotNull(that, "that");
86 var timer = new Timer(CancelByTimeoutCallback, that, milliseconds, -1);
87 that.On(timer.Dispose, PromiseEventType.All);
88 return that;
89 }
90
91 public static IPromise Bundle(this ICollection<IPromise> that) {
92 Safe.ArgumentNotNull(that, "that");
93
94 int count = that.Count;
95 int errors = 0;
96 var medium = new Promise();
97
98 if (count == 0) {
99 medium.Resolve();
100 return medium;
101 }
102
103 medium.On(() => {
104 foreach(var p2 in that)
105 p2.Cancel();
106 }, PromiseEventType.ErrorOrCancel);
107
108 foreach (var p in that)
109 p.On(
110 () => {
111 if (Interlocked.Decrement(ref count) == 0)
112 medium.Resolve();
113 },
114 error => {
115 if (Interlocked.Increment(ref errors) == 1)
116 medium.Reject(
117 new Exception("The dependency promise is failed", error)
118 );
119 },
120 reason => {
121 if (Interlocked.Increment(ref errors) == 1)
122 medium.Cancel(
123 new Exception("The dependency promise is cancelled")
124 );
125 }
126 );
127
128 return medium;
129 }
130
131 public static IPromise<T[]> Bundle<T>(this ICollection<IPromise<T>> that) {
132 Safe.ArgumentNotNull(that, "that");
133
134 int count = that.Count;
135 int errors = 0;
136 var medium = new Promise<T[]>();
137 var results = new T[that.Count];
138
139 medium.On(() => {
140 foreach(var p2 in that)
141 p2.Cancel();
142 }, PromiseEventType.ErrorOrCancel);
143
144 int i = 0;
145 foreach (var p in that) {
146 var idx = i;
147 p.On(
148 x => {
149 results[idx] = x;
150 if (Interlocked.Decrement(ref count) == 0)
151 medium.Resolve(results);
152 },
153 error => {
154 if (Interlocked.Increment(ref errors) == 1)
155 medium.Reject(
156 new Exception("The dependency promise is failed", error)
157 );
158 },
159 reason => {
160 if (Interlocked.Increment(ref errors) == 1)
161 medium.Cancel(
162 new Exception("The dependency promise is cancelled", reason)
163 );
164 }
165 );
166 i++;
167 }
168
169 return medium;
170 }
171
172 public static IPromise Then(this IPromise that, Action success, Action<Exception> error, Action<Exception> cancel) {
173 Safe.ArgumentNotNull(that, "that");
174
175 var d = new ActionTask(success, error, cancel, false);
176 that.On(d.Resolve, d.Reject, d.CancelOperation);
177 d.CancellationRequested(that.Cancel);
178 return d;
179 }
180
181 public static IPromise Then(this IPromise that, Action success, Action<Exception> error) {
182 return Then(that, success, error, null);
183 }
184
185 public static IPromise Then(this IPromise that, Action success) {
186 return Then(that, success, null, null);
187 }
188
189 public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error, Func<Exception, T> cancel) {
190 Safe.ArgumentNotNull(that, "that");
191
192 var d = new FuncTask<T>(success, error, cancel, false);
193 that.On(d.Resolve, d.Reject, d.CancelOperation);
194 d.CancellationRequested(that.Cancel);
195 return d;
196 }
197
198 public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error) {
199 return Then(that, success, error, null);
200 }
201
202 public static IPromise<T> Then<T>(this IPromise that, Func<T> success) {
203 return Then(that, success, null, null);
204 }
205
206 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error, Func<Exception, T2> cancel) {
207 Safe.ArgumentNotNull(that, "that");
208 var d = new FuncTask<T,T2>(success, error, cancel, false);
209 that.On(d.Resolve, d.Reject, d.CancelOperation);
210 d.CancellationRequested(that.Cancel);
211 return d;
212 }
213
214 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error) {
215 return Then(that, success, error, null);
216 }
217
218 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success) {
219 return Then(that, success, null, null);
220 }
221
222 #region chain traits
223 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception,IPromise> error, Func<Exception,IPromise> cancel) {
224 Safe.ArgumentNotNull(that, "that");
225
226 var d = new ActionChainTask(success, error, cancel, false);
227 that.On(d.Resolve, d.Reject, d.CancelOperation);
228 d.CancellationRequested(that.Cancel);
229 return d;
230 }
231
232 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception,IPromise> error) {
233 return Chain(that, success, error, null);
234 }
235
236 public static IPromise Chain(this IPromise that, Func<IPromise> success) {
237 return Chain(that, success, null, null);
238 }
239
240 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error, Func<Exception, IPromise<T>> cancel) {
241 Safe.ArgumentNotNull(that, "that");
242
243 var d = new FuncChainTask<T>(success, error, cancel, false);
244 that.On(d.Resolve, d.Reject, d.CancelOperation);
245 if (success != null)
246 d.CancellationRequested(that.Cancel);
247 return d;
248 }
249
250 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error) {
251 return Chain(that, success, error, null);
252 }
253
254 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success) {
255 return Chain(that, success, null, null);
256 }
257
258 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) {
259 Safe.ArgumentNotNull(that, "that");
260 var d = new FuncChainTask<T,T2>(success, error, cancel, false);
261 that.On(d.Resolve, d.Reject, d.CancelOperation);
262 if (success != null)
263 d.CancellationRequested(that.Cancel);
264 return d;
265 }
266
267 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error) {
268 return Chain(that, success, error, null);
269 }
270
271 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success) {
272 return Chain(that, success, null, null);
273 }
274
275 #endregion
276
277
278 #if NET_4_5
279
280 public static PromiseAwaiter<T> GetAwaiter<T>(this IPromise<T> that) {
281 Safe.ArgumentNotNull(that, "that");
282
283 return new PromiseAwaiter<T>(that);
284 }
285
286 #endif
287 }
288 }
289