Last active
April 17, 2023 08:25
-
-
Save rpoisel/6de075a672e2f9152a9e15274be5f661 to your computer and use it in GitHub Desktop.
Simple State-Machine similar to HFSM2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <csignal> | |
#include <cstdlib> | |
#include <ctime> | |
#include <atomic> | |
#include <chrono> | |
#include <iostream> | |
#include <optional> | |
#include <thread> | |
#include <variant> | |
using namespace std::chrono_literals; | |
static inline std::size_t rand_number(std::size_t min, std::size_t max) { | |
return min + std::rand() / ((RAND_MAX + 1u) / max); | |
} | |
template <class... States> class FSM { | |
public: | |
using StateVariant = std::variant<States...>; | |
using OptionalStateVariant = std::optional<StateVariant>; | |
FSM(StateVariant initialState) : curState{std::move(initialState)} {} | |
void update() { | |
auto newState = std::visit( | |
[](auto &arg) -> OptionalStateVariant { | |
arg.update(); | |
return transition(arg); | |
}, | |
curState); | |
if (newState) { | |
curState = std::move(newState.value()); | |
} | |
std::this_thread::sleep_for(500ms); | |
} | |
private: | |
StateVariant curState; | |
}; | |
class LightOn; | |
class LightOff; | |
using StateVariant = std::variant<LightOn, LightOff>; | |
using OptionalStateVariant = std::optional<StateVariant>; | |
class LightOn { | |
public: | |
LightOn(std::size_t c) : cycles{c}, cycle{0} {} | |
virtual ~LightOn() = default; | |
void update() { | |
std::cout << "Light on: " << ++cycle << " of " << cycles << std::endl; | |
} | |
friend OptionalStateVariant transition(LightOn &on); | |
private: | |
std::size_t cycles; | |
std::size_t cycle; | |
}; | |
class LightOff { | |
public: | |
LightOff() = default; | |
virtual ~LightOff() = default; | |
void update() { std::cout << "Light off" << std::endl; } | |
friend OptionalStateVariant transition(LightOff &on); | |
}; | |
OptionalStateVariant transition(LightOn &on) { | |
if (on.cycle == on.cycles) { | |
return LightOff(); | |
} | |
return std::nullopt; | |
} | |
OptionalStateVariant transition(LightOff &off) { | |
return LightOn(rand_number(1, 6)); | |
} | |
static std::atomic_bool is_running = true; | |
auto main() noexcept -> int { | |
std::srand(std::time(nullptr)); | |
FSM<LightOn, LightOff> fsm{LightOff{}}; | |
std::signal(SIGINT, [](int signal) -> void { is_running = false; }); | |
while (is_running) { | |
fsm.update(); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment