Mercurial > pub > ImplabNet
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
--- /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; + } + } +}