Mercurial > pub > ImplabNet
changeset 138:f75cfa58e3d4 v2
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
author | cin |
---|---|
date | Tue, 17 Feb 2015 18:16:26 +0300 |
parents | 238e15580926 |
children | 041b77711262 |
files | Implab.Fx/ControlBoundPromise.cs Implab.Test/AsyncTests.cs Implab/AbstractPromise.cs Implab/Diagnostics/Extensions.cs Implab/ICancellable.cs Implab/IDeferred.cs Implab/IPromise.cs Implab/IPromiseT.cs Implab/Promise.cs Implab/PromiseExtensions.cs Implab/PromiseT.cs Implab/PromiseTransientException.cs Implab/SyncContextPromise.cs Implab/TaskController.cs MonoPlay/Program.cs |
diffstat | 15 files changed, 169 insertions(+), 257 deletions(-) [+] |
line wrap: on
line diff
--- a/Implab.Fx/ControlBoundPromise.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/Implab.Fx/ControlBoundPromise.cs Tue Feb 17 18:16:26 2015 +0300 @@ -19,11 +19,11 @@ base.SignalSuccess(handler); } - protected override void SignalCancelled(IDeferred<T> handler) { + protected override void SignalCancelled(IDeferred<T> handler, Exception reason) { if (m_target.InvokeRequired) - m_target.BeginInvoke(new Action<IDeferred<T>>(base.SignalCancelled), handler); + m_target.BeginInvoke(new Action<IDeferred<T>,Exception>(base.SignalCancelled), handler, reason); else - base.SignalCancelled(handler); + base.SignalCancelled(handler, reason); } protected override void SignalError(IDeferred<T> handler, Exception error) {
--- a/Implab.Test/AsyncTests.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/Implab.Test/AsyncTests.cs Tue Feb 17 18:16:26 2015 +0300 @@ -53,7 +53,7 @@ var p = new Promise<bool>(); p.Cancel(); - var p2 = p.Cancelled(() => { + var p2 = p.Then(x => x, null, reason => { throw new ApplicationException("CANCELLED"); }); @@ -72,10 +72,10 @@ p.Cancel(); var p2 = p - .Cancelled<bool>(() => { + .Then<bool>(x => x, null, reason => { throw new ApplicationException("CANCELLED"); }) - .Error(e => true); + .Then(x => x, e => true); Assert.AreEqual(true, p2.Join()); } @@ -116,7 +116,7 @@ public void FixErrorTest() { var p = new Promise<int>(); - var p2 = p.Error(e => 101); + var p2 = p.Then(x => x, e => 101); p.Reject(new Exception()); @@ -760,7 +760,7 @@ }); result - .Cancelled(() => pSurvive.Resolve(true)); + .On(() => pSurvive.Resolve(true), PromiseEventType.Cancelled); return result; });
--- a/Implab/AbstractPromise.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/Implab/AbstractPromise.cs Tue Feb 17 18:16:26 2015 +0300 @@ -68,9 +68,15 @@ /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception> protected void SetError(Exception error) { if (BeginTransit()) { - m_error = error is PromiseTransientException ? error.InnerException : error; - CompleteTransit(REJECTED_STATE); - OnError(); + if (error is OperationCanceledException) { + CompleteTransit(CANCELLED_STATE); + m_error = error.InnerException; + OnCancelled(); + } else { + m_error = error is PromiseTransientException ? error.InnerException : error; + CompleteTransit(REJECTED_STATE); + OnError(); + } } else { WaitTransition(); if (m_state == SUCCEEDED_STATE) @@ -82,8 +88,9 @@ /// Отменяет операцию, если это возможно. /// </summary> /// <remarks>Для определения была ли операция отменена следует использовать свойство <see cref="IsCancelled"/>.</remarks> - protected void SetCancelled() { + protected void SetCancelled(Exception reason) { if (BeginTransit()) { + m_error = reason; CompleteTransit(CANCELLED_STATE); OnCancelled(); } @@ -93,7 +100,7 @@ protected abstract void SignalError(THandler handler, Exception error); - protected abstract void SignalCancelled(THandler handler); + protected abstract void SignalCancelled(THandler handler, Exception reason); void OnSuccess() { var hp = m_handlerPointer; @@ -137,7 +144,7 @@ var slot = hp +1 ; while (slot < m_handlersCommited) { if (Interlocked.CompareExchange(ref m_handlerPointer, slot, hp) == hp) { - SignalCancelled(m_handlers[slot]); + SignalCancelled(m_handlers[slot], m_error); } hp = m_handlerPointer; slot = hp +1 ; @@ -146,7 +153,7 @@ if (m_extraHandlers != null) { THandler handler; while (m_extraHandlers.TryDequeue(out handler)) - SignalCancelled(handler); + SignalCancelled(handler, m_error); } } @@ -241,7 +248,7 @@ SignalSuccess(handler); break; case CANCELLED_STATE: - SignalCancelled(handler); + SignalCancelled(handler, m_error); break; case REJECTED_STATE: SignalError(handler, m_error); @@ -282,10 +289,20 @@ #region ICancellable implementation public void Cancel() { - SetCancelled(); + SetCancelled(null); + } + + public void Cancel(Exception reason) { + SetCancelled(reason); } #endregion + + public Exception Error { + get { + return m_error; + } + } } }
--- a/Implab/Diagnostics/Extensions.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/Implab/Diagnostics/Extensions.cs Tue Feb 17 18:16:26 2015 +0300 @@ -17,9 +17,9 @@ TraceLog.EndLogicalOperation(); TraceContext.Instance.Leave(); }, - () => { + reason => { TraceContext.Instance.EnterLogicalOperation(op,true); - TraceLog.TraceInformation("promise cancelled"); + TraceLog.TraceInformation("promise cancelled {0}", reason.Message); TraceLog.EndLogicalOperation(); TraceContext.Instance.Leave(); }
--- a/Implab/ICancellable.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/Implab/ICancellable.cs Tue Feb 17 18:16:26 2015 +0300 @@ -6,5 +6,6 @@ namespace Implab { public interface ICancellable { void Cancel(); + void Cancel(Exception reason); } }
--- a/Implab/IDeferred.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/Implab/IDeferred.cs Tue Feb 17 18:16:26 2015 +0300 @@ -8,6 +8,16 @@ void Resolve(); + /// <summary> + /// Reject the promise with the specified error. + /// </summary> + /// <param name="error">The reason why the promise is rejected.</param> + /// <remarks> + /// Some exceptions are treated in a special case: + /// <see cref="OperationCanceledException"/> is interpreted as call to <see cref="Cancel()"/> method, + /// and <see cref="PromiseTransientException"/> is always unwrapped and its + /// <see cref="PromiseTransientException.InnerException"> is used as the reason to reject promise. + /// </remarks> void Reject(Exception error); } }
--- a/Implab/IPromise.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/Implab/IPromise.cs Tue Feb 17 18:16:26 2015 +0300 @@ -22,6 +22,11 @@ bool IsCancelled { get; } /// <summary> + /// Исключение возникшее в результате выполнения обещания, либо причина отмены. + /// </summary> + Exception Error { get; } + + /// <summary> /// Creates a new promise dependend on the current one and resolved on /// executing the specified handlers. /// </summary> @@ -43,19 +48,21 @@ /// exception then the dependant promise will be resolved successfully, otherwise the exception /// raised by the handler will be transmitted to the dependent promise. If the handler wants /// to passthrough the original exception it needs to wrap the exception with - /// the <see cref="PromiseTransientException"/>. + /// the <see cref="PromiseTransientException"/>. The handler may raise <see cref="OperationCanceledException"/> + /// to cancel the dependant promise, the innner exception specifies the reason why the promise + /// is canceled. /// </para> /// <para> /// If the cancelation handler is specified and the current promise is cancelled then the dependent - /// promise will be resolved after the handler is executed. If the cancelation hendler raises the + /// promise will be resolved after the handler is executed. If the cancelation handler raises the /// exception it will be passed to the dependent promise. /// </para> /// </remarks> - IPromise Then(Action success, Action<Exception> error, Action cancel); + IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel); IPromise Then(Action success, Action<Exception> error); IPromise Then(Action success); - IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<IPromise> cancel); + IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel); IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error); IPromise Chain(Func<IPromise> chained); @@ -66,7 +73,7 @@ /// <param name="error">The handler is called if an error while completing the promise occurred.</param> /// <param name="cancel">The handler is called in case of promise cancellation.</param> /// <returns>The current promise.</returns> - IPromise On(Action success, Action<Exception> error, Action cancel); + IPromise On(Action success, Action<Exception> error, Action<Exception> cancel); IPromise On(Action success, Action<Exception> error); IPromise On(Action success); @@ -80,42 +87,6 @@ IPromise On(Action handler, PromiseEventType events); /// <summary> - /// Adds the specified error handler to the current promise - /// and creates the new dependant promise. - /// </summary> - /// <param name="error"> - /// The error handler. If the error handler returns without - /// an error the dependant promise will be successfully resolved. - /// </param> - /// <returns> - /// The new dependant promise which will be resolved after the error - /// handler is executed. - /// </returns> - /// <remarks> - /// The successfull result of the current promise will be ignored. - /// </remarks> - IPromise Error(Action<Exception> error); - - /// <summary> - /// Adds the specified cncellation handler to the current promise - /// and creates the new dependant promise. - /// </summary> - /// <returns> - /// The new dependant promise which will be resolved after the cancellation - /// handler is executed. - /// </returns> - /// <param name="handler"> - /// The cancellation handler. - /// </param> - /// <remarks> - /// If the cancellation handler is executed without an error the dependent - /// promise will be successfully resolved, otherwise the raised exception - /// will be passed to the dependant promise. The successful result of the - /// current promise will be ignored. - /// </remarks> - IPromise Cancelled(Action handler); - - /// <summary> /// Преобразует результат обещания к заданному типу и возвращает новое обещание. /// </summary> IPromise<T> Cast<T>();
--- a/Implab/IPromiseT.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/Implab/IPromiseT.cs Tue Feb 17 18:16:26 2015 +0300 @@ -7,7 +7,7 @@ new T Join(int timeout); - IPromise<T> On(Action<T> success, Action<Exception> error, Action cancel); + IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel); IPromise<T> On(Action<T> success, Action<Exception> error); @@ -15,20 +15,16 @@ new IPromise<T> On(Action handler, PromiseEventType events); - IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception,T2> error, Func<T2> cancel); + IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error, Func<Exception, T2> cancel); - IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception,T2> error); + IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error); IPromise<T2> Then<T2>(Func<T, T2> mapper); - IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception,IPromise<T2>> error, Func<IPromise<T2>> cancel); + IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel); - IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception,IPromise<T2>> error); + IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error); IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained); - - IPromise<T2> Error<T2>(Func<Exception,T2> error); - - IPromise<T2> Cancelled<T2>(Func<T2> handler); } }
--- a/Implab/Promise.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/Implab/Promise.cs Tue Feb 17 18:16:26 2015 +0300 @@ -7,10 +7,10 @@ public struct HandlerDescriptor { readonly Action m_success; readonly Action<Exception> m_error; - readonly Action m_cancel; + readonly Action<Exception> m_cancel; readonly IDeferred m_deferred; - public HandlerDescriptor(Action success, Action<Exception> error, Action cancel, IDeferred deferred) { + public HandlerDescriptor(Action success, Action<Exception> error, Action<Exception> cancel, IDeferred deferred) { m_success = success; m_error = error; m_cancel = cancel; @@ -45,10 +45,18 @@ } } - public void SignalCancel() { + public void SignalCancel(Exception reason) { if (m_cancel != null) { try { - m_cancel(); + m_cancel(reason); + if (m_deferred != null) + m_deferred.Resolve(); + } catch (Exception err) { + SignalError(err); + } + } else if (reason != null && m_error != null) { + try { + m_error(new OperationCanceledException("The operation was canceled.", reason)); if (m_deferred != null) m_deferred.Resolve(); } catch (Exception err) { @@ -56,7 +64,7 @@ } } else { if (m_deferred != null) - m_deferred.Cancel(); + m_deferred.Cancel(reason); } } } @@ -80,15 +88,15 @@ handler.SignalError(error); } - protected override void SignalCancelled(HandlerDescriptor handler) { - handler.SignalCancel(); + protected override void SignalCancelled(HandlerDescriptor handler, Exception reason) { + handler.SignalCancel(reason); } protected override void Listen(PromiseEventType events, Action handler) { AddHandler(new HandlerDescriptor( events.HasFlag(PromiseEventType.Success) ? handler : null, events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null, - events.HasFlag(PromiseEventType.Cancelled) ? handler : null, + events.HasFlag(PromiseEventType.Cancelled) ? new Action<Exception>(reason => handler()) : null, null )); } @@ -102,7 +110,7 @@ } } - public IPromise Then(Action success, Action<Exception> error, Action cancel) { + public IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel) { var promise = new Promise(); if (success != null) promise.On(Cancel, PromiseEventType.Cancelled); @@ -120,7 +128,7 @@ return Then(success, null, null); } - public IPromise On(Action success, Action<Exception> error, Action cancel) { + public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) { AddHandler(new HandlerDescriptor(success, error, cancel, null)); return this; } @@ -137,7 +145,7 @@ return On( events.HasFlag(PromiseEventType.Success) ? handler : null, events.HasFlag(PromiseEventType.Error) ? new Action<Exception>(err => handler()) : null, - events.HasFlag(PromiseEventType.Cancelled) ? handler : null + events.HasFlag(PromiseEventType.Cancelled) ? new Action<Exception>(reason => handler()) : null ); } @@ -145,7 +153,7 @@ throw new InvalidCastException(); } - public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<IPromise> cancel) { + public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception,IPromise> cancel) { var medium = new Promise(); On( @@ -168,13 +176,13 @@ medium.Reject(ex); } }, - () => { + reason => { if (medium.IsCancelled) return; if (cancel != null) - ConnectPromise(cancel(), medium); + ConnectPromise(cancel(reason), medium); else - medium.Cancel(); + medium.Cancel(reason); } ); @@ -189,9 +197,9 @@ result.On( medium.Resolve, medium.Reject, - () => medium.Reject(new OperationCanceledException()) + medium.Cancel ); - medium.On(result.Cancel, PromiseEventType.Cancelled); + medium.On(null,null,result.Cancel); } else { medium.Reject( new NullReferenceException( @@ -209,50 +217,6 @@ public IPromise Chain(Func<IPromise> chained) { return Chain(chained, null, null); } - - public IPromise Error(Action<Exception> error) { - var promise = new Promise(); - On( - null, - err => { - if (error != null) - try { - error(err); - promise.Resolve(); - } catch (Exception err2) { - promise.Reject(err2); - } - else - promise.Reject(err); - } - ); - - return promise; - } - - public IPromise Cancelled(Action handler) { - var promise = new Promise(); - On( - null, - null, - () => { - if (handler != null) { - try { - handler(); - promise.Resolve(); - } catch (Exception err) { - promise.Reject(err); - } - } else { - promise.Cancel(); - } - } - ); - - return promise; - } - - } }
--- a/Implab/PromiseExtensions.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/Implab/PromiseExtensions.cs Tue Feb 17 18:16:26 2015 +0300 @@ -56,7 +56,7 @@ Safe.ArgumentNotNull(that, "that"); Safe.ArgumentNotNull(head, "head"); - that.On(null,null,() => head.On(cleanup)); + that.On(() => head.On(cleanup), PromiseEventType.Cancelled); return that; } @@ -123,9 +123,9 @@ new Exception("The dependency promise is failed", error) ); }, - () => { + reason => { if (Interlocked.Increment(ref errors) == 1) - medium.Reject( + medium.Cancel( new Exception("The dependency promise is cancelled") ); } @@ -162,10 +162,10 @@ new Exception("The dependency promise is failed", error) ); }, - () => { + reason => { if (Interlocked.Increment(ref errors) == 1) - medium.Reject( - new Exception("The dependency promise is cancelled") + medium.Cancel( + new Exception("The dependency promise is cancelled", reason) ); } ); @@ -181,7 +181,7 @@ Safe.ArgumentNotNull(that, "that"); var tcs = new TaskCompletionSource<T>(); - that.On(tcs.SetResult, tcs.SetException, tcs.SetCanceled); + that.On(tcs.SetResult, tcs.SetException, r => tcs.SetCanceled()); return tcs.Task; }
--- a/Implab/PromiseT.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/Implab/PromiseT.cs Tue Feb 17 18:16:26 2015 +0300 @@ -39,7 +39,7 @@ /// </remarks> public class Promise<T> : AbstractPromise<IDeferred<T>>, IPromise<T>, IDeferred<T> { - class StubDeferred : IDeferred<T> { + class StubDeferred : IDeferred, IDeferred<T> { public static readonly StubDeferred instance = new StubDeferred(); StubDeferred() { @@ -50,6 +50,9 @@ public void Resolve(T value) { } + public void Resolve() { + } + public void Reject(Exception error) { } @@ -60,6 +63,9 @@ public void Cancel() { } + public void Cancel(Exception reason) { + } + #endregion @@ -67,11 +73,11 @@ class RemapDescriptor<T2> : IDeferred<T> { readonly Func<T,T2> m_remap; - readonly Func<Exception,T2> m_failed; - readonly Func<T2> m_cancel; + readonly Func<Exception, T2> m_failed; + readonly Func<Exception, T2> m_cancel; readonly IDeferred<T2> m_deferred; - public RemapDescriptor(Func<T,T2> remap, Func<Exception,T2> failed, Func<T2> cancel, IDeferred<T2> deferred ) { + public RemapDescriptor(Func<T,T2> remap, Func<Exception,T2> failed, Func<Exception, T2> cancel, IDeferred<T2> deferred ) { Debug.Assert(deferred != null); m_remap = remap; m_failed = failed; @@ -110,18 +116,21 @@ #region ICancellable implementation - public void Cancel() { + public void Cancel(Exception reason) { if (m_cancel != null) { try { - m_deferred.Resolve(m_cancel()); + m_deferred.Resolve(m_cancel(reason)); } catch (Exception ex) { Reject(ex); } } else { - m_deferred.Cancel(); + m_deferred.Cancel(reason); } } + public void Cancel() { + Cancel(null); + } #endregion } @@ -163,6 +172,10 @@ #region ICancellable implementation public void Cancel() { + Cancel(null); + } + + public void Cancel(Exception reason) { if (m_events.HasFlag(PromiseEventType.Cancelled)){ try { m_handler(); @@ -178,10 +191,10 @@ class ValueEventDescriptor : IDeferred<T> { readonly Action<T> m_success; readonly Action<Exception> m_failed; - readonly Action m_cancelled; + readonly Action<Exception> m_cancelled; readonly IDeferred<T> m_deferred; - public ValueEventDescriptor(Action<T> success, Action<Exception> failed, Action cancelled, IDeferred<T> deferred) { + public ValueEventDescriptor(Action<T> success, Action<Exception> failed, Action<Exception> cancelled, IDeferred<T> deferred) { Debug.Assert(deferred != null); m_success = success; @@ -220,29 +233,33 @@ #region ICancellable implementation - public void Cancel() { + public void Cancel(Exception reason) { if (m_cancelled != null) { try { - m_cancelled(); + m_cancelled(reason); m_deferred.Resolve(default(T)); - } catch(Exception ex) { + } catch (Exception ex) { Reject(ex); } } else { - m_deferred.Cancel(); + m_deferred.Cancel(reason); } } + public void Cancel() { + Cancel(null); + } + #endregion } public class EventDescriptor : IDeferred<T> { readonly Action m_success; readonly Action<Exception> m_failed; - readonly Action m_cancelled; - readonly IDeferred<T> m_deferred; + readonly Action<Exception> m_cancelled; + readonly IDeferred m_deferred; - public EventDescriptor(Action success, Action<Exception> failed, Action cancelled, IDeferred<T> deferred) { + public EventDescriptor(Action success, Action<Exception> failed, Action<Exception> cancelled, IDeferred deferred) { Debug.Assert(deferred != null); m_success = success; @@ -257,7 +274,7 @@ if (m_success != null) { try { m_success(); - m_deferred.Resolve(value); + m_deferred.Resolve(); } catch (Exception ex) { Reject(ex); } @@ -268,34 +285,36 @@ if (m_failed != null) { try { m_failed(error); - m_deferred.Resolve(default(T)); - }catch (Exception ex) - { + m_deferred.Resolve(); + } catch (Exception ex) { m_deferred.Reject(ex); } } else { m_deferred.Reject(error); } - } #endregion #region ICancellable implementation - public void Cancel() { + public void Cancel(Exception reason) { if (m_cancelled != null) { try { - m_cancelled(); - m_deferred.Resolve(default(T)); + m_cancelled(reason); + m_deferred.Resolve(); } catch (Exception ex) { Reject(ex); } } else { - m_deferred.Cancel(); + m_deferred.Cancel(reason); } } + public void Cancel() { + Cancel(null); + } + #endregion } @@ -327,7 +346,7 @@ return m_result; } - public IPromise<T> On(Action<T> success, Action<Exception> error, Action cancel) { + public IPromise<T> On(Action<T> success, Action<Exception> error, Action<Exception> cancel) { AddHandler(new ValueEventDescriptor(success, error, cancel, StubDeferred.instance)); return this; } @@ -347,10 +366,10 @@ return this; } - public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error, Func<T2> cancel) { + public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error, Func<Exception, T2> cancel) { var promise = new Promise<T2>(); if (mapper != null) - promise.On(Cancel, PromiseEventType.Cancelled); + promise.On((Action)null, null, Cancel); AddHandler(new RemapDescriptor<T2>(mapper, error, cancel, promise)); return promise; } @@ -358,7 +377,7 @@ public IPromise<T2> Then<T2>(Func<T, T2> mapper, Func<Exception, T2> error) { var promise = new Promise<T2>(); if (mapper != null) - promise.On(Cancel, PromiseEventType.Cancelled); + promise.On((Action)null, null, Cancel); AddHandler(new RemapDescriptor<T2>(mapper, error, null, promise)); return promise; } @@ -366,12 +385,12 @@ public IPromise<T2> Then<T2>(Func<T, T2> mapper) { var promise = new Promise<T2>(); if (mapper != null) - promise.On(Cancel, PromiseEventType.Cancelled); + promise.On((Action)null, null, Cancel); AddHandler(new RemapDescriptor<T2>(mapper, null, null, promise)); return promise; } - public IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error, Func<IPromise<T2>> cancel) { + public IPromise<T2> Chain<T2>(Func<T, IPromise<T2>> chained, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel) { // this promise will be resolved when an asyc operation is started var promise = new Promise<IPromise<T2>>(); @@ -404,7 +423,7 @@ result.On( medium.Resolve, medium.Reject, - () => medium.Reject(new OperationCanceledException()) + medium.Cancel ); medium.On(result.Cancel, PromiseEventType.Cancelled); } else { @@ -425,46 +444,10 @@ return Chain(chained, null, null); } - public IPromise<T2> Error<T2>(Func<Exception, T2> error) { - var promise = new Promise<T2>(); - if (error != null) - On( - (Action<T>)null, - ex => { - try { - promise.Resolve(error(ex)); - } catch (Exception ex2) { - promise.Reject(ex2); - } - } - ); - else - Listen(PromiseEventType.Error, () => promise.Resolve(default(T2))); - return promise; - } - - public IPromise<T2> Cancelled<T2>(Func<T2> handler) { - var promise = new Promise<T2>(); - if (handler != null) - On( - (Action<T>)null, - null, - () => { - try { - promise.Resolve(handler()); - } catch (Exception ex) { - promise.Reject(ex); - } - }); - else - Listen(PromiseEventType.Cancelled, () => promise.Resolve(default(T2))); - return promise; - } - - public IPromise Then(Action success, Action<Exception> error, Action cancel) { - var promise = new Promise<T>(); + public IPromise Then(Action success, Action<Exception> error, Action<Exception> cancel) { + var promise = new Promise(); if (success != null) - promise.On(Cancel, PromiseEventType.Cancelled); + promise.On(null, null, Cancel); AddHandler(new EventDescriptor(success, error, cancel, promise)); @@ -479,7 +462,7 @@ return Then(success, null, null); } - public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<IPromise> cancel) { + public IPromise Chain(Func<IPromise> chained, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel) { var promise = new Promise<IPromise>(); AddHandler( @@ -493,7 +476,7 @@ var medium = new Promise(); if (chained != null) - medium.On(Cancel, PromiseEventType.Cancelled); + medium.On(null, null, Cancel); promise.On( result => ConnectPromise(result, medium), @@ -509,9 +492,9 @@ result.On( medium.Resolve, medium.Reject, - () => medium.Reject(new OperationCanceledException()) + medium.Cancel ); - medium.On(result.Cancel, PromiseEventType.Cancelled); + medium.On(null, null, result.Cancel); } else { medium.Reject( new NullReferenceException( @@ -530,7 +513,7 @@ return Chain(chained, null, null); } - public IPromise On(Action success, Action<Exception> error, Action cancel) { + public IPromise On(Action success, Action<Exception> error, Action<Exception> cancel) { AddHandler(new EventDescriptor(success,error,cancel, StubDeferred.instance)); return this; } @@ -550,43 +533,6 @@ return this; } - public IPromise Error(Action<Exception> error) { - var promise = new Promise(); - if (error != null) - On( - (Action<T>)null, - ex => { - try { - error(ex); - promise.Resolve(); - } catch (Exception ex2) { - promise.Reject(ex2); - } - }); - else - Listen(PromiseEventType.Error, promise.Resolve); - return promise; - } - - public IPromise Cancelled(Action handler) { - var promise = new Promise(); - if (handler != null) - On( - (Action<T>)null, - null, - () => { - try { - handler(); - promise.Resolve(); - } catch (Exception ex) { - promise.Reject(ex); - } - }); - else - Listen(PromiseEventType.Cancelled, promise.Resolve); - return promise; - } - public IPromise<T2> Cast<T2>() { return (IPromise<T2>)this; } @@ -601,8 +547,8 @@ handler.Reject(error); } - protected override void SignalCancelled(IDeferred<T> handler) { - handler.Cancel(); + protected override void SignalCancelled(IDeferred<T> handler, Exception reason) { + handler.Cancel(reason); } protected override void Listen(PromiseEventType events, Action handler) {
--- a/Implab/PromiseTransientException.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/Implab/PromiseTransientException.cs Tue Feb 17 18:16:26 2015 +0300 @@ -1,7 +1,6 @@ using System; namespace Implab { - [Serializable] public class PromiseTransientException : Exception { /// <summary>
--- a/Implab/SyncContextPromise.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/Implab/SyncContextPromise.cs Tue Feb 17 18:16:26 2015 +0300 @@ -1,4 +1,5 @@ using System.Threading; +using System; namespace Implab { public class SyncContextPromise<T> : Promise<T> { @@ -13,12 +14,12 @@ m_context.Post(x => base.SignalSuccess(handler), null); } - protected override void SignalError(IDeferred<T> handler, System.Exception error) { + protected override void SignalError(IDeferred<T> handler, Exception error) { m_context.Post(x => base.SignalError(handler, error), null); } - protected override void SignalCancelled(IDeferred<T> handler) { - m_context.Post(x => base.SignalCancelled(handler), null); + protected override void SignalCancelled(IDeferred<T> handler, Exception reason) { + m_context.Post(x => base.SignalCancelled(handler, reason), null); } } }
--- a/Implab/TaskController.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/Implab/TaskController.cs Tue Feb 17 18:16:26 2015 +0300 @@ -99,6 +99,13 @@ } } + public void Cancel(Exception reason) { + lock (m_lock) { + if (!m_cancelled) + m_cancelled = true; + } + } + protected virtual void OnCancelled() { var temp = Cancelled; if (temp != null) {
--- a/MonoPlay/Program.cs Mon Feb 16 17:48:39 2015 +0300 +++ b/MonoPlay/Program.cs Tue Feb 17 18:16:26 2015 +0300 @@ -69,7 +69,7 @@ var readers = new IPromise[readThreads]; for (int i = 0; i < readThreads; i++) - readers[i] = AsyncPool.RunThread(reader1); + readers[i] = AsyncPool.RunThread(reader2); var writers = new IPromise[writeThreads]; for (int i = 0; i < writeThreads; i++)