Mercurial > pub > ImplabNet
view Implab/Components/RunnableComponent.cs @ 157:948c015a9011 v2
sync
author | cin |
---|---|
date | Thu, 18 Feb 2016 11:03:47 +0300 |
parents | 97fbbf816844 |
children | 130781364799 |
line wrap: on
line source
using System; using Implab.Parsing; namespace Implab.Components { public class RunnableComponent : Disposable, IRunnable, IInitializable { class Automaton { enum Operations { Initialize, Start, Stop, Fail, Success, Dispose } static readonly EDFADefinition<ExecutionState> _def = new EDFADefinition<ExecutionState>(EnumAlphabet<ExecutionState>.FullAlphabet); static readonly DFAStateDescriptior[] _states; static Automaton() { var created = _def.AddState(); // initial state var initializing = _def.AddState(); var ready = _def.AddState(); var starting = _def.AddState(); var running = _def.AddState(); var stopping = _def.AddState(); var error = _def.AddState(); var disposing = _def.AddState(); var disposed = _def.AddState(new int[] { 0 }); _def.DefineTransition(created,initializing,(int)Operations.Initialize); _def.DefineTransition(initializing,ready,(int)Operations.Success); _def.DefineTransition(initializing,error,(int)Operations.Fail); _def.DefineTransition(ready, starting, (int)Operations.Start); _def.DefineTransition(ready, disposing, (int)Operations.Dispose); _def.DefineTransition(starting, running, (int)Operations.Success); _def.DefineTransition(starting, error, (int)Operations.Fail); _def.DefineTransition(running, stopping, (int)Operations.Stop); _def.DefineTransition(running, error, (int)Operations.Fail); _def.DefineTransition(stopping, ready, (int)Operations.Success); _def.DefineTransition(stopping, error, (int)Operations.Fail); _def.DefineTransition(disposing, disposed, (int)Operations.Success); _states = _def.States; } int m_state; public Automaton() { m_state = DFADefinitionBase.INITIAL_STATE; } void Move(Operations op) { } public ExecutionState Current { get { return (ExecutionState)m_context.info; } } } readonly Automaton m_automaton = new Automaton(); IPromise m_pending; Exception m_lastError; protected RunnableComponent(bool initialized) { if (initialized) m_automaton.MoveTo(ExecutionState.Ready); else m_automaton.MoveTo(ExecutionState.Uninitialized); } #region IInitializable implementation public void Init() { } #endregion #region IRunnable implementation public IPromise Start() { return Safe.InvokePromise(() => { Promise promise; lock (m_automaton) { if (m_automaton.Current == ExecutionState.Starting) return m_pending; m_automaton.MoveTo(ExecutionState.Starting); m_pending = promise = new Promise(); } var start = Safe.InvokePromise(OnStart); promise.On(null, null, start.Cancel); start.On(promise.Resolve, promise.Reject, promise.CancelOperation); return promise.Then(() => { lock(m_automaton) { m_automaton.MoveTo(ExecutionState.Running); m_pending = null; } Run(); }, err => { if (BeginTransition(RUNNING_REQUIRE)) { m_lastError = err; CompleteTransition(FAILED_STATE); throw new PromiseTransientException(err); } throw new OperationCanceledException(); }, reason => { throw new OperationCanceledException("The operation was cancelled", reason); }); }); } protected virtual IPromise OnStart() { return Promise.SUCCESS; } protected virtual void Run() { } public IPromise Stop() { throw new NotImplementedException(); } public ExecutionState State { get { throw new NotImplementedException(); } } public Exception LastError { get { throw new NotImplementedException(); } } #endregion } }