From 7b1e600266dfd38cc11a69678246eeeb52243033 Mon Sep 17 00:00:00 2001 From: Amar Mahmutbegovic Date: Sat, 11 Jan 2025 22:22:11 +0100 Subject: [PATCH] add tag dispatching example --- .../fsm/app/src/main_fsm_state_pattern.cpp | 3 +- .../main_fsm_state_pattern_tag_dispatch.cpp | 175 ++++++++++++++++++ 2 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 Chapter17/fsm/app/src/main_fsm_state_pattern_tag_dispatch.cpp diff --git a/Chapter17/fsm/app/src/main_fsm_state_pattern.cpp b/Chapter17/fsm/app/src/main_fsm_state_pattern.cpp index bf4044e..8b25eb5 100644 --- a/Chapter17/fsm/app/src/main_fsm_state_pattern.cpp +++ b/Chapter17/fsm/app/src/main_fsm_state_pattern.cpp @@ -81,7 +81,7 @@ public: } return get_state_enum(); } - + ble_state get_state_enum() { return ble_state::connected; } @@ -135,7 +135,6 @@ const char* state_to_string(ble_state state) { } } - int main() { hal::init(); diff --git a/Chapter17/fsm/app/src/main_fsm_state_pattern_tag_dispatch.cpp b/Chapter17/fsm/app/src/main_fsm_state_pattern_tag_dispatch.cpp new file mode 100644 index 0000000..46ff90e --- /dev/null +++ b/Chapter17/fsm/app/src/main_fsm_state_pattern_tag_dispatch.cpp @@ -0,0 +1,175 @@ +#include +#include + +#include + +#include + +#include +#include +#include + +#include + +#include "etl/vector.h" + +enum class ble_state { + idle, + advertising, + connected +}; + +struct ble_button_pressed{}; +struct connection_request{}; +struct timer_expired{}; + +class state { +public: + virtual ble_state handle_event(ble_button_pressed) { + return get_state_enum(); + } + virtual ble_state handle_event(connection_request) { + return get_state_enum(); + } + virtual ble_state handle_event(timer_expired) { + return get_state_enum(); + } + virtual ble_state get_state_enum() = 0; +}; + +class idle : public state{ +public: + ble_state handle_event(ble_button_pressed bbp) override { + start_advertising(); + return ble_state::advertising; + } + + ble_state get_state_enum() { + return ble_state::idle; + } +private: + void start_advertising() { + printf("Action: start_advertising()\n"); + } +}; + +class advertising : public state{ +public: + ble_state handle_event(connection_request cr) override { + return ble_state::connected; + } + + ble_state handle_event(timer_expired te) override { + stop_advertising(); + return ble_state::idle; + } + + ble_state get_state_enum() { + return ble_state::advertising; + } +private: + void stop_advertising() { + printf("Action: stop_advertising()\n"); + } +}; + +class connected : public state{ +public: + ble_state handle_event(ble_button_pressed) { + disconnect(); + return ble_state::idle; + } + + ble_state get_state_enum() { + return ble_state::connected; + } +private: + void disconnect() { + printf("Action: disconnect()\n"); + } +}; + +class ble_fsm { +public: + template + void handle_event(E event) { + if(auto the_state = get_the_state(current_state_)) { + current_state_ = the_state->handle_event(event); + } + } + + ble_state get_state() const { + return current_state_; + } + + void add_state(state *the_state) { + states_.push_back(the_state); + } + +private: + etl::vector states_; + ble_state current_state_ = ble_state::idle; + + state* get_the_state(ble_state state_enum) { + const auto is_state_enum = [&] (state *the_state) { + return the_state->get_state_enum() == state_enum; + }; + auto it = std::find_if(states_.begin(), states_.end(), is_state_enum); + + if(it != states_.end()) { + return *it; + } + return nullptr; + } +}; + +namespace { +const char* state_to_string(ble_state state) { + switch (state) { + case ble_state::idle: return "idle"; + case ble_state::advertising: return "advertising"; + case ble_state::connected: return "connected"; + default: return "unknown"; + } +} +} + +int main() +{ + hal::init(); + + hal::uart_stm32 uart(USART2); + uart.init(); + + retarget::set_stdio_uart(&uart); + + ble_fsm my_ble_fsm; + + idle idle_s; + advertising advertising_s; + connected connected_s; + + my_ble_fsm.add_state(&idle_s); + my_ble_fsm.add_state(&advertising_s); + my_ble_fsm.add_state(&connected_s); + + const auto print_current_state = [&]() { + printf("Current State: %s\n", state_to_string(my_ble_fsm.get_state())); + }; + + print_current_state(); + + my_ble_fsm.handle_event(ble_button_pressed{}); + print_current_state(); + + my_ble_fsm.handle_event(connection_request{}); + print_current_state(); + + my_ble_fsm.handle_event(ble_button_pressed{}); + print_current_state(); + + + while(true) + { + } +}