Mercurial > pub > ImplabNet
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 |