Reference
States and transitions
This page lists all states and transitions of the device state machine as tables. It also gives the keys of the interactive controller, the name functions and the errors of invalid transitions. For an introduction, see Device states.
States
Section titled “States”The enum fair::mq::State is in
fairmq/States.h. Its underlying type is int. The name is the
string that GetStateName() returns and that the log shows.
| State | Value | Name | Kind | Hooks |
|---|---|---|---|---|
Undefined |
0 | UNDEFINED |
Not used | — |
Ok |
1 | OK |
Internal, see below | — |
Error |
2 | ERROR |
Error state, final | — |
Idle |
3 | IDLE |
Idling state, initial | — |
InitializingDevice |
4 | INITIALIZING DEVICE |
Working state | Init() |
Initialized |
5 | INITIALIZED |
Idling state | — |
Binding |
6 | BINDING |
Working state | Bind() |
Bound |
7 | BOUND |
Idling state | — |
Connecting |
8 | CONNECTING |
Working state | Connect() |
DeviceReady |
9 | DEVICE READY |
Idling state | — |
InitializingTask |
10 | INITIALIZING TASK |
Working state | InitTask() |
Ready |
11 | READY |
Idling state | — |
Running |
12 | RUNNING |
Working state | PreRun(), ConditionalRun(), Run(), PostRun(), data callbacks |
ResettingTask |
13 | RESETTING TASK |
Working state | ResetTask() |
ResettingDevice |
14 | RESETTING DEVICE |
Working state | Reset() |
Exiting |
15 | EXITING |
Final state | — |
The state machine has two regions. The first region holds the states from IDLE to EXITING. The
second region holds OK and ERROR, and starts in OK. A device does not report the state OK.
StateQueue::WaitForNext() with a timeout returns Ok
when no state arrives.
The log line No transition from state … on transition … uses other names. They have an underscore
instead of a space, for example DEVICE_READY and INIT_TASK
(StateMachine.cxx).
Transitions
Section titled “Transitions”The enum fair::mq::Transition is in
fairmq/States.h. The key column gives the key of the
interactive controller.
| Transition | Value | Name | From | To | Requested by | Key |
|---|---|---|---|---|---|---|
Auto |
0 | AUTO |
BINDING, CONNECTING, INITIALIZING TASK, RESETTING TASK, RESETTING DEVICE |
The next state, see the matrix | The device | — |
InitDevice |
1 | INIT DEVICE |
IDLE |
INITIALIZING DEVICE |
Controller | i |
CompleteInit |
2 | COMPLETE INIT |
INITIALIZING DEVICE |
INITIALIZED |
Controller | i |
Bind |
3 | BIND |
INITIALIZED |
BINDING |
Controller | b |
Connect |
4 | CONNECT |
BOUND |
CONNECTING |
Controller | x |
InitTask |
5 | INIT TASK |
DEVICE READY |
INITIALIZING TASK |
Controller | j |
Run |
6 | RUN |
READY |
RUNNING |
Controller | r |
Stop |
7 | STOP |
RUNNING |
READY |
Controller, or the device at the end of its work | s |
ResetTask |
8 | RESET TASK |
READY |
RESETTING TASK |
Controller | t |
ResetDevice |
9 | RESET DEVICE |
INITIALIZED, BOUND, DEVICE READY |
RESETTING DEVICE |
Controller | d |
End |
10 | END |
IDLE |
EXITING |
Controller | q (shutdown sequence) |
ErrorFound |
11 | ERROR FOUND |
All states | ERROR |
The device after an exception, or your code | — |
Transition matrix
Section titled “Transition matrix”The rows are the current states, and the columns are the transitions. A cell gives the next state.
A dash means that the state machine refuses the transition. The column ErrorFound is not in the
matrix: from all states, ErrorFound leads to ERROR. The source is the transition_table in
StateMachine.cxx.
| Current state | InitDevice |
CompleteInit |
Bind |
Connect |
InitTask |
Run |
Stop |
ResetTask |
ResetDevice |
End |
Auto |
|---|---|---|---|---|---|---|---|---|---|---|---|
IDLE |
INITIALIZING DEVICE |
— | — | — | — | — | — | — | — | EXITING |
— |
INITIALIZING DEVICE |
— | INITIALIZED |
— | — | — | — | — | — | — | — | — |
INITIALIZED |
— | — | BINDING |
— | — | — | — | — | RESETTING DEVICE |
— | — |
BINDING |
— | — | — | — | — | — | — | — | — | — | BOUND |
BOUND |
— | — | — | CONNECTING |
— | — | — | — | RESETTING DEVICE |
— | — |
CONNECTING |
— | — | — | — | — | — | — | — | — | — | DEVICE READY |
DEVICE READY |
— | — | — | — | INITIALIZING TASK |
— | — | — | RESETTING DEVICE |
— | — |
INITIALIZING TASK |
— | — | — | — | — | — | — | — | — | — | READY |
READY |
— | — | — | — | — | RUNNING |
— | RESETTING TASK |
— | — | — |
RUNNING |
— | — | — | — | — | — | READY |
— | — | — | — |
RESETTING TASK |
— | — | — | — | — | — | — | — | — | — | DEVICE READY |
RESETTING DEVICE |
— | — | — | — | — | — | — | — | — | — | IDLE |
EXITING |
— | — | — | — | — | — | — | — | — | — | — |
ERROR |
— | — | — | — | — | — | — | — | — | — | — |
- The state machine accepts one transition at a time. While a transition is pending, it refuses all
other transitions except
ErrorFound. - A transition is pending from the call of
ChangeState()until the next state starts. The next state starts only after the hooks of the current state return. - In a working state, the device requests
Autoafter its hooks, but only when no other transition is pending. At the end ofRUNNING, the device requestsStopin the same way. INITIALIZING DEVICEwaits forCompleteInitbefore it callsInit().- Each new transition interrupts the transports. The transports resume at the start of the next state.
- In
EXITINGandERROR, the state machine has stopped, and the state does not change. InEXITING,ChangeState()returnsfalsefor all transitions exceptErrorFound. InERROR,ChangeState()can returntrue(known defect, see the disabled testStateMachine.RefusesTransitionsInError).
Keys of the interactive controller
Section titled “Keys of the interactive controller”With --control dynamic (default), interactive or external, the control plugin reads keys from
the standard input. It reads one character at a time, without Enter. The plugin prints the line
--> [key] action before it does the action. Source:
Control.cxx.
| Key | Action |
|---|---|
h |
Prints the help and the state machine. |
c |
Logs the current state. The plugin prints --> [i] check current state. |
p |
Logs the number of connected peers of each sub-channel. |
i |
Requests InitDevice. When INITIALIZING DEVICE starts, it requests CompleteInit. |
b |
Requests Bind. |
x |
Requests Connect. |
j |
Requests InitTask. |
r |
Requests Run. |
s |
Requests Stop. |
t |
Requests ResetTask. |
d |
Requests ResetDevice. |
q |
Ends the key input and runs the shutdown sequence (see below). |
k |
Increases the log severity of the console. |
l |
Decreases the log severity of the console. |
n |
Increases the log verbosity. |
m |
Decreases the log verbosity. |
| Other | Prints Invalid input: [key]. and the help. |
The keys b, x, j, r, s, t and d request only one transition. They do not wait for
the Auto transitions. If the state does not accept the transition, the state does not change.
Startup and shutdown sequences
Section titled “Startup and shutdown sequences”The control modes dynamic, static and gui start with the same sequence
(RunStartupSequence()). The plugin requests
a transition and waits for the next states:
| Step | Request | Wait for |
|---|---|---|
| 1 | InitDevice |
INITIALIZING DEVICE |
| 2 | CompleteInit |
INITIALIZED |
| 3 | Bind |
BINDING, then BOUND |
| 4 | Connect |
CONNECTING, then DEVICE READY |
| 5 | InitTask |
INITIALIZING TASK, then READY |
| 6 | Run |
RUNNING |
A signal stops the sequence after the current step, and the plugin runs the shutdown sequence. The
state ERROR also stops the sequence, but without the shutdown sequence. The shutdown sequence
(RunShutdownSequence()) requests one
transition for each state, until EXITING or ERROR:
| Current state | Request |
|---|---|
IDLE |
End |
INITIALIZING DEVICE |
CompleteInit |
INITIALIZED, BOUND, DEVICE READY |
ResetDevice |
READY |
ResetTask |
RUNNING |
Stop |
| Other states | None. The plugin waits for the next state. |
Name functions
Section titled “Name functions”These functions in the namespace fair::mq convert between the enums and the names
(States.h):
std::string GetStateName(State);std::string GetTransitionName(Transition);State GetState(const std::string& state);Transition GetTransition(const std::string& transition);
struct DeviceErrorState : std::runtime_error { using std::runtime_error::runtime_error; };
inline std::ostream& operator<<(std::ostream& os, const State& state) { return os << GetStateName(state); }inline std::ostream& operator<<(std::ostream& os, const Transition& transition) { return os << GetTransitionName(transition); }GetStateName()andGetTransitionName()return the name with spaces, for exampleDEVICE READY. Theoperator<<forStateandTransitionwrites the same name.GetState()andGetTransition()accept only these names, in upper case and with spaces.- All four functions throw
std::out_of_rangefor an unknown name or value.
Other functions use the same names:
| Function | Description |
|---|---|
Device::ChangeState(const std::string&) |
Requests the transition with this name, for example "INIT DEVICE". |
Device::ChangeStateOrThrow(const std::string&) |
The same, but throws if the state machine refuses the transition. |
Device::WaitForState(const std::string&) |
Waits for the state with this name. |
Device::GetCurrentStateName() |
Returns the name of the current state. |
PluginServices::ToDeviceState(), ToDeviceStateTransition() |
Call GetState() and GetTransition(). |
PluginServices::ToStr(), ToStr() |
Call GetStateName() and GetTransitionName(). |
Device::GetStateName(), Device::GetTransitionName() |
Deprecated static functions. Use the functions of States.h. |
The test States.UnknownNameThrows shows the exceptions:
TEST(States, UnknownNameThrows){ EXPECT_THROW(GetState("NO SUCH STATE"), std::out_of_range); EXPECT_THROW(GetTransition("NO SUCH TRANSITION"), std::out_of_range); EXPECT_THROW(GetStateName(static_cast<State>(100)), std::out_of_range); EXPECT_THROW(GetTransitionName(static_cast<Transition>(100)), std::out_of_range);}Errors of invalid transitions
Section titled “Errors of invalid transitions”| Call | Problem | Result |
|---|---|---|
Device::ChangeState(Transition) |
The current state does not accept the transition. | Returns false. Logs No transition from state … on transition …. |
Device::ChangeState(Transition) |
Another transition is pending. | Returns false. Logs Transition … incoming, but another state transition is already ongoing. |
Device::ChangeStateOrThrow(Transition) |
ChangeState() returns false. |
Throws std::system_error with the code ErrorCode::DeviceChangeStateFailed and the text Invalid transition: <NAME>. |
The functions with a std::string |
The name is unknown. | Throw std::out_of_range. |
PluginServices::ChangeDeviceState() |
Another plugin controls the device. | Throws PluginServices::DeviceControlError. Otherwise, it returns the result of ChangeState(). Without a controller, the calling plugin becomes the controller. |
Device::WaitForState(), Device::WaitForNextState() |
The next state in the queue is ERROR. |
Throw DeviceErrorState with the text Controlled device transitioned to error state. |
ChangeState() is [[nodiscard]]. The compiler warns when your code ignores the return value.
Use ChangeStateOrThrow() when a refused transition is an error in your program. The test
Transitions.InvalidChangeStateOrThrow requests Connect in IDLE:
TEST(Transitions, InvalidChangeStateOrThrow){ Device device; test::StateMachineThread t(device);
ASSERT_THROW(device.ChangeStateOrThrow(Transition::Connect), std::system_error);
ASSERT_NO_THROW(device.ChangeStateOrThrow(Transition::End)); t.Join();}For the error codes and all exceptions of FairMQ, see Transfer codes and errors.
Related pages
Section titled “Related pages”- Device states: the state machine with a diagram, and the hooks in each state.
- Plugins and control: the control plugin and the device control of plugins.
- Control a device from code: request transitions in your program.
- Transfer codes and errors:
ErrorCodeand the exceptions.