# HG changeset patch # User cin # Date 2015-02-17 15:16:26 # Node ID f75cfa58e3d4c2be9d05c597206517df7c6dbb41 # Parent 238e15580926ee5d0388c090e6e1602f20f68456 added ICancellable.Cancel(Exception) to allow specify the reason of cancellation diff --git a/Implab.Fx/ControlBoundPromise.cs b/Implab.Fx/ControlBoundPromise.cs --- a/Implab.Fx/ControlBoundPromise.cs +++ b/Implab.Fx/ControlBoundPromise.cs @@ -19,11 +19,11 @@ namespace Implab.Fx { base.SignalSuccess(handler); } - protected override void SignalCancelled(IDeferred handler) { + protected override void SignalCancelled(IDeferred handler, Exception reason) { if (m_target.InvokeRequired) - m_target.BeginInvoke(new Action>(base.SignalCancelled), handler); + m_target.BeginInvoke(new Action,Exception>(base.SignalCancelled), handler, reason); else - base.SignalCancelled(handler); + base.SignalCancelled(handler, reason); } protected override void SignalError(IDeferred handler, Exception error) { diff --git a/Implab.Test/AsyncTests.cs b/Implab.Test/AsyncTests.cs --- a/Implab.Test/AsyncTests.cs +++ b/Implab.Test/AsyncTests.cs @@ -53,7 +53,7 @@ namespace Implab.Test { var p = new Promise(); p.Cancel(); - var p2 = p.Cancelled(() => { + var p2 = p.Then(x => x, null, reason => { throw new ApplicationException("CANCELLED"); }); @@ -72,10 +72,10 @@ namespace Implab.Test { p.Cancel(); var p2 = p - .Cancelled(() => { + .Then(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 @@ namespace Implab.Test { public void FixErrorTest() { var p = new Promise(); - var p2 = p.Error(e => 101); + var p2 = p.Then(x => x, e => 101); p.Reject(new Exception()); @@ -760,7 +760,7 @@ namespace Implab.Test { }); result - .Cancelled(() => pSurvive.Resolve(true)); + .On(() => pSurvive.Resolve(true), PromiseEventType.Cancelled); return result; }); diff --git a/Implab/AbstractPromise.cs b/Implab/AbstractPromise.cs --- a/Implab/AbstractPromise.cs +++ b/Implab/AbstractPromise.cs @@ -68,9 +68,15 @@ namespace Implab { /// Данное обещание уже выполнено 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 @@ namespace Implab { /// Отменяет операцию, если это возможно. /// /// Для определения была ли операция отменена следует использовать свойство . - protected void SetCancelled() { + protected void SetCancelled(Exception reason) { if (BeginTransit()) { + m_error = reason; CompleteTransit(CANCELLED_STATE); OnCancelled(); } @@ -93,7 +100,7 @@ namespace Implab { 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 @@ namespace Implab { 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 @@ namespace Implab { if (m_extraHandlers != null) { THandler handler; while (m_extraHandlers.TryDequeue(out handler)) - SignalCancelled(handler); + SignalCancelled(handler, m_error); } } @@ -241,7 +248,7 @@ namespace Implab { SignalSuccess(handler); break; case CANCELLED_STATE: - SignalCancelled(handler); + SignalCancelled(handler, m_error); break; case REJECTED_STATE: SignalError(handler, m_error); @@ -282,10 +289,20 @@ namespace Implab { #region ICancellable implementation public void Cancel() { - SetCancelled(); + SetCancelled(null); + } + + public void Cancel(Exception reason) { + SetCancelled(reason); } #endregion + + public Exception Error { + get { + return m_error; + } + } } } diff --git a/Implab/Diagnostics/Extensions.cs b/Implab/Diagnostics/Extensions.cs --- a/Implab/Diagnostics/Extensions.cs +++ b/Implab/Diagnostics/Extensions.cs @@ -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(); } diff --git a/Implab/ICancellable.cs b/Implab/ICancellable.cs --- a/Implab/ICancellable.cs +++ b/Implab/ICancellable.cs @@ -6,5 +6,6 @@ using System.Text; namespace Implab { public interface ICancellable { void Cancel(); + void Cancel(Exception reason); } } diff --git a/Implab/IDeferred.cs b/Implab/IDeferred.cs --- a/Implab/IDeferred.cs +++ b/Implab/IDeferred.cs @@ -8,6 +8,16 @@ namespace Implab { void Resolve(); + /// + /// Reject the promise with the specified error. + /// + /// The reason why the promise is rejected. + /// + /// Some exceptions are treated in a special case: + /// is interpreted as call to method, + /// and is always unwrapped and its + /// is used as the reason to reject promise. + /// void Reject(Exception error); } } diff --git a/Implab/IPromise.cs b/Implab/IPromise.cs --- a/Implab/IPromise.cs +++ b/Implab/IPromise.cs @@ -22,6 +22,11 @@ namespace Implab { bool IsCancelled { get; } /// + /// Исключение возникшее в результате выполнения обещания, либо причина отмены. + /// + Exception Error { get; } + + /// /// Creates a new promise dependend on the current one and resolved on /// executing the specified handlers. /// @@ -43,19 +48,21 @@ namespace Implab { /// 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 . + /// the . The handler may raise + /// to cancel the dependant promise, the innner exception specifies the reason why the promise + /// is canceled. /// /// /// 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. /// /// - IPromise Then(Action success, Action error, Action cancel); + IPromise Then(Action success, Action error, Action cancel); IPromise Then(Action success, Action error); IPromise Then(Action success); - IPromise Chain(Func chained, Func error, Func cancel); + IPromise Chain(Func chained, Func error, Func cancel); IPromise Chain(Func chained, Func error); IPromise Chain(Func chained); @@ -66,7 +73,7 @@ namespace Implab { /// The handler is called if an error while completing the promise occurred. /// The handler is called in case of promise cancellation. /// The current promise. - IPromise On(Action success, Action error, Action cancel); + IPromise On(Action success, Action error, Action cancel); IPromise On(Action success, Action error); IPromise On(Action success); @@ -80,42 +87,6 @@ namespace Implab { IPromise On(Action handler, PromiseEventType events); /// - /// Adds the specified error handler to the current promise - /// and creates the new dependant promise. - /// - /// - /// The error handler. If the error handler returns without - /// an error the dependant promise will be successfully resolved. - /// - /// - /// The new dependant promise which will be resolved after the error - /// handler is executed. - /// - /// - /// The successfull result of the current promise will be ignored. - /// - IPromise Error(Action error); - - /// - /// Adds the specified cncellation handler to the current promise - /// and creates the new dependant promise. - /// - /// - /// The new dependant promise which will be resolved after the cancellation - /// handler is executed. - /// - /// - /// The cancellation handler. - /// - /// - /// 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. - /// - IPromise Cancelled(Action handler); - - /// /// Преобразует результат обещания к заданному типу и возвращает новое обещание. /// IPromise Cast(); diff --git a/Implab/IPromiseT.cs b/Implab/IPromiseT.cs --- a/Implab/IPromiseT.cs +++ b/Implab/IPromiseT.cs @@ -7,7 +7,7 @@ namespace Implab { new T Join(int timeout); - IPromise On(Action success, Action error, Action cancel); + IPromise On(Action success, Action error, Action cancel); IPromise On(Action success, Action error); @@ -15,20 +15,16 @@ namespace Implab { new IPromise On(Action handler, PromiseEventType events); - IPromise Then(Func mapper, Func error, Func cancel); + IPromise Then(Func mapper, Func error, Func cancel); - IPromise Then(Func mapper, Func error); + IPromise Then(Func mapper, Func error); IPromise Then(Func mapper); - IPromise Chain(Func> chained, Func> error, Func> cancel); + IPromise Chain(Func> chained, Func> error, Func> cancel); - IPromise Chain(Func> chained, Func> error); + IPromise Chain(Func> chained, Func> error); IPromise Chain(Func> chained); - - IPromise Error(Func error); - - IPromise Cancelled(Func handler); } } diff --git a/Implab/Promise.cs b/Implab/Promise.cs --- a/Implab/Promise.cs +++ b/Implab/Promise.cs @@ -7,10 +7,10 @@ namespace Implab { public struct HandlerDescriptor { readonly Action m_success; readonly Action m_error; - readonly Action m_cancel; + readonly Action m_cancel; readonly IDeferred m_deferred; - public HandlerDescriptor(Action success, Action error, Action cancel, IDeferred deferred) { + public HandlerDescriptor(Action success, Action error, Action cancel, IDeferred deferred) { m_success = success; m_error = error; m_cancel = cancel; @@ -45,10 +45,18 @@ namespace Implab { } } - 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 @@ namespace Implab { } } else { if (m_deferred != null) - m_deferred.Cancel(); + m_deferred.Cancel(reason); } } } @@ -80,15 +88,15 @@ namespace Implab { 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(err => handler()) : null, - events.HasFlag(PromiseEventType.Cancelled) ? handler : null, + events.HasFlag(PromiseEventType.Cancelled) ? new Action(reason => handler()) : null, null )); } @@ -102,7 +110,7 @@ namespace Implab { } } - public IPromise Then(Action success, Action error, Action cancel) { + public IPromise Then(Action success, Action error, Action cancel) { var promise = new Promise(); if (success != null) promise.On(Cancel, PromiseEventType.Cancelled); @@ -120,7 +128,7 @@ namespace Implab { return Then(success, null, null); } - public IPromise On(Action success, Action error, Action cancel) { + public IPromise On(Action success, Action error, Action cancel) { AddHandler(new HandlerDescriptor(success, error, cancel, null)); return this; } @@ -137,7 +145,7 @@ namespace Implab { return On( events.HasFlag(PromiseEventType.Success) ? handler : null, events.HasFlag(PromiseEventType.Error) ? new Action(err => handler()) : null, - events.HasFlag(PromiseEventType.Cancelled) ? handler : null + events.HasFlag(PromiseEventType.Cancelled) ? new Action(reason => handler()) : null ); } @@ -145,7 +153,7 @@ namespace Implab { throw new InvalidCastException(); } - public IPromise Chain(Func chained, Func error, Func cancel) { + public IPromise Chain(Func chained, Func error, Func cancel) { var medium = new Promise(); On( @@ -168,13 +176,13 @@ namespace Implab { 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 @@ namespace Implab { 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 @@ namespace Implab { public IPromise Chain(Func chained) { return Chain(chained, null, null); } - - public IPromise Error(Action 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; - } - - } } diff --git a/Implab/PromiseExtensions.cs b/Implab/PromiseExtensions.cs --- a/Implab/PromiseExtensions.cs +++ b/Implab/PromiseExtensions.cs @@ -56,7 +56,7 @@ namespace Implab { 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 @@ namespace Implab { 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 @@ namespace Implab { 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 @@ namespace Implab { Safe.ArgumentNotNull(that, "that"); var tcs = new TaskCompletionSource(); - that.On(tcs.SetResult, tcs.SetException, tcs.SetCanceled); + that.On(tcs.SetResult, tcs.SetException, r => tcs.SetCanceled()); return tcs.Task; } diff --git a/Implab/PromiseT.cs b/Implab/PromiseT.cs --- a/Implab/PromiseT.cs +++ b/Implab/PromiseT.cs @@ -39,7 +39,7 @@ namespace Implab { /// public class Promise : AbstractPromise>, IPromise, IDeferred { - class StubDeferred : IDeferred { + class StubDeferred : IDeferred, IDeferred { public static readonly StubDeferred instance = new StubDeferred(); StubDeferred() { @@ -50,6 +50,9 @@ namespace Implab { public void Resolve(T value) { } + public void Resolve() { + } + public void Reject(Exception error) { } @@ -60,6 +63,9 @@ namespace Implab { public void Cancel() { } + public void Cancel(Exception reason) { + } + #endregion @@ -67,11 +73,11 @@ namespace Implab { class RemapDescriptor : IDeferred { readonly Func m_remap; - readonly Func m_failed; - readonly Func m_cancel; + readonly Func m_failed; + readonly Func m_cancel; readonly IDeferred m_deferred; - public RemapDescriptor(Func remap, Func failed, Func cancel, IDeferred deferred ) { + public RemapDescriptor(Func remap, Func failed, Func cancel, IDeferred deferred ) { Debug.Assert(deferred != null); m_remap = remap; m_failed = failed; @@ -110,18 +116,21 @@ namespace Implab { #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 @@ namespace Implab { #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 @@ namespace Implab { class ValueEventDescriptor : IDeferred { readonly Action m_success; readonly Action m_failed; - readonly Action m_cancelled; + readonly Action m_cancelled; readonly IDeferred m_deferred; - public ValueEventDescriptor(Action success, Action failed, Action cancelled, IDeferred deferred) { + public ValueEventDescriptor(Action success, Action failed, Action cancelled, IDeferred deferred) { Debug.Assert(deferred != null); m_success = success; @@ -220,29 +233,33 @@ namespace Implab { #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 { readonly Action m_success; readonly Action m_failed; - readonly Action m_cancelled; - readonly IDeferred m_deferred; + readonly Action m_cancelled; + readonly IDeferred m_deferred; - public EventDescriptor(Action success, Action failed, Action cancelled, IDeferred deferred) { + public EventDescriptor(Action success, Action failed, Action cancelled, IDeferred deferred) { Debug.Assert(deferred != null); m_success = success; @@ -257,7 +274,7 @@ namespace Implab { if (m_success != null) { try { m_success(); - m_deferred.Resolve(value); + m_deferred.Resolve(); } catch (Exception ex) { Reject(ex); } @@ -268,34 +285,36 @@ namespace Implab { 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 @@ namespace Implab { return m_result; } - public IPromise On(Action success, Action error, Action cancel) { + public IPromise On(Action success, Action error, Action cancel) { AddHandler(new ValueEventDescriptor(success, error, cancel, StubDeferred.instance)); return this; } @@ -347,10 +366,10 @@ namespace Implab { return this; } - public IPromise Then(Func mapper, Func error, Func cancel) { + public IPromise Then(Func mapper, Func error, Func cancel) { var promise = new Promise(); if (mapper != null) - promise.On(Cancel, PromiseEventType.Cancelled); + promise.On((Action)null, null, Cancel); AddHandler(new RemapDescriptor(mapper, error, cancel, promise)); return promise; } @@ -358,7 +377,7 @@ namespace Implab { public IPromise Then(Func mapper, Func error) { var promise = new Promise(); if (mapper != null) - promise.On(Cancel, PromiseEventType.Cancelled); + promise.On((Action)null, null, Cancel); AddHandler(new RemapDescriptor(mapper, error, null, promise)); return promise; } @@ -366,12 +385,12 @@ namespace Implab { public IPromise Then(Func mapper) { var promise = new Promise(); if (mapper != null) - promise.On(Cancel, PromiseEventType.Cancelled); + promise.On((Action)null, null, Cancel); AddHandler(new RemapDescriptor(mapper, null, null, promise)); return promise; } - public IPromise Chain(Func> chained, Func> error, Func> cancel) { + public IPromise Chain(Func> chained, Func> error, Func> cancel) { // this promise will be resolved when an asyc operation is started var promise = new Promise>(); @@ -404,7 +423,7 @@ namespace Implab { result.On( medium.Resolve, medium.Reject, - () => medium.Reject(new OperationCanceledException()) + medium.Cancel ); medium.On(result.Cancel, PromiseEventType.Cancelled); } else { @@ -425,46 +444,10 @@ namespace Implab { return Chain(chained, null, null); } - public IPromise Error(Func error) { - var promise = new Promise(); - if (error != null) - On( - (Action)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 Cancelled(Func handler) { - var promise = new Promise(); - if (handler != null) - On( - (Action)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 error, Action cancel) { - var promise = new Promise(); + public IPromise Then(Action success, Action error, Action 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 @@ namespace Implab { return Then(success, null, null); } - public IPromise Chain(Func chained, Func error, Func cancel) { + public IPromise Chain(Func chained, Func error, Func cancel) { var promise = new Promise(); AddHandler( @@ -493,7 +476,7 @@ namespace Implab { 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 @@ namespace Implab { 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 @@ namespace Implab { return Chain(chained, null, null); } - public IPromise On(Action success, Action error, Action cancel) { + public IPromise On(Action success, Action error, Action cancel) { AddHandler(new EventDescriptor(success,error,cancel, StubDeferred.instance)); return this; } @@ -550,43 +533,6 @@ namespace Implab { return this; } - public IPromise Error(Action error) { - var promise = new Promise(); - if (error != null) - On( - (Action)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)null, - null, - () => { - try { - handler(); - promise.Resolve(); - } catch (Exception ex) { - promise.Reject(ex); - } - }); - else - Listen(PromiseEventType.Cancelled, promise.Resolve); - return promise; - } - public IPromise Cast() { return (IPromise)this; } @@ -601,8 +547,8 @@ namespace Implab { handler.Reject(error); } - protected override void SignalCancelled(IDeferred handler) { - handler.Cancel(); + protected override void SignalCancelled(IDeferred handler, Exception reason) { + handler.Cancel(reason); } protected override void Listen(PromiseEventType events, Action handler) { diff --git a/Implab/PromiseTransientException.cs b/Implab/PromiseTransientException.cs --- a/Implab/PromiseTransientException.cs +++ b/Implab/PromiseTransientException.cs @@ -1,7 +1,6 @@ using System; namespace Implab { - [Serializable] public class PromiseTransientException : Exception { /// diff --git a/Implab/SyncContextPromise.cs b/Implab/SyncContextPromise.cs --- a/Implab/SyncContextPromise.cs +++ b/Implab/SyncContextPromise.cs @@ -1,4 +1,5 @@ using System.Threading; +using System; namespace Implab { public class SyncContextPromise : Promise { @@ -13,12 +14,12 @@ namespace Implab { m_context.Post(x => base.SignalSuccess(handler), null); } - protected override void SignalError(IDeferred handler, System.Exception error) { + protected override void SignalError(IDeferred handler, Exception error) { m_context.Post(x => base.SignalError(handler, error), null); } - protected override void SignalCancelled(IDeferred handler) { - m_context.Post(x => base.SignalCancelled(handler), null); + protected override void SignalCancelled(IDeferred handler, Exception reason) { + m_context.Post(x => base.SignalCancelled(handler, reason), null); } } } diff --git a/Implab/TaskController.cs b/Implab/TaskController.cs --- a/Implab/TaskController.cs +++ b/Implab/TaskController.cs @@ -99,6 +99,13 @@ namespace Implab } } + public void Cancel(Exception reason) { + lock (m_lock) { + if (!m_cancelled) + m_cancelled = true; + } + } + protected virtual void OnCancelled() { var temp = Cancelled; if (temp != null) { diff --git a/MonoPlay/Program.cs b/MonoPlay/Program.cs --- a/MonoPlay/Program.cs +++ b/MonoPlay/Program.cs @@ -69,7 +69,7 @@ namespace MonoPlay { 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++)