Mercurial > pub > ImplabNet
comparison Implab/Components/RunnableComponent.cs @ 156:97fbbf816844 v2
Promises: SignalXXX methods merged into SignalHandler method.
Components: RunnableComponent In progress
| author | cin |
|---|---|
| date | Mon, 15 Feb 2016 04:22:15 +0300 |
| parents | |
| children | 948c015a9011 |
comparison
equal
deleted
inserted
replaced
| 155:037df317f126 | 156:97fbbf816844 |
|---|---|
| 1 using System; | |
| 2 using Implab.Parsing; | |
| 3 | |
| 4 namespace Implab.Components { | |
| 5 public class RunnableComponent : Disposable, IRunnable, IInitializable { | |
| 6 class Automaton : DFAutomaton<ExecutionState> { | |
| 7 static readonly EDFADefinition<ExecutionState> _dfa; | |
| 8 | |
| 9 static Automaton() { | |
| 10 | |
| 11 var token = Token | |
| 12 .New(ExecutionState.Uninitialized).Optional() // we can skip uninitialized state | |
| 13 .Cat( | |
| 14 Token.New(ExecutionState.Ready) // uninitialized -> initial | |
| 15 .Cat( | |
| 16 Token.New(ExecutionState.Starting) // initial -> starting | |
| 17 .Cat( | |
| 18 Token.New(ExecutionState.Running) // running -> {stopping -> stopped | failed } | |
| 19 .Cat( | |
| 20 Token.New(ExecutionState.Stopping) // running -> stopping | |
| 21 .Cat( | |
| 22 Token.New(ExecutionState.Stopped) // stopping -> stopped | |
| 23 .Or(Token.New(ExecutionState.Failed)) // stopping -> failed | |
| 24 ) | |
| 25 .Or(Token.New(ExecutionState.Failed)) // running -> failed | |
| 26 ) | |
| 27 .Or(Token.New(ExecutionState.Failed)) // starting -> failed | |
| 28 ).EClosure() | |
| 29 ) | |
| 30 .Or(Token.New(ExecutionState.Failed)) // uninitialized->failed | |
| 31 .Cat(Token.New(ExecutionState.Disposed).Tag(0)) // ... -> disposed | |
| 32 ); | |
| 33 | |
| 34 var builder = new DFABuilder(); | |
| 35 token.Accept(builder); | |
| 36 | |
| 37 var _dfa = new EDFADefinition<ExecutionState>(EnumAlphabet<ExecutionState>.FullAlphabet); | |
| 38 builder.BuildDFA(_dfa); // don't optimize dfa to avoid remapping of the alphabet | |
| 39 | |
| 40 } | |
| 41 | |
| 42 public Automaton() : base(_dfa.States, INITIAL_STATE, ExecutionState.Reserved) { | |
| 43 } | |
| 44 | |
| 45 public void MoveTo(ExecutionState state) { | |
| 46 | |
| 47 if (!CanMove((int)state)) | |
| 48 throw new InvalidOperationException(String.Format("Illegal state transition from {0} to {1}", Current, state)); | |
| 49 Move((int)state); | |
| 50 m_context.info = state; | |
| 51 } | |
| 52 | |
| 53 public ExecutionState Current { | |
| 54 get { | |
| 55 return (ExecutionState)m_context.info; | |
| 56 } | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 readonly Automaton m_automaton = new Automaton(); | |
| 61 IPromise m_pending; | |
| 62 Exception m_lastError; | |
| 63 | |
| 64 protected RunnableComponent(bool initialized) { | |
| 65 if (initialized) | |
| 66 m_automaton.MoveTo(ExecutionState.Ready); | |
| 67 else | |
| 68 m_automaton.MoveTo(ExecutionState.Uninitialized); | |
| 69 } | |
| 70 | |
| 71 #region IInitializable implementation | |
| 72 | |
| 73 public void Init() { | |
| 74 | |
| 75 } | |
| 76 | |
| 77 #endregion | |
| 78 | |
| 79 #region IRunnable implementation | |
| 80 | |
| 81 public IPromise Start() { | |
| 82 return Safe.InvokePromise(() => { | |
| 83 Promise promise; | |
| 84 lock (m_automaton) { | |
| 85 if (m_automaton.Current == ExecutionState.Starting) | |
| 86 return m_pending; | |
| 87 m_automaton.MoveTo(ExecutionState.Starting); | |
| 88 m_pending = promise = new Promise(); | |
| 89 } | |
| 90 | |
| 91 var start = Safe.InvokePromise(OnStart); | |
| 92 promise.On(null, null, start.Cancel); | |
| 93 start.On(promise.Resolve, promise.Reject, promise.CancelOperation); | |
| 94 | |
| 95 return promise.Then(() => { | |
| 96 lock(m_automaton) { | |
| 97 m_automaton.MoveTo(ExecutionState.Running); | |
| 98 m_pending = null; | |
| 99 } | |
| 100 | |
| 101 Run(); | |
| 102 }, err => { | |
| 103 if (BeginTransition(RUNNING_REQUIRE)) { | |
| 104 m_lastError = err; | |
| 105 CompleteTransition(FAILED_STATE); | |
| 106 throw new PromiseTransientException(err); | |
| 107 } | |
| 108 throw new OperationCanceledException(); | |
| 109 }, reason => { | |
| 110 throw new OperationCanceledException("The operation was cancelled", reason); | |
| 111 }); | |
| 112 }); | |
| 113 } | |
| 114 | |
| 115 protected virtual IPromise OnStart() { | |
| 116 return Promise.SUCCESS; | |
| 117 } | |
| 118 | |
| 119 protected virtual void Run() { | |
| 120 } | |
| 121 | |
| 122 public IPromise Stop() { | |
| 123 throw new NotImplementedException(); | |
| 124 } | |
| 125 | |
| 126 public ExecutionState State { | |
| 127 get { | |
| 128 throw new NotImplementedException(); | |
| 129 } | |
| 130 } | |
| 131 | |
| 132 public Exception LastError { | |
| 133 get { | |
| 134 throw new NotImplementedException(); | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 #endregion | |
| 139 } | |
| 140 } | |
| 141 |
