Mercurial > pub > ImplabNet
comparison Implab/Components/RunnableComponent.cs @ 256:c52691faaf21 v3
Removed obsolete App, ComponentContainer
Extracted IAsyncComponent interface
Working on RunnableComponent
author | cin |
---|---|
date | Wed, 11 Apr 2018 03:05:14 +0300 |
parents | 6f4630d0bcd9 |
children | 440801d88019 |
comparison
equal
deleted
inserted
replaced
255:b00441e04738 | 256:c52691faaf21 |
---|---|
10 /// </summary> | 10 /// </summary> |
11 /// <remarks> | 11 /// <remarks> |
12 /// This class provides a basic lifecycle from the creation to the | 12 /// This class provides a basic lifecycle from the creation to the |
13 /// termination of the component. | 13 /// termination of the component. |
14 /// </remarks> | 14 /// </remarks> |
15 public class RunnableComponent : IRunnable, IInitializable, IDisposable { | 15 public class RunnableComponent : IAsyncComponent, IRunnable, IInitializable, IDisposable { |
16 | 16 |
17 /// <summary> | 17 /// <summary> |
18 /// This class bounds <see cref="CancellationTokenSource"/> lifetime to the task, | 18 /// This class bounds <see cref="CancellationTokenSource"/> lifetime to the task, |
19 /// when the task completes the associated token source will be disposed. | 19 /// when the task completes the associated token source will be disposed. |
20 /// </summary> | 20 /// </summary> |
78 } | 78 } |
79 | 79 |
80 } | 80 } |
81 | 81 |
82 // this lock is used to synchronize state flow of the component during | 82 // this lock is used to synchronize state flow of the component during |
83 // completions or the operations. | 83 // processing calls from a client and internal processes. |
84 readonly object m_lock = new object(); | 84 readonly object m_lock = new object(); |
85 | 85 |
86 // current operation cookie, used to check wheather a call to | 86 // current operation cookie, used to check wheather a call to |
87 // MoveSuccess/MoveFailed method belongs to the current | 87 // MoveSuccess/MoveFailed method belongs to the current |
88 // operation, if cookies didn't match ignore completion result. | 88 // operation, if cookies didn't match ignore completion result. |
89 object m_cookie; | 89 object m_cookie; |
90 | 90 |
91 // AsyncOperationDscriptor aggregates a task and it's cancellation token | |
91 AsyncOperationDescriptor m_current = AsyncOperationDescriptor.None; | 92 AsyncOperationDescriptor m_current = AsyncOperationDescriptor.None; |
92 | 93 |
93 ExecutionState m_state; | 94 ExecutionState m_state; |
94 | 95 |
95 | 96 |
150 | 151 |
151 public void Initialize() { | 152 public void Initialize() { |
152 var cookie = new object(); | 153 var cookie = new object(); |
153 if (MoveInitialize(cookie)) | 154 if (MoveInitialize(cookie)) |
154 ScheduleTask(InitializeInternalAsync, CancellationToken.None, cookie); | 155 ScheduleTask(InitializeInternalAsync, CancellationToken.None, cookie); |
156 else | |
157 throw new InvalidOperationException(); | |
155 } | 158 } |
156 | 159 |
157 /// <summary> | 160 /// <summary> |
158 /// This method is used for initialization during a component creation. | 161 /// This method is used for initialization during a component creation. |
159 /// </summary> | 162 /// </summary> |
169 | 172 |
170 public void Start(CancellationToken ct) { | 173 public void Start(CancellationToken ct) { |
171 var cookie = new object(); | 174 var cookie = new object(); |
172 if (MoveStart(cookie)) | 175 if (MoveStart(cookie)) |
173 ScheduleTask(StartInternalAsync, ct, cookie); | 176 ScheduleTask(StartInternalAsync, ct, cookie); |
177 else | |
178 throw new InvalidOperationException(); | |
174 } | 179 } |
175 | 180 |
176 protected virtual Task StartInternalAsync(CancellationToken ct) { | 181 protected virtual Task StartInternalAsync(CancellationToken ct) { |
177 return Task.CompletedTask; | 182 return Task.CompletedTask; |
178 } | 183 } |
179 | 184 |
180 public void Stop(CancellationToken ct) { | 185 public void Stop(CancellationToken ct) { |
181 var cookie = new object(); | 186 var cookie = new object(); |
182 if (MoveStop(cookie)) | 187 if (MoveStop(cookie)) |
183 ScheduleTask(StopAsync, ct, cookie); | 188 ScheduleTask(StopAsync, ct, cookie); |
189 else | |
190 throw new InvalidOperationException(); | |
184 } | 191 } |
185 | 192 |
186 async Task StopAsync(CancellationToken ct) { | 193 async Task StopAsync(CancellationToken ct) { |
187 m_current.Cancel(); | 194 m_current.Cancel(); |
188 await Completion; | 195 await Completion; |
192 await StopInternalAsync(ct); | 199 await StopInternalAsync(ct); |
193 } | 200 } |
194 | 201 |
195 protected virtual Task StopInternalAsync(CancellationToken ct) { | 202 protected virtual Task StopInternalAsync(CancellationToken ct) { |
196 return Task.CompletedTask; | 203 return Task.CompletedTask; |
204 } | |
205 | |
206 protected void Fail(Exception err) { | |
207 lock(m_lock) { | |
208 if (m_state != ExecutionState.Running) | |
209 return; | |
210 m_cookie = new object(); | |
211 LastError = err; | |
212 State = ExecutionState.Failed; | |
213 } | |
197 } | 214 } |
198 | 215 |
199 | 216 |
200 #region state management | 217 #region state management |
201 | 218 |
254 LastError = err; | 271 LastError = err; |
255 State = ExecutionState.Failed; | 272 State = ExecutionState.Failed; |
256 } | 273 } |
257 } | 274 } |
258 | 275 |
259 | 276 void ScheduleTask(Func<CancellationToken, Task> next, CancellationToken ct, object cookie) { |
260 | 277 |
261 protected async void ScheduleTask(Func<CancellationToken, Task> next, CancellationToken ct, object cookie) { | 278 m_current = AsyncOperationDescriptor.Create(async (x) => { |
262 try { | 279 try { |
263 m_current = AsyncOperationDescriptor.Create(next, ct); | 280 await next(x); |
264 await m_current.Task; | 281 MoveSuccess(cookie); |
265 MoveSuccess(cookie); | 282 } catch (Exception e) { |
266 } catch (Exception e) { | 283 MoveFailed(e, cookie); |
267 MoveFailed(e, cookie); | 284 } |
268 } | 285 }, ct); |
269 } | 286 } |
270 | 287 |
271 #endregion | 288 #endregion |
272 } | 289 } |
273 } | 290 } |