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 = {})
State implementation that forwards enter and exit virtual methods to callbacks.
Definition: pistatemachine_state.h:195
String class.
Definition: pistring.h:42
Final state of state machine.
Final state that finishes its parent state when entered.
Definition: pistatemachine_state.h:227
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
Root object that owns and runs a hierarchical state machine.
Definition: pistatemachine.h:43
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
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