##// END OF EJS Templates
Promises: SignalXXX methods merged into SignalHandler method....
Promises: SignalXXX methods merged into SignalHandler method. Components: RunnableComponent In progress

File last commit:

r156:97fbbf816844 v2
r156:97fbbf816844 v2
Show More
RunnableComponent.cs
141 lines | 4.9 KiB | text/x-csharp | CSharpLexer
using System;
using Implab.Parsing;
namespace Implab.Components {
public class RunnableComponent : Disposable, IRunnable, IInitializable {
class Automaton : DFAutomaton<ExecutionState> {
static readonly EDFADefinition<ExecutionState> _dfa;
static Automaton() {
var token = Token
.New(ExecutionState.Uninitialized).Optional() // we can skip uninitialized state
.Cat(
Token.New(ExecutionState.Ready) // uninitialized -> initial
.Cat(
Token.New(ExecutionState.Starting) // initial -> starting
.Cat(
Token.New(ExecutionState.Running) // running -> {stopping -> stopped | failed }
.Cat(
Token.New(ExecutionState.Stopping) // running -> stopping
.Cat(
Token.New(ExecutionState.Stopped) // stopping -> stopped
.Or(Token.New(ExecutionState.Failed)) // stopping -> failed
)
.Or(Token.New(ExecutionState.Failed)) // running -> failed
)
.Or(Token.New(ExecutionState.Failed)) // starting -> failed
).EClosure()
)
.Or(Token.New(ExecutionState.Failed)) // uninitialized->failed
.Cat(Token.New(ExecutionState.Disposed).Tag(0)) // ... -> disposed
);
var builder = new DFABuilder();
token.Accept(builder);
var _dfa = new EDFADefinition<ExecutionState>(EnumAlphabet<ExecutionState>.FullAlphabet);
builder.BuildDFA(_dfa); // don't optimize dfa to avoid remapping of the alphabet
}
public Automaton() : base(_dfa.States, INITIAL_STATE, ExecutionState.Reserved) {
}
public void MoveTo(ExecutionState state) {
if (!CanMove((int)state))
throw new InvalidOperationException(String.Format("Illegal state transition from {0} to {1}", Current, state));
Move((int)state);
m_context.info = state;
}
public ExecutionState Current {
get {
return (ExecutionState)m_context.info;
}
}
}
readonly Automaton m_automaton = new Automaton();
IPromise m_pending;
Exception m_lastError;
protected RunnableComponent(bool initialized) {
if (initialized)
m_automaton.MoveTo(ExecutionState.Ready);
else
m_automaton.MoveTo(ExecutionState.Uninitialized);
}
#region IInitializable implementation
public void Init() {
}
#endregion
#region IRunnable implementation
public IPromise Start() {
return Safe.InvokePromise(() => {
Promise promise;
lock (m_automaton) {
if (m_automaton.Current == ExecutionState.Starting)
return m_pending;
m_automaton.MoveTo(ExecutionState.Starting);
m_pending = promise = new Promise();
}
var start = Safe.InvokePromise(OnStart);
promise.On(null, null, start.Cancel);
start.On(promise.Resolve, promise.Reject, promise.CancelOperation);
return promise.Then(() => {
lock(m_automaton) {
m_automaton.MoveTo(ExecutionState.Running);
m_pending = null;
}
Run();
}, err => {
if (BeginTransition(RUNNING_REQUIRE)) {
m_lastError = err;
CompleteTransition(FAILED_STATE);
throw new PromiseTransientException(err);
}
throw new OperationCanceledException();
}, reason => {
throw new OperationCanceledException("The operation was cancelled", reason);
});
});
}
protected virtual IPromise OnStart() {
return Promise.SUCCESS;
}
protected virtual void Run() {
}
public IPromise Stop() {
throw new NotImplementedException();
}
public ExecutionState State {
get {
throw new NotImplementedException();
}
}
public Exception LastError {
get {
throw new NotImplementedException();
}
}
#endregion
}
}