diff --git a/cxx/mcc_finite_state_machine.h b/cxx/mcc_finite_state_machine.h index 713d530..06419f3 100644 --- a/cxx/mcc_finite_state_machine.h +++ b/cxx/mcc_finite_state_machine.h @@ -1,7 +1,11 @@ #pragma once +#include +#include + #include #include +#include #include #include #include @@ -22,11 +26,15 @@ concept fsm_event_c = std::is_default_constructible_v && std::is_move_constru /* - The only requirement to State-class is public-accepted static constant 'ID' + The only requirements to State-class is public-accepted static constant 'ID' and + definition of type transition_table_t */ template -concept fsm_state_c = std::is_default_constructible_v && std::is_move_constructible_v && std::movable && - requires { requires std::same_as; }; +concept fsm_state_c = + std::is_default_constructible_v && std::is_move_constructible_v && std::movable && requires { + requires std::same_as; + typename T::transition_t; + }; // concept for std::pair @@ -40,6 +48,9 @@ concept fsm_tuple_of_pairs_c = requires { [](std::type_identity>) {}(std::type_identity()); }; +template +concept fsm_tuple_of_events_c = + requires { [](std::type_identity>) {}(std::type_identity()); }; } // namespace traits @@ -54,9 +65,9 @@ struct fsm_transition_table_t { using event_state_pair_t = PT; - using unique_states = std::tuple; + using unique_states_t = std::tuple; - template + template using find_state_by_event_t = std::conditional_t, typename PT::second_type, void>; }; @@ -81,7 +92,7 @@ public: std::declval>(), std::declval::event_state_pair_t>()))>; - using unique_states = std::conditional_t< + using unique_states_t = std::conditional_t< non_unique_event, typename fsm_transition_table_t::unique_states_t, std::conditional_t<(std::same_as || ...), @@ -107,8 +118,9 @@ private: }; public: - template - using find_state_by_event_t = typename find_state_by_event::state_t; + // template + template + using find_state_by_event_t = typename find_state_by_event::state_t; }; @@ -145,7 +157,7 @@ protected: }; template - using merge_tuples_t = typename merge_tuples::res_t; + using merge_tuples_t = typename merge_tuples::result_t; // deduce all unique states from the initial one @@ -164,12 +176,50 @@ protected: using states_t = typename deduce_states == std::tuple_size_v, curr_collection_t, - typename StTs::transition_t::unique_states_t...>::states_t; + typename StTs::transition_t::unique_states_t..., + InTplTs...>::states_t; }; template using deduce_states_t = typename deduce_states, std::tuple>::states_t; + + // deduce all unique events from the initial state transition table + template + struct deduce_events; + + template + struct deduce_events { + using events_t = ResTplT; + }; + + template + struct deduce_events> { + using curr_collection_t = typename StT::transition_t::events_t; + using events_t = typename deduce_states::events_t; + }; + + template + struct deduce_events, InTplTs...> { + using curr_collection_t = merge_tuples_t; + + using events_t = typename deduce_states == std::tuple_size_v, + curr_collection_t, + typename StTs::transition_t::events_t..., + typename StTs::transition_t::unique_states_t...>::events_t; + }; + + template + using deduce_events_t = typename deduce_events::events_t; + // using deduce_events_t = typename deduce_events, std::tuple<>, + // std::tuple>::events_t; + template struct variant_from_tuple; @@ -182,13 +232,95 @@ protected: using variant_from_tuple_t = typename variant_from_tuple::variant_t; + // + template + static void for_each_event(FT&& func, std::index_sequence) + { + (func(std::get(EvTplT{})), ...); + }; + + template + static void for_each_event(FT&& func) + { + for_each_event(std::forward(func), std::make_index_sequence>()); + }; + + template - inline static std::unordered_map> _dispatchEventFunc{}; + inline static std::unordered_map> _dispatchEventFunc{}; public: template MccFiniteStateMachine(InitStateT) { + using states_t = deduce_states_t; + auto states = std::make_shared(); + + auto currentState = std::make_shared>(); + *currentState = &std::get(*states); + + int status; + char* aa = abi::__cxa_demangle(typeid(states_t).name(), NULL, NULL, &status); + std::cout << "states_t = " << aa << '\n'; + free(aa); + + /* + aa = abi::__cxa_demangle(typeid(deduce_events_t).name(), NULL, NULL, &status); + std::cout << "events_t = " << aa << '\n'; + free(aa); + + + // setup dispatch event functions + for_each_event>([states, currentState, this](EvT) { + _dispatchEventFunc[this] = [states, currentState, this](EvT& event) { + std::visit( + [&event, states](curr_state_t*) { + using to_state_t = curr_state_t::trasition_table_t::template find_state_by_event_t; + if constexpr (std::is_void_v) { + /// throw?!! + return; + } + + // 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(); + } + + // 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); + }; + }); + */ + } + + + template + auto dispatchEvent(EvT& event) + { + _dispatchEventFunc[this](event); } }; diff --git a/cxx/tests/fsm_test.cpp b/cxx/tests/fsm_test.cpp index 7d8eaf1..fded000 100644 --- a/cxx/tests/fsm_test.cpp +++ b/cxx/tests/fsm_test.cpp @@ -2,7 +2,8 @@ #include #include -#include "../mcc_fsm.h" +#include "../mcc_finite_state_machine.h" +// #include "../mcc_fsm.h" using namespace mcc; @@ -30,34 +31,52 @@ struct EV3 { struct ST1; struct ST2; -struct STN : fsm::MccFsmAbstractState { +struct STN { static constexpr std::string_view ID = "STN"; - using transition_t = trans_table_t, std::pair>; + using transition_t = fsm::fsm_transition_table_t, std::pair>; }; -struct ST3 : fsm::MccFsmAbstractState { +struct ST3 { static constexpr std::string_view ID = "ST3"; - using transition_t = trans_table_t, std::pair>; + using transition_t = fsm::fsm_transition_table_t, std::pair>; }; -struct ST2 : fsm::MccFsmAbstractState { +struct ST2 { static constexpr std::string_view ID = "ST2"; - using transition_t = trans_table_t, std::pair>; + using transition_t = fsm::fsm_transition_table_t, std::pair>; }; -struct ST1 : fsm::MccFsmAbstractState { +struct ST1 { static constexpr std::string_view ID = "ST1"; - using transition_t = trans_table_t, std::pair>; + using transition_t = fsm::fsm_transition_table_t, std::pair>; }; -// using tr_t = fsm::MccFsmAbstractState::trans_table_t>; +// struct STN : fsm::MccFsmAbstractState { +// static constexpr std::string_view ID = "STN"; +// using transition_t = trans_table_t, std::pair>; +// }; -// static_assert(fsm::traits::fsm_trans_table_c, "!!!!!!!!!!!!!"); +// struct ST3 : fsm::MccFsmAbstractState { +// static constexpr std::string_view ID = "ST3"; +// using transition_t = trans_table_t, std::pair>; +// }; -fsm::MccFiniteStateMachine fsm; +// struct ST2 : fsm::MccFsmAbstractState { +// static constexpr std::string_view ID = "ST2"; +// using transition_t = trans_table_t, std::pair>; +// }; + +// struct ST1 : fsm::MccFsmAbstractState { +// static constexpr std::string_view ID = "ST1"; +// using transition_t = trans_table_t, std::pair>; +// }; + + +// fsm::MccFiniteStateMachine fsm; int main() { + /* typedef fsm::unique_tuple_t ut_t; std::cout << "type index: " << fsm::unique_tuple_type_index_t::index << " (double)\n"; @@ -100,6 +119,11 @@ int main() aa = abi::__cxa_demangle(typeid(fsm::MccFiniteStateMachine::states_t).name(), NULL, NULL, &status); std::cout << "states = " << aa << "\n"; + free(aa); + + */ + + fsm::MccFiniteStateMachine(ST1{}); return 0; }