From 02afd65d6feaa039f1eacc8d948429aee9c795b1 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Tue, 17 Jun 2025 00:46:13 +0300 Subject: [PATCH] ... --- cxx/mcc_finite_state_machine.h | 30 +++++++++++--- cxx/mcc_mount.h | 13 ++++-- cxx/mcc_mount_events_states.h | 6 +-- cxx/mcc_mount_pz.h | 73 ++++++++++++---------------------- cxx/tests/mount.cpp | 7 +++- 5 files changed, 69 insertions(+), 60 deletions(-) diff --git a/cxx/mcc_finite_state_machine.h b/cxx/mcc_finite_state_machine.h index ebc5a97..caa6717 100644 --- a/cxx/mcc_finite_state_machine.h +++ b/cxx/mcc_finite_state_machine.h @@ -317,7 +317,7 @@ protected: std::vector _stateID{}; std::vector _eventID{}; - std::mutex _transitionMutex{}; + std::recursive_mutex _transitionMutex{}; static MccFiniteStateMachine& copyInstance(const MccFiniteStateMachine* from, MccFiniteStateMachine* to) @@ -385,18 +385,23 @@ public: [states, currentState, this](std::index_sequence) { ((_dispatchEventFunc>[this] = [states, currentState, this](EvT& event) { - std::lock_guard lock(_transitionMutex); + // to avoid effects of possible compiler optimizations + // (here one needs to be sure that inside the lambda 'event' is used by reference) + const auto p_event = &event; std::visit( - [&event, states, currentState, this](curr_state_t*) { + [p_event, states, currentState, this](curr_state_t*) { using to_state_t = curr_state_t::transition_t::template find_state_by_event_t; if constexpr (!std::is_void_v) { + std::lock_guard lock(_transitionMutex); + // exit from current if constexpr (requires(curr_state_t inst) { { inst.exit(std::declval()) }; }) { - std::get(*states).exit(event); + // std::get(*states).exit(event); + std::get(*states).exit(*p_event); } else if constexpr (requires(curr_state_t inst) { { inst.exit() }; }) { @@ -407,7 +412,8 @@ public: if constexpr (requires(EvT inst) { { inst.onTransit() }; }) { - event.onTransit(); + // event.onTransit(); + p_event->onTransit(); } *currentState = &std::get(*states); @@ -417,7 +423,8 @@ public: if constexpr (requires(to_state_t inst) { { inst.enter(std::declval()) }; }) { - std::get(*states).enter(event); + // std::get(*states).enter(event); + std::get(*states).enter(*p_event); } else if constexpr (requires(to_state_t inst) { { inst.enter() }; }) { @@ -450,6 +457,17 @@ public: (_eventID.emplace_back(std::tuple_element_t::ID), ...); }(std::make_index_sequence>()); + + // call enter() method (if it exists) of the initial state + std::visit( + [](curr_state_t* cstate) { + if constexpr (requires(curr_state_t inst) { + { inst.enter() }; + }) { + cstate->enter(); + } + }, + *currentState); } MccFiniteStateMachine(const MccFiniteStateMachine& other) diff --git a/cxx/mcc_mount.h b/cxx/mcc_mount.h index 6941b16..a39a08a 100644 --- a/cxx/mcc_mount.h +++ b/cxx/mcc_mount.h @@ -155,13 +155,17 @@ public: template MccMount(InitStateT, - const LogMarkT& logger_mark = "[MOUNT]", - std::shared_ptr logger = spdlog::null_logger_mt("NULL")) + std::shared_ptr logger = spdlog::null_logger_mt("NULL"), + const LogMarkT& logger_mark = "[MOUNT]") : fsm::MccFiniteStateMachine(InitStateT{}), utils::MccSpdlogLogger(logger) { addMarkToPatternIdx(logger_mark); logDebug("Create MccMount class instance: thread = {}", getThreadId()); + + auto ids = this->stateIDs(); + auto r = ids | std::views::join_with(','); + logDebug("{}", std::string(r.begin(), r.end())); } @@ -173,7 +177,10 @@ public: /* public methods */ - void initMount() {} + void initMount() + { + this->logInfo("STATE: {}", this->currentStateID()); + } void stopMount() {} diff --git a/cxx/mcc_mount_events_states.h b/cxx/mcc_mount_events_states.h index e63636e..1dc7d8d 100644 --- a/cxx/mcc_mount_events_states.h +++ b/cxx/mcc_mount_events_states.h @@ -318,7 +318,7 @@ struct MccMountStateInit : MccMountStateBase { { this->enterLog(event); - auto mount = event.mount(); + MountT& mount = event.mount(); mount.initMount(); // switch to IDLE state @@ -403,13 +403,13 @@ struct MccMountStateIDLE : MccMountStateBase { std::pair, MccMountStateIDLE>, std::pair, MccMountStateShutdown>>; - template > EvT> + template > EvT> void exit(EvT& event) { this->exitLog(event); } - template > EvT> + template > EvT> void enter(EvT& event) { this->enterLog(event); diff --git a/cxx/mcc_mount_pz.h b/cxx/mcc_mount_pz.h index 9236960..b7b3225 100644 --- a/cxx/mcc_mount_pz.h +++ b/cxx/mcc_mount_pz.h @@ -39,53 +39,47 @@ public: // check if given position (x,y) in the zone template XT, std::derived_from YT> - bool inZone(this auto&& self, - const XT& x, - const YT& y, - traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) + bool inZone(const XT&, const YT&, traits::mcc_systime_c auto const&) { - return std::forward(self).inZoneImpl(x, y, utc); + return false; } // returns a time duration to reach the zone // 0 - if already within // Inf - if it never reaches the zone template XT, std::derived_from YT> - pz_duration_t timeTo(this auto&& self, - const XT& x, - const YT& y, - traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) + pz_duration_t timeTo(const XT&, const YT&, traits::mcc_systime_c auto const&) { - return std::forward(self).timeToImpl(x, y, utc); + return pz_duration_t{std::numeric_limits::infinity()}; } // returns a time duration to exit from the zone // 0 - if given position (x,y) is out of the zone // Inf - if (x,y) is always within the zone template XT, std::derived_from YT> - pz_duration_t timeFrom(this auto&& self, - const XT& x, - const YT& y, - traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) + pz_duration_t timeFrom(const XT&, const YT&, traits::mcc_systime_c auto const&) { - return std::forward(self).timeFromImpl(x, y, utc); + return pz_duration_t{0.0}; } // all-in-one request (call three methods above) template XT, std::derived_from YT> - pz_request_t request(const XT& x, + pz_request_t request(this auto&& self, + const XT& x, const YT& y, traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) { + using self_t = decltype(self); + pz_request_t res{.in_zone = false, .time_to = pz_duration_t{0.0}, .time_from{0.0}}; - res.in_zone = inZone(x, y, utc); + res.in_zone = std::forward(self).inZone(x, y, utc); if (res.in_zone) { - res.time_from = timeFrom(x, y, utc); + res.time_from = std::forward(self).timeFrom(x, y, utc); } else { - res.time_to = timeFrom(x, y, utc); + res.time_to = std::forward(self).timeTo(x, y, utc); } return res; @@ -95,30 +89,10 @@ protected: MccProhibitedZone(std::string_view name) : _name(name) {} std::string_view _name; - - - template XT, std::derived_from YT> - bool inZoneImpl(const XT&, const YT&, traits::mcc_systime_c auto const&) - { - return false; - } - - - template XT, std::derived_from YT> - pz_duration_t timeToImpl(const XT&, const YT&, traits::mcc_systime_c auto const&) - { - return pz_duration_t{std::numeric_limits::infinity()}; - } - - - template XT, std::derived_from YT> - pz_duration_t timeFromImpl(const XT&, const YT&, traits::mcc_systime_c auto const&) - { - return pz_duration_t{0.0}; - } }; + /* SOME PROHIBITED ZONE IMPLEMENTATIONS */ @@ -145,11 +119,8 @@ public: _altLimit.normalize(); } -private: - MccAngle _altLimit; - template XT, std::derived_from YT> - bool inZoneImpl(const XT& x, const YT& y, traits::mcc_systime_c auto const& utc) + bool inZone(const XT& x, const YT& y, traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) { static constexpr MccCoordPairKind coord_kind = traits::mcc_type_pair_hash(); @@ -160,7 +131,7 @@ private: return y >= _altLimit; } } else if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_AZZD) { // trivial case - return inZoneImpl(x, MccAngleALT(std::numbers::pi / 2 - (double)y), utc); + return inZone(x, MccAngleALT(std::numbers::pi / 2 - (double)y), utc); } else if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_HADEC_APP) { // implementation ... return false; @@ -176,17 +147,25 @@ private: template XT, std::derived_from YT> - pz_duration_t timeToImpl(const XT&, const YT&, traits::mcc_systime_c auto const&) + pz_duration_t timeTo(const XT& x, + const YT& y, + traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) { return pz_duration_t{std::numeric_limits::infinity()}; } template XT, std::derived_from YT> - pz_duration_t timeFromImpl(const XT&, const YT&, traits::mcc_systime_c auto const&) + pz_duration_t timeFrom(const XT& x, + const YT& y, + traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) { return pz_duration_t{0.0}; } + +private: + MccAngle _altLimit; }; + } // namespace mcc diff --git a/cxx/tests/mount.cpp b/cxx/tests/mount.cpp index 8437bc7..a4c49c6 100644 --- a/cxx/tests/mount.cpp +++ b/cxx/tests/mount.cpp @@ -1,3 +1,5 @@ +#include + #include "../mcc_mount.h" #include "../mcc_mount_events_states.h" @@ -7,9 +9,12 @@ int tests_mount(int, char**) using mount_t = MccMount, MccMountTelemetry>; - mount_t mount(MccMountStateIDLE{}); + auto logger = spdlog::stdout_color_mt("MOUNT"); + logger->set_level(spdlog::level::debug); + mount_t mount(MccMountStateIDLE{}, logger); + mount.dispatchEvent(MccMountEventInit{mount}); return 0; }