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 }