This commit is contained in:
Timur A. Fatkhullin 2025-06-17 00:46:13 +03:00
parent 64a3544bd8
commit 02afd65d6f
5 changed files with 69 additions and 60 deletions

View File

@ -317,7 +317,7 @@ protected:
std::vector<std::string_view> _stateID{};
std::vector<std::string_view> _eventID{};
std::mutex _transitionMutex{};
std::recursive_mutex _transitionMutex{};
static MccFiniteStateMachine& copyInstance(const MccFiniteStateMachine* from, MccFiniteStateMachine* to)
@ -385,18 +385,23 @@ public:
[states, currentState, this]<size_t... Is>(std::index_sequence<Is...>) {
((_dispatchEventFunc<std::tuple_element_t<Is, all_events_t>>[this] =
[states, currentState, this]<traits::fsm_event_c EvT>(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]<traits::fsm_state_c curr_state_t>(curr_state_t*) {
[p_event, states, currentState, this]<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>) {
std::lock_guard lock(_transitionMutex);
// exit from current
if constexpr (requires(curr_state_t inst) {
{ inst.exit(std::declval<EvT&>()) };
}) {
std::get<curr_state_t>(*states).exit(event);
// std::get<curr_state_t>(*states).exit(event);
std::get<curr_state_t>(*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<to_state_t>(*states);
@ -417,7 +423,8 @@ public:
if constexpr (requires(to_state_t inst) {
{ inst.enter(std::declval<EvT&>()) };
}) {
std::get<to_state_t>(*states).enter(event);
// std::get<to_state_t>(*states).enter(event);
std::get<to_state_t>(*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<Is, all_events_t>::ID), ...);
}(std::make_index_sequence<std::tuple_size_v<all_events_t>>());
// call enter() method (if it exists) of the initial state
std::visit(
[]<traits::fsm_state_c curr_state_t>(curr_state_t* cstate) {
if constexpr (requires(curr_state_t inst) {
{ inst.enter() };
}) {
cstate->enter();
}
},
*currentState);
}
MccFiniteStateMachine(const MccFiniteStateMachine& other)

View File

@ -155,13 +155,17 @@ public:
template <fsm::traits::fsm_state_c InitStateT, traits::mcc_input_char_range LogMarkT = std::string_view>
MccMount(InitStateT,
const LogMarkT& logger_mark = "[MOUNT]",
std::shared_ptr<spdlog::logger> logger = spdlog::null_logger_mt("NULL"))
std::shared_ptr<spdlog::logger> 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() {}

View File

@ -318,7 +318,7 @@ struct MccMountStateInit : MccMountStateBase<MountT> {
{
this->enterLog(event);
auto mount = event.mount();
MountT& mount = event.mount();
mount.initMount();
// switch to IDLE state
@ -403,13 +403,13 @@ struct MccMountStateIDLE : MccMountStateBase<MountT> {
std::pair<MccMountEventStop<MountT>, MccMountStateIDLE<MountT>>,
std::pair<MccMountEventShutdown<MountT>, MccMountStateShutdown<MountT>>>;
template <std::derived_from<MccMountStateBase<MountT>> EvT>
template <std::derived_from<MccMountEventBase<MountT>> EvT>
void exit(EvT& event)
{
this->exitLog(event);
}
template <std::derived_from<MccMountStateBase<MountT>> EvT>
template <std::derived_from<MccMountEventBase<MountT>> EvT>
void enter(EvT& event)
{
this->enterLog(event);

View File

@ -39,53 +39,47 @@ public:
// check if given position (x,y) in the zone
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> 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<decltype(self)>(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 <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> 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<decltype(self)>(self).timeToImpl(x, y, utc);
return pz_duration_t{std::numeric_limits<double>::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 <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> 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<decltype(self)>(self).timeFromImpl(x, y, utc);
return pz_duration_t{0.0};
}
// all-in-one request (call three methods above)
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> 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_t>(self).inZone(x, y, utc);
if (res.in_zone) {
res.time_from = timeFrom(x, y, utc);
res.time_from = std::forward<self_t>(self).timeFrom(x, y, utc);
} else {
res.time_to = timeFrom(x, y, utc);
res.time_to = std::forward<self_t>(self).timeTo(x, y, utc);
}
return res;
@ -95,30 +89,10 @@ protected:
MccProhibitedZone(std::string_view name) : _name(name) {}
std::string_view _name;
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
bool inZoneImpl(const XT&, const YT&, traits::mcc_systime_c auto const&)
{
return false;
}
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
pz_duration_t timeToImpl(const XT&, const YT&, traits::mcc_systime_c auto const&)
{
return pz_duration_t{std::numeric_limits<double>::infinity()};
}
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> 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<MccAngle::NORM_KIND_90_90>();
}
private:
MccAngle _altLimit;
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> 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<XT, YT>();
@ -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 <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> 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<double>::infinity()};
}
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> 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

View File

@ -1,3 +1,5 @@
#include <spdlog/sinks/stdout_color_sinks.h>
#include "../mcc_mount.h"
#include "../mcc_mount_events_states.h"
@ -7,9 +9,12 @@ int tests_mount(int, char**)
using mount_t = MccMount<MccMountConfig<MccMountType::CROSSAXIS_TYPE>, MccMountTelemetry>;
mount_t mount(MccMountStateIDLE<mount_t>{});
auto logger = spdlog::stdout_color_mt("MOUNT");
logger->set_level(spdlog::level::debug);
mount_t mount(MccMountStateIDLE<mount_t>{}, logger);
mount.dispatchEvent(MccMountEventInit<mount_t>{mount});
return 0;
}