From 9bee1ca0ea7eb37b33053d7147e836143c7ec267 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Mon, 2 Jun 2025 02:10:57 +0300 Subject: [PATCH] ... --- cxx/mcc_finite_state_machine.h | 118 ++++++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 30 deletions(-) diff --git a/cxx/mcc_finite_state_machine.h b/cxx/mcc_finite_state_machine.h index dbe330f..9f84361 100644 --- a/cxx/mcc_finite_state_machine.h +++ b/cxx/mcc_finite_state_machine.h @@ -238,6 +238,40 @@ protected: template inline static std::unordered_map> _dispatchEventFunc{}; + std::vector> _moveFunc{}; + std::vector> _copyFunc{}; + std::vector> _destroyFunc{}; + + static MccFiniteStateMachine& copyInstance(const MccFiniteStateMachine* from, MccFiniteStateMachine* to) + { + if (from != to) { + for (auto& func : from->_copyFunc) { + func(from, to); + } + + to->_moveFunc = from->_moveFunc; + to->_copyFunc = from->_copyFunc; + to->_destroyFunc = from->_destroyFunc; + } + + return *to; + } + + static MccFiniteStateMachine& moveInstance(MccFiniteStateMachine* from, MccFiniteStateMachine* to) + { + if (from != to) { + for (auto& func : from->_moveFunc) { + func(from, to); + } + + to->_moveFunc = std::move(from->_moveFunc); + to->_copyFunc = std::move(from->_copyFunc); + to->_destroyFunc = std::move(from->_destroyFunc); + } + + return *to; + } + public: template MccFiniteStateMachine(InitStateT) @@ -277,47 +311,71 @@ public: for_each_event>([states, currentState, this](EvT) mutable { _dispatchEventFunc[this] = [states, currentState, this](EvT& event) mutable { std::visit( - [&event, states](curr_state_t*) { + [&event, states, currentState](curr_state_t*) { using to_state_t = curr_state_t::transition_t::template find_state_by_event_t; - if constexpr (std::is_void_v) { - /// throw?!! - return; - } + if constexpr (!std::is_void_v) { + // exit from current + if constexpr (requires(curr_state_t inst) { + { inst.exit(std::declval()) }; + }) { + std::get(*states).exit(event); + } else if constexpr (requires(curr_state_t inst) { + { inst.exit() }; + }) { + std::get(*states).exit(); + } - // exit from current - if constexpr (requires(curr_state_t inst) { - { inst.exit(std::declval()) }; - }) { - std::get(states).exit(event); - } else if constexpr (requires(curr_state_t inst) { - { inst.exit() }; - }) { - std::get(states).exit(); - } + // transit ... + if constexpr (requires(EvT inst) { + { inst.on_transit() }; + }) { + event.on_transit(); + } - // transit ... - if constexpr (requires(EvT inst) { - { inst.on_transit() }; - }) { - event.on_transit(); - } + *currentState = std::get(*states); - // enter to new - if constexpr (requires(to_state_t inst) { - { inst.enter(std::declval()) }; - }) { - std::get(states).enter(event); - } else if constexpr (requires(to_state_t inst) { - { inst.enter() }; - }) { - std::get(states).enter(); + // enter to new + if constexpr (requires(to_state_t inst) { + { inst.enter(std::declval()) }; + }) { + std::get(*states).enter(event); + } else if constexpr (requires(to_state_t inst) { + { inst.enter() }; + }) { + std::get(*states).enter(); + } } }, *currentState); }; + + _moveFunc.emplace_back([](MccFiniteStateMachine* from, MccFiniteStateMachine* to) { + _dispatchEventFunc[to] = std::move(_dispatchEventFunc[from]); + }); + _copyFunc.emplace_back([](const MccFiniteStateMachine* from, MccFiniteStateMachine* to) { + _dispatchEventFunc[to] = _dispatchEventFunc[from]; + }); + _destroyFunc.emplace_back([](MccFiniteStateMachine* inst) { + // + _dispatchEventFunc.erase(inst); + }); }); } + MccFiniteStateMachine(const MccFiniteStateMachine& other) { copyInstance(&other, this); } + + MccFiniteStateMachine(MccFiniteStateMachine&& other) { moveInstance(&other, this); } + + MccFiniteStateMachine& operator=(const MccFiniteStateMachine& other) { return copyInstance(&other, this); } + + MccFiniteStateMachine& operator=(MccFiniteStateMachine&& other) { return moveInstance(&other, this); } + + virtual ~MccFiniteStateMachine() + { + for (auto& func : _destroyFunc) { + func(); + } + } template auto dispatchEvent(EvT& event)