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 |
