annotate Implab/Components/RunnableComponent.cs @ 278:6691aff01de1 v3

Implab: added XmlDefaultSeializer (SerializersPool is now obsolete) Implab.ServiceHost: rewritten TypeReference (added support for nested types), stable API
author cin
date Thu, 03 May 2018 09:59:44 +0300
parents f1696cdc3d7a
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
1 using System;
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
2 using System.Diagnostics;
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
3 using System.Threading;
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
4 using System.Threading.Tasks;
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
5
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
6 namespace Implab.Components {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
7 /// <summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
8 /// Base class for implementing components which support start and stop operations,
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
9 /// such components may represent running services.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
10 /// </summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
11 /// <remarks>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
12 /// This class provides a basic lifecycle from the creation to the
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
13 /// termination of the component.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
14 /// </remarks>
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
15 public abstract class RunnableComponent : IAsyncComponent, IRunnable, IInitializable, IDisposable {
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
16
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
17 /// <summary>
252
6f4630d0bcd9 removed absolete Diagnostics classes
cin
parents: 251
diff changeset
18 /// This class bounds <see cref="CancellationTokenSource"/> lifetime to the task,
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
19 /// when the task completes the associated token source will be disposed.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
20 /// </summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
21 class AsyncOperationDescriptor {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
22
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
23 public static AsyncOperationDescriptor None { get; } = new AsyncOperationDescriptor();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
24
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
25 readonly CancellationTokenSource m_cts;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
26
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
27 bool m_done;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
28
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
29 public CancellationToken Token {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
30 get { return m_cts == null ? CancellationToken.None : m_cts.Token; }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
31 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
32
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
33 public Task Task { get; private set; }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
34
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
35 private AsyncOperationDescriptor(Task task, CancellationTokenSource cts) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
36 m_cts = cts;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
37 Task = Chain(task);
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
38 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
39
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
40 private AsyncOperationDescriptor() {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
41 Task = Task.CompletedTask;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
42 }
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
43
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
44 public void Cancel() {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
45 if (m_cts != null) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
46 lock (m_cts) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
47 if (!m_done)
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
48 m_cts.Cancel();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
49 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
50 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
51 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
52
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
53 void Done() {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
54 if (m_cts != null) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
55 lock (m_cts) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
56 m_done = true;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
57 m_cts.Dispose();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
58 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
59 } else {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
60 m_done = true;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
61 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
62 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
63
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
64 async Task Chain(Task other) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
65 try {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
66 await other;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
67 } finally {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
68 Done();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
69 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
70 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
71
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
72 public static AsyncOperationDescriptor Create(Func<CancellationToken, Task> factory, CancellationToken ct) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
73 var cts = ct.CanBeCanceled ?
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
74 CancellationTokenSource.CreateLinkedTokenSource(ct) :
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
75 new CancellationTokenSource();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
76
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
77 return new AsyncOperationDescriptor(factory(cts.Token), cts);
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
78 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
79
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
80 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
81
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
82 // this lock is used to synchronize state flow of the component during
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
83 // processing calls from a client and internal processes.
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
84 readonly object m_lock = new object();
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
85
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
86 // current operation cookie, used to check wheather a call to
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
87 // MoveSuccess/MoveFailed method belongs to the current
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
88 // operation, if cookies didn't match ignore completion result.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
89 object m_cookie;
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
90
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
91 // AsyncOperationDscriptor aggregates a task and it's cancellation token
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
92 AsyncOperationDescriptor m_current = AsyncOperationDescriptor.None;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
93
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
94 ExecutionState m_state;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
95
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
96 /// <summary>
440801d88019 working on runnable components
cin
parents: 256
diff changeset
97 /// Объект синхронизации используется для обеспечения совместного доступа
440801d88019 working on runnable components
cin
parents: 256
diff changeset
98 /// клиента компоненты и процессов, протекающих внутри компоненты, к общему
440801d88019 working on runnable components
cin
parents: 256
diff changeset
99 /// состоянию, т.е.true таким свойствам, как <see cref="State"/>,
440801d88019 working on runnable components
cin
parents: 256
diff changeset
100 /// <see cref="LastError"/>. Обработчики события <see cref="StateChanged"/>
440801d88019 working on runnable components
cin
parents: 256
diff changeset
101 /// вызываются уже с установленной блокировкой, поэтому дополнительная
440801d88019 working on runnable components
cin
parents: 256
diff changeset
102 /// синхронизация не требуется.
440801d88019 working on runnable components
cin
parents: 256
diff changeset
103 /// </summary>
440801d88019 working on runnable components
cin
parents: 256
diff changeset
104 public object SynchronizationObject { get { return m_lock; } }
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
105
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
106 protected RunnableComponent(bool initialized) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
107 State = initialized ? ExecutionState.Ready : ExecutionState.Created;
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
108 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
109
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
110 public Task Completion {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
111 get { return m_current.Task; }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
112 }
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
113
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
114 public ExecutionState State {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
115 get { return m_state; }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
116 private set {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
117 if (m_state != value) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
118 m_state = value;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
119 StateChanged.DispatchEvent(this, new StateChangeEventArgs {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
120 State = value,
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
121 LastError = LastError
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
122 });
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
123 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
124 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
125 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
126
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
127 public Exception LastError { get; private set; }
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
128
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
129 /// <summary>
440801d88019 working on runnable components
cin
parents: 256
diff changeset
130 /// Событие изменения состояния компоненты.see Обработчики данного события
440801d88019 working on runnable components
cin
parents: 256
diff changeset
131 /// вызываются внутри блокировки <see cref="SynchronizationObject"/> и должны
440801d88019 working on runnable components
cin
parents: 256
diff changeset
132 /// выполняться максимально быстро.
440801d88019 working on runnable components
cin
parents: 256
diff changeset
133 /// </summary>
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
134 public event EventHandler<StateChangeEventArgs> StateChanged;
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
135
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
136 /// <summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
137 /// Releases all resources used by the current component regardless of its
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
138 /// execution state.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
139 /// </summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
140 /// <remarks>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
141 /// Calling to this method may result unexpedted results if the component
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
142 /// isn't in the stopped state. Call this method after the component is
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
143 /// stopped if needed or if the component is in the failed state.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
144 /// </remarks>
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
145 public void Dispose() {
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
146 bool dispose = false;
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
147 lock (SynchronizationObject) {
440801d88019 working on runnable components
cin
parents: 256
diff changeset
148 if (m_state != ExecutionState.Disposed) {
440801d88019 working on runnable components
cin
parents: 256
diff changeset
149 dispose = true;
440801d88019 working on runnable components
cin
parents: 256
diff changeset
150 m_state = ExecutionState.Disposed;
440801d88019 working on runnable components
cin
parents: 256
diff changeset
151 m_cookie = new object();
440801d88019 working on runnable components
cin
parents: 256
diff changeset
152 }
440801d88019 working on runnable components
cin
parents: 256
diff changeset
153 }
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
154 if (dispose) {
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
155 Dispose(true);
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
156 GC.SuppressFinalize(this);
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
157 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
158 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
159
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
160 ~RunnableComponent() {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
161 Dispose(false);
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
162 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
163
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
164 /// <summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
165 /// Releases all resources used by the current component regardless of its
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
166 /// execution state.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
167 /// </summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
168 /// <param name="disposing">Indicates that the component is disposed
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
169 /// during a normal disposing or during GC.</param>
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
170 protected virtual void Dispose(bool disposing) {
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
171 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
172
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
173 public void Initialize() {
262
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
174 Initialize(CancellationToken.None);
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
175 }
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
176
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
177 public void Initialize(CancellationToken ct) {
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
178 var cookie = new object();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
179 if (MoveInitialize(cookie))
262
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
180 Safe.NoWait(ScheduleTask(InitializeInternalAsync, ct, cookie));
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
181 else
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
182 throw new InvalidOperationException();
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
183 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
184
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
185 /// <summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
186 /// This method is used for initialization during a component creation.
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
187 /// </summary>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
188 /// <param name="ct">A cancellation token for this operation</param>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
189 /// <remarks>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
190 /// This method should be used for short and mostly syncronous operations,
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
191 /// other operations which require time to run shoud be placed in
252
6f4630d0bcd9 removed absolete Diagnostics classes
cin
parents: 251
diff changeset
192 /// <see cref="StartInternalAsync(CancellationToken)"/> method.
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
193 /// </remarks>
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
194 protected virtual Task InitializeInternalAsync(CancellationToken ct) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
195 return Task.CompletedTask;
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
196 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
197
262
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
198 public void Start() {
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
199 Start(CancellationToken.None);
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
200 }
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
201
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
202 public void Start(CancellationToken ct) {
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
203 var cookie = new object();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
204 if (MoveStart(cookie))
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
205 Safe.NoWait(ScheduleStartAndRun(ct, cookie));
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
206 else
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
207 throw new InvalidOperationException();
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
208 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
209
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
210 async Task ScheduleStartAndRun(CancellationToken ct, object cookie) {
440801d88019 working on runnable components
cin
parents: 256
diff changeset
211 try {
440801d88019 working on runnable components
cin
parents: 256
diff changeset
212 await ScheduleTask(StartInternalAsync, ct, cookie);
440801d88019 working on runnable components
cin
parents: 256
diff changeset
213 RunInternal();
440801d88019 working on runnable components
cin
parents: 256
diff changeset
214 } catch (Exception err) {
440801d88019 working on runnable components
cin
parents: 256
diff changeset
215 Fail(err);
440801d88019 working on runnable components
cin
parents: 256
diff changeset
216 }
440801d88019 working on runnable components
cin
parents: 256
diff changeset
217 }
440801d88019 working on runnable components
cin
parents: 256
diff changeset
218
252
6f4630d0bcd9 removed absolete Diagnostics classes
cin
parents: 251
diff changeset
219 protected virtual Task StartInternalAsync(CancellationToken ct) {
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
220 return Task.CompletedTask;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
221 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
222
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
223 /// <summary>
440801d88019 working on runnable components
cin
parents: 256
diff changeset
224 /// This method is called after the component is enetered running state,
440801d88019 working on runnable components
cin
parents: 256
diff changeset
225 /// use this method to
440801d88019 working on runnable components
cin
parents: 256
diff changeset
226 /// </summary>
440801d88019 working on runnable components
cin
parents: 256
diff changeset
227 protected virtual void RunInternal() {
440801d88019 working on runnable components
cin
parents: 256
diff changeset
228
440801d88019 working on runnable components
cin
parents: 256
diff changeset
229 }
440801d88019 working on runnable components
cin
parents: 256
diff changeset
230
262
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
231 public void Stop() {
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
232 Stop(CancellationToken.None);
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
233 }
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
234
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
235 public void Stop(CancellationToken ct) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
236 var cookie = new object();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
237 if (MoveStop(cookie))
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
238 Safe.NoWait(ScheduleTask(StopAsync, ct, cookie));
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
239 else
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
240 throw new InvalidOperationException();
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
241 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
242
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
243 async Task StopAsync(CancellationToken ct) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
244 m_current.Cancel();
262
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
245
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
246 try {
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
247 await Completion;
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
248 } catch(OperationCanceledException) {
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
249 // OK
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
250 }
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
252 ct.ThrowIfCancellationRequested();
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
253
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
254 await StopInternalAsync(ct);
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
255 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
256
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
257 protected virtual Task StopInternalAsync(CancellationToken ct) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
258 return Task.CompletedTask;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
259 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
260
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
261 protected void Fail(Exception err) {
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
262 lock(m_lock) {
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
263 if (m_state != ExecutionState.Running)
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
264 return;
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
265 m_cookie = new object();
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
266 LastError = err;
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
267 State = ExecutionState.Failed;
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
268 }
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
269 }
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
270
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
271
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
272 #region state management
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
273
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
274 bool MoveInitialize(object cookie) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
275 lock (m_lock) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
276 if (State != ExecutionState.Created)
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
277 return false;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
278 State = ExecutionState.Initializing;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
279 m_cookie = cookie;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
280 return true;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
281 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
282 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
283
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
284 bool MoveStart(object cookie) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
285 lock (m_lock) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
286 if (State != ExecutionState.Ready)
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
287 return false;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
288 State = ExecutionState.Starting;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
289 m_cookie = cookie;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
290 return true;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
291 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
292 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
293
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
294 bool MoveStop(object cookie) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
295 lock (m_lock) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
296 if (State != ExecutionState.Starting && State != ExecutionState.Running)
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
297 return false;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
298 State = ExecutionState.Stopping;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
299 m_cookie = cookie;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
300 return true;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
301 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
302 }
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
303
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
304 void MoveSuccess(object cookie) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
305 lock (m_lock) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
306 if (m_cookie != cookie)
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
307 return;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
308 switch (State) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
309 case ExecutionState.Initializing:
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
310 State = ExecutionState.Ready;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
311 break;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
312 case ExecutionState.Starting:
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
313 State = ExecutionState.Running;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
314 break;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
315 case ExecutionState.Stopping:
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
316 State = ExecutionState.Stopped;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
317 break;
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
318 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
319 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
320 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
321
262
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
322 bool MoveFailed(Exception err, object cookie) {
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
323 lock (m_lock) {
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
324 if (m_cookie != cookie)
262
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
325 return false;
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
326 LastError = err;
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
327 State = ExecutionState.Failed;
262
f1696cdc3d7a Added IInitializable.Initialize() overload
cin
parents: 260
diff changeset
328 return true;
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
329 }
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
330 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
331
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
332 Task ScheduleTask(Func<CancellationToken, Task> next, CancellationToken ct, object cookie) {
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
333
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
334 var op = AsyncOperationDescriptor.Create(async (x) => {
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
335 try {
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
336 await next(x);
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
337 MoveSuccess(cookie);
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
338 } catch (Exception e) {
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
339 MoveFailed(e, cookie);
260
547a2fc0d93e minor fixes
cin
parents: 257
diff changeset
340 throw;
256
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
341 }
c52691faaf21 Removed obsolete App, ComponentContainer
cin
parents: 252
diff changeset
342 }, ct);
257
440801d88019 working on runnable components
cin
parents: 256
diff changeset
343
440801d88019 working on runnable components
cin
parents: 256
diff changeset
344 m_current = op;
440801d88019 working on runnable components
cin
parents: 256
diff changeset
345 return op.Task;
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
346 }
251
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
347
7c7e9ad6fe4a Prerelease version of RunnableComponent
cin
parents: 250
diff changeset
348 #endregion
250
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
349 }
9f63dade3a40 Working on runnable component
cin
parents:
diff changeset
350 }