template<std::size_t states, std::size_t inputs, class State, class Input>
Corrade::Interconnect::StateMachine class

State machine.

Exploits the Interconnect library for a simple state machine. Information about state transitions is broadcasted through signals. The machine is meant to be defined and connected at compile time.

Basic usage

Define two enums for states and inputs. The enums should have consecutive values starting from 0.

enum class State: std::uint8_t {
    Ready,
    Printing,
    Finished
};

enum class Input: std::uint8_t {
    Operate,
    TakeDocument
};

Then typedef the state machine consisting of these two enums, count of all states and count of all inputs:

typedef Interconnect::StateMachine<3, 2, State, Input> Printer;

Now add your state transitions, for each transition first original state, then input, and then state after transition. Everything else is implicitly a no-op.

Printer p;
p.addTransitions({
    {State::Ready,      Input::Operate,         State::Printing},
    {State::Printing,   Input::Operate,         State::Finished},
    {State::Finished,   Input::TakeDocument,    State::Ready}
});

Lastly connect transition signals to desired slots, so you can react to state changes:

Interconnect::connect(p, &Printer::entered<State::Ready>,
    [](State) { Utility::Debug() << "Printer is ready."; });
Interconnect::connect(p, &Printer::entered<State::Finished>,
    [](State) { Utility::Debug() << "Finished. Please take the document."; });
Interconnect::connect(p, &Printer::entered<State::Printing>,
    [](State) { Utility::Debug() << "Starting the print..."; });
Interconnect::connect(p, &Printer::exited<State::Printing>,
    [](State) { Utility::Debug() << "Finishing the print..."; });

Now, stepping the machine:

p.step(Input::Operate);
p.step(Input::Operate);
p.step(Input::TakeDocument);

will print the following output:

Starting the print...
Finishing the print...
Finished. Please take the document.
Printer is ready.

Base classes

class Emitter
Emitter object.

Public types

enum (anonymous): std::size_t { StateCount = states, InputCount = inputs }

Constructors, destructors, conversion operators

StateMachine() explicit
Constructor.

Public functions

auto current() const -> State
Current state.
void addTransitions(std::initializer_list<StateTransition<State, Input>> transitions)
Add transitions to the list.
auto step(Input input) -> StateMachine<states, inputs, State, Input>&
Step the machine.
template<State previous, State next>
auto stepped() -> Signal
The machine is switching states.
template<State state>
auto entered(State previous) -> Signal
The machine entered given state.
template<State state>
auto exited(State next) -> Signal
The machine exited given state.

Enum documentation

template<std::size_t states, std::size_t inputs, class State, class Input>
enum Corrade::Interconnect::StateMachine<states, inputs, State, Input>::(anonymous): std::size_t

Enumerators
StateCount

Count of states in the machine

InputCount

Count of inputs for the machine

Function documentation

template<std::size_t states, std::size_t inputs, class State, class Input>
Corrade::Interconnect::StateMachine<states, inputs, State, Input>::StateMachine() explicit

Constructor.

All states are initially no-op (i.e., given state will not be changed to anything else for any input).

template<std::size_t states, std::size_t inputs, class State, class Input>
State Corrade::Interconnect::StateMachine<states, inputs, State, Input>::current() const

Current state.

Initial state is the one corresponding to 0 (i.e., usually the first).

template<std::size_t states, std::size_t inputs, class State, class Input>
void Corrade::Interconnect::StateMachine<states, inputs, State, Input>::addTransitions(std::initializer_list<StateTransition<State, Input>> transitions)

Add transitions to the list.

Expects that all states have a value less than StateCount and inputs a value less than InputCount.

template<std::size_t states, std::size_t inputs, class State, class Input>
StateMachine<states, inputs, State, Input>& Corrade::Interconnect::StateMachine<states, inputs, State, Input>::step(Input input)

Step the machine.

Returns Reference to self (for method chaining)

Switches current state based on the input. If the new state is different from previous one, emits exited() with the old state and then entered() with the new one.

template<std::size_t states, std::size_t inputs, class State, class Input> template<State previous, State next>
Signal Corrade::Interconnect::StateMachine<states, inputs, State, Input>::stepped()

The machine is switching states.

Emitted when machine goes from previous state to next state and they are different ones. Emitted after corresponding exited() signal and before corresponding entered() one.

template<std::size_t states, std::size_t inputs, class State, class Input> template<State state>
Signal Corrade::Interconnect::StateMachine<states, inputs, State, Input>::entered(State previous)

The machine entered given state.

Parameters
previous State which was exited

Emitted when machine goes to given state from different one, right after corresponding stepped() signal.

template<std::size_t states, std::size_t inputs, class State, class Input> template<State state>
Signal Corrade::Interconnect::StateMachine<states, inputs, State, Input>::exited(State next)

The machine exited given state.

Parameters
next State which will be entered

Emitted when machine leaves given state for different one. The corresponding stepped() signal is emitted after this one.