##// END OF EJS Templates
sync
cin -
r157:948c015a9011 v2
parent child
Show More
@@ -1,141 +1,153
1 1 using System;
2 2 using Implab.Parsing;
3 3
4 4 namespace Implab.Components {
5 5 public class RunnableComponent : Disposable, IRunnable, IInitializable {
6 class Automaton : DFAutomaton<ExecutionState> {
7 static readonly EDFADefinition<ExecutionState> _dfa;
6
7
8 class Automaton {
9 enum Operations {
10 Initialize,
11 Start,
12 Stop,
13 Fail,
14 Success,
15 Dispose
16 }
17
18 static readonly EDFADefinition<ExecutionState> _def = new EDFADefinition<ExecutionState>(EnumAlphabet<ExecutionState>.FullAlphabet);
19 static readonly DFAStateDescriptior[] _states;
8 20
9 21 static Automaton() {
22 var created = _def.AddState(); // initial state
23 var initializing = _def.AddState();
24 var ready = _def.AddState();
25 var starting = _def.AddState();
26 var running = _def.AddState();
27 var stopping = _def.AddState();
28 var error = _def.AddState();
29 var disposing = _def.AddState();
30 var disposed = _def.AddState(new int[] { 0 });
10 31
11 var token = Token
12 .New(ExecutionState.Uninitialized).Optional() // we can skip uninitialized state
13 .Cat(
14 Token.New(ExecutionState.Ready) // uninitialized -> initial
15 .Cat(
16 Token.New(ExecutionState.Starting) // initial -> starting
17 .Cat(
18 Token.New(ExecutionState.Running) // running -> {stopping -> stopped | failed }
19 .Cat(
20 Token.New(ExecutionState.Stopping) // running -> stopping
21 .Cat(
22 Token.New(ExecutionState.Stopped) // stopping -> stopped
23 .Or(Token.New(ExecutionState.Failed)) // stopping -> failed
24 )
25 .Or(Token.New(ExecutionState.Failed)) // running -> failed
26 )
27 .Or(Token.New(ExecutionState.Failed)) // starting -> failed
28 ).EClosure()
29 )
30 .Or(Token.New(ExecutionState.Failed)) // uninitialized->failed
31 .Cat(Token.New(ExecutionState.Disposed).Tag(0)) // ... -> disposed
32 );
32 _def.DefineTransition(created,initializing,(int)Operations.Initialize);
33
34 _def.DefineTransition(initializing,ready,(int)Operations.Success);
35 _def.DefineTransition(initializing,error,(int)Operations.Fail);
36
37 _def.DefineTransition(ready, starting, (int)Operations.Start);
38 _def.DefineTransition(ready, disposing, (int)Operations.Dispose);
39
33 40
34 var builder = new DFABuilder();
35 token.Accept(builder);
41 _def.DefineTransition(starting, running, (int)Operations.Success);
42 _def.DefineTransition(starting, error, (int)Operations.Fail);
43
44 _def.DefineTransition(running, stopping, (int)Operations.Stop);
45 _def.DefineTransition(running, error, (int)Operations.Fail);
36 46
37 var _dfa = new EDFADefinition<ExecutionState>(EnumAlphabet<ExecutionState>.FullAlphabet);
38 builder.BuildDFA(_dfa); // don't optimize dfa to avoid remapping of the alphabet
47 _def.DefineTransition(stopping, ready, (int)Operations.Success);
48 _def.DefineTransition(stopping, error, (int)Operations.Fail);
39 49
50 _def.DefineTransition(disposing, disposed, (int)Operations.Success);
51
52 _states = _def.States;
40 53 }
41 54
42 public Automaton() : base(_dfa.States, INITIAL_STATE, ExecutionState.Reserved) {
55 int m_state;
56
57 public Automaton() {
58 m_state = DFADefinitionBase.INITIAL_STATE;
43 59 }
44 60
45 public void MoveTo(ExecutionState state) {
61 void Move(Operations op) {
46 62
47 if (!CanMove((int)state))
48 throw new InvalidOperationException(String.Format("Illegal state transition from {0} to {1}", Current, state));
49 Move((int)state);
50 m_context.info = state;
51 63 }
52 64
53 65 public ExecutionState Current {
54 66 get {
55 67 return (ExecutionState)m_context.info;
56 68 }
57 69 }
58 70 }
59 71
60 72 readonly Automaton m_automaton = new Automaton();
61 73 IPromise m_pending;
62 74 Exception m_lastError;
63 75
64 76 protected RunnableComponent(bool initialized) {
65 77 if (initialized)
66 78 m_automaton.MoveTo(ExecutionState.Ready);
67 79 else
68 80 m_automaton.MoveTo(ExecutionState.Uninitialized);
69 81 }
70 82
71 83 #region IInitializable implementation
72 84
73 85 public void Init() {
74 86
75 87 }
76 88
77 89 #endregion
78 90
79 91 #region IRunnable implementation
80 92
81 93 public IPromise Start() {
82 94 return Safe.InvokePromise(() => {
83 95 Promise promise;
84 96 lock (m_automaton) {
85 97 if (m_automaton.Current == ExecutionState.Starting)
86 98 return m_pending;
87 99 m_automaton.MoveTo(ExecutionState.Starting);
88 100 m_pending = promise = new Promise();
89 101 }
90 102
91 103 var start = Safe.InvokePromise(OnStart);
92 104 promise.On(null, null, start.Cancel);
93 105 start.On(promise.Resolve, promise.Reject, promise.CancelOperation);
94 106
95 107 return promise.Then(() => {
96 108 lock(m_automaton) {
97 109 m_automaton.MoveTo(ExecutionState.Running);
98 110 m_pending = null;
99 111 }
100 112
101 113 Run();
102 114 }, err => {
103 115 if (BeginTransition(RUNNING_REQUIRE)) {
104 116 m_lastError = err;
105 117 CompleteTransition(FAILED_STATE);
106 118 throw new PromiseTransientException(err);
107 119 }
108 120 throw new OperationCanceledException();
109 121 }, reason => {
110 122 throw new OperationCanceledException("The operation was cancelled", reason);
111 123 });
112 124 });
113 125 }
114 126
115 127 protected virtual IPromise OnStart() {
116 128 return Promise.SUCCESS;
117 129 }
118 130
119 131 protected virtual void Run() {
120 132 }
121 133
122 134 public IPromise Stop() {
123 135 throw new NotImplementedException();
124 136 }
125 137
126 138 public ExecutionState State {
127 139 get {
128 140 throw new NotImplementedException();
129 141 }
130 142 }
131 143
132 144 public Exception LastError {
133 145 get {
134 146 throw new NotImplementedException();
135 147 }
136 148 }
137 149
138 150 #endregion
139 151 }
140 152 }
141 153
@@ -1,32 +1,36
1 1 using Implab;
2 2 using System;
3 3
4 4 namespace Implab.Parsing {
5 5 public class EDFADefinition<T> : DFADefinitionBase where T : struct, IConvertible {
6 6 readonly EnumAlphabet<T> m_alphabet;
7 7
8 8 public EnumAlphabet<T> Alphabet {
9 9 get { return m_alphabet; }
10 10 }
11 11
12 12 public EDFADefinition(EnumAlphabet<T> alphabet) {
13 13 Safe.ArgumentNotNull(alphabet, "alphabet");
14 14 m_alphabet = alphabet;
15 15 }
16 16
17 17 public override int AlphabetSize {
18 18 get { return m_alphabet.Count; }
19 19 }
20 20
21 public void DefineTransition(int s1, int s2, T input) {
22 DefineTransition(s1, s2, m_alphabet.Translate(input));
23 }
24
21 25 public EDFADefinition<T> Optimize() {
22 26 var optimized = new EDFADefinition<T>(new EnumAlphabet<T>());
23 27 Optimize(optimized, m_alphabet, optimized.Alphabet);
24 28
25 29 return optimized;
26 30 }
27 31
28 32 public void PrintDFA() {
29 33 PrintDFA(m_alphabet);
30 34 }
31 35 }
32 36 }
General Comments 0
You need to be logged in to leave comments. Login now