##// END OF EJS Templates
working on runnable component
cin -
r184:d6a8cba73acc ref20160224
parent child
Show More
@@ -10,7 +10,7 namespace Implab.Format.Test {
10 public void TestScannerValidTokens() {
10 public void TestScannerValidTokens() {
11 using (var scanner = new JSONScanner(@"9123, -123, 0, 0.1, -0.2, -0.1e3, 1.3E-3, ""some \t\n\u0020 text"", literal []{}:")) {
11 using (var scanner = new JSONScanner(@"9123, -123, 0, 0.1, -0.2, -0.1e3, 1.3E-3, ""some \t\n\u0020 text"", literal []{}:")) {
12
12
13 Tuple<JsonTokenType,object>[] expexted = new [] {
13 Tuple<JsonTokenType,object>[] expexted = {
14 new Tuple<JsonTokenType,object>(JsonTokenType.Number, 9123d),
14 new Tuple<JsonTokenType,object>(JsonTokenType.Number, 9123d),
15 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, ", "),
15 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, ", "),
16 new Tuple<JsonTokenType,object>(JsonTokenType.Number, -123d),
16 new Tuple<JsonTokenType,object>(JsonTokenType.Number, -123d),
@@ -1,14 +1,24
1 namespace Implab.Components {
1 namespace Implab.Components {
2
2
3 public enum ExecutionState {
3 public enum ExecutionState {
4 Reserved = 0,
4 Undefined = 0,
5 Uninitialized,
5
6 Created,
7
8 Initializing,
9
6 Ready,
10 Ready,
11
7 Starting,
12 Starting,
13
8 Running,
14 Running,
15
9 Stopping,
16 Stopping,
10 Stopped,
17
18 Failed,
19
11 Disposed,
20 Disposed,
12 Failed
21
22 Last = Disposed
13 }
23 }
14 } No newline at end of file
24 }
@@ -11,7 +11,7 namespace Implab.Components {
11 /// Completes initialization.
11 /// Completes initialization.
12 /// </summary>
12 /// </summary>
13 /// <remarks>
13 /// <remarks>
14 /// Normally virtual shouldn't be called from the constructor, due to the incomplete object state, but
14 /// Normally virtual methods shouldn't be called from the constructor, due to the incomplete object state, but
15 /// they can be called from this method. This method is also usefull when we constructing a complex grpah
15 /// they can be called from this method. This method is also usefull when we constructing a complex grpah
16 /// of components where cyclic references may take place.
16 /// of components where cyclic references may take place.
17 /// </remarks>
17 /// </remarks>
@@ -3,22 +3,149 using Implab.Formats;
3
3
4 namespace Implab.Components {
4 namespace Implab.Components {
5 public class RunnableComponent : Disposable, IRunnable, IInitializable {
5 public class RunnableComponent : Disposable, IRunnable, IInitializable {
6 enum Commands {
7 Ok = 0,
8 Fail,
9 Init,
10 Start,
11 Stop,
12 Dispose,
13 Last = Dispose
14 }
6
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);
7
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);
8
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 }
9
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 }
10
63
11 IPromise m_pending;
64 IPromise m_pending;
12 Exception m_lastError;
65 Exception m_lastError;
13
66
67 readonly StateMachine m_stateMachine;
68
14 protected RunnableComponent(bool initialized) {
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 );
128
129
130
131 return Safe.InvokePromise(action).Then(
132 Success,
133 Fail
134 );
135 }
136
137 void AddPending(IPromise result) {
15
138
16 }
139 }
17
140
141
18 #region IInitializable implementation
142 #region IInitializable implementation
19
143
20 public void Init() {
144 public void Init() {
145 Invoke(Commands.Init, OnInitialize);
146 }
21
147
148 protected virtual void OnInitialize() {
22 }
149 }
23
150
24 #endregion
151 #endregion
@@ -26,7 +153,17 namespace Implab.Components {
26 #region IRunnable implementation
153 #region IRunnable implementation
27
154
28 public IPromise Start() {
155 public IPromise Start() {
29 throw new NotImplementedException();
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 );
30 }
167 }
31
168
32 protected virtual IPromise OnStart() {
169 protected virtual IPromise OnStart() {
General Comments 0
You need to be logged in to leave comments. Login now