From 2a62206b5eb6be723f72f64e0ea49cea7df5053e Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Thu, 14 Apr 2022 09:12:33 +0200 Subject: [PATCH] Add "simple" example of a nested FSM As reported in #1, the motor example is too complex for newcomers. Hopefully, this one is more understandable. --- examples/meson.build | 1 + examples/simple-nested.cpp | 113 +++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 examples/simple-nested.cpp diff --git a/examples/meson.build b/examples/meson.build index 5e29ebd..8d0dbcb 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -4,6 +4,7 @@ examples = [ 'simple', 'events', 'elevator', 'elevator2', + 'simple-nested', 'motor', 'states_out', ] diff --git a/examples/simple-nested.cpp b/examples/simple-nested.cpp new file mode 100644 index 0000000..aadc95a --- /dev/null +++ b/examples/simple-nested.cpp @@ -0,0 +1,113 @@ +#include "msfsm.hpp" +#include + +using namespace msfsm; +using namespace std; + +class SimpleNested : public msfsm::Fsm +{ +public: + SimpleNested() { transition(outerState1); } + + // Events + struct ToggleOuter {}; + struct ToggleInner {}; + +private: + friend Fsm; + + // Base class for outer states + class State : public Fsm::State { + friend Fsm; + using Fsm::State::State; + virtual void event(ToggleOuter) = 0; + virtual void event(ToggleInner) = 0; + }; + + // This is both a state of SimpleNested FSM and a nested FSM with two inner states + class OuterState1 : public State, public Fsm { + friend Fsm; + friend Fsm; + public: + using SimpleNested::State::State; + private: + void entry() { cout << "OuterState1" << endl; Fsm::transition(innerState11); } + void event(ToggleOuter) override { fsm.transition(fsm.outerState2); } + void event(ToggleInner e) override { handle(e); } + void exit() override { destroy(); } // destroy inner FSM + + // Base class of inner states + class State : public Fsm::State { + friend Fsm; + using Fsm::State::State; + virtual void event(ToggleInner e) = 0; + }; + + class InnerState11 : public State { + friend Fsm; + using State::State; + + void entry() { cout << "InnerState11" << endl; }; + void event(ToggleInner e) override { transition(fsm.innerState12); } + } innerState11 {this}; + + class InnerState12 : public State { + friend Fsm; + using State::State; + void entry() { cout << "InnerState12" << endl; } + void event(ToggleInner e) override { transition(fsm.innerState11); } + } innerState12{this}; + + } outerState1 {this}; + + class OuterState2 : public State, public Fsm { + friend Fsm; + friend Fsm; + public: + using SimpleNested::State::State; + private: + void entry() { cout << "OuterState2" << endl; Fsm::transition(innerState22); } + void event(ToggleOuter) override { fsm.transition(fsm.outerState1); } + void event(ToggleInner e) override { this->handle(e); } + void exit() override { destroy(); } // destroy inner FSM + + // Base class of inner states + class State : public Fsm::State { + friend Fsm; + using Fsm::State::State; + virtual void event(ToggleInner e) = 0; + }; + + class InnerState21 : public State { + friend Fsm; + using State::State; + void entry() { cout << "InnerState21" << endl; } + void event(ToggleInner e) override { transition(fsm.innerState22); } + } innerState21 {this}; + + class InnerState22 : public State { + friend Fsm; + using State::State; + void entry() { cout << "InnerState22" << endl; } + void event(ToggleInner e) override { transition(fsm.innerState21); } + } innerState22{this}; + + } outerState2 {this}; + +}; + +int main(int argc, char *argv[]) +{ + SimpleNested fsm; + fsm.handle(SimpleNested::ToggleInner()); + fsm.handle(SimpleNested::ToggleInner()); + fsm.handle(SimpleNested::ToggleInner()); + + fsm.handle(SimpleNested::ToggleOuter()); + + fsm.handle(SimpleNested::ToggleInner()); + fsm.handle(SimpleNested::ToggleInner()); + + fsm.handle(SimpleNested::ToggleOuter()); + return 0; +}