changeset 7:7ea9363fef6c promises

inital progress handling
author cin
date Fri, 01 Nov 2013 16:03:08 +0400
parents dfa21d507bc5
children 849075f49d5c
files Implab.suo Implab/IPromise.cs Implab/Implab.csproj Implab/ProgressInitEventArgs.cs Implab/Promise.cs Implab/PromiseState.cs Implab/TaskController.cs Implab/ValueEventArgs.cs
diffstat 8 files changed, 243 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
Binary file Implab.suo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab/IPromise.cs	Fri Nov 01 16:03:08 2013 +0400
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Implab
+{
+    public interface IPromise
+    {
+        /// <summary>
+        /// Check whereather the promise has no more than one dependent promise.
+        /// </summary>
+        bool IsExclusive
+        {
+            get;
+        }
+
+        /// <summary>
+        /// The current state of the promise.
+        /// </summary>
+        PromiseState State
+        {
+            get;
+        }
+
+        /// <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>
+        /// <returns></returns>
+        bool Cancel(bool dependencies);
+    }
+}
--- a/Implab/Implab.csproj	Mon Oct 21 02:34:31 2013 +0400
+++ b/Implab/Implab.csproj	Fri Nov 01 16:03:08 2013 +0400
@@ -32,10 +32,14 @@
     <Reference Include="System" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="ICancellable.cs" />
+    <Compile Include="TaskController.cs" />
+    <Compile Include="ProgressInitEventArgs.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Promise.cs" />
     <Compile Include="AsyncPool.cs" />
     <Compile Include="Safe.cs" />
+    <Compile Include="ValueEventArgs.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab/ProgressInitEventArgs.cs	Fri Nov 01 16:03:08 2013 +0400
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Implab
+{
+
+    public class ProgressInitEventArgs: EventArgs
+    {
+        public float MaxProgress
+        {
+            get;
+            private set;
+        }
+
+        public float CurrentProgress
+        {
+            get;
+            private set;
+        }
+
+        public string Message
+        {
+            get;
+            private set;
+        }
+
+        public ProgressInitEventArgs(float current, float max, string message)
+        {
+            this.MaxProgress = max;
+            this.CurrentProgress = current;
+            this.Message = message;
+        }
+    }
+}
--- a/Implab/Promise.cs	Mon Oct 21 02:34:31 2013 +0400
+++ b/Implab/Promise.cs	Fri Nov 01 16:03:08 2013 +0400
@@ -48,30 +48,32 @@
     /// только инициатор обещания иначе могут возникнуть противоречия.
     /// </para>
     /// </remarks>
-    public class Promise<T> {
+    public class Promise<T>: IPromise {
 
         struct ResultHandlerInfo {
             public ResultHandler<T> resultHandler;
             public ErrorHandler errorHandler;
-        }
-
-        enum State {
-            Unresolved,
-            Resolving,
-            Resolved,
-            Cancelled
+            public Action cancelHandler;
         }
 
         LinkedList<ResultHandlerInfo> m_handlersChain = new LinkedList<ResultHandlerInfo>();
-        State m_state;
+        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)
+        {
+            m_cancellable = cancellable;
+            m_parent = parent;
+        }
+
         /// <summary>
         /// Событие, возникающее при отмене асинхронной операции.
         /// </summary>
@@ -87,12 +89,12 @@
         /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception>
         public void Resolve(T result) {
             lock (this) {
-                if (m_state == State.Cancelled)
+                if (m_state == PromiseState.Cancelled)
                     return;
-                if (m_state != State.Unresolved)
+                if (m_state != PromiseState.Unresolved)
                     throw new InvalidOperationException("The promise is already resolved");
                 m_result = result;
-                m_state = State.Resolving;
+                m_state = PromiseState.Resolved;
             }
 
             ResultHandlerInfo handler;
@@ -107,12 +109,12 @@
         /// <exception cref="InvalidOperationException">Данное обещание уже выполнено</exception>
         public void Reject(Exception error) {
             lock (this) {
-                if (m_state == State.Cancelled)
+                if (m_state == PromiseState.Cancelled)
                     return;
-                if (m_state != State.Unresolved)
+                if (m_state != PromiseState.Unresolved)
                     throw new InvalidOperationException("The promise is already resolved");
                 m_error = error;
-                m_state = State.Resolving;
+                m_state = PromiseState.Rejected;
             }
 
             ResultHandlerInfo handler;
@@ -126,8 +128,9 @@
         /// <returns><c>true</c> Операция была отменена, обработчики не будут вызваны.<c>false</c> отмена не возможна, поскольку обещание уже выполнено и обработчики отработали.</returns>
         public bool Cancel() {
             lock (this) {
-                if (m_state == State.Unresolved && m_cancellable) {
-                    m_state = State.Cancelled;
+                if (m_state == PromiseState.Unresolved && m_cancellable)
+                {
+                    m_state = PromiseState.Cancelled;
                     EventHandler temp = Cancelled;
 
                     if (temp != null)
@@ -348,14 +351,13 @@
             handler = default(ResultHandlerInfo);
 
             lock (this) {
-                Debug.Assert(m_state == State.Resolving);
+                Debug.Assert(m_state != PromiseState.Unresolved);
 
                 if (m_handlersChain.Count > 0) {
                     handler = m_handlersChain.First.Value;
                     m_handlersChain.RemoveFirst();
                     return true;
                 } else {
-                    m_state = State.Resolved;
                     return false;
                 }
             }
@@ -365,7 +367,7 @@
             bool invokeRequired = false;
 
             lock (this) {
-                if (m_state != State.Resolved)
+                if (m_state == PromiseState.Unresolved)
                     m_handlersChain.AddLast(handler);
                 else
                     invokeRequired = true;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab/PromiseState.cs	Fri Nov 01 16:03:08 2013 +0400
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Implab
+{
+    public enum PromiseState
+    {
+        Unresolved,
+        Resolved,
+        Cancelled,
+        Rejected
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab/TaskController.cs	Fri Nov 01 16:03:08 2013 +0400
@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+
+namespace Implab
+{
+    /// <summary>
+    /// This class allows to interact with asyncronuos task.
+    /// </summary>
+    /// <remarks>
+    /// Members of this object are thread safe.
+    /// </remarks>
+    class TaskController
+    {
+        object m_lock;
+        string m_message;
+        bool m_cancelled;
+
+        float m_current;
+        float m_max;
+
+        public event EventHandler<ValueEventArgs<string>> MessageUpdated;
+        public event EventHandler<ValueEventArgs<float>> ProgressUpdated;
+        public event EventHandler<ProgressInitEventArgs> ProgressInit;
+
+        public TaskController()
+        {
+            m_lock = new Object();
+        }
+
+        public string Message
+        {
+            get
+            {
+                lock (m_lock)
+                    return m_message;
+            }
+            set
+            {
+                lock (m_lock)
+                {
+                    m_message = value;
+                    OnMessageUpdated();
+                }
+            }
+        }
+
+        public float CurrentProgress
+        {
+            get
+            {
+                lock (m_lock)
+                    return m_current;
+            }
+            set
+            {
+                lock (m_lock)
+                {
+                    var prev = m_current;
+                    m_current = value;
+                    if (m_current >= m_max)
+                        m_current = m_max;
+                    if (m_current != prev)
+                        OnProgressUpdated();
+                }
+            }
+        }
+
+        public void InitProgress(float current, float max, string message)
+        {
+            if (max < 0)
+                throw new ArgumentOutOfRangeException("max");
+            if (current < 0 || current > max)
+                throw new ArgumentOutOfRangeException("current");
+
+            lock(m_lock) {
+                m_current = current;
+                m_max = max;
+                m_message = message;
+                OnProgressInit();
+            }
+        }
+
+        protected virtual void OnMessageUpdated()
+        {
+            var temp = MessageUpdated;
+            if (temp != null)
+            {
+                temp(this, new ValueEventArgs<string>(m_message));
+            }
+        }
+
+        protected virtual void OnProgressUpdated()
+        {
+            var temp = ProgressUpdated;
+            if (temp != null)
+            {
+                temp(this,new ValueEventArgs<float>(m_current));
+            }
+        }
+
+        protected virtual void OnProgressInit()
+        {
+            var temp = ProgressInit;
+            if (temp != null)
+            {
+                temp(this, new ProgressInitEventArgs(m_current,m_max, m_message));
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab/ValueEventArgs.cs	Fri Nov 01 16:03:08 2013 +0400
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Implab
+{
+    public class ValueEventArgs<T>: EventArgs
+    {
+        public ValueEventArgs(T value)
+        {
+            this.Value = value;
+        }
+        public T Value
+        {
+            get;
+            private set;
+        }
+    }
+}