Mercurial > pub > ImplabNet
annotate Implab/PromiseExtensions.cs @ 200:71e543dbe65a v2
working version of the project
| author | cin | 
|---|---|
| date | Fri, 14 Oct 2016 04:03:10 +0300 | 
| parents | 822aab37b107 | 
| children | 8200ab154c8a | 
| 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; | 
| 109 | 5 | 
| 72 | 6 namespace Implab { | 
| 7 public static class PromiseExtensions { | |
| 8 public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) { | |
| 75 | 9 Safe.ArgumentNotNull(that, "that"); | 
| 72 | 10 var context = SynchronizationContext.Current; | 
| 11 if (context == null) | |
| 12 return that; | |
| 13 | |
| 
119
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
14 var p = new SyncContextPromise<T>(context); | 
| 185 | 15 p.CancellationRequested(that.Cancel); | 
| 72 | 16 | 
| 104 | 17 that.On( | 
| 76 | 18 p.Resolve, | 
| 19 p.Reject, | |
| 185 | 20 p.CancelOperation | 
| 72 | 21 ); | 
| 22 return p; | |
| 23 } | |
| 24 | |
| 25 public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) { | |
| 75 | 26 Safe.ArgumentNotNull(that, "that"); | 
| 72 | 27 Safe.ArgumentNotNull(context, "context"); | 
| 28 | |
| 
119
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
29 var p = new SyncContextPromise<T>(context); | 
| 185 | 30 p.CancellationRequested(that.Cancel); | 
| 72 | 31 | 
| 104 | 32 that.On( | 
| 76 | 33 p.Resolve, | 
| 34 p.Reject, | |
| 185 | 35 p.CancelOperation | 
| 72 | 36 ); | 
| 37 return p; | |
| 38 } | |
| 75 | 39 | 
| 101 | 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 | |
| 
138
 
f75cfa58e3d4
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
 
cin 
parents: 
136 
diff
changeset
 | 
53 that.On(() => head.On(cleanup), PromiseEventType.Cancelled); | 
| 101 | 54 | 
| 55 return that; | |
| 56 } | |
| 57 | |
| 75 | 58 public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult,T> callback) { | 
| 59 Safe.ArgumentNotNull(that, "that"); | |
| 60 Safe.ArgumentNotNull(callback, "callback"); | |
| 109 | 61 var op = TraceContext.Instance.CurrentOperation; | 
| 75 | 62 return ar => { | 
| 109 | 63 TraceContext.Instance.EnterLogicalOperation(op,false); | 
| 75 | 64 try { | 
| 65 that.Resolve(callback(ar)); | |
| 66 } catch (Exception err) { | |
| 67 that.Reject(err); | |
| 109 | 68 } finally { | 
| 69 TraceContext.Instance.Leave(); | |
| 75 | 70 } | 
| 71 }; | |
| 72 } | |
| 110 | 73 | 
| 185 | 74 static void CancelByTimeoutCallback(object cookie) { | 
| 75 ((ICancellable)cookie).Cancel(new TimeoutException()); | |
| 110 | 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"); | |
| 185 | 86 var timer = new Timer(CancelByTimeoutCallback, that, milliseconds, -1); | 
| 110 | 87 that.On(timer.Dispose, PromiseEventType.All); | 
| 88 return that; | |
| 89 } | |
| 
119
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
90 | 
| 124 | 91 public static IPromise Bundle(this ICollection<IPromise> that) { | 
| 
119
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
92 Safe.ArgumentNotNull(that, "that"); | 
| 
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
93 | 
| 
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
94 int count = that.Count; | 
| 124 | 95 int errors = 0; | 
| 
119
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
96 var medium = new Promise(); | 
| 
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
97 | 
| 136 | 98 if (count == 0) { | 
| 99 medium.Resolve(); | |
| 100 return medium; | |
| 101 } | |
| 102 | |
| 124 | 103 medium.On(() => { | 
| 104 foreach(var p2 in that) | |
| 105 p2.Cancel(); | |
| 106 }, PromiseEventType.ErrorOrCancel); | |
| 107 | |
| 
119
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
108 foreach (var p in that) | 
| 
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
109 p.On( | 
| 
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
110 () => { | 
| 
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
111 if (Interlocked.Decrement(ref count) == 0) | 
| 
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
112 medium.Resolve(); | 
| 
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
113 }, | 
| 
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
114 error => { | 
| 124 | 115 if (Interlocked.Increment(ref errors) == 1) | 
| 116 medium.Reject( | |
| 117 new Exception("The dependency promise is failed", error) | |
| 118 ); | |
| 
119
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
119 }, | 
| 
138
 
f75cfa58e3d4
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
 
cin 
parents: 
136 
diff
changeset
 | 
120 reason => { | 
| 124 | 121 if (Interlocked.Increment(ref errors) == 1) | 
| 
138
 
f75cfa58e3d4
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
 
cin 
parents: 
136 
diff
changeset
 | 
122 medium.Cancel( | 
| 124 | 123 new Exception("The dependency promise is cancelled") | 
| 124 ); | |
| 
119
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
125 } | 
| 
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
126 ); | 
| 
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
127 | 
| 
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
128 return medium; | 
| 
 
2573b562e328
Promises rewritten, added improved version of AsyncQueue
 
cin 
parents: 
110 
diff
changeset
 | 
129 } | 
| 124 | 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 }, | |
| 
138
 
f75cfa58e3d4
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
 
cin 
parents: 
136 
diff
changeset
 | 
159 reason => { | 
| 124 | 160 if (Interlocked.Increment(ref errors) == 1) | 
| 
138
 
f75cfa58e3d4
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
 
cin 
parents: 
136 
diff
changeset
 | 
161 medium.Cancel( | 
| 
 
f75cfa58e3d4
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
 
cin 
parents: 
136 
diff
changeset
 | 
162 new Exception("The dependency promise is cancelled", reason) | 
| 124 | 163 ); | 
| 164 } | |
| 165 ); | |
| 166 i++; | |
| 167 } | |
| 168 | |
| 169 return medium; | |
| 170 } | |
| 145 | 171 | 
| 172 public static IPromise Then(this IPromise that, Action success, Action<Exception> error, Action<Exception> cancel) { | |
| 173 Safe.ArgumentNotNull(that, "that"); | |
| 174 | |
| 149 | 175 var d = new ActionTask(success, error, cancel, false); | 
| 145 | 176 that.On(d.Resolve, d.Reject, d.CancelOperation); | 
| 185 | 177 d.CancellationRequested(that.Cancel); | 
| 145 | 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 | |
| 149 | 192 var d = new FuncTask<T>(success, error, cancel, false); | 
| 145 | 193 that.On(d.Resolve, d.Reject, d.CancelOperation); | 
| 185 | 194 d.CancellationRequested(that.Cancel); | 
| 145 | 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"); | |
| 149 | 208 var d = new FuncTask<T,T2>(success, error, cancel, false); | 
| 145 | 209 that.On(d.Resolve, d.Reject, d.CancelOperation); | 
| 185 | 210 d.CancellationRequested(that.Cancel); | 
| 145 | 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 | |
| 149 | 226 var d = new ActionChainTask(success, error, cancel, false); | 
| 145 | 227 that.On(d.Resolve, d.Reject, d.CancelOperation); | 
| 185 | 228 d.CancellationRequested(that.Cancel); | 
| 145 | 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 | |
| 149 | 243 var d = new FuncChainTask<T>(success, error, cancel, false); | 
| 145 | 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"); | |
| 149 | 260 var d = new FuncChainTask<T,T2>(success, error, cancel, false); | 
| 145 | 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 | |
| 75 | 277 | 
| 278 #if NET_4_5 | |
| 279 | |
| 151 | 280 public static PromiseAwaiter<T> GetAwaiter<T>(this IPromise<T> that) { | 
| 75 | 281 Safe.ArgumentNotNull(that, "that"); | 
| 282 | |
| 151 | 283 return new PromiseAwaiter<T>(that); | 
| 75 | 284 } | 
| 285 | |
| 286 #endif | |
| 72 | 287 } | 
| 288 } | |
| 289 | 
