...
This commit is contained in:
parent
52a29e0f91
commit
d502796d6b
@ -12,6 +12,8 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
|
#include "mcc_traits.h"
|
||||||
|
|
||||||
namespace mcc::fsm
|
namespace mcc::fsm
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -230,14 +232,14 @@ protected:
|
|||||||
|
|
||||||
template <typename ResTplT, traits::fsm_state_c... StTs, typename... InTplTs>
|
template <typename ResTplT, traits::fsm_state_c... StTs, typename... InTplTs>
|
||||||
struct deduce_states<false, ResTplT, std::tuple<StTs...>, InTplTs...> {
|
struct deduce_states<false, ResTplT, std::tuple<StTs...>, InTplTs...> {
|
||||||
// using curr_collection_t = merge_tuples_t<ResTplT, std::tuple<StTs...>>;
|
using curr_collection_t = merge_tuples_t<ResTplT, std::tuple<StTs...>>;
|
||||||
using curr_collection_t =
|
// using curr_collection_t =
|
||||||
merge_tuples_t<ResTplT, std::tuple<StTs...>, typename StTs::transition_t::unique_states_t...>;
|
// merge_tuples_t<ResTplT, std::tuple<StTs...>, typename StTs::transition_t::unique_states_t...>;
|
||||||
|
|
||||||
using states_t = typename deduce_states<std::tuple_size_v<ResTplT> == std::tuple_size_v<curr_collection_t>,
|
using states_t = typename deduce_states<std::tuple_size_v<ResTplT> == std::tuple_size_v<curr_collection_t>,
|
||||||
curr_collection_t,
|
curr_collection_t,
|
||||||
// merge_tuples_t<typename StTs::transition_t::unique_states_t...>,
|
merge_tuples_t<typename StTs::transition_t::unique_states_t...>,
|
||||||
typename StTs::transition_t::unique_states_t...,
|
// typename StTs::transition_t::unique_states_t...,
|
||||||
InTplTs...>::states_t;
|
InTplTs...>::states_t;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -336,9 +338,44 @@ protected:
|
|||||||
std::vector<std::function<void(const MccFiniteStateMachine*)>> _destroyFunc{};
|
std::vector<std::function<void(const MccFiniteStateMachine*)>> _destroyFunc{};
|
||||||
|
|
||||||
std::string_view _currentStateID;
|
std::string_view _currentStateID;
|
||||||
|
std::vector<std::string_view> _stateID;
|
||||||
|
std::vector<std::string_view> _eventID;
|
||||||
|
|
||||||
std::mutex _transitionMutex;
|
std::mutex _transitionMutex;
|
||||||
|
|
||||||
|
|
||||||
|
template <traits::fsm_tuple_of_events_c EvTplT, typename FT, size_t... Is>
|
||||||
|
void setupInstanceFuncs(FT&& func, std::index_sequence<Is...>)
|
||||||
|
{
|
||||||
|
((_dispatchEventFunc<std::tuple_element_t<Is, EvTplT>>[this] = std::forward<FT>(func)), ...);
|
||||||
|
|
||||||
|
(_moveFunc.emplace_back([](MccFiniteStateMachine* from, MccFiniteStateMachine* to) {
|
||||||
|
_dispatchEventFunc<std::tuple_element_t<Is, EvTplT>>[to] =
|
||||||
|
std::move(_dispatchEventFunc<std::tuple_element_t<Is, EvTplT>>[from]);
|
||||||
|
}),
|
||||||
|
...);
|
||||||
|
|
||||||
|
(_copyFunc.emplace_back([](const MccFiniteStateMachine* from, MccFiniteStateMachine* to) {
|
||||||
|
_dispatchEventFunc<std::tuple_element_t<Is, EvTplT>>[to] =
|
||||||
|
_dispatchEventFunc<std::tuple_element_t<Is, EvTplT>>[from];
|
||||||
|
}),
|
||||||
|
...);
|
||||||
|
|
||||||
|
(_destroyFunc.emplace_back([](const MccFiniteStateMachine* inst) {
|
||||||
|
//
|
||||||
|
_dispatchEventFunc<std::tuple_element_t<Is, EvTplT>>.erase(inst);
|
||||||
|
}),
|
||||||
|
...);
|
||||||
|
|
||||||
|
(_eventID.emplace_back(std::tuple_element_t<Is, EvTplT>::ID), ...);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <traits::fsm_tuple_of_events_c EvTplT, typename FT>
|
||||||
|
void setupInstanceFuncs(FT&& func)
|
||||||
|
{
|
||||||
|
setupInstanceFuncs<EvTplT>(std::forward<FT>(func), std::make_index_sequence<std::tuple_size_v<EvTplT>>());
|
||||||
|
};
|
||||||
|
|
||||||
static MccFiniteStateMachine& copyInstance(const MccFiniteStateMachine* from, MccFiniteStateMachine* to)
|
static MccFiniteStateMachine& copyInstance(const MccFiniteStateMachine* from, MccFiniteStateMachine* to)
|
||||||
{
|
{
|
||||||
if (from != to) {
|
if (from != to) {
|
||||||
@ -381,6 +418,10 @@ public:
|
|||||||
auto currentState = std::make_shared<variant_from_tuple_t<states_t>>();
|
auto currentState = std::make_shared<variant_from_tuple_t<states_t>>();
|
||||||
*currentState = &std::get<InitStateT>(*states);
|
*currentState = &std::get<InitStateT>(*states);
|
||||||
|
|
||||||
|
_stateID = []<typename... STs>(std::tuple<STs...>&) {
|
||||||
|
return std::vector<std::string_view>({STs::ID...});
|
||||||
|
}(*states);
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
char* aa = abi::__cxa_demangle(typeid(states_t).name(), NULL, NULL, &status);
|
char* aa = abi::__cxa_demangle(typeid(states_t).name(), NULL, NULL, &status);
|
||||||
std::cout << "deduced states_t = " << aa << '\n';
|
std::cout << "deduced states_t = " << aa << '\n';
|
||||||
@ -409,6 +450,10 @@ public:
|
|||||||
// setup dispatch event functions
|
// setup dispatch event functions
|
||||||
|
|
||||||
using all_events_t = deduce_events_t<InitStateT>;
|
using all_events_t = deduce_events_t<InitStateT>;
|
||||||
|
|
||||||
|
// for_each_event<all_events_t>([this]<traits::fsm_event_c EvT>(EvT) { _eventID.emplace_back(EvT::ID); });
|
||||||
|
|
||||||
|
/*
|
||||||
for_each_event<all_events_t>([states, currentState, this]<traits::fsm_event_c EvT>(EvT) mutable {
|
for_each_event<all_events_t>([states, currentState, this]<traits::fsm_event_c EvT>(EvT) mutable {
|
||||||
if constexpr (!in_tuple_v<EvT, all_events_t>) {
|
if constexpr (!in_tuple_v<EvT, all_events_t>) {
|
||||||
throw std::system_error(MccFiniteStateMachineErrorCode::ERROR_UNREGISTERED_EVENT_TYPE);
|
throw std::system_error(MccFiniteStateMachineErrorCode::ERROR_UNREGISTERED_EVENT_TYPE);
|
||||||
@ -470,6 +515,52 @@ public:
|
|||||||
_dispatchEventFunc<EvT>.erase(inst);
|
_dispatchEventFunc<EvT>.erase(inst);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
setupInstanceFuncs<all_events_t>([states, currentState, this]<traits::fsm_event_c EvT>(EvT& event) mutable {
|
||||||
|
std::lock_guard lock(_transitionMutex);
|
||||||
|
|
||||||
|
std::visit(
|
||||||
|
[&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>) {
|
||||||
|
// 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.onTransit() };
|
||||||
|
}) {
|
||||||
|
event.onTransit();
|
||||||
|
}
|
||||||
|
|
||||||
|
*currentState = &std::get<to_state_t>(*states);
|
||||||
|
_currentStateID = to_state_t::ID;
|
||||||
|
|
||||||
|
// enter to new
|
||||||
|
if constexpr (requires(to_state_t inst) {
|
||||||
|
{ inst.enter(std::declval<EvT&>()) };
|
||||||
|
}) {
|
||||||
|
std::get<to_state_t>(*states).enter(event);
|
||||||
|
} else if constexpr (requires(to_state_t inst) {
|
||||||
|
{ inst.enter() };
|
||||||
|
}) {
|
||||||
|
std::get<to_state_t>(*states).enter();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw std::system_error(MccFiniteStateMachineErrorCode::ERROR_UNHANDLED_TRANSITION);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
*currentState);
|
||||||
|
});
|
||||||
|
|
||||||
std::cout << "MOVE VEC: " << _moveFunc.size() << "\n";
|
std::cout << "MOVE VEC: " << _moveFunc.size() << "\n";
|
||||||
}
|
}
|
||||||
@ -518,6 +609,40 @@ public:
|
|||||||
{
|
{
|
||||||
return _currentStateID;
|
return _currentStateID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <mcc::traits::mcc_range_of_input_char_range R>
|
||||||
|
R stateIDs() const
|
||||||
|
{
|
||||||
|
R r;
|
||||||
|
for (auto& el : _stateID) {
|
||||||
|
std::back_inserter(r) = {el.begin(), el.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string_view> stateIDs() const
|
||||||
|
{
|
||||||
|
return stateIDs<std::vector<std::string_view>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <mcc::traits::mcc_range_of_input_char_range R>
|
||||||
|
R eventIDs() const
|
||||||
|
{
|
||||||
|
R r;
|
||||||
|
for (auto& el : _eventID) {
|
||||||
|
std::back_inserter(r) = {el.begin(), el.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string_view> eventIDs() const
|
||||||
|
{
|
||||||
|
return eventIDs<std::vector<std::string_view>>();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -32,6 +32,11 @@ concept mcc_range_of_input_char_range =
|
|||||||
std::ranges::range<R> && traits::mcc_input_char_range<std::ranges::range_value_t<R>>;
|
std::ranges::range<R> && traits::mcc_input_char_range<std::ranges::range_value_t<R>>;
|
||||||
|
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
concept mcc_range_of_output_char_range =
|
||||||
|
std::ranges::range<R> && traits::mcc_output_char_range<std::ranges::range_value_t<R>>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/72430369/how-to-check-that-a-type-is-formattable-using-type-traits-concepts)
|
// https://stackoverflow.com/questions/72430369/how-to-check-that-a-type-is-formattable-using-type-traits-concepts)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
@ -138,6 +138,18 @@ int main()
|
|||||||
|
|
||||||
fsm::MccFiniteStateMachine fsmach(ST1{});
|
fsm::MccFiniteStateMachine fsmach(ST1{});
|
||||||
|
|
||||||
|
std::cout << "STATES: ";
|
||||||
|
for (auto& el : fsmach.stateIDs()) {
|
||||||
|
std::cout << std::quoted(el) << " ";
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
|
|
||||||
|
std::cout << "EVENTS: ";
|
||||||
|
for (auto& el : fsmach.eventIDs()) {
|
||||||
|
std::cout << std::quoted(el) << " ";
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
|
|
||||||
fsmach.dispatchEvent<EV1>();
|
fsmach.dispatchEvent<EV1>();
|
||||||
// fsmach.dispatchEvent<EV1>();
|
// fsmach.dispatchEvent<EV1>();
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user