annotate Implab/Components/RunnableComponent.cs @ 203:4d9830a9bbb8 v2

Added 'Fail' method to RunnableComponent which allows component to move from Running to Failed state. Added PollingComponent a timer based runnable component More tests Added FailPromise a thin class to wrap exceptions Fixed error handling in SuccessPromise classes.
author cin
date Tue, 18 Oct 2016 17:49:54 +0300
parents 2651cb9a4250
children 8200ab154c8a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
1 using System;
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
2
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
3 namespace Implab.Components {
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
4 public abstract class RunnableComponent : IDisposable, IRunnable, IInitializable {
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
5 enum Commands {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
6 Ok = 0,
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
7 Fail,
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
8 Init,
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
9 Start,
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
10 Stop,
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
11 Dispose,
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
12 Last = Dispose
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
13 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
14
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
15 class StateMachine {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
16 static readonly ExecutionState[,] _transitions;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
17
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
18 static StateMachine() {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
19 _transitions = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1];
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
20
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
21 Edge(ExecutionState.Created, ExecutionState.Initializing, Commands.Init);
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
22 Edge(ExecutionState.Created, ExecutionState.Disposed, Commands.Dispose);
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
23
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
24 Edge(ExecutionState.Initializing, ExecutionState.Ready, Commands.Ok);
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
25 Edge(ExecutionState.Initializing, ExecutionState.Failed, Commands.Fail);
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
26
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
27 Edge(ExecutionState.Ready, ExecutionState.Starting, Commands.Start);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
28 Edge(ExecutionState.Ready, ExecutionState.Disposed, Commands.Dispose);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
29
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
30 Edge(ExecutionState.Starting, ExecutionState.Running, Commands.Ok);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
31 Edge(ExecutionState.Starting, ExecutionState.Failed, Commands.Fail);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
32 Edge(ExecutionState.Starting, ExecutionState.Stopping, Commands.Stop);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
33 Edge(ExecutionState.Starting, ExecutionState.Disposed, Commands.Dispose);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
34
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
35 Edge(ExecutionState.Running, ExecutionState.Failed, Commands.Fail);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
36 Edge(ExecutionState.Running, ExecutionState.Stopping, Commands.Stop);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
37 Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
38
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
39 Edge(ExecutionState.Stopping, ExecutionState.Failed, Commands.Fail);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
40 Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Ok);
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
41
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
42 Edge(ExecutionState.Failed, ExecutionState.Disposed, Commands.Dispose);
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
43 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
44
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
45 static void Edge(ExecutionState s1, ExecutionState s2, Commands cmd) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
46 _transitions[(int)s1, (int)cmd] = s2;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
47 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
48
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
49 public ExecutionState State {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
50 get;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
51 private set;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
52 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
53
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
54 public StateMachine(ExecutionState initial) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
55 State = initial;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
56 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
57
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
58 public bool Move(Commands cmd) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
59 var next = _transitions[(int)State, (int)cmd];
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
60 if (next == ExecutionState.Undefined)
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
61 return false;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
62 State = next;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
63 return true;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
64 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
65 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
66
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
67 IPromise m_pending;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
68 Exception m_lastError;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
69
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
70 readonly StateMachine m_stateMachine;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
71
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
72 protected RunnableComponent(bool initialized) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
73 m_stateMachine = new StateMachine(initialized ? ExecutionState.Ready : ExecutionState.Created);
203
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
74 DisposeTimeout = 10000;
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
75 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
76
203
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
77 /// <summary>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
78 /// 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
79 /// </summary>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
80 protected int DisposeTimeout {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
81 get;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
82 set;
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
83 }
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
84
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
85 void ThrowInvalidCommand(Commands cmd) {
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
86 if (m_stateMachine.State == ExecutionState.Disposed)
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
87 throw new ObjectDisposedException(ToString());
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
88
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
89 throw new InvalidOperationException(String.Format("Commnd {0} is not allowed in the state {1}", cmd, m_stateMachine.State));
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
90 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
91
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
92 void Move(Commands cmd) {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
93 if (!m_stateMachine.Move(cmd))
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
94 ThrowInvalidCommand(cmd);
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
95 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
96
203
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
97 /// <summary>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
98 /// 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
99 /// </summary>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
100 /// <param name="error">The exception which is describing the error.</param>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
101 /// <returns>Returns true if the component is set to the failed state, false - otherwise.
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
102 /// This method works only for the running state, in any other state it will return false.</returns>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
103 protected bool Fail(Exception error) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
104 lock (m_stateMachine) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
105 if(m_stateMachine.State == ExecutionState.Running) {
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
106 m_stateMachine.Move(Commands.Fail);
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
107 m_lastError = error;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
108 return true;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
109 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
110 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
111 return false;
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
112 }
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
113
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
114 void Invoke(Commands cmd, Action action) {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
115 lock (m_stateMachine)
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
116 Move(cmd);
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
117
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
118 try {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
119 action();
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
120 lock(m_stateMachine)
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
121 Move(Commands.Ok);
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
122
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
123 } catch (Exception err) {
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
124 lock (m_stateMachine) {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
125 Move(Commands.Fail);
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
126 m_lastError = err;
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
127 }
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
128 throw;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
129 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
130 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
131
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
132 IPromise InvokeAsync(Commands cmd, Func<IPromise> action, Action<IPromise, IDeferred> chain) {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
133 IPromise promise = null;
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
134 IPromise prev;
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
135
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
136 var task = new ActionChainTask(action, null, null, true);
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
137
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
138 lock (m_stateMachine) {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
139 Move(cmd);
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
140
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
141 prev = m_pending;
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
142
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
143 Action<Exception> errorOrCancel = e => {
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
144 if (e == null)
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
145 e = new OperationCanceledException();
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
146
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
147 lock (m_stateMachine) {
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
148 if (m_pending == promise) {
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
149 Move(Commands.Fail);
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
150 m_pending = null;
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
151 m_lastError = e;
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
152 }
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
153 }
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
154 throw new PromiseTransientException(e);
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
155 };
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
156
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
157 promise = task.Then(
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
158 () => {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
159 lock(m_stateMachine) {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
160 if (m_pending == promise) {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
161 Move(Commands.Ok);
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
162 m_pending = null;
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
163 }
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
164 }
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
165 },
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
166 errorOrCancel,
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
167 errorOrCancel
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
168 );
157
cin
parents: 156
diff changeset
169
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
170 m_pending = promise;
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
171 }
157
cin
parents: 156
diff changeset
172
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
173 if (prev == null)
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
174 task.Resolve();
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
175 else
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
176 chain(prev, task);
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
177
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
178 return promise;
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
179 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
180
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
181
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
182 #region IInitializable implementation
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
183
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
184 public void Init() {
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
185 Invoke(Commands.Init, OnInitialize);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
186 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
187
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
188 protected virtual void OnInitialize() {
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
189 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
190
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
191 #endregion
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
192
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
193 #region IRunnable implementation
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
194
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
195 public IPromise Start() {
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
196 return InvokeAsync(Commands.Start, OnStart, null);
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
197 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
198
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
199 protected virtual IPromise OnStart() {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
200 return Promise.SUCCESS;
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
201 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
202
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
203 public IPromise Stop() {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
204 return InvokeAsync(Commands.Stop, OnStop, StopPending).Then(Dispose);
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
205 }
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
206
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
207 protected virtual IPromise OnStop() {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
208 return Promise.SUCCESS;
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
209 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
210
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
211 /// <summary>
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
212 /// Stops the current operation if one exists.
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
213 /// </summary>
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
214 /// <param name="current">Current.</param>
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
215 /// <param name="stop">Stop.</param>
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
216 protected virtual void StopPending(IPromise current, IDeferred stop) {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
217 if (current == null) {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
218 stop.Resolve();
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
219 } 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
220 // связваем текущую операцию с операцией остановки
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
221 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
222 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
223 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
224 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
225 );
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
226 // посылаем текущей операции сигнал остановки
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
227 current.Cancel();
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
228 }
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
229 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
230
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
231 public ExecutionState State {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
232 get {
203
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
233 return m_stateMachine.State;
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
234 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
235 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
236
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
237 public Exception LastError {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
238 get {
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
239 return m_lastError;
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
240 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
241 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
242
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
243 #endregion
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
244
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
245 #region IDisposable implementation
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
246
203
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
247 /// <summary>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
248 /// 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
249 /// </summary>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
250 /// <remarks>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
251 /// <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
252 /// 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
253 /// <para>
4d9830a9bbb8 Added 'Fail' method to RunnableComponent which allows component to move from
cin
parents: 202
diff changeset
254 /// 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
255 /// 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
256 /// 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
257 /// 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
258 /// </para></remarks>
185
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
259 public void Dispose() {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
260 IPromise pending;
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
261 lock (m_stateMachine) {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
262 if (m_stateMachine.State == ExecutionState.Disposed)
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
263 return;
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
264
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
265 Move(Commands.Dispose);
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
266
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
267 GC.SuppressFinalize(this);
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
268
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
269 pending = m_pending;
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
270 m_pending = null;
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
271 }
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
272 if (pending != null) {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
273 pending.Cancel();
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
274 pending.Timeout(DisposeTimeout).On(
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
275 () => Dispose(true, null),
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
276 err => Dispose(true, err),
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
277 reason => Dispose(true, new OperationCanceledException("The operation is cancelled", reason))
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
278 );
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
279 } else {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
280 Dispose(true, m_lastError);
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
281 }
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
282 }
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
283
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
284 ~RunnableComponent() {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
285 Dispose(false, null);
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
286 }
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
287
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
288 #endregion
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
289
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
290 protected virtual void Dispose(bool disposing, Exception lastError) {
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
291
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
292 }
822aab37b107 runnable component, work in progress
cin
parents: 184
diff changeset
293
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
294 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
295 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
296