Mercurial > pub > ImplabNet
diff Implab/PromiseExtensions.cs @ 248:5cb4826c2c2a v3
Added awaiters to promises
Added static methods to Promise Resolve, Reject, All.
Updated promise helpers
author | cin |
---|---|
date | Tue, 30 Jan 2018 01:37:17 +0300 |
parents | a867536c68fc |
children | d82909310094 |
line wrap: on
line diff
--- a/Implab/PromiseExtensions.cs Fri Jan 26 18:46:27 2018 +0300 +++ b/Implab/PromiseExtensions.cs Tue Jan 30 01:37:17 2018 +0300 @@ -2,474 +2,130 @@ using System; using Implab.Diagnostics; using System.Collections.Generic; -using System.Linq; - +using System.Linq; + namespace Implab { public static class PromiseExtensions { - public static IPromise<T> DispatchToCurrentContext<T>(this IPromise<T> that) { - Safe.ArgumentNotNull(that, "that"); - var context = SynchronizationContext.Current; - if (context == null) - return that; - var p = new SyncContextPromise<T>(context); - p.CancellationRequested(that.Cancel); - - that.On( - p.Resolve, - p.Reject, - p.CancelOperation - ); - return p; - } - - public static IPromise<T> DispatchToContext<T>(this IPromise<T> that, SynchronizationContext context) { - Safe.ArgumentNotNull(that, "that"); - Safe.ArgumentNotNull(context, "context"); - - var p = new SyncContextPromise<T>(context); - p.CancellationRequested(that.Cancel); - - that.On( - p.Resolve, - p.Reject, - p.CancelOperation - ); - return p; - } - - /// <summary> - /// Ensures the dispatched. - /// </summary> - /// <returns>The dispatched.</returns> - /// <param name="that">That.</param> - /// <param name="head">Head.</param> - /// <param name="cleanup">Cleanup.</param> - /// <typeparam name="TPromise">The 1st type parameter.</typeparam> - /// <typeparam name="T">The 2nd type parameter.</typeparam> - public static TPromise EnsureDispatched<TPromise, T>(this TPromise that, IPromise<T> head, Action<T> cleanup) where TPromise : IPromise { - Safe.ArgumentNotNull(that, "that"); - Safe.ArgumentNotNull(head, "head"); - - that.On(() => head.On(cleanup), PromiseEventType.Cancelled); - - return that; + public static IPromise Then(this IPromise that, Action fulfilled, Action<Exception> rejected) { + var reaction = new PromiseActionReaction(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - /// <summary> - /// Adds a cancellation point to the chain of promises. When a cancellation request reaches the cancellation point the operation is - /// cancelled immediatelly, and the request is passed towards. If the operation at the higher level can not be cancelled is't result - /// will be collected with <paramref name="cleanup"/> callback. - /// </summary> - /// <typeparam name="T">The type of the promise result.</typeparam> - /// <param name="that">The promise to which the cancellation point should be attached.</param> - /// <param name="cleanup">The callback which is used to cleanup the result of the operation if the cancellation point is cancelled already.</param> - /// <returns>The promise</returns> - public static IPromise<T> CancellationPoint<T>(this IPromise<T> that, Action<T> cleanup) { - var meduim = new Promise<T>(); - - that.On(meduim.Resolve, meduim.Reject, meduim.CancelOperation); - - meduim.CancellationRequested(that.Cancel); - meduim.CancellationRequested(meduim.CancelOperation); - - if (cleanup != null) - meduim.On((Action<T>)null, null, (e) => { - that.On(cleanup); - }); - - return meduim; + public static IPromise Then(this IPromise that, Action fulfilled, Func<Exception, IPromise> rejected) { + var reaction = new PromiseActionReaction(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult, T> callback) { - Safe.ArgumentNotNull(that, "that"); - Safe.ArgumentNotNull(callback, "callback"); - var op = TraceContext.Instance.CurrentOperation; - return ar => { - TraceContext.Instance.EnterLogicalOperation(op, false); - try { - that.Resolve(callback(ar)); - } catch (Exception err) { - that.Reject(err); - } finally { - TraceContext.Instance.Leave(); - } - }; + public static IPromise Then(this IPromise that, Func<IPromise> fulfilled, Action<Exception> rejected) { + var reaction = new PromiseActionReaction(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - static void CancelByTimeoutCallback(object cookie) { - ((ICancellable)cookie).Cancel(new TimeoutException()); - } - - /// <summary> - /// Cancells promise after the specified timeout is elapsed. - /// </summary> - /// <param name="that">The promise to cancel on timeout.</param> - /// <param name="milliseconds">The timeout in milliseconds.</param> - /// <typeparam name="TPromise">The 1st type parameter.</typeparam> - public static TPromise Timeout<TPromise>(this TPromise that, int milliseconds) where TPromise : IPromise { - Safe.ArgumentNotNull(that, "that"); - var timer = new Timer(CancelByTimeoutCallback, that, milliseconds, -1); - that.On(timer.Dispose, PromiseEventType.All); - return that; + public static IPromise Then(this IPromise that, Func<IPromise> fulfilled, Func<Exception, IPromise> rejected) { + var reaction = new PromiseActionReaction(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - public static IPromise PromiseAll(this IEnumerable<IPromise> that) { - Safe.ArgumentNotNull(that, "that"); - return PromiseAll(that.ToList()); - } - - public static IPromise<T[]> PromiseAll<T>(this IEnumerable<IPromise<T>> that) { - return PromiseAll(that, null); - } - - public static IPromise<T[]> PromiseAll<T>(this IEnumerable<IPromise<T>> that, Action<T> cleanup) { - Safe.ArgumentNotNull(that, "that"); - return PromiseAll(that.ToList(), cleanup); + public static IPromise Then<T>(this IPromise<T> that, Action<T> fulfilled, Action<Exception> rejected) { + var reaction = new PromiseActionReaction<T>(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - public static IPromise PromiseAll(this ICollection<IPromise> that) { - Safe.ArgumentNotNull(that, "that"); - - int count = that.Count; - int errors = 0; - var medium = new Promise(); - - if (count == 0) { - medium.Resolve(); - return medium; - } - - medium.On(() => { - foreach (var p2 in that) - p2.Cancel(); - }, PromiseEventType.ErrorOrCancel); - - foreach (var p in that) - p.On( - () => { - if (Interlocked.Decrement(ref count) == 0) - medium.Resolve(); - }, - error => { - if (Interlocked.Increment(ref errors) == 1) - medium.Reject( - new Exception("The dependency promise is failed", error) - ); - }, - reason => { - if (Interlocked.Increment(ref errors) == 1) - medium.Cancel( - new Exception("The dependency promise is cancelled") - ); - } - ); - - return medium; - } - - public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that) { - return PromiseAll(that, null); + public static IPromise Then<T>(this IPromise<T> that, Action<T> fulfilled, Func<Exception, IPromise> rejected) { + var reaction = new PromiseActionReaction<T>(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - /// <summary> - /// Creates a new promise which will be satisfied when all promises are satisfied. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="that"></param> - /// <param name="cleanup">A callback used to cleanup already resolved promises in case of an error</param> - /// <returns></returns> - public static IPromise<T[]> PromiseAll<T>(this ICollection<IPromise<T>> that, Action<T> cleanup) { - Safe.ArgumentNotNull(that, "that"); - - int count = that.Count; - - if (count == 0) - return Promise<T[]>.FromResult(new T[0]); - - int errors = 0; - var medium = new Promise<T[]>(); - var results = new T[that.Count]; - - medium.On(() => { - foreach (var p2 in that) { - p2.Cancel(); - if (cleanup != null) - p2.On(cleanup); - } - }, PromiseEventType.ErrorOrCancel); - - int i = 0; - foreach (var p in that) { - var idx = i; - p.On( - x => { - results[idx] = x; - if (Interlocked.Decrement(ref count) == 0) - medium.Resolve(results); - }, - error => { - if (Interlocked.Increment(ref errors) == 1) - medium.Reject( - new Exception("The dependency promise is failed", error) - ); - }, - reason => { - if (Interlocked.Increment(ref errors) == 1) - medium.Cancel( - new Exception("The dependency promise is cancelled", reason) - ); - } - ); - i++; - } - - return medium; + public static IPromise Then<T>(this IPromise<T> that, Func<T, IPromise> fulfilled, Action<Exception> rejected) { + var reaction = new PromiseActionReaction<T>(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - public static IPromise Then(this IPromise that, Action success, Action<Exception> error, Action<Exception> cancel) { - Safe.ArgumentNotNull(that, "that"); + public static IPromise Then<T>(this IPromise<T> that, Func<T, IPromise> fulfilled, Func<Exception, IPromise> rejected) { + var reaction = new PromiseActionReaction<T>(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; + } - var d = new ActionTask(success, error, cancel, false); - that.On(d.Resolve, d.Reject, d.CancelOperation); - d.CancellationRequested(that.Cancel); - return d; + public static IPromise<Tout> Then<Tout>(this IPromise that, Func<Tout> fulfilled, Func<Exception, Tout> rejected) { + var reaction = new PromiseFuncReaction<Tout>(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - public static IPromise Then(this IPromise that, Action success, Action<Exception> error) { - return Then(that, success, error, null); - } - - public static IPromise Then(this IPromise that, Action success) { - return Then(that, success, null, null); - } - - public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error, Func<Exception, T> cancel) { - Safe.ArgumentNotNull(that, "that"); - - var d = new FuncTask<T>(success, error, cancel, false); - that.On(d.Resolve, d.Reject, d.CancelOperation); - d.CancellationRequested(that.Cancel); - return d; - } - - public static IPromise<T> Then<T>(this IPromise that, Func<T> success, Func<Exception, T> error) { - return Then(that, success, error, null); - } - - public static IPromise<T> Then<T>(this IPromise that, Func<T> success) { - return Then(that, success, null, null); + public static IPromise<Tout> Then<Tout>(this IPromise that, Func<Tout> fulfilled, Func<Exception, IPromise<Tout>> rejected) { + var reaction = new PromiseFuncReaction<Tout>(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error, Func<Exception, T2> cancel) { - Safe.ArgumentNotNull(that, "that"); - Safe.ArgumentNotNull(success, "success"); - - var d = new FuncTask<T, T2>(success, error, cancel, false); - that.On(d.Resolve, d.Reject, d.CancelOperation); - d.CancellationRequested(that.Cancel); - return d; - } - - public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success, Func<Exception, T> error, Func<Exception, T> cancel) { - Safe.ArgumentNotNull(that, "that"); - var d = new FuncTask<T, T>( - x => { - success(x); - return x; - }, - error, - cancel, - false - ); - that.On(d.Resolve, d.Reject, d.CancelOperation); - d.CancellationRequested(that.Cancel); - return d; - } - - public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success, Func<Exception, T> error) { - return Then(that, success, error, null); + public static IPromise<Tout> Then<Tout>(this IPromise that, Func<IPromise<Tout>> fulfilled, Func<Exception, Tout> rejected) { + var reaction = new PromiseFuncReaction<Tout>(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success) { - return Then(that, success, null, null); - } - - public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error) { - return Then(that, success, error, null); - } - - public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success) { - return Then(that, success, null, null); + public static IPromise<Tout> Then<Tout>(this IPromise that, Func<IPromise<Tout>> fulfilled, Func<Exception, IPromise<Tout>> rejected) { + var reaction = new PromiseFuncReaction<Tout>(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - public static IPromise<T> Always<T>(this IPromise<T> that, Action handler) { - Func<Exception, T> errorOrCancel; - if (handler != null) - errorOrCancel = e => { - handler(); - throw new PromiseTransientException(e); - }; - else - errorOrCancel = null; - - return Then( - that, - x => { - handler(); - return x; - }, - errorOrCancel, - errorOrCancel); + public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, Tout> fulfilled, Func<Exception, Tout> rejected) { + var reaction = new PromiseFuncReaction<Tin, Tout>(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - public static IPromise Always(this IPromise that, Action handler) { - Action<Exception> errorOrCancel; - if (handler != null) - errorOrCancel = e => { - handler(); - throw new PromiseTransientException(e); - }; - else - errorOrCancel = null; - - return Then( - that, - handler, - errorOrCancel, - errorOrCancel); - } - - public static IPromise Error(this IPromise that, Action<Exception> handler, bool handleCancellation) { - Action<Exception> errorOrCancel; - if (handler != null) - errorOrCancel = e => { - handler(e); - throw new PromiseTransientException(e); - }; - else - errorOrCancel = null; - - return Then(that, null, errorOrCancel, handleCancellation ? errorOrCancel : null); + public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, Tout> fulfilled, Func<Exception, IPromise<Tout>> rejected) { + var reaction = new PromiseFuncReaction<Tin, Tout>(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - public static IPromise Error(this IPromise that, Action<Exception> handler) { - return Error(that, handler, false); - } - - public static IPromise<T> Error<T>(this IPromise<T> that, Action<Exception> handler, bool handleCancellation) { - Func<Exception, T> errorOrCancel; - if (handler != null) - errorOrCancel = e => { - handler(e); - throw new PromiseTransientException(e); - }; - else - errorOrCancel = null; - - return Then(that, null, errorOrCancel, handleCancellation ? errorOrCancel : null); + public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, IPromise<Tout>> fulfilled, Func<Exception, Tout> rejected) { + var reaction = new PromiseFuncReaction<Tin, Tout>(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - public static IPromise<T> Error<T>(this IPromise<T> that, Action<Exception> handler) { - return Error(that, handler, false); - } - - #region chain traits - public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel) { - Safe.ArgumentNotNull(that, "that"); - - var d = new ActionChainTask(success, error, cancel, false); - that.On(d.Resolve, d.Reject, d.CancelOperation); - d.CancellationRequested(that.Cancel); - return d; - } - - public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception, IPromise> error) { - return Chain(that, success, error, null); + public static IPromise<Tout> Then<Tin, Tout>(this IPromise<Tin> that, Func<Tin, IPromise<Tout>> fulfilled, Func<Exception, IPromise<Tout>> rejected) { + var reaction = new PromiseFuncReaction<Tin, Tout>(fulfilled, rejected, Promise.DefaultDispatcher); + that.Then(reaction); + return reaction.Promise; } - public static IPromise Chain(this IPromise that, Func<IPromise> success) { - return Chain(that, success, null, null); - } - - public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error, Func<Exception, IPromise<T>> cancel) { - Safe.ArgumentNotNull(that, "that"); - - var d = new FuncChainTask<T>(success, error, cancel, false); - that.On(d.Resolve, d.Reject, d.CancelOperation); - if (success != null) - d.CancellationRequested(that.Cancel); - return d; - } - - public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success, Func<Exception, IPromise<T>> error) { - return Chain(that, success, error, null); - } - - public static IPromise<T> Chain<T>(this IPromise that, Func<IPromise<T>> success) { - return Chain(that, success, null, null); + public static IPromise Catch(this IPromise that, Action<Exception> rejected) { + return Then(that, null, rejected); } - 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) { - Safe.ArgumentNotNull(that, "that"); - var d = new FuncChainTask<T, T2>(success, error, cancel, false); - that.On(d.Resolve, d.Reject, d.CancelOperation); - if (success != null) - d.CancellationRequested(that.Cancel); - return d; + public static IPromise Catch(this IPromise that, Func<Exception, IPromise> rejected) { + return Then(that, null, rejected); } - public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error) { - return Chain(that, success, error, null); + public static IPromise<Tout> Catch<Tout>(this IPromise that, Func<Exception, Tout> rejected) { + return Then(that, (Func<Tout>)null, rejected); } - public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success) { - return Chain(that, success, null, null); - } - - #endregion - - public static IPromise<T2> Guard<T, T2>(this IPromise<T> that, Func<IPromise<T>, IPromise<T2>> continuation, Action<T> cleanup) { - Safe.ArgumentNotNull(that, "that"); - Safe.ArgumentNotNull(continuation, "continuation"); - return continuation(that).Error((err) => { - that.On(cleanup); - }, true); - } - -#if NET_4_5 - - public static PromiseAwaiter<T> GetAwaiter<T>(this IPromise<T> that) { - Safe.ArgumentNotNull(that, "that"); + public static IPromise<Tout> Catch<Tout>(this IPromise that, Func<Exception, IPromise<Tout>> rejected) { + return Then(that, (Func<Tout>)null, rejected); + } - return new PromiseAwaiter<T>(that); - } - - public static PromiseAwaiter GetAwaiter(this IPromise that) { - Safe.ArgumentNotNull(that, "that"); + public static IPromise<Tout> Catch<Tin, Tout>(this IPromise<Tin> that, Func<Exception, Tout> rejected) { + return Then(that, (Func<Tin, Tout>)null, rejected); + } - return new PromiseAwaiter(that); - } - - public static IPromise BoundCancellationToken(this IPromise that, CancellationToken ct) { - Safe.ArgumentNotNull(that, "that"); - ct.Register(that.Cancel); - return that.Then(null, null, (err) => { - ct.ThrowIfCancellationRequested(); - throw new PromiseTransientException(err); - }); - } - - public static IPromise<T> BoundCancellationToken<T>(this IPromise<T> that, CancellationToken ct) { - Safe.ArgumentNotNull(that, "that"); - ct.Register(that.Cancel); - return that.Then(null, null, (err) => { - ct.ThrowIfCancellationRequested(); - throw new PromiseTransientException(err); - }); - } - -#endif + public static IPromise<Tout> Catch<Tin, Tout>(this IPromise<Tin> that, Func<Exception, IPromise<Tout>> rejected) { + return Then(that, (Func<Tin, Tout>)null, rejected); + } } }