This commit is contained in:
Timur A. Fatkhullin 2025-06-02 02:10:57 +03:00
parent e069ed84f0
commit 9bee1ca0ea

View File

@ -238,6 +238,40 @@ protected:
template <traits::fsm_event_c EvT>
inline static std::unordered_map<const MccFiniteStateMachine*, std::function<void(EvT&)>> _dispatchEventFunc{};
std::vector<std::function<void(MccFiniteStateMachine*, MccFiniteStateMachine*)>> _moveFunc{};
std::vector<std::function<void(const MccFiniteStateMachine*, MccFiniteStateMachine*)>> _copyFunc{};
std::vector<std::function<void()>> _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 <traits::fsm_state_c InitStateT>
MccFiniteStateMachine(InitStateT)
@ -277,47 +311,71 @@ public:
for_each_event<deduce_events_t<InitStateT>>([states, currentState, this]<traits::fsm_event_c EvT>(EvT) mutable {
_dispatchEventFunc<EvT>[this] = [states, currentState, this](EvT& event) mutable {
std::visit(
[&event, states]<traits::fsm_state_c curr_state_t>(curr_state_t*) {
[&event, states, currentState]<traits::fsm_state_c curr_state_t>(curr_state_t*) {
using to_state_t = curr_state_t::transition_t::template find_state_by_event_t<EvT>;
if constexpr (std::is_void_v<to_state_t>) {
/// throw?!!
return;
}
if constexpr (!std::is_void_v<to_state_t>) {
// exit from current
if constexpr (requires(curr_state_t inst) {
{ inst.exit(std::declval<EvT>()) };
}) {
std::get<curr_state_t>(*states).exit(event);
} else if constexpr (requires(curr_state_t inst) {
{ inst.exit() };
}) {
std::get<curr_state_t>(*states).exit();
}
// exit from current
if constexpr (requires(curr_state_t inst) {
{ inst.exit(std::declval<EvT>()) };
}) {
std::get<curr_state_t>(states).exit(event);
} else if constexpr (requires(curr_state_t inst) {
{ inst.exit() };
}) {
std::get<curr_state_t>(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<to_state_t*>(*states);
// enter to new
if constexpr (requires(to_state_t inst) {
{ inst.enter(std::declval<EvT>()) };
}) {
std::get<curr_state_t>(states).enter(event);
} else if constexpr (requires(to_state_t inst) {
{ inst.enter() };
}) {
std::get<curr_state_t>(states).enter();
// enter to new
if constexpr (requires(to_state_t inst) {
{ inst.enter(std::declval<EvT>()) };
}) {
std::get<curr_state_t>(*states).enter(event);
} else if constexpr (requires(to_state_t inst) {
{ inst.enter() };
}) {
std::get<curr_state_t>(*states).enter();
}
}
},
*currentState);
};
_moveFunc.emplace_back([](MccFiniteStateMachine* from, MccFiniteStateMachine* to) {
_dispatchEventFunc<EvT>[to] = std::move(_dispatchEventFunc<EvT>[from]);
});
_copyFunc.emplace_back([](const MccFiniteStateMachine* from, MccFiniteStateMachine* to) {
_dispatchEventFunc<EvT>[to] = _dispatchEventFunc<EvT>[from];
});
_destroyFunc.emplace_back([](MccFiniteStateMachine* inst) {
//
_dispatchEventFunc<EvT>.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 <traits::fsm_event_c EvT>
auto dispatchEvent(EvT& event)