Mercurial > pub > ImplabNet
changeset 9:c82e0dfbb4dd promises
sync
author | cin |
---|---|
date | Sat, 02 Nov 2013 00:55:47 +0400 |
parents | 849075f49d5c |
children | aa33d0bb8c0c |
files | Implab/IPromise.cs Implab/Promise.cs |
diffstat | 2 files changed, 73 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/Implab/IPromise.cs Fri Nov 01 16:03:52 2013 +0400 +++ b/Implab/IPromise.cs Sat Nov 02 00:55:47 2013 +0400 @@ -26,7 +26,7 @@ /// <summary> /// Tries to cancel the promise or the complete chain. /// </summary> - /// <param name="dependencies">Try to cancel the parent promise is it has the only one child</param> + /// <param name="dependencies">Try to cancel the whole promise chain, the parent promise will be cancelled only if it has only one promise</param> /// <returns></returns> bool Cancel(bool dependencies); }
--- a/Implab/Promise.cs Fri Nov 01 16:03:52 2013 +0400 +++ b/Implab/Promise.cs Sat Nov 02 00:55:47 2013 +0400 @@ -48,28 +48,32 @@ /// только инициатор обещания иначе могут возникнуть противоречия. /// </para> /// </remarks> - public class Promise<T>: IPromise { + public class Promise<T> : IPromise { struct ResultHandlerInfo { public ResultHandler<T> resultHandler; public ErrorHandler errorHandler; - public Action cancelHandler; } - LinkedList<ResultHandlerInfo> m_handlersChain = new LinkedList<ResultHandlerInfo>(); + IPromise m_parent; + + LinkedList<ResultHandlerInfo> m_resultHandlers = new LinkedList<ResultHandlerInfo>(); + LinkedList<Action> m_cancelHandlers = new LinkedList<Action>(); + + object m_lock = new Object(); + bool m_cancellable; + PromiseState m_state; - bool m_cancellable; T m_result; Exception m_error; - IPromise m_parent; + int m_childrenCount; public Promise() { m_cancellable = true; } - public Promise(IPromise parent, bool cancellable) - { + public Promise(IPromise parent, bool cancellable) { m_cancellable = cancellable; m_parent = parent; } @@ -97,9 +101,14 @@ m_state = PromiseState.Resolved; } - ResultHandlerInfo handler; + // state has been changed to rejected new handlers can't be added + + foreach (var handler in m_resultHandlers) + InvokeHandler(handler); + + /* ResultHandlerInfo handler; while (FetchNextHandler(out handler)) - InvokeHandler(handler); + InvokeHandler(handler); */ } /// <summary> @@ -117,9 +126,14 @@ m_state = PromiseState.Rejected; } - ResultHandlerInfo handler; + // state has been changed to rejected new handlers can't be added + + foreach (var handler in m_resultHandlers) + InvokeHandler(handler); + + /*ResultHandlerInfo handler; while (FetchNextHandler(out handler)) - InvokeHandler(handler); + InvokeHandler(handler);*/ } /// <summary> @@ -127,19 +141,7 @@ /// </summary> /// <returns><c>true</c> Операция была отменена, обработчики не будут вызваны.<c>false</c> отмена не возможна, поскольку обещание уже выполнено и обработчики отработали.</returns> public bool Cancel() { - lock (this) { - if (m_state == PromiseState.Unresolved && m_cancellable) - { - m_state = PromiseState.Cancelled; - EventHandler temp = Cancelled; - - if (temp != null) - temp(this, new EventArgs()); - - return true; - } else - return false; - } + return Cancel(true); } /// <summary> @@ -353,9 +355,9 @@ lock (this) { Debug.Assert(m_state != PromiseState.Unresolved); - if (m_handlersChain.Count > 0) { - handler = m_handlersChain.First.Value; - m_handlersChain.RemoveFirst(); + if (m_resultHandlers.Count > 0) { + handler = m_resultHandlers.First.Value; + m_resultHandlers.RemoveFirst(); return true; } else { return false; @@ -368,7 +370,7 @@ lock (this) { if (m_state == PromiseState.Unresolved) - m_handlersChain.AddLast(handler); + m_resultHandlers.AddLast(handler); else invokeRequired = true; } @@ -395,5 +397,47 @@ } + + public bool IsExclusive { + get { + lock (m_lock) { + return m_childrenCount <= 1; + } + } + } + + public PromiseState State { + get { + lock (m_lock) { + return m_state; + } + } + } + + public bool Cancel(bool dependencies) { + bool result; + + lock (m_lock) { + if (m_state == PromiseState.Unresolved) { + m_state = PromiseState.Cancelled; + result = true; + } else { + result = false; + } + } + + if (dependencies && m_parent != null && m_parent.IsExclusive) { + // TODO syncronize IsExclusive, AddHandler, Cancel (maybe CancelExclusive) + m_parent.Cancel(true); + } + + if (result) { + // state has been changed to cancelled, new handlers can't be added + foreach (var handler in m_cancelHandlers) + handler(); + } + + return result; + } } }