Mercurial > pub > ImplabNet
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 |
rev | line source |
---|---|
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
1 using System; |
180 | 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 | 6 enum Commands { |
7 Ok = 0, | |
8 Fail, | |
9 Init, | |
10 Start, | |
11 Stop, | |
12 Dispose, | |
13 Last = Dispose | |
14 } | |
15 | |
16 class StateMachine { | |
17 static readonly ExecutionState[,] _transitions; | |
18 | |
19 static StateMachine() { | |
20 _transitions = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1]; | |
21 | |
22 Edge(ExecutionState.Created, ExecutionState.Ready, Commands.Ok); | |
23 Edge(ExecutionState.Created, ExecutionState.Failed, Commands.Fail); | |
24 | |
25 Edge(ExecutionState.Ready, ExecutionState.Starting, Commands.Start); | |
26 Edge(ExecutionState.Ready, ExecutionState.Disposed, Commands.Dispose); | |
27 | |
28 Edge(ExecutionState.Starting, ExecutionState.Running, Commands.Ok); | |
29 Edge(ExecutionState.Starting, ExecutionState.Failed, Commands.Fail); | |
30 Edge(ExecutionState.Starting, ExecutionState.Stopping, Commands.Stop); | |
31 Edge(ExecutionState.Starting, ExecutionState.Disposed, Commands.Dispose); | |
32 | |
33 Edge(ExecutionState.Running, ExecutionState.Failed, Commands.Fail); | |
34 Edge(ExecutionState.Running, ExecutionState.Stopping, Commands.Stop); | |
35 Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose); | |
36 | |
37 Edge(ExecutionState.Stopping, ExecutionState.Failed, Commands.Fail); | |
38 Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Ok); | |
39 Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Dispose); | |
40 } | |
41 | |
42 static void Edge(ExecutionState s1, ExecutionState s2, Commands cmd) { | |
43 _transitions[(int)s1, (int)cmd] = s2; | |
44 } | |
45 | |
46 public ExecutionState State { | |
47 get; | |
48 private set; | |
49 } | |
50 | |
51 public StateMachine(ExecutionState initial) { | |
52 State = initial; | |
53 } | |
54 | |
55 public bool Move(Commands cmd) { | |
56 var next = _transitions[(int)State, (int)cmd]; | |
57 if (next == ExecutionState.Undefined) | |
58 return false; | |
59 State = next; | |
60 return true; | |
61 } | |
62 } | |
63 | |
64 IPromise m_pending; | |
65 Exception m_lastError; | |
66 | |
67 readonly StateMachine m_stateMachine; | |
68 | |
69 protected RunnableComponent(bool initialized) { | |
70 m_stateMachine = new StateMachine(initialized ? ExecutionState.Ready : ExecutionState.Created); | |
71 } | |
72 | |
73 void ThrowInvalidCommand(Commands cmd) { | |
74 throw new InvalidOperationException(String.Format("Commnd {0} is not allowed in the state {1}", cmd, m_stateMachine.State)); | |
75 } | |
76 | |
77 protected void Move(Commands cmd) { | |
78 lock (m_stateMachine) | |
79 if (!m_stateMachine.Move(cmd)) | |
80 ThrowInvalidCommand(cmd); | |
81 } | |
82 | |
83 protected void Fail(Exception err) { | |
84 lock (m_stateMachine) { | |
85 if (!m_stateMachine.Move(Commands.Fail)) | |
86 ThrowInvalidCommand(Commands.Fail); | |
87 | |
88 m_lastError = err; | |
89 } | |
90 } | |
91 | |
92 protected void Success() { | |
93 Move(Commands.Ok); | |
94 } | |
95 | |
96 protected void Invoke(Commands cmd, Action action) { | |
97 Move(cmd); | |
98 try { | |
99 action(); | |
100 Move(Commands.Ok); | |
101 } catch (Exception err) { | |
102 Fail(err); | |
103 throw; | |
104 } | |
105 } | |
106 | |
107 protected IPromise InvokeAsync(Commands cmd, Func<IPromise> action) { | |
108 Move(cmd); | |
109 var medium = new Promise(); | |
110 | |
111 IPromise promise = null; | |
112 | |
113 promise = medium.Then( | |
114 () => { | |
115 lock(m_stateMachine) { | |
116 if (m_pending == promise) { | |
117 m_pending = null; | |
118 Move(Commands.Ok); | |
119 } | |
120 } | |
121 }, e => { | |
122 if (m_pending == promise) { | |
123 m_pending = null; | |
124 Fail( | |
125 } | |
126 } | |
127 ); | |
157 | 128 |
129 | |
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
130 |
184 | 131 return Safe.InvokePromise(action).Then( |
132 Success, | |
133 Fail | |
134 ); | |
135 } | |
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
diff
changeset
|
136 |
184 | 137 void AddPending(IPromise result) { |
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 | 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 | 145 Invoke(Commands.Init, OnInitialize); |
146 } | |
147 | |
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 | 156 Move(Commands.Start); |
157 | |
158 return Safe.InvokePromise(OnStart).Then( | |
159 () => { | |
160 Move(Commands.Ok); | |
161 Run(); | |
162 }, | |
163 () => { | |
164 Move(Commands.Fail); | |
165 } | |
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 |