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