comparison Implab/Components/RunnableComponent.cs @ 156:97fbbf816844 v2

Promises: SignalXXX methods merged into SignalHandler method. Components: RunnableComponent In progress
author cin
date Mon, 15 Feb 2016 04:22:15 +0300
parents
children 948c015a9011
comparison
equal deleted inserted replaced
155:037df317f126 156:97fbbf816844
1 using System;
2 using Implab.Parsing;
3
4 namespace Implab.Components {
5 public class RunnableComponent : Disposable, IRunnable, IInitializable {
6 class Automaton : DFAutomaton<ExecutionState> {
7 static readonly EDFADefinition<ExecutionState> _dfa;
8
9 static Automaton() {
10
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 );
33
34 var builder = new DFABuilder();
35 token.Accept(builder);
36
37 var _dfa = new EDFADefinition<ExecutionState>(EnumAlphabet<ExecutionState>.FullAlphabet);
38 builder.BuildDFA(_dfa); // don't optimize dfa to avoid remapping of the alphabet
39
40 }
41
42 public Automaton() : base(_dfa.States, INITIAL_STATE, ExecutionState.Reserved) {
43 }
44
45 public void MoveTo(ExecutionState state) {
46
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 }
52
53 public ExecutionState Current {
54 get {
55 return (ExecutionState)m_context.info;
56 }
57 }
58 }
59
60 readonly Automaton m_automaton = new Automaton();
61 IPromise m_pending;
62 Exception m_lastError;
63
64 protected RunnableComponent(bool initialized) {
65 if (initialized)
66 m_automaton.MoveTo(ExecutionState.Ready);
67 else
68 m_automaton.MoveTo(ExecutionState.Uninitialized);
69 }
70
71 #region IInitializable implementation
72
73 public void Init() {
74
75 }
76
77 #endregion
78
79 #region IRunnable implementation
80
81 public IPromise Start() {
82 return Safe.InvokePromise(() => {
83 Promise promise;
84 lock (m_automaton) {
85 if (m_automaton.Current == ExecutionState.Starting)
86 return m_pending;
87 m_automaton.MoveTo(ExecutionState.Starting);
88 m_pending = promise = new Promise();
89 }
90
91 var start = Safe.InvokePromise(OnStart);
92 promise.On(null, null, start.Cancel);
93 start.On(promise.Resolve, promise.Reject, promise.CancelOperation);
94
95 return promise.Then(() => {
96 lock(m_automaton) {
97 m_automaton.MoveTo(ExecutionState.Running);
98 m_pending = null;
99 }
100
101 Run();
102 }, err => {
103 if (BeginTransition(RUNNING_REQUIRE)) {
104 m_lastError = err;
105 CompleteTransition(FAILED_STATE);
106 throw new PromiseTransientException(err);
107 }
108 throw new OperationCanceledException();
109 }, reason => {
110 throw new OperationCanceledException("The operation was cancelled", reason);
111 });
112 });
113 }
114
115 protected virtual IPromise OnStart() {
116 return Promise.SUCCESS;
117 }
118
119 protected virtual void Run() {
120 }
121
122 public IPromise Stop() {
123 throw new NotImplementedException();
124 }
125
126 public ExecutionState State {
127 get {
128 throw new NotImplementedException();
129 }
130 }
131
132 public Exception LastError {
133 get {
134 throw new NotImplementedException();
135 }
136 }
137
138 #endregion
139 }
140 }
141