diff --git a/Implab.suo b/Implab.suo index 61301b443c112c10f3b3ee2fe11cecb25781ac9c..a4caa1b66292871242b4a6969b61dedacfacbecf GIT binary patch literal 41984 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 diff --git a/Implab/IPromise.cs b/Implab/IPromise.cs new file mode 100644 --- /dev/null +++ b/Implab/IPromise.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Implab +{ + public interface IPromise + { + /// + /// Check whereather the promise has no more than one dependent promise. + /// + bool IsExclusive + { + get; + } + + /// + /// The current state of the promise. + /// + PromiseState State + { + get; + } + + /// + /// Tries to cancel the promise or the complete chain. + /// + /// Try to cancel the parent promise is it has the only one child + /// + bool Cancel(bool dependencies); + } +} diff --git a/Implab/Implab.csproj b/Implab/Implab.csproj --- a/Implab/Implab.csproj +++ b/Implab/Implab.csproj @@ -32,10 +32,14 @@ + + + + diff --git a/Implab/ProgressInitEventArgs.cs b/Implab/ProgressInitEventArgs.cs new file mode 100644 --- /dev/null +++ b/Implab/ProgressInitEventArgs.cs @@ -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; + } + } +} diff --git a/Implab/Promise.cs b/Implab/Promise.cs --- a/Implab/Promise.cs +++ b/Implab/Promise.cs @@ -48,30 +48,32 @@ namespace Implab { /// только инициатор обещания иначе могут возникнуть противоречия. /// /// - public class Promise { + public class Promise: IPromise { struct ResultHandlerInfo { public ResultHandler resultHandler; public ErrorHandler errorHandler; - } - - enum State { - Unresolved, - Resolving, - Resolved, - Cancelled + public Action cancelHandler; } LinkedList m_handlersChain = new LinkedList(); - 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; + } + /// /// Событие, возникающее при отмене асинхронной операции. /// @@ -87,12 +89,12 @@ namespace Implab { /// Данное обещание уже выполнено 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 @@ namespace Implab { /// Данное обещание уже выполнено 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 @@ namespace Implab { /// true Операция была отменена, обработчики не будут вызваны.false отмена не возможна, поскольку обещание уже выполнено и обработчики отработали. 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 @@ namespace Implab { 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 @@ namespace Implab { bool invokeRequired = false; lock (this) { - if (m_state != State.Resolved) + if (m_state == PromiseState.Unresolved) m_handlersChain.AddLast(handler); else invokeRequired = true; diff --git a/Implab/PromiseState.cs b/Implab/PromiseState.cs new file mode 100644 --- /dev/null +++ b/Implab/PromiseState.cs @@ -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 + } +} diff --git a/Implab/TaskController.cs b/Implab/TaskController.cs new file mode 100644 --- /dev/null +++ b/Implab/TaskController.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; + +namespace Implab +{ + /// + /// This class allows to interact with asyncronuos task. + /// + /// + /// Members of this object are thread safe. + /// + class TaskController + { + object m_lock; + string m_message; + bool m_cancelled; + + float m_current; + float m_max; + + public event EventHandler> MessageUpdated; + public event EventHandler> ProgressUpdated; + public event EventHandler 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(m_message)); + } + } + + protected virtual void OnProgressUpdated() + { + var temp = ProgressUpdated; + if (temp != null) + { + temp(this,new ValueEventArgs(m_current)); + } + } + + protected virtual void OnProgressInit() + { + var temp = ProgressInit; + if (temp != null) + { + temp(this, new ProgressInitEventArgs(m_current,m_max, m_message)); + } + } + } +} diff --git a/Implab/ValueEventArgs.cs b/Implab/ValueEventArgs.cs new file mode 100644 --- /dev/null +++ b/Implab/ValueEventArgs.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Implab +{ + public class ValueEventArgs: EventArgs + { + public ValueEventArgs(T value) + { + this.Value = value; + } + public T Value + { + get; + private set; + } + } +}