Mercurial > pub > ImplabNet
annotate Implab/Components/RunnableComponent.cs @ 234:8dd666e6b6bf v2
Added implab nuget spec
| author | cin |
|---|---|
| date | Thu, 05 Oct 2017 09:21:23 +0300 |
| parents | 5dc21f6a3222 |
| children | eee3e49dd1ff |
| rev | line source |
|---|---|
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
1 using System; |
|
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
205
diff
changeset
|
2 using System.Diagnostics.CodeAnalysis; |
|
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
205
diff
changeset
|
3 |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
4 namespace Implab.Components { |
| 185 | 5 public abstract class RunnableComponent : IDisposable, IRunnable, IInitializable { |
| 184 | 6 enum Commands { |
| 7 Ok = 0, | |
| 8 Fail, | |
| 9 Init, | |
| 10 Start, | |
| 11 Stop, | |
| 12 Dispose, | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
13 Reset, |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
14 Last = Reset |
| 184 | 15 } |
| 16 | |
| 17 class StateMachine { | |
| 210 | 18 public static readonly ExecutionState[,] ReusableTransitions; |
| 19 public static readonly ExecutionState[,] NonreusableTransitions; | |
| 20 | |
| 21 class StateBuilder { | |
| 22 readonly ExecutionState[,] m_states; | |
| 23 | |
| 24 public ExecutionState[,] States { | |
| 25 get { return m_states; } | |
| 26 } | |
| 27 public StateBuilder(ExecutionState[,] states) { | |
| 28 m_states = states; | |
| 29 } | |
| 30 | |
| 31 public StateBuilder() { | |
| 32 m_states = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1]; | |
| 33 } | |
| 34 | |
| 35 public StateBuilder Edge(ExecutionState s1, ExecutionState s2, Commands cmd) { | |
| 36 m_states[(int)s1, (int)cmd] = s2; | |
| 37 return this; | |
| 38 } | |
| 39 | |
| 40 public StateBuilder Clone() { | |
| 41 return new StateBuilder((ExecutionState[,])m_states.Clone()); | |
| 42 } | |
| 43 } | |
| 184 | 44 |
| 45 static StateMachine() { | |
| 210 | 46 ReusableTransitions = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1]; |
| 184 | 47 |
| 210 | 48 var common = new StateBuilder() |
| 49 .Edge(ExecutionState.Created, ExecutionState.Initializing, Commands.Init) | |
| 50 .Edge(ExecutionState.Created, ExecutionState.Disposed, Commands.Dispose) | |
| 185 | 51 |
| 210 | 52 .Edge(ExecutionState.Initializing, ExecutionState.Ready, Commands.Ok) |
| 53 .Edge(ExecutionState.Initializing, ExecutionState.Failed, Commands.Fail) | |
| 184 | 54 |
| 210 | 55 .Edge(ExecutionState.Ready, ExecutionState.Starting, Commands.Start) |
| 56 .Edge(ExecutionState.Ready, ExecutionState.Disposed, Commands.Dispose) | |
| 57 | |
| 58 .Edge(ExecutionState.Starting, ExecutionState.Running, Commands.Ok) | |
| 59 .Edge(ExecutionState.Starting, ExecutionState.Failed, Commands.Fail) | |
| 60 .Edge(ExecutionState.Starting, ExecutionState.Stopping, Commands.Stop) | |
| 61 .Edge(ExecutionState.Starting, ExecutionState.Disposed, Commands.Dispose) | |
| 184 | 62 |
| 210 | 63 .Edge(ExecutionState.Running, ExecutionState.Failed, Commands.Fail) |
| 64 .Edge(ExecutionState.Running, ExecutionState.Stopping, Commands.Stop) | |
| 65 .Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose) | |
| 66 | |
| 67 .Edge(ExecutionState.Failed, ExecutionState.Disposed, Commands.Dispose) | |
| 68 .Edge(ExecutionState.Failed, ExecutionState.Initializing, Commands.Reset) | |
| 69 | |
| 70 .Edge(ExecutionState.Stopping, ExecutionState.Failed, Commands.Fail) | |
| 71 .Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Dispose) | |
| 72 | |
| 73 .Edge(ExecutionState.Disposed, ExecutionState.Disposed, Commands.Dispose); | |
| 184 | 74 |
| 210 | 75 var reusable = common |
| 76 .Clone() | |
| 77 .Edge(ExecutionState.Stopping, ExecutionState.Ready, Commands.Ok); | |
| 78 | |
| 79 var nonreusable = common | |
| 80 .Clone() | |
| 81 .Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Ok); | |
| 82 | |
| 83 NonreusableTransitions = nonreusable.States; | |
| 84 ReusableTransitions = reusable.States; | |
| 184 | 85 |
| 86 } | |
| 87 | |
| 210 | 88 readonly ExecutionState[,] m_states; |
| 184 | 89 |
| 90 public ExecutionState State { | |
| 91 get; | |
| 92 private set; | |
| 93 } | |
| 94 | |
| 210 | 95 public StateMachine(ExecutionState[,] states, ExecutionState initial) { |
| 184 | 96 State = initial; |
| 210 | 97 m_states = states; |
| 184 | 98 } |
| 99 | |
| 100 public bool Move(Commands cmd) { | |
| 210 | 101 var next = m_states[(int)State, (int)cmd]; |
| 184 | 102 if (next == ExecutionState.Undefined) |
| 103 return false; | |
| 104 State = next; | |
| 105 return true; | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 IPromise m_pending; | |
| 110 Exception m_lastError; | |
| 111 | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
112 readonly StateMachine m_stateMachine; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
113 readonly bool m_reusable; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
114 public event EventHandler<StateChangeEventArgs> StateChanged; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
115 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
116 /// <summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
117 /// Initializes component state. |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
118 /// </summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
119 /// <param name="initialized">If set, the component initial state is <see cref="ExecutionState.Ready"/> and the component is ready to start, otherwise initialization is required.</param> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
120 /// <param name="reusable">If set, the component may start after it has been stopped, otherwise the component is disposed after being stopped.</param> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
121 protected RunnableComponent(bool initialized, bool reusable) { |
| 210 | 122 m_stateMachine = new StateMachine( |
| 123 reusable ? StateMachine.ReusableTransitions : StateMachine.NonreusableTransitions, | |
| 124 initialized ? ExecutionState.Ready : ExecutionState.Created | |
| 125 ); | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
126 m_reusable = reusable; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
127 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
128 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
129 /// <summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
130 /// Initializes component state. The component created with this constructor is not reusable, i.e. it will be disposed after stop. |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
131 /// </summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
132 /// <param name="initialized">If set, the component initial state is <see cref="ExecutionState.Ready"/> and the component is ready to start, otherwise initialization is required.</param> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
133 protected RunnableComponent(bool initialized) : this(initialized, false) { |
| 184 | 134 } |
| 135 | |
| 136 void ThrowInvalidCommand(Commands cmd) { | |
| 185 | 137 if (m_stateMachine.State == ExecutionState.Disposed) |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
138 throw new ObjectDisposedException(ToString()); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
139 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
140 throw new InvalidOperationException(String.Format("Command {0} is not allowed in the state {1}", cmd, m_stateMachine.State)); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
141 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
142 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
143 bool MoveIfInState(Commands cmd, IPromise pending, Exception error, ExecutionState state) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
144 ExecutionState prev, current; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
145 lock (m_stateMachine) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
146 if (m_stateMachine.State != state) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
147 return false; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
148 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
149 prev = m_stateMachine.State; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
150 if (!m_stateMachine.Move(cmd)) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
151 ThrowInvalidCommand(cmd); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
152 current = m_stateMachine.State; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
153 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
154 m_pending = pending; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
155 m_lastError = error; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
156 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
157 if (prev != current) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
158 OnStateChanged(prev, current, error); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
159 return true; |
| 184 | 160 } |
| 161 | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
162 bool MoveIfPending(Commands cmd, IPromise pending, Exception error, IPromise expected) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
163 ExecutionState prev, current; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
164 lock (m_stateMachine) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
165 if (m_pending != expected) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
166 return false; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
167 prev = m_stateMachine.State; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
168 if (!m_stateMachine.Move(cmd)) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
169 ThrowInvalidCommand(cmd); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
170 current = m_stateMachine.State; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
171 m_pending = pending; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
172 m_lastError = error; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
173 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
174 if (prev != current) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
175 OnStateChanged(prev, current, error); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
176 return true; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
177 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
178 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
179 IPromise Move(Commands cmd, IPromise pending, Exception error) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
180 ExecutionState prev, current; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
181 IPromise ret; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
182 lock (m_stateMachine) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
183 prev = m_stateMachine.State; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
184 if (!m_stateMachine.Move(cmd)) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
185 ThrowInvalidCommand(cmd); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
186 current = m_stateMachine.State; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
187 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
188 ret = m_pending; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
189 m_pending = pending; |
| 210 | 190 m_lastError = error; |
| 191 | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
192 } |
| 210 | 193 if (prev != current) |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
194 OnStateChanged(prev, current, error); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
195 return ret; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
196 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
197 |
| 210 | 198 /// <summary> |
| 199 /// Handles the state of the component change event, raises the <see cref="StateChanged"/> event, handles | |
| 200 /// the transition to the <see cref="ExecutionState.Disposed"/> state (calls <see cref="Dispose(bool)"/> method). | |
| 201 /// </summary> | |
| 202 /// <param name="previous">The previous state</param> | |
| 203 /// <param name="current">The current state</param> | |
| 204 /// <param name="error">The last error if any.</param> | |
| 205 /// <remarks> | |
| 206 /// <para> | |
| 207 /// If the previous state and the current state are same this method isn't called, such situiation is treated | |
| 208 /// as the component hasn't changed it's state. | |
| 209 /// </para> | |
| 210 /// <para> | |
| 211 /// When overriding this method ensure the call is made to the base implementation, otherwise it will lead to | |
| 212 /// the wrong behavior of the component. | |
| 213 /// </para> | |
| 214 /// </remarks> | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
215 protected virtual void OnStateChanged(ExecutionState previous, ExecutionState current, Exception error) { |
| 210 | 216 StateChanged.DispatchEvent( |
| 217 this, | |
| 218 new StateChangeEventArgs { | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
219 State = current, |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
220 LastError = error |
| 210 | 221 } |
| 222 ); | |
| 223 if (current == ExecutionState.Disposed) { | |
| 224 GC.SuppressFinalize(this); | |
| 225 Dispose(true); | |
| 226 } | |
| 184 | 227 } |
| 228 | |
|
203
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
229 /// <summary> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
230 /// Moves the component from running to failed state. |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
231 /// </summary> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
232 /// <param name="error">The exception which is describing the error.</param> |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
233 protected bool Fail(Exception error) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
234 return MoveIfInState(Commands.Fail, null, error, ExecutionState.Running); |
|
203
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
235 } |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
236 |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
237 /// <summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
238 /// Tries to reset <see cref="ExecutionState.Failed"/> state to <see cref="ExecutionState.Ready"/>. |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
239 /// </summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
240 /// <returns>True if component is reset to <see cref="ExecutionState.Ready"/>, false if the componet wasn't |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
241 /// in <see cref="ExecutionState.Failed"/> state.</returns> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
242 /// <remarks> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
243 /// This method checks the current state of the component and if it's in <see cref="ExecutionState.Failed"/> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
244 /// moves component to <see cref="ExecutionState.Initializing"/>. |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
245 /// The <see cref="OnResetState()"/> is called and if this method completes succesfully the component moved |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
246 /// to <see cref="ExecutionState.Ready"/> state, otherwise the component is moved to <see cref="ExecutionState.Failed"/> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
247 /// state. If <see cref="OnResetState()"/> throws an exception it will be propagated by this method to the caller. |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
248 /// </remarks> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
249 protected bool ResetState() { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
250 if (!MoveIfInState(Commands.Reset, null, null, ExecutionState.Failed)) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
251 return false; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
252 |
| 184 | 253 try { |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
254 OnResetState(); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
255 Move(Commands.Ok, null, null); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
256 return true; |
| 184 | 257 } catch (Exception err) { |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
258 Move(Commands.Fail, null, err); |
| 184 | 259 throw; |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
260 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
261 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
262 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
263 /// <summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
264 /// This method is called by <see cref="ResetState"/> to reinitialize component in the failed state. |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
265 /// </summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
266 /// <remarks> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
267 /// Default implementation throws <see cref="NotImplementedException"/> which will cause the component |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
268 /// fail to reset it's state and it left in <see cref="ExecutionState.Failed"/> state. |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
269 /// If this method doesn't throw exceptions the component is moved to <see cref="ExecutionState.Ready"/> state. |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
270 /// </remarks> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
271 protected virtual void OnResetState() { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
272 throw new NotImplementedException(); |
| 184 | 273 } |
| 274 | |
| 185 | 275 IPromise InvokeAsync(Commands cmd, Func<IPromise> action, Action<IPromise, IDeferred> chain) { |
| 276 IPromise promise = null; | |
| 277 IPromise prev; | |
| 184 | 278 |
| 185 | 279 var task = new ActionChainTask(action, null, null, true); |
| 280 | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
281 Action<Exception> errorOrCancel = e => { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
282 if (e == null) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
283 e = new OperationCanceledException(); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
284 MoveIfPending(Commands.Fail, null, e, promise); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
285 throw new PromiseTransientException(e); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
286 }; |
| 184 | 287 |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
288 promise = task.Then( |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
289 () => MoveIfPending(Commands.Ok, null, null, promise), |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
290 errorOrCancel, |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
291 errorOrCancel |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
292 ); |
|
196
40d7fed4a09e
fixed promise chaining behavior, the error handler doesn't handle result or cancellation handlers exceptions these exceptions are propagated to the next handlers.
cin
parents:
187
diff
changeset
|
293 |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
294 prev = Move(cmd, promise, null); |
| 157 | 295 |
| 185 | 296 if (prev == null) |
| 297 task.Resolve(); | |
| 298 else | |
| 299 chain(prev, task); | |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
300 |
| 185 | 301 return promise; |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
302 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
303 |
| 184 | 304 |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
305 #region IInitializable implementation |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
306 |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
307 public void Initialize() { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
308 Move(Commands.Init, null, null); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
309 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
310 try { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
311 OnInitialize(); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
312 Move(Commands.Ok, null, null); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
313 } catch (Exception err) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
314 Move(Commands.Fail, null, err); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
315 throw; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
316 } |
| 184 | 317 } |
| 318 | |
| 319 protected virtual void OnInitialize() { | |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
320 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
321 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
322 #endregion |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
323 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
324 #region IRunnable implementation |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
325 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
326 public IPromise Start() { |
| 185 | 327 return InvokeAsync(Commands.Start, OnStart, null); |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
328 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
329 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
330 protected virtual IPromise OnStart() { |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
331 return Promise.Success; |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
332 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
333 |
| 185 | 334 public IPromise Stop() { |
| 210 | 335 return InvokeAsync(Commands.Stop, OnStop, StopPending); |
| 185 | 336 } |
| 337 | |
| 338 protected virtual IPromise OnStop() { | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
339 return Promise.Success; |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
340 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
341 |
| 185 | 342 /// <summary> |
| 343 /// Stops the current operation if one exists. | |
| 344 /// </summary> | |
| 345 /// <param name="current">Current.</param> | |
| 346 /// <param name="stop">Stop.</param> | |
| 347 protected virtual void StopPending(IPromise current, IDeferred stop) { | |
| 348 if (current == null) { | |
| 349 stop.Resolve(); | |
| 350 } else { | |
|
187
dd4a3590f9c6
Reworked cancelation handling, if the cancel handler isn't specified the OperationCanceledException will be handled by the error handler
cin
parents:
186
diff
changeset
|
351 // связваем текущую операцию с операцией остановки |
|
dd4a3590f9c6
Reworked cancelation handling, if the cancel handler isn't specified the OperationCanceledException will be handled by the error handler
cin
parents:
186
diff
changeset
|
352 current.On( |
|
dd4a3590f9c6
Reworked cancelation handling, if the cancel handler isn't specified the OperationCanceledException will be handled by the error handler
cin
parents:
186
diff
changeset
|
353 stop.Resolve, // если текущая операция заверщилась, то можно начинать остановку |
|
dd4a3590f9c6
Reworked cancelation handling, if the cancel handler isn't specified the OperationCanceledException will be handled by the error handler
cin
parents:
186
diff
changeset
|
354 stop.Reject, // если текущая операция дала ошибку - то все плохо, нельзя продолжать |
|
dd4a3590f9c6
Reworked cancelation handling, if the cancel handler isn't specified the OperationCanceledException will be handled by the error handler
cin
parents:
186
diff
changeset
|
355 e => stop.Resolve() // если текущая отменилась, то можно начинать остановку |
|
dd4a3590f9c6
Reworked cancelation handling, if the cancel handler isn't specified the OperationCanceledException will be handled by the error handler
cin
parents:
186
diff
changeset
|
356 ); |
|
dd4a3590f9c6
Reworked cancelation handling, if the cancel handler isn't specified the OperationCanceledException will be handled by the error handler
cin
parents:
186
diff
changeset
|
357 // посылаем текущей операции сигнал остановки |
| 185 | 358 current.Cancel(); |
| 359 } | |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
360 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
361 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
362 public ExecutionState State { |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
363 get { |
|
203
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
364 return m_stateMachine.State; |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
365 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
366 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
367 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
368 public Exception LastError { |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
369 get { |
| 185 | 370 return m_lastError; |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
371 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
372 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
373 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
374 #endregion |
| 185 | 375 |
| 376 #region IDisposable implementation | |
| 377 | |
|
203
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
378 /// <summary> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
379 /// Releases all resource used by the <see cref="Implab.Components.RunnableComponent"/> object. |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
380 /// </summary> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
381 /// <remarks> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
382 /// <para>Will not try to stop the component, it will just release all resources. |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
383 /// To cleanup the component gracefully use <see cref="Stop()"/> method.</para> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
384 /// <para> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
385 /// In normal cases the <see cref="Dispose()"/> method shouldn't be called, the call to the <see cref="Stop()"/> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
386 /// method is sufficient to cleanup the component. Call <see cref="Dispose()"/> only to cleanup after errors, |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
387 /// especially if <see cref="Stop"/> method is failed. Using this method insted of <see cref="Stop()"/> may |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
388 /// lead to the data loss by the component. |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
389 /// </para></remarks> |
|
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
205
diff
changeset
|
390 [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Dipose(bool) and GC.SuppessFinalize are called")] |
| 185 | 391 public void Dispose() { |
| 210 | 392 Move(Commands.Dispose, null, null); |
| 185 | 393 } |
| 394 | |
| 395 ~RunnableComponent() { | |
|
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
205
diff
changeset
|
396 Dispose(false); |
| 185 | 397 } |
| 398 | |
| 399 #endregion | |
| 400 | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
401 /// <summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
402 /// Releases all resources used by the component, called automatically, override this method to implement your cleanup. |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
403 /// </summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
404 /// <param name="disposing">true if this method is called during normal dispose process.</param> |
|
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
205
diff
changeset
|
405 /// <param name="pending">The operation which is currenty pending</param> |
|
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
205
diff
changeset
|
406 protected virtual void Dispose(bool disposing) { |
| 185 | 407 } |
| 408 | |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
409 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
410 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
411 |
