State Machine
State Machine Description
State machine is a behavioral design pattern that allows an object to change its behavior when its internal state changes. Implementation in PIP is based on the SCXML (State Chart XML) standard.
SCXML Concepts
- State — a node in the state tree, can be atomic or compound
- Transition — a connection between states that triggers on an event
- Event — a trigger that causes a transition
- Guard — a condition that must be true for a transition to execute
- Action — an operation executed during a transition
- Parallel — a state where all substates are activated simultaneously
PIP State Machine Features
- Cannot create state, event, transition on stack — all objects are created via new and managed via pointers
- State machine is the root state — PIStateMachine inherits from PIStateBase
- All transitions and states are automatically deleted — when the parent object is destroyed
State Types
- Atomic state — a state without nested substates
- Compound state — a state containing nested substates
- Final state — a terminating state indicating the end of machine execution
- Parallel state — a state where all substates are activated simultaneously
Transition Types
- Normal transition — triggers on receiving a specific event
- Timeout transition — triggers automatically after a specified time interval
- Guarded transition — triggers only when a specific condition is met
State Machine API
Main Classes
Main state machine class.
Key methods:
- bool start() — starts state machine execution
- bool isRunning() — checks if state machine is running
- void setOnFinish(std::function<void()> f) — sets finish callback
- bool postEvent(int event_id, Args... args) — posts event to state machine
Base class for all states.
Key methods:
- virtual void onEnter() — called when state is entered
- virtual void onExit() — called when state is exited
- void addState(PIStateBase *s) — adds child state
- PITransitionBase *addTransition(PIStateBase *target, int event_id) — adds transition
- PITransitionTimeout *addTimeoutTransition(PIStateBase *target, PISystemTime timeout) — adds timeout transition
- void setParallel(bool yes) — sets parallel mode
State with lambda callbacks.
PIStateLambda(std::function<
void()> on_enter, std::function<
void()> on_exit =
nullptr,
const PIString &n = {})
PIStateLambda(std::function< void()> on_enter, std::function< void()> on_exit=nullptr, const PIString &n={})
Creates a state backed by enter and exit callbacks.
Definition pistatemachine_state.h:199
String class.
Definition pistring.h:42
Final state of state machine.
PIStateFinal(std::function< void()> on_finish=nullptr, const PIString &n={})
Creates a final state with an optional callback executed on entry.
Definition pistatemachine_state.h:231
Base class for transitions.
Key methods:
- PITransitionBase *addGuard(std::function<R(Args...)> f) — adds guard function
- PITransitionBase *addAction(std::function<void()> a) — adds action
- void trigger() — triggers transition
Transition that triggers after a specified timeout.
Usage Examples
Simple State Machine
[]() {
piCout <<
"Entering Idle state\n"; },
[]() {
piCout <<
"Exiting Idle state\n"; },
"Idle"
);
[]() {
piCout <<
"Entering Running state\n"; },
[]() {
piCout <<
"Exiting Running state\n"; },
"Running"
);
[]() {
piCout <<
"Machine finished\n"; },
"Finish"
);
running->setInitialState(running);
running->addTransition(finish, 2);
void setInitialState(PIStateBase *s)
Sets the initial child state for a non-parallel compound state.
Definition pistatemachine_state.cpp:63
PITransitionBase * addTransition(PIStateBase *target, int event_id)
Adds an event-driven transition from this state to target.
Definition pistatemachine_state.cpp:71
void addState(PIStateBase *s)
Adds a child state owned by this state.
Definition pistatemachine_state.cpp:48
Final state that finishes its parent state when entered.
Definition pistatemachine_state.h:227
State implementation that forwards enter and exit virtual methods to callbacks.
Definition pistatemachine_state.h:195
Root object that owns and runs a hierarchical state machine.
Definition pistatemachine.h:43
PIStateMachine(const PIString &n={})
Creates a state machine with an optional name.
Definition pistatemachine.cpp:23
void setOnFinish(std::function< void()> f)
Sets a callback invoked when the machine finishes.
Definition pistatemachine.h:60
bool start()
Starts the machine from its initial active configuration.
Definition pistatemachine.cpp:28
bool postEvent(int event_id, Args... args)
Posts an event to active states and triggers the first matching transition.
Definition pistatemachine.h:66
#define piCout
Macro used for conditional (piDebug) output to PICout(StdOut).
Definition picout.h:36
State machine. Main state machine class that manages states and transitions. Thread-safe implementati...
System time structs and methods.
Guarded Transitions
return value > 10;
});
auto *t2 = stateB->addTransition(stateC, 2);
return msg == "allowed";
});
PITransitionBase * addGuard(std::function< R(Args...)> f)
Sets a guard function that must return bool.
Definition pistatemachine_transition.h:74
Timeout Transitions
[]() {
piCout <<
"Working...\n"; },
[]() {
piCout <<
"Stop working\n"; },
"Working"
);
timeoutState->addTransition(finish, 1);
PITransitionTimeout * addTimeoutTransition(PIStateBase *target, PISystemTime timeout)
Adds a timeout transition that fires while this state stays active.
Definition pistatemachine_state.cpp:79
static PISystemTime fromSeconds(double v)
Contructs time from seconds "v".
Definition pisystemtime.h:374
Compound States
parent->addState(child1);
parent->addState(child2);
parent->addTransition(root, 2);
Parallel States
parallel->addState(sub1);
parallel->addState(sub2);
parallel->setInitialState(sub1);
void setParallel(bool yes)
Enables or disables parallel activation of child states.
Definition pistatemachine_state.h:119
Transitions with Actions
PITransitionBase * addAction(std::function< void()> a)
Sets an action executed when the transition fires.
Definition pistatemachine_transition.cpp:37
Thread Safety
State machine is thread-safe. The postEvent method uses a queue to handle nested calls, allowing safe event posting from different threads.
Usage Rules
Cannot Create on Stack
Proper Object Hierarchy
Memory Cleanup
All objects (states, transitions) are automatically deleted when the parent object is destroyed:
- When PIStateMachine is destroyed, all states and transitions are deleted
- When PIStateBase is destroyed, all child states and transitions are deleted
Debugging
For debugging, you can use the print() method to output the state tree:
void print(PIString prefix={})
Prints the state tree and active branches to piCout.
Definition pistatemachine_state.cpp:87
Also, you can use activeAtomics() to get a list of active states.
Related Modules
- DateTime module for PISystemTime used in timeout transitions