Mercurial > pub > ImplabNet
annotate Implab/Components/RunnableComponent.cs @ 184:d6a8cba73acc ref20160224
working on runnable component
| author | cin |
|---|---|
| date | Sat, 16 Apr 2016 03:23:26 +0300 |
| parents | c32688129f14 |
| children | 822aab37b107 |
| rev | line source |
|---|---|
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
1 using System; |
| 180 | 2 using Implab.Formats; |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
3 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
4 namespace Implab.Components { |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
5 public class RunnableComponent : Disposable, IRunnable, IInitializable { |
| 184 | 6 enum Commands { |
| 7 Ok = 0, | |
| 8 Fail, | |
| 9 Init, | |
| 10 Start, | |
| 11 Stop, | |
| 12 Dispose, | |
| 13 Last = Dispose | |
| 14 } | |
| 15 | |
| 16 class StateMachine { | |
| 17 static readonly ExecutionState[,] _transitions; | |
| 18 | |
| 19 static StateMachine() { | |
| 20 _transitions = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1]; | |
| 21 | |
| 22 Edge(ExecutionState.Created, ExecutionState.Ready, Commands.Ok); | |
| 23 Edge(ExecutionState.Created, ExecutionState.Failed, Commands.Fail); | |
| 24 | |
| 25 Edge(ExecutionState.Ready, ExecutionState.Starting, Commands.Start); | |
| 26 Edge(ExecutionState.Ready, ExecutionState.Disposed, Commands.Dispose); | |
| 27 | |
| 28 Edge(ExecutionState.Starting, ExecutionState.Running, Commands.Ok); | |
| 29 Edge(ExecutionState.Starting, ExecutionState.Failed, Commands.Fail); | |
| 30 Edge(ExecutionState.Starting, ExecutionState.Stopping, Commands.Stop); | |
| 31 Edge(ExecutionState.Starting, ExecutionState.Disposed, Commands.Dispose); | |
| 32 | |
| 33 Edge(ExecutionState.Running, ExecutionState.Failed, Commands.Fail); | |
| 34 Edge(ExecutionState.Running, ExecutionState.Stopping, Commands.Stop); | |
| 35 Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose); | |
| 36 | |
| 37 Edge(ExecutionState.Stopping, ExecutionState.Failed, Commands.Fail); | |
| 38 Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Ok); | |
| 39 Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Dispose); | |
| 40 } | |
| 41 | |
| 42 static void Edge(ExecutionState s1, ExecutionState s2, Commands cmd) { | |
| 43 _transitions[(int)s1, (int)cmd] = s2; | |
| 44 } | |
| 45 | |
| 46 public ExecutionState State { | |
| 47 get; | |
| 48 private set; | |
| 49 } | |
| 50 | |
| 51 public StateMachine(ExecutionState initial) { | |
| 52 State = initial; | |
| 53 } | |
| 54 | |
| 55 public bool Move(Commands cmd) { | |
| 56 var next = _transitions[(int)State, (int)cmd]; | |
| 57 if (next == ExecutionState.Undefined) | |
| 58 return false; | |
| 59 State = next; | |
| 60 return true; | |
| 61 } | |
| 62 } | |
| 63 | |
| 64 IPromise m_pending; | |
| 65 Exception m_lastError; | |
| 66 | |
| 67 readonly StateMachine m_stateMachine; | |
| 68 | |
| 69 protected RunnableComponent(bool initialized) { | |
| 70 m_stateMachine = new StateMachine(initialized ? ExecutionState.Ready : ExecutionState.Created); | |
| 71 } | |
| 72 | |
| 73 void ThrowInvalidCommand(Commands cmd) { | |
| 74 throw new InvalidOperationException(String.Format("Commnd {0} is not allowed in the state {1}", cmd, m_stateMachine.State)); | |
| 75 } | |
| 76 | |
| 77 protected void Move(Commands cmd) { | |
| 78 lock (m_stateMachine) | |
| 79 if (!m_stateMachine.Move(cmd)) | |
| 80 ThrowInvalidCommand(cmd); | |
| 81 } | |
| 82 | |
| 83 protected void Fail(Exception err) { | |
| 84 lock (m_stateMachine) { | |
| 85 if (!m_stateMachine.Move(Commands.Fail)) | |
| 86 ThrowInvalidCommand(Commands.Fail); | |
| 87 | |
| 88 m_lastError = err; | |
| 89 } | |
| 90 } | |
| 91 | |
| 92 protected void Success() { | |
| 93 Move(Commands.Ok); | |
| 94 } | |
| 95 | |
| 96 protected void Invoke(Commands cmd, Action action) { | |
| 97 Move(cmd); | |
| 98 try { | |
| 99 action(); | |
| 100 Move(Commands.Ok); | |
| 101 } catch (Exception err) { | |
| 102 Fail(err); | |
| 103 throw; | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 protected IPromise InvokeAsync(Commands cmd, Func<IPromise> action) { | |
| 108 Move(cmd); | |
| 109 var medium = new Promise(); | |
| 110 | |
| 111 IPromise promise = null; | |
| 112 | |
| 113 promise = medium.Then( | |
| 114 () => { | |
| 115 lock(m_stateMachine) { | |
| 116 if (m_pending == promise) { | |
| 117 m_pending = null; | |
| 118 Move(Commands.Ok); | |
| 119 } | |
| 120 } | |
| 121 }, e => { | |
| 122 if (m_pending == promise) { | |
| 123 m_pending = null; | |
| 124 Fail( | |
| 125 } | |
| 126 } | |
| 127 ); | |
| 157 | 128 |
| 129 | |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
130 |
| 184 | 131 return Safe.InvokePromise(action).Then( |
| 132 Success, | |
| 133 Fail | |
| 134 ); | |
| 135 } | |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
136 |
| 184 | 137 void AddPending(IPromise result) { |
| 138 | |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
139 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
140 |
| 184 | 141 |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
142 #region IInitializable implementation |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
143 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
144 public void Init() { |
| 184 | 145 Invoke(Commands.Init, OnInitialize); |
| 146 } | |
| 147 | |
| 148 protected virtual void OnInitialize() { | |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
149 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
150 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
151 #endregion |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
152 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
153 #region IRunnable implementation |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
154 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
155 public IPromise Start() { |
| 184 | 156 Move(Commands.Start); |
| 157 | |
| 158 return Safe.InvokePromise(OnStart).Then( | |
| 159 () => { | |
| 160 Move(Commands.Ok); | |
| 161 Run(); | |
| 162 }, | |
| 163 () => { | |
| 164 Move(Commands.Fail); | |
| 165 } | |
| 166 ); | |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
167 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
168 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
169 protected virtual IPromise OnStart() { |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
170 return Promise.SUCCESS; |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
171 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
172 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
173 protected virtual void Run() { |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
174 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
175 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
176 public IPromise Stop() { |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
177 throw new NotImplementedException(); |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
178 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
179 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
180 public ExecutionState State { |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
181 get { |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
182 throw new NotImplementedException(); |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
183 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
184 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
185 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
186 public Exception LastError { |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
187 get { |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
188 throw new NotImplementedException(); |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
189 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
190 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
191 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
192 #endregion |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
193 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
194 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
195 |
