Finite State Machine
The Finite State Machine (FSM) describes how the Component behaves.
Note that only Components use FSMs, Resources use Interfaces instead (see Interfaces).
A FSM is created by extending the class mauve::runtime::FiniteStateMachine
, templated by the Shell
and Core
used by this FSM.
#include "mauve/runtime.hpp"
struct MyFSM: public mauve::runtime::FIniteStateMachine<MyShell, MyCore> {
/* ... */
};
FSMs are built using two state types: Execution States and Synchronization States.
You must define the states, the initial state, and the transitions of the FSM
in the configure_hook
(see Constructing a simple FSM).
You can define either an Execution State or a Synchronization State as initial state.
There is no restriction about state transitions.
Execution State
Each Execution State must be bound to a single function/method on declaration.
mauve::runtime::ExecState<MyCore> & execState = mk_execution("execState", &MyCore::execMethod);
Here, we define an Execution State execState, named execState, and calling MyCore::execMethod
.
Synchronization State
Each Synchronization State must have its synchronization time set on declaration.
mauve::runtime::SynchroState<MyCore> & syncState = mk_synchronization("syncState", mauve::runtime::ms_to_ns(100));
Here, we define a Synchronization State syncState, named syncState, and with a synchronization time of 100ms.
Note that the synchronization time must be given in nanoseconds, but we provide some helper functions to convert from
other units, like ms_to_ns
and sec_to_ns
.
Constructing a simple FSM
As said above, you must define an initial state and the transitions in order to setup the FSM.
bool MyFSM::configure_hook() {
set_inital(execState);
set_next(execState, syncState);
set_next(syncState, execState);
return FiniteStateMachine::configure_hook();
}
Here, we define execState as the initial state, syncState following execState, and then execState following syncState.
The resulting FSM can be drawn as:
Constructing a complex FSM
FSMs can also handle conditional transitions using mk_transition. Each of these transitions must be bound to a function/method returning a bool.
bool MyFSM::configure_hook() {
set_inital(execState);
mk_transition(execState, &MyCore::sleeping, execState);
set_next(execState, syncState);
set_next(syncState, execState);
return FiniteStateMachine::configure_hook();
}
Here, we define a conditional reflexive transition on execState. While MyCore::sleeping()
returns true, the FSM will loop on execState.
The resulting FSM can be drawn as:
When several conditional transitions from the same state are defined, they are evaluated by order of definition. If all the conditional transition fails, the default transition (defined using set_next
) fires. You should define only one outgoing transition per state using set_next
.