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;
+        }
     }
 }