Mercurial > pub > ImplabNet
annotate Implab/PromiseExtensions.cs @ 243:b1e0ffdf3451 v3
working on promises
author | cin |
---|---|
date | Wed, 24 Jan 2018 19:24:10 +0300 |
parents | a867536c68fc |
children | 5cb4826c2c2a |
rev | line source |
---|---|
72 | 1 using System.Threading; |
75 | 2 using System; |
109 | 3 using Implab.Diagnostics; |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
4 using System.Collections.Generic; |
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
185
diff
changeset
|
5 using System.Linq; |
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
185
diff
changeset
|
6 |
72 | 7 namespace Implab { |
8 public static class PromiseExtensions { | |
9 public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) { | |
75 | 10 Safe.ArgumentNotNull(that, "that"); |
72 | 11 var context = SynchronizationContext.Current; |
12 if (context == null) | |
13 return that; | |
14 | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
15 var p = new SyncContextPromise<T>(context); |
185 | 16 p.CancellationRequested(that.Cancel); |
72 | 17 |
104 | 18 that.On( |
76 | 19 p.Resolve, |
20 p.Reject, | |
185 | 21 p.CancelOperation |
72 | 22 ); |
23 return p; | |
24 } | |
25 | |
26 public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) { | |
75 | 27 Safe.ArgumentNotNull(that, "that"); |
72 | 28 Safe.ArgumentNotNull(context, "context"); |
29 | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
30 var p = new SyncContextPromise<T>(context); |
185 | 31 p.CancellationRequested(that.Cancel); |
72 | 32 |
104 | 33 that.On( |
76 | 34 p.Resolve, |
35 p.Reject, | |
185 | 36 p.CancelOperation |
72 | 37 ); |
38 return p; | |
39 } | |
75 | 40 |
101 | 41 /// <summary> |
42 /// Ensures the dispatched. | |
43 /// </summary> | |
44 /// <returns>The dispatched.</returns> | |
45 /// <param name="that">That.</param> | |
46 /// <param name="head">Head.</param> | |
47 /// <param name="cleanup">Cleanup.</param> | |
48 /// <typeparam name="TPromise">The 1st type parameter.</typeparam> | |
49 /// <typeparam name="T">The 2nd type parameter.</typeparam> | |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
50 public static TPromise EnsureDispatched<TPromise, T>(this TPromise that, IPromise<T> head, Action<T> cleanup) where TPromise : IPromise { |
101 | 51 Safe.ArgumentNotNull(that, "that"); |
52 Safe.ArgumentNotNull(head, "head"); | |
53 | |
138
f75cfa58e3d4
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents:
136
diff
changeset
|
54 that.On(() => head.On(cleanup), PromiseEventType.Cancelled); |
101 | 55 |
56 return that; | |
57 } | |
58 | |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
59 /// <summary> |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
60 /// Adds a cancellation point to the chain of promises. When a cancellation request reaches the cancellation point the operation is |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
61 /// cancelled immediatelly, and the request is passed towards. If the operation at the higher level can not be cancelled is't result |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
62 /// will be collected with <paramref name="cleanup"/> callback. |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
63 /// </summary> |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
64 /// <typeparam name="T">The type of the promise result.</typeparam> |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
65 /// <param name="that">The promise to which the cancellation point should be attached.</param> |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
66 /// <param name="cleanup">The callback which is used to cleanup the result of the operation if the cancellation point is cancelled already.</param> |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
67 /// <returns>The promise</returns> |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
68 public static IPromise<T> CancellationPoint<T>(this IPromise<T> that, Action<T> cleanup) { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
69 var meduim = new Promise<T>(); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
70 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
71 that.On(meduim.Resolve, meduim.Reject, meduim.CancelOperation); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
72 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
73 meduim.CancellationRequested(that.Cancel); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
74 meduim.CancellationRequested(meduim.CancelOperation); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
75 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
76 if (cleanup != null) |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
77 meduim.On((Action<T>)null, null, (e) => { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
78 that.On(cleanup); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
79 }); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
80 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
81 return meduim; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
82 } |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
83 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
84 public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult, T> callback) { |
75 | 85 Safe.ArgumentNotNull(that, "that"); |
86 Safe.ArgumentNotNull(callback, "callback"); | |
109 | 87 var op = TraceContext.Instance.CurrentOperation; |
75 | 88 return ar => { |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
89 TraceContext.Instance.EnterLogicalOperation(op, false); |
75 | 90 try { |
91 that.Resolve(callback(ar)); | |
92 } catch (Exception err) { | |
93 that.Reject(err); | |
109 | 94 } finally { |
95 TraceContext.Instance.Leave(); | |
75 | 96 } |
97 }; | |
98 } | |
110 | 99 |
185 | 100 static void CancelByTimeoutCallback(object cookie) { |
101 ((ICancellable)cookie).Cancel(new TimeoutException()); | |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
102 } |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
103 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
104 /// <summary> |
110 | 105 /// Cancells promise after the specified timeout is elapsed. |
106 /// </summary> | |
107 /// <param name="that">The promise to cancel on timeout.</param> | |
108 /// <param name="milliseconds">The timeout in milliseconds.</param> | |
109 /// <typeparam name="TPromise">The 1st type parameter.</typeparam> | |
110 public static TPromise Timeout<TPromise>(this TPromise that, int milliseconds) where TPromise : IPromise { | |
111 Safe.ArgumentNotNull(that, "that"); | |
185 | 112 var timer = new Timer(CancelByTimeoutCallback, that, milliseconds, -1); |
110 | 113 that.On(timer.Dispose, PromiseEventType.All); |
114 return that; | |
115 } | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
116 |
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
185
diff
changeset
|
117 public static IPromise PromiseAll(this IEnumerable<IPromise> that) { |
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
185
diff
changeset
|
118 Safe.ArgumentNotNull(that, "that"); |
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
185
diff
changeset
|
119 return PromiseAll(that.ToList()); |
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
185
diff
changeset
|
120 } |
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
185
diff
changeset
|
121 |
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
185
diff
changeset
|
122 public static IPromise<T[]> PromiseAll<T>(this IEnumerable<IPromise<T>> that) { |
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
123 return PromiseAll(that, null); |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
124 } |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
125 |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
126 public static IPromise<T[]> PromiseAll<T>(this IEnumerable<IPromise<T>> that, Action<T> cleanup) { |
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
185
diff
changeset
|
127 Safe.ArgumentNotNull(that, "that"); |
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
128 return PromiseAll(that.ToList(), cleanup); |
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
185
diff
changeset
|
129 } |
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
185
diff
changeset
|
130 |
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
185
diff
changeset
|
131 public static IPromise PromiseAll(this ICollection<IPromise> that) { |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
132 Safe.ArgumentNotNull(that, "that"); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
133 |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
134 int count = that.Count; |
124 | 135 int errors = 0; |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
136 var medium = new Promise(); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
137 |
136 | 138 if (count == 0) { |
139 medium.Resolve(); | |
140 return medium; | |
141 } | |
142 | |
124 | 143 medium.On(() => { |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
144 foreach (var p2 in that) |
124 | 145 p2.Cancel(); |
146 }, PromiseEventType.ErrorOrCancel); | |
147 | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
148 foreach (var p in that) |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
149 p.On( |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
150 () => { |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
151 if (Interlocked.Decrement(ref count) == 0) |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
152 medium.Resolve(); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
153 }, |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
154 error => { |
124 | 155 if (Interlocked.Increment(ref errors) == 1) |
156 medium.Reject( | |
157 new Exception("The dependency promise is failed", error) | |
158 ); | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
159 }, |
138
f75cfa58e3d4
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents:
136
diff
changeset
|
160 reason => { |
124 | 161 if (Interlocked.Increment(ref errors) == 1) |
138
f75cfa58e3d4
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents:
136
diff
changeset
|
162 medium.Cancel( |
124 | 163 new Exception("The dependency promise is cancelled") |
164 ); | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
165 } |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
166 ); |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
167 |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
168 return medium; |
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
110
diff
changeset
|
169 } |
124 | 170 |
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
171 public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that) { |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
172 return PromiseAll(that, null); |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
173 } |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
174 |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
175 /// <summary> |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
176 /// Creates a new promise which will be satisfied when all promises are satisfied. |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
177 /// </summary> |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
178 /// <typeparam name="T"></typeparam> |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
179 /// <param name="that"></param> |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
180 /// <param name="cleanup">A callback used to cleanup already resolved promises in case of an error</param> |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
181 /// <returns></returns> |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
182 public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that, Action<T> cleanup) { |
209 | 183 Safe.ArgumentNotNull(that, "that"); |
184 | |
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
185 int count = that.Count; |
124 | 186 |
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
187 if (count == 0) |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
188 return Promise<T[]>.FromResult(new T[0]); |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
189 |
124 | 190 int errors = 0; |
191 var medium = new Promise<T[]>(); | |
192 var results = new T[that.Count]; | |
193 | |
194 medium.On(() => { | |
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
195 foreach (var p2 in that) { |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
196 p2.Cancel(); |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
197 if (cleanup != null) |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
198 p2.On(cleanup); |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
199 } |
124 | 200 }, PromiseEventType.ErrorOrCancel); |
201 | |
202 int i = 0; | |
203 foreach (var p in that) { | |
204 var idx = i; | |
205 p.On( | |
206 x => { | |
207 results[idx] = x; | |
208 if (Interlocked.Decrement(ref count) == 0) | |
209 medium.Resolve(results); | |
210 }, | |
211 error => { | |
212 if (Interlocked.Increment(ref errors) == 1) | |
213 medium.Reject( | |
214 new Exception("The dependency promise is failed", error) | |
215 ); | |
216 }, | |
138
f75cfa58e3d4
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents:
136
diff
changeset
|
217 reason => { |
124 | 218 if (Interlocked.Increment(ref errors) == 1) |
138
f75cfa58e3d4
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents:
136
diff
changeset
|
219 medium.Cancel( |
f75cfa58e3d4
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
cin
parents:
136
diff
changeset
|
220 new Exception("The dependency promise is cancelled", reason) |
124 | 221 ); |
222 } | |
223 ); | |
224 i++; | |
225 } | |
226 | |
227 return medium; | |
228 } | |
145 | 229 |
230 public static IPromise Then(this IPromise that, Action success, Action<Exception> error, Action<Exception> cancel) { | |
231 Safe.ArgumentNotNull(that, "that"); | |
232 | |
149 | 233 var d = new ActionTask(success, error, cancel, false); |
145 | 234 that.On(d.Resolve, d.Reject, d.CancelOperation); |
185 | 235 d.CancellationRequested(that.Cancel); |
145 | 236 return d; |
237 } | |
238 | |
239 public static IPromise Then(this IPromise that, Action success, Action<Exception> error) { | |
240 return Then(that, success, error, null); | |
241 } | |
242 | |
243 public static IPromise Then(this IPromise that, Action success) { | |
244 return Then(that, success, null, null); | |
245 } | |
246 | |
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"); | |
249 | |
149 | 250 var d = new FuncTask<T>(success, error, cancel, false); |
145 | 251 that.On(d.Resolve, d.Reject, d.CancelOperation); |
185 | 252 d.CancellationRequested(that.Cancel); |
145 | 253 return d; |
254 } | |
255 | |
256 public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error) { | |
257 return Then(that, success, error, null); | |
258 } | |
259 | |
260 public static IPromise<T> Then<T>(this IPromise that, Func<T> success) { | |
261 return Then(that, success, null, null); | |
262 } | |
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) { | |
265 Safe.ArgumentNotNull(that, "that"); | |
209 | 266 Safe.ArgumentNotNull(success, "success"); |
267 | |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
268 var d = new FuncTask<T, T2>(success, error, cancel, false); |
145 | 269 that.On(d.Resolve, d.Reject, d.CancelOperation); |
185 | 270 d.CancellationRequested(that.Cancel); |
145 | 271 return d; |
272 } | |
273 | |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
274 public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success, Func<Exception, T> error, Func<Exception, T> cancel) { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
275 Safe.ArgumentNotNull(that, "that"); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
276 var d = new FuncTask<T, T>( |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
277 x => { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
278 success(x); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
279 return x; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
280 }, |
209 | 281 error, |
282 cancel, | |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
283 false |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
284 ); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
285 that.On(d.Resolve, d.Reject, d.CancelOperation); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
286 d.CancellationRequested(that.Cancel); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
287 return d; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
288 } |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
289 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
290 public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success, Func<Exception, T> error) { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
291 return Then(that, success, error, null); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
292 } |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
293 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
294 public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success) { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
295 return Then(that, success, null, null); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
296 } |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
297 |
145 | 298 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error) { |
299 return Then(that, success, error, null); | |
300 } | |
301 | |
302 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success) { | |
303 return Then(that, success, null, null); | |
304 } | |
305 | |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
306 public static IPromise<T> Always<T>(this IPromise<T> that, Action handler) { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
307 Func<Exception, T> errorOrCancel; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
308 if (handler != null) |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
309 errorOrCancel = e => { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
310 handler(); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
311 throw new PromiseTransientException(e); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
312 }; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
313 else |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
314 errorOrCancel = null; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
315 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
316 return Then( |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
317 that, |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
318 x => { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
319 handler(); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
320 return x; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
321 }, |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
322 errorOrCancel, |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
323 errorOrCancel); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
324 } |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
325 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
326 public static IPromise Always(this IPromise that, Action handler) { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
327 Action<Exception> errorOrCancel; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
328 if (handler != null) |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
329 errorOrCancel = e => { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
330 handler(); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
331 throw new PromiseTransientException(e); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
332 }; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
333 else |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
334 errorOrCancel = null; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
335 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
336 return Then( |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
337 that, |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
338 handler, |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
339 errorOrCancel, |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
340 errorOrCancel); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
341 } |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
342 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
343 public static IPromise Error(this IPromise that, Action<Exception> handler, bool handleCancellation) { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
344 Action<Exception> errorOrCancel; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
345 if (handler != null) |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
346 errorOrCancel = e => { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
347 handler(e); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
348 throw new PromiseTransientException(e); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
349 }; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
350 else |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
351 errorOrCancel = null; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
352 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
353 return Then(that, null, errorOrCancel, handleCancellation ? errorOrCancel : null); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
354 } |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
355 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
356 public static IPromise Error(this IPromise that, Action<Exception> handler) { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
357 return Error(that, handler, false); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
358 } |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
359 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
360 public static IPromise<T> Error<T>(this IPromise<T> that, Action<Exception> handler, bool handleCancellation) { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
361 Func<Exception, T> errorOrCancel; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
362 if (handler != null) |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
363 errorOrCancel = e => { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
364 handler(e); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
365 throw new PromiseTransientException(e); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
366 }; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
367 else |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
368 errorOrCancel = null; |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
369 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
370 return Then(that, null, errorOrCancel, handleCancellation ? errorOrCancel : null); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
371 } |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
372 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
373 public static IPromise<T> Error<T>(this IPromise<T> that, Action<Exception> handler) { |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
374 return Error(that, handler, false); |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
375 } |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
376 |
145 | 377 #region chain traits |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
378 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel) { |
145 | 379 Safe.ArgumentNotNull(that, "that"); |
380 | |
149 | 381 var d = new ActionChainTask(success, error, cancel, false); |
145 | 382 that.On(d.Resolve, d.Reject, d.CancelOperation); |
185 | 383 d.CancellationRequested(that.Cancel); |
145 | 384 return d; |
385 } | |
386 | |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
387 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception, IPromise> error) { |
145 | 388 return Chain(that, success, error, null); |
389 } | |
390 | |
391 public static IPromise Chain(this IPromise that, Func<IPromise> success) { | |
392 return Chain(that, success, null, null); | |
393 } | |
394 | |
395 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error, Func<Exception, IPromise<T>> cancel) { | |
396 Safe.ArgumentNotNull(that, "that"); | |
397 | |
149 | 398 var d = new FuncChainTask<T>(success, error, cancel, false); |
145 | 399 that.On(d.Resolve, d.Reject, d.CancelOperation); |
400 if (success != null) | |
401 d.CancellationRequested(that.Cancel); | |
402 return d; | |
403 } | |
404 | |
405 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error) { | |
406 return Chain(that, success, error, null); | |
407 } | |
408 | |
409 public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success) { | |
410 return Chain(that, success, null, null); | |
411 } | |
412 | |
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) { | |
414 Safe.ArgumentNotNull(that, "that"); | |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
415 var d = new FuncChainTask<T, T2>(success, error, cancel, false); |
145 | 416 that.On(d.Resolve, d.Reject, d.CancelOperation); |
417 if (success != null) | |
418 d.CancellationRequested(that.Cancel); | |
419 return d; | |
420 } | |
421 | |
422 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error) { | |
423 return Chain(that, success, error, null); | |
424 } | |
425 | |
426 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success) { | |
427 return Chain(that, success, null, null); | |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
428 } |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
429 |
145 | 430 #endregion |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
431 |
209 | 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 } | |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
439 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
440 #if NET_4_5 |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
441 |
151 | 442 public static PromiseAwaiter<T> GetAwaiter<T>(this IPromise<T> that) { |
75 | 443 Safe.ArgumentNotNull(that, "that"); |
444 | |
151 | 445 return new PromiseAwaiter<T>(that); |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
446 } |
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
447 |
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
448 public static PromiseAwaiter GetAwaiter(this IPromise that) { |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
449 Safe.ArgumentNotNull(that, "that"); |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
450 |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
451 return new PromiseAwaiter(that); |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
452 } |
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
207
diff
changeset
|
453 |
209 | 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 | |
207
558f34b2fb50
added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()'
cin
parents:
205
diff
changeset
|
472 #endif |
72 | 473 } |
474 } | |
475 |