Skip to content

Commit ee7b059

Browse files
committed
docs: enhance StateMachine and SM classes with additional methods and documentation
1 parent dc971f5 commit ee7b059

File tree

1 file changed

+64
-2
lines changed

1 file changed

+64
-2
lines changed

Application/Inc/StateMachine.hpp

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,23 @@
99
#include <vector>
1010
#include <ranges>
1111

12+
/// @brief Values injected into actions and guards.
1213
using Injection = std::vector<std::any>;
14+
15+
/// @brief Optional transition action callback.
16+
/// @see std::function<void()>
1317
using Action = std::optional<std::function<void()>>;
18+
19+
/// @brief Optional guard predicate for transitions.
20+
/// @return true if transition is allowed.
1421
using Guard = std::optional<std::function<bool()>>;
1522

23+
/// @brief Forward declaration of the state machine engine.
1624
template <typename Parent>
1725
class SM;
1826

27+
/// @brief Container for states, transitions, and injections of the state machine.
28+
/// @tparam Parent Type defining State and Event.
1929
template<typename Parent>
2030
struct StateMachineContainer {
2131
using State = typename Parent::State;
@@ -24,21 +34,44 @@ struct StateMachineContainer {
2434
using Transition = std::tuple< State, Event, State, Guard, Action, Injection >;
2535
using Anonymous = std::tuple< State, State, Guard, Action, Injection >;
2636

37+
/// @brief Current active state of the state machine.
2738
State currentState;
39+
40+
/// @brief Registered state entries with guards and entry actions.
2841
std::vector<Entry> entries;
42+
43+
/// @brief Event-driven transitions.
2944
std::vector<Transition> transitions;
45+
46+
/// @brief Automatic transitions executed without an explicit event.
3047
std::vector<Anonymous> anonymous;
48+
49+
/// @brief Values injected into callbacks during state changes.
3150
Injection injections;
3251

3352
// Member convenience methods
53+
/// @brief Trigger a state machine event.
54+
/// @tparam ExternalInjection Types of additional data to inject.
55+
/// @param event Event to trigger.
56+
/// @param args Optional injection values.
3457
template<typename... ExternalInjection>
3558
void triggerEvent(typename Parent::Event event, ExternalInjection&&... args) {
3659
SM<Parent>::triggerEvent(event, *this, std::forward<ExternalInjection>(args)...);
3760
}
61+
62+
/// @brief Set a new state directly, bypassing events.
63+
/// @tparam ExternalInjection Types of additional data to inject.
64+
/// @param state Target state to set.
65+
/// @param args Optional injection values.
3866
template<typename... ExternalInjection>
3967
void setState(typename Parent::State state, ExternalInjection&&... args) {
4068
SM<Parent>::setState(state, *this, std::forward<ExternalInjection>(args)...);
4169
}
70+
71+
/// @brief Run anonymous transitions until none remain.
72+
/// @tparam ExternalInjection Types of additional data to inject.
73+
/// @param args Optional injection values.
74+
/// @return true if any anonymous transition executed.
4275
template<typename... ExternalInjection>
4376
bool runAnonymous(ExternalInjection&&... args) {
4477
return SM<Parent>::runAnonymous(*this, std::forward<ExternalInjection>(args)...);
@@ -48,13 +81,20 @@ struct StateMachineContainer {
4881
template<typename Parent>
4982
using StateMachine = StateMachineContainer<Parent>;
5083

84+
/// @brief State machine engine implementing transitions and state changes.
85+
/// @tparam Parent Type defining State and Event.
5186
template <typename Parent>
5287
class SM {
5388
public:
5489
using State = typename Parent::State;
5590
using Event = typename Parent::Event;
5691
using StateMachine = StateMachineContainer<Parent>;
5792

93+
/// @brief Process an event and transition state if matching.
94+
/// @tparam ExternalInjection Types of optional injection values.
95+
/// @param event Event to handle.
96+
/// @param sm StateMachine instance to operate on.
97+
/// @param args Additional values for injection.
5898
template <typename... ExternalInjection>
5999
static void triggerEvent(Parent::Event event, StateMachine &sm, ExternalInjection... args) {
60100
auto it = std::ranges::find_if(sm.transitions.begin(), sm.transitions.end(), [&](const auto &t) {
@@ -69,6 +109,11 @@ class SM {
69109
while(runAnonymous(sm, std::forward<ExternalInjection>(args)...)) {}
70110
}
71111

112+
/// @brief Force set the state with injection values.
113+
/// @tparam ExternalInjection Types of optional injection values.
114+
/// @param state New state to set.
115+
/// @param sm StateMachine instance to operate on.
116+
/// @param args Additional values for injection.
72117
template <typename... ExternalInjection>
73118
static void setState(Parent::State state, StateMachine &sm, ExternalInjection... args) {
74119
auto it = std::ranges::find_if(sm.entries.begin(), sm.entries.end(),
@@ -82,6 +127,11 @@ class SM {
82127
while(runAnonymous(sm, std::forward<ExternalInjection>(args)...)) {}
83128
}
84129

130+
/// @brief Execute an anonymous transition if the current state matches.
131+
/// @tparam ExternalInjection Types of optional injection values.
132+
/// @param sm StateMachine instance to operate on.
133+
/// @param args Additional values for injection.
134+
/// @return true if a transition occurred.
85135
template <typename... ExternalInjection>
86136
static bool runAnonymous(StateMachine &sm, ExternalInjection... args) {
87137
auto it = std::ranges::find_if(sm.anonymous.begin(), sm.anonymous.end(),
@@ -91,20 +141,32 @@ class SM {
91141
auto [fromState, nextState, guard, action, injection] = *it;
92142
updateInjection(sm, injection, std::forward<ExternalInjection>(args)...);
93143
handleStateChange(sm, nextState, guard, action);
94-
return true;
144+
return true;
95145
}
96-
return false;
146+
return false;
97147
}
98148

149+
/// @brief Retrieve the current state from the state machine.
150+
/// @param sm StateMachine instance.
151+
/// @return Current active state.
99152
static Parent::State getState(StateMachine &sm) { return sm.currentState; }
100153

101154
private:
155+
/// @brief Evaluate guard and perform state change and action.
156+
/// @param sm Instance to update.
157+
/// @param nextState State to transition to.
158+
/// @param guard Optional guard predicate.
159+
/// @param action Optional action to execute.
102160
static void handleStateChange(StateMachine &sm, Parent::State nextState, Guard guard, Action action) {
103161
if (guard && !(*guard)()) return;
104162
sm.currentState = nextState;
105163
if (action) (*action)();
106164
}
107165

166+
/// @brief Populate the injection vector for upcoming callbacks.
167+
/// @param sm Instance whose injections will be updated.
168+
/// @param injection Predefined injection values.
169+
/// @param args Additional values to inject.
108170
template <typename... ExternalInjection>
109171
static void updateInjection(StateMachine &sm, Injection injection, ExternalInjection &&...args) {
110172
if (!injection.empty()) {

0 commit comments

Comments
 (0)