Mercurial > pub > ImplabNet
annotate Implab/Components/RunnableComponent.cs @ 208:7d07503621fe v2
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
IRunnable is now disposable
Code cleanups, suppressed some CodeAnalysis warnings
| author | cin |
|---|---|
| date | Sun, 13 Nov 2016 18:28:17 +0300 |
| parents | 8200ab154c8a |
| children | 5dc21f6a3222 |
| 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 { | |
| 18 static readonly ExecutionState[,] _transitions; | |
| 19 | |
| 20 static StateMachine() { | |
| 21 _transitions = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1]; | |
| 22 | |
| 185 | 23 Edge(ExecutionState.Created, ExecutionState.Initializing, Commands.Init); |
| 24 Edge(ExecutionState.Created, ExecutionState.Disposed, Commands.Dispose); | |
| 25 | |
| 26 Edge(ExecutionState.Initializing, ExecutionState.Ready, Commands.Ok); | |
| 27 Edge(ExecutionState.Initializing, ExecutionState.Failed, Commands.Fail); | |
| 184 | 28 |
| 29 Edge(ExecutionState.Ready, ExecutionState.Starting, Commands.Start); | |
| 30 Edge(ExecutionState.Ready, ExecutionState.Disposed, Commands.Dispose); | |
| 31 | |
| 32 Edge(ExecutionState.Starting, ExecutionState.Running, Commands.Ok); | |
| 33 Edge(ExecutionState.Starting, ExecutionState.Failed, Commands.Fail); | |
| 34 Edge(ExecutionState.Starting, ExecutionState.Stopping, Commands.Stop); | |
| 35 Edge(ExecutionState.Starting, ExecutionState.Disposed, Commands.Dispose); | |
| 36 | |
| 37 Edge(ExecutionState.Running, ExecutionState.Failed, Commands.Fail); | |
| 38 Edge(ExecutionState.Running, ExecutionState.Stopping, Commands.Stop); | |
| 39 Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose); | |
| 40 | |
| 41 Edge(ExecutionState.Stopping, ExecutionState.Failed, Commands.Fail); | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
42 Edge(ExecutionState.Stopping, ExecutionState.Ready, Commands.Ok); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
43 Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Dispose); |
| 185 | 44 |
| 45 Edge(ExecutionState.Failed, ExecutionState.Disposed, Commands.Dispose); | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
46 Edge(ExecutionState.Failed, ExecutionState.Initializing, Commands.Reset); |
| 184 | 47 } |
| 48 | |
| 49 static void Edge(ExecutionState s1, ExecutionState s2, Commands cmd) { | |
| 50 _transitions[(int)s1, (int)cmd] = s2; | |
| 51 } | |
| 52 | |
| 53 public ExecutionState State { | |
| 54 get; | |
| 55 private set; | |
| 56 } | |
| 57 | |
| 58 public StateMachine(ExecutionState initial) { | |
| 59 State = initial; | |
| 60 } | |
| 61 | |
| 62 public bool Move(Commands cmd) { | |
| 63 var next = _transitions[(int)State, (int)cmd]; | |
| 64 if (next == ExecutionState.Undefined) | |
| 65 return false; | |
| 66 State = next; | |
| 67 return true; | |
| 68 } | |
| 69 } | |
| 70 | |
| 71 IPromise m_pending; | |
| 72 Exception m_lastError; | |
| 73 | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
74 readonly StateMachine m_stateMachine; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
75 readonly bool m_reusable; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
76 public event EventHandler<StateChangeEventArgs> StateChanged; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
77 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
78 /// <summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
79 /// Initializes component state. |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
80 /// </summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
81 /// <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
|
82 /// <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
|
83 protected RunnableComponent(bool initialized, bool reusable) { |
| 184 | 84 m_stateMachine = new StateMachine(initialized ? ExecutionState.Ready : ExecutionState.Created); |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
85 m_reusable = reusable; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
86 DisposeTimeout = 10000; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
87 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
88 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
89 /// <summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
90 /// 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
|
91 /// </summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
92 /// <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
|
93 protected RunnableComponent(bool initialized) : this(initialized, false) { |
| 184 | 94 } |
| 95 | |
|
203
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
96 /// <summary> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
97 /// Gets or sets the timeout to wait for the pending operation to complete. If the pending operation doesn't finish than the component will be disposed anyway. |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
98 /// </summary> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
99 protected int DisposeTimeout { |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
100 get; |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
101 set; |
| 185 | 102 } |
| 103 | |
| 184 | 104 void ThrowInvalidCommand(Commands cmd) { |
| 185 | 105 if (m_stateMachine.State == ExecutionState.Disposed) |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
106 throw new ObjectDisposedException(ToString()); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
107 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
108 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
|
109 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
110 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
111 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
|
112 ExecutionState prev, current; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
113 lock (m_stateMachine) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
114 if (m_stateMachine.State != state) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
115 return false; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
116 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
117 prev = m_stateMachine.State; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
118 if (!m_stateMachine.Move(cmd)) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
119 ThrowInvalidCommand(cmd); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
120 current = m_stateMachine.State; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
121 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
122 m_pending = pending; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
123 m_lastError = error; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
124 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
125 if (prev != current) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
126 OnStateChanged(prev, current, error); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
127 return true; |
| 184 | 128 } |
| 129 | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
130 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
|
131 ExecutionState prev, current; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
132 lock (m_stateMachine) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
133 if (m_pending != expected) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
134 return false; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
135 prev = m_stateMachine.State; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
136 if (!m_stateMachine.Move(cmd)) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
137 ThrowInvalidCommand(cmd); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
138 current = m_stateMachine.State; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
139 m_pending = pending; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
140 m_lastError = error; |
|
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 if (prev != current) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
143 OnStateChanged(prev, current, error); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
144 return true; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
145 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
146 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
147 IPromise Move(Commands cmd, IPromise pending, Exception error) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
148 ExecutionState prev, current; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
149 IPromise ret; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
150 lock (m_stateMachine) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
151 prev = m_stateMachine.State; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
152 if (!m_stateMachine.Move(cmd)) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
153 ThrowInvalidCommand(cmd); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
154 current = m_stateMachine.State; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
155 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
156 ret = m_pending; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
157 m_pending = pending; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
158 m_lastError = error; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
159 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
160 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
161 if(prev != current) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
162 OnStateChanged(prev, current, error); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
163 return ret; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
164 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
165 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
166 protected virtual void OnStateChanged(ExecutionState previous, ExecutionState current, Exception error) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
167 var h = StateChanged; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
168 if (h != null) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
169 h(this, new StateChangeEventArgs { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
170 State = current, |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
171 LastError = error |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
172 }); |
| 184 | 173 } |
| 174 | |
|
203
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
175 /// <summary> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
176 /// 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
|
177 /// </summary> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
178 /// <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
|
179 protected bool Fail(Exception error) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
180 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
|
181 } |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
182 |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
183 /// <summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
184 /// 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
|
185 /// </summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
186 /// <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
|
187 /// in <see cref="ExecutionState.Failed"/> state.</returns> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
188 /// <remarks> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
189 /// 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
|
190 /// moves component to <see cref="ExecutionState.Initializing"/>. |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
191 /// 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
|
192 /// 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
|
193 /// 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
|
194 /// </remarks> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
195 protected bool ResetState() { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
196 if (!MoveIfInState(Commands.Reset, null, null, ExecutionState.Failed)) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
197 return false; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
198 |
| 184 | 199 try { |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
200 OnResetState(); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
201 Move(Commands.Ok, null, null); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
202 return true; |
| 184 | 203 } catch (Exception err) { |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
204 Move(Commands.Fail, null, err); |
| 184 | 205 throw; |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
206 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
207 } |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
208 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
209 /// <summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
210 /// 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
|
211 /// </summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
212 /// <remarks> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
213 /// 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
|
214 /// 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
|
215 /// 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
|
216 /// </remarks> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
217 protected virtual void OnResetState() { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
218 throw new NotImplementedException(); |
| 184 | 219 } |
| 220 | |
| 185 | 221 IPromise InvokeAsync(Commands cmd, Func<IPromise> action, Action<IPromise, IDeferred> chain) { |
| 222 IPromise promise = null; | |
| 223 IPromise prev; | |
| 184 | 224 |
| 185 | 225 var task = new ActionChainTask(action, null, null, true); |
| 226 | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
227 Action<Exception> errorOrCancel = e => { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
228 if (e == null) |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
229 e = new OperationCanceledException(); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
230 MoveIfPending(Commands.Fail, null, e, promise); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
231 throw new PromiseTransientException(e); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
232 }; |
| 184 | 233 |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
234 promise = task.Then( |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
235 () => MoveIfPending(Commands.Ok, null, null, promise), |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
236 errorOrCancel, |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
237 errorOrCancel |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
238 ); |
|
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
|
239 |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
240 prev = Move(cmd, promise, null); |
| 157 | 241 |
| 185 | 242 if (prev == null) |
| 243 task.Resolve(); | |
| 244 else | |
| 245 chain(prev, task); | |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
246 |
| 185 | 247 return promise; |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
248 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
249 |
| 184 | 250 |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
251 #region IInitializable implementation |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
252 |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
253 public void Initialize() { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
254 Move(Commands.Init, null, null); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
255 |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
256 try { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
257 OnInitialize(); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
258 Move(Commands.Ok, null, null); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
259 } catch (Exception err) { |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
260 Move(Commands.Fail, null, err); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
261 throw; |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
262 } |
| 184 | 263 } |
| 264 | |
| 265 protected virtual void OnInitialize() { | |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
266 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
267 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
268 #endregion |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
269 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
270 #region IRunnable implementation |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
271 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
272 public IPromise Start() { |
| 185 | 273 return InvokeAsync(Commands.Start, OnStart, null); |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
274 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
275 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
276 protected virtual IPromise OnStart() { |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
277 return Promise.Success; |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
278 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
279 |
| 185 | 280 public IPromise Stop() { |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
281 var pending = InvokeAsync(Commands.Stop, OnStop, StopPending); |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
282 return m_reusable ? pending : pending.Then(Dispose); |
| 185 | 283 } |
| 284 | |
| 285 protected virtual IPromise OnStop() { | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
286 return Promise.Success; |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
287 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
288 |
| 185 | 289 /// <summary> |
| 290 /// Stops the current operation if one exists. | |
| 291 /// </summary> | |
| 292 /// <param name="current">Current.</param> | |
| 293 /// <param name="stop">Stop.</param> | |
| 294 protected virtual void StopPending(IPromise current, IDeferred stop) { | |
| 295 if (current == null) { | |
| 296 stop.Resolve(); | |
| 297 } 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
|
298 // связваем текущую операцию с операцией остановки |
|
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
|
299 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
|
300 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
|
301 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
|
302 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
|
303 ); |
|
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
|
304 // посылаем текущей операции сигнал остановки |
| 185 | 305 current.Cancel(); |
| 306 } | |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
307 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
308 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
309 public ExecutionState State { |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
310 get { |
|
203
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
311 return m_stateMachine.State; |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
312 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
313 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
314 |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
315 public Exception LastError { |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
316 get { |
| 185 | 317 return m_lastError; |
|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
318 } |
|
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
319 } |
|
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 #endregion |
| 185 | 322 |
| 323 #region IDisposable implementation | |
| 324 | |
|
203
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
325 /// <summary> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
326 /// 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
|
327 /// </summary> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
328 /// <remarks> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
329 /// <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
|
330 /// 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
|
331 /// <para> |
|
4d9830a9bbb8
Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents:
202
diff
changeset
|
332 /// 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
|
333 /// 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
|
334 /// 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
|
335 /// 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
|
336 /// </para></remarks> |
|
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
205
diff
changeset
|
337 [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Dipose(bool) and GC.SuppessFinalize are called")] |
| 185 | 338 public void Dispose() { |
| 339 IPromise pending; | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
340 |
| 185 | 341 lock (m_stateMachine) { |
| 342 if (m_stateMachine.State == ExecutionState.Disposed) | |
| 343 return; | |
|
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
205
diff
changeset
|
344 Move(Commands.Dispose, null, null); |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
345 } |
| 185 | 346 |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
347 GC.SuppressFinalize(this); |
|
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
205
diff
changeset
|
348 Dispose(true); |
| 185 | 349 } |
| 350 | |
| 351 ~RunnableComponent() { | |
|
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
205
diff
changeset
|
352 Dispose(false); |
| 185 | 353 } |
| 354 | |
| 355 #endregion | |
| 356 | |
|
205
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
357 /// <summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
358 /// 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
|
359 /// </summary> |
|
8200ab154c8a
Added ResetState to RunnableComponent to reset in case of failure
cin
parents:
203
diff
changeset
|
360 /// <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
|
361 /// <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
|
362 protected virtual void Dispose(bool disposing) { |
| 185 | 363 |
| 364 } | |
| 365 | |
|
156
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 |
