annotate Implab/Components/RunnableComponent.cs @ 184:d6a8cba73acc ref20160224

working on runnable component
author cin
date Sat, 16 Apr 2016 03:23:26 +0300
parents c32688129f14
children 822aab37b107
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;
180
c32688129f14 refactoring complete, JSONParser rewritten
cin
parents: 158
diff changeset
2 using Implab.Formats;
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
3
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
4 namespace Implab.Components {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
5 public class RunnableComponent : Disposable, IRunnable, IInitializable {
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
6 enum Commands {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
7 Ok = 0,
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
8 Fail,
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
9 Init,
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
10 Start,
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
11 Stop,
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
12 Dispose,
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
13 Last = Dispose
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
14 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
15
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
16 class StateMachine {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
17 static readonly ExecutionState[,] _transitions;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
18
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
19 static StateMachine() {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
20 _transitions = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1];
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
21
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
22 Edge(ExecutionState.Created, ExecutionState.Ready, Commands.Ok);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
23 Edge(ExecutionState.Created, ExecutionState.Failed, Commands.Fail);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
24
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
25 Edge(ExecutionState.Ready, ExecutionState.Starting, Commands.Start);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
26 Edge(ExecutionState.Ready, ExecutionState.Disposed, Commands.Dispose);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
27
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
28 Edge(ExecutionState.Starting, ExecutionState.Running, Commands.Ok);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
29 Edge(ExecutionState.Starting, ExecutionState.Failed, Commands.Fail);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
30 Edge(ExecutionState.Starting, ExecutionState.Stopping, Commands.Stop);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
31 Edge(ExecutionState.Starting, ExecutionState.Disposed, Commands.Dispose);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
32
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
33 Edge(ExecutionState.Running, ExecutionState.Failed, Commands.Fail);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
34 Edge(ExecutionState.Running, ExecutionState.Stopping, Commands.Stop);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
35 Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
36
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
37 Edge(ExecutionState.Stopping, ExecutionState.Failed, Commands.Fail);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
38 Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Ok);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
39 Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Dispose);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
40 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
41
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
42 static void Edge(ExecutionState s1, ExecutionState s2, Commands cmd) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
43 _transitions[(int)s1, (int)cmd] = s2;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
44 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
45
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
46 public ExecutionState State {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
47 get;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
48 private set;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
49 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
50
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
51 public StateMachine(ExecutionState initial) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
52 State = initial;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
53 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
54
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
55 public bool Move(Commands cmd) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
56 var next = _transitions[(int)State, (int)cmd];
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
57 if (next == ExecutionState.Undefined)
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
58 return false;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
59 State = next;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
60 return true;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
61 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
62 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
63
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
64 IPromise m_pending;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
65 Exception m_lastError;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
66
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
67 readonly StateMachine m_stateMachine;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
68
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
69 protected RunnableComponent(bool initialized) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
70 m_stateMachine = new StateMachine(initialized ? ExecutionState.Ready : ExecutionState.Created);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
71 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
72
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
73 void ThrowInvalidCommand(Commands cmd) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
74 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
75 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
76
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
77 protected void Move(Commands cmd) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
78 lock (m_stateMachine)
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
79 if (!m_stateMachine.Move(cmd))
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
80 ThrowInvalidCommand(cmd);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
81 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
82
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
83 protected void Fail(Exception err) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
84 lock (m_stateMachine) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
85 if (!m_stateMachine.Move(Commands.Fail))
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
86 ThrowInvalidCommand(Commands.Fail);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
87
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
88 m_lastError = err;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
89 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
90 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
91
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
92 protected void Success() {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
93 Move(Commands.Ok);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
94 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
95
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
96 protected void Invoke(Commands cmd, Action action) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
97 Move(cmd);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
98 try {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
99 action();
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
100 Move(Commands.Ok);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
101 } catch (Exception err) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
102 Fail(err);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
103 throw;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
104 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
105 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
106
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
107 protected IPromise InvokeAsync(Commands cmd, Func<IPromise> action) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
108 Move(cmd);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
109 var medium = new Promise();
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
110
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
111 IPromise promise = null;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
112
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
113 promise = medium.Then(
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
114 () => {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
115 lock(m_stateMachine) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
116 if (m_pending == promise) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
117 m_pending = null;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
118 Move(Commands.Ok);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
119 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
120 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
121 }, e => {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
122 if (m_pending == promise) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
123 m_pending = null;
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
124 Fail(
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
125 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
126 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
127 );
157
cin
parents: 156
diff changeset
128
cin
parents: 156
diff changeset
129
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
130
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
131 return Safe.InvokePromise(action).Then(
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
132 Success,
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
133 Fail
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
134 );
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
135 }
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
136
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
137 void AddPending(IPromise result) {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
138
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
139 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
140
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
141
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
142 #region IInitializable implementation
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
143
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
144 public void Init() {
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
145 Invoke(Commands.Init, OnInitialize);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
146 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
147
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
148 protected virtual void OnInitialize() {
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
149 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
150
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
151 #endregion
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
152
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
153 #region IRunnable implementation
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
154
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
155 public IPromise Start() {
184
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
156 Move(Commands.Start);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
157
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
158 return Safe.InvokePromise(OnStart).Then(
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
159 () => {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
160 Move(Commands.Ok);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
161 Run();
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
162 },
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
163 () => {
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
164 Move(Commands.Fail);
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
165 }
d6a8cba73acc working on runnable component
cin
parents: 180
diff changeset
166 );
156
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
167 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
168
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
169 protected virtual IPromise OnStart() {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
170 return Promise.SUCCESS;
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
171 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
172
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
173 protected virtual void Run() {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
174 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
175
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
176 public IPromise Stop() {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
177 throw new NotImplementedException();
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
178 }
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 public ExecutionState State {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
181 get {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
182 throw new NotImplementedException();
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 }
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
185
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
186 public Exception LastError {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
187 get {
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
188 throw new NotImplementedException();
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
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
192 #endregion
97fbbf816844 Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff changeset
193 }
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