...
This commit is contained in:
parent
74b4cf06b1
commit
f4bd1ceee1
@ -1,7 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cxxabi.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <concepts>
|
#include <concepts>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@ -22,11 +26,15 @@ concept fsm_event_c = std::is_default_constructible_v<T> && 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 <typename T>
|
template <typename T>
|
||||||
concept fsm_state_c = std::is_default_constructible_v<T> && std::is_move_constructible_v<T> && std::movable<T> &&
|
concept fsm_state_c =
|
||||||
requires { requires std::same_as<const std::string_view, decltype(T::ID)>; };
|
std::is_default_constructible_v<T> && std::is_move_constructible_v<T> && std::movable<T> && requires {
|
||||||
|
requires std::same_as<const std::string_view, decltype(T::ID)>;
|
||||||
|
typename T::transition_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// concept for std::pair
|
// concept for std::pair
|
||||||
@ -40,6 +48,9 @@ concept fsm_tuple_of_pairs_c =
|
|||||||
requires { []<fsm_pair_of_types_c... PTs>(std::type_identity<std::tuple<PTs...>>) {}(std::type_identity<T>()); };
|
requires { []<fsm_pair_of_types_c... PTs>(std::type_identity<std::tuple<PTs...>>) {}(std::type_identity<T>()); };
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept fsm_tuple_of_events_c =
|
||||||
|
requires { []<fsm_event_c... EvTs>(std::type_identity<std::tuple<EvTs...>>) {}(std::type_identity<T>()); };
|
||||||
} // namespace traits
|
} // namespace traits
|
||||||
|
|
||||||
|
|
||||||
@ -54,9 +65,9 @@ struct fsm_transition_table_t<PT> {
|
|||||||
|
|
||||||
using event_state_pair_t = PT;
|
using event_state_pair_t = PT;
|
||||||
|
|
||||||
using unique_states = std::tuple<typename PT::second_type>;
|
using unique_states_t = std::tuple<typename PT::second_type>;
|
||||||
|
|
||||||
template <traits::fsm_event_c EvT>
|
template <typename EvT>
|
||||||
using find_state_by_event_t =
|
using find_state_by_event_t =
|
||||||
std::conditional_t<std::same_as<EvT, typename PT::first_type>, typename PT::second_type, void>;
|
std::conditional_t<std::same_as<EvT, typename PT::first_type>, typename PT::second_type, void>;
|
||||||
};
|
};
|
||||||
@ -81,7 +92,7 @@ public:
|
|||||||
std::declval<std::tuple<PT>>(),
|
std::declval<std::tuple<PT>>(),
|
||||||
std::declval<typename fsm_transition_table_t<PTs...>::event_state_pair_t>()))>;
|
std::declval<typename fsm_transition_table_t<PTs...>::event_state_pair_t>()))>;
|
||||||
|
|
||||||
using unique_states = std::conditional_t<
|
using unique_states_t = std::conditional_t<
|
||||||
non_unique_event,
|
non_unique_event,
|
||||||
typename fsm_transition_table_t<PTs...>::unique_states_t,
|
typename fsm_transition_table_t<PTs...>::unique_states_t,
|
||||||
std::conditional_t<(std::same_as<typename PT::second_type, typename PTs::second_type> || ...),
|
std::conditional_t<(std::same_as<typename PT::second_type, typename PTs::second_type> || ...),
|
||||||
@ -107,8 +118,9 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename EvT, traits::fsm_tuple_of_pairs_c TplT>
|
// template <typename EvT, traits::fsm_tuple_of_pairs_c TplT>
|
||||||
using find_state_by_event_t = typename find_state_by_event<EvT, TplT>::state_t;
|
template <typename EvT>
|
||||||
|
using find_state_by_event_t = typename find_state_by_event<EvT, event_state_pair_t>::state_t;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -145,7 +157,7 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename... TplTs>
|
template <typename... TplTs>
|
||||||
using merge_tuples_t = typename merge_tuples<TplTs...>::res_t;
|
using merge_tuples_t = typename merge_tuples<TplTs...>::result_t;
|
||||||
|
|
||||||
|
|
||||||
// deduce all unique states from the initial one
|
// deduce all unique states from the initial one
|
||||||
@ -164,12 +176,50 @@ protected:
|
|||||||
|
|
||||||
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,
|
||||||
typename StTs::transition_t::unique_states_t...>::states_t;
|
typename StTs::transition_t::unique_states_t...,
|
||||||
|
InTplTs...>::states_t;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <traits::fsm_state_c InitStateT>
|
template <traits::fsm_state_c InitStateT>
|
||||||
using deduce_states_t = typename deduce_states<false, std::tuple<>, std::tuple<InitStateT>>::states_t;
|
using deduce_states_t = typename deduce_states<false, std::tuple<>, std::tuple<InitStateT>>::states_t;
|
||||||
|
|
||||||
|
|
||||||
|
// deduce all unique events from the initial state transition table
|
||||||
|
template <bool stop, typename ResTplT, typename... InTplTs>
|
||||||
|
struct deduce_events;
|
||||||
|
|
||||||
|
template <typename ResTplT, typename... InTplTs>
|
||||||
|
struct deduce_events<true, ResTplT, InTplTs...> {
|
||||||
|
using events_t = ResTplT;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <traits::fsm_state_c StT>
|
||||||
|
struct deduce_events<false, typename StT::transition_t::events_t, std::tuple<>> {
|
||||||
|
using curr_collection_t = typename StT::transition_t::events_t;
|
||||||
|
using events_t = typename deduce_states<false,
|
||||||
|
curr_collection_t,
|
||||||
|
typename StT::transition_t::events_t,
|
||||||
|
typename StT::transition_t::unique_states_t>::events_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <traits::fsm_tuple_of_events_c ResTplT,
|
||||||
|
traits::fsm_tuple_of_events_c... EvTplTs,
|
||||||
|
traits::fsm_state_c... StTs,
|
||||||
|
typename... InTplTs>
|
||||||
|
struct deduce_events<false, ResTplT, EvTplTs..., std::tuple<StTs...>, InTplTs...> {
|
||||||
|
using curr_collection_t = merge_tuples_t<ResTplT, EvTplTs...>;
|
||||||
|
|
||||||
|
using events_t = typename deduce_states<std::tuple_size_v<ResTplT> == std::tuple_size_v<curr_collection_t>,
|
||||||
|
curr_collection_t,
|
||||||
|
typename StTs::transition_t::events_t...,
|
||||||
|
typename StTs::transition_t::unique_states_t...>::events_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <traits::fsm_state_c InitStateT>
|
||||||
|
using deduce_events_t = typename deduce_events<false, InitStateT>::events_t;
|
||||||
|
// using deduce_events_t = typename deduce_events<false, std::tuple<>, std::tuple<>,
|
||||||
|
// std::tuple<InitStateT>>::events_t;
|
||||||
|
|
||||||
template <typename TplT>
|
template <typename TplT>
|
||||||
struct variant_from_tuple;
|
struct variant_from_tuple;
|
||||||
|
|
||||||
@ -182,13 +232,95 @@ protected:
|
|||||||
using variant_from_tuple_t = typename variant_from_tuple<TplT>::variant_t;
|
using variant_from_tuple_t = typename variant_from_tuple<TplT>::variant_t;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
template <typename EvTplT, typename FT, size_t... Is>
|
||||||
|
static void for_each_event(FT&& func, std::index_sequence<Is...>)
|
||||||
|
{
|
||||||
|
(func(std::get<Is>(EvTplT{})), ...);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename EvTplT, typename FT>
|
||||||
|
static void for_each_event(FT&& func)
|
||||||
|
{
|
||||||
|
for_each_event<EvTplT>(std::forward<FT>(func), std::make_index_sequence<std::tuple_size_v<EvTplT>>());
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template <traits::fsm_event_c EvT>
|
template <traits::fsm_event_c EvT>
|
||||||
inline static std::unordered_map<const MccFiniteStateMachine*, std::function<void(EvT)>> _dispatchEventFunc{};
|
inline static std::unordered_map<const MccFiniteStateMachine*, std::function<void(EvT&)>> _dispatchEventFunc{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <traits::fsm_state_c InitStateT>
|
template <traits::fsm_state_c InitStateT>
|
||||||
MccFiniteStateMachine(InitStateT)
|
MccFiniteStateMachine(InitStateT)
|
||||||
{
|
{
|
||||||
|
using states_t = deduce_states_t<InitStateT>;
|
||||||
|
auto states = std::make_shared<states_t>();
|
||||||
|
|
||||||
|
auto currentState = std::make_shared<variant_from_tuple_t<states_t>>();
|
||||||
|
*currentState = &std::get<InitStateT>(*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<InitStateT>).name(), NULL, NULL, &status);
|
||||||
|
std::cout << "events_t = " << aa << '\n';
|
||||||
|
free(aa);
|
||||||
|
|
||||||
|
|
||||||
|
// setup dispatch event functions
|
||||||
|
for_each_event<deduce_events_t<InitStateT>>([states, currentState, this]<traits::fsm_event_c EvT>(EvT) {
|
||||||
|
_dispatchEventFunc<EvT>[this] = [states, currentState, this](EvT& event) {
|
||||||
|
std::visit(
|
||||||
|
[&event, states]<traits::fsm_state_c curr_state_t>(curr_state_t*) {
|
||||||
|
using to_state_t = curr_state_t::trasition_table_t::template find_state_by_event_t<EvT>;
|
||||||
|
if constexpr (std::is_void_v<to_state_t>) {
|
||||||
|
/// throw?!!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <traits::fsm_event_c EvT>
|
||||||
|
auto dispatchEvent(EvT& event)
|
||||||
|
{
|
||||||
|
_dispatchEventFunc<EvT>[this](event);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
#include "../mcc_fsm.h"
|
#include "../mcc_finite_state_machine.h"
|
||||||
|
// #include "../mcc_fsm.h"
|
||||||
|
|
||||||
using namespace mcc;
|
using namespace mcc;
|
||||||
|
|
||||||
@ -30,34 +31,52 @@ struct EV3 {
|
|||||||
struct ST1;
|
struct ST1;
|
||||||
struct ST2;
|
struct ST2;
|
||||||
|
|
||||||
struct STN : fsm::MccFsmAbstractState {
|
struct STN {
|
||||||
static constexpr std::string_view ID = "STN";
|
static constexpr std::string_view ID = "STN";
|
||||||
using transition_t = trans_table_t<std::pair<EV1, STN>, std::pair<EV2, ST2>>;
|
using transition_t = fsm::fsm_transition_table_t<std::pair<EV1, STN>, std::pair<EV2, ST2>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ST3 : fsm::MccFsmAbstractState {
|
struct ST3 {
|
||||||
static constexpr std::string_view ID = "ST3";
|
static constexpr std::string_view ID = "ST3";
|
||||||
using transition_t = trans_table_t<std::pair<EV1, ST1>, std::pair<EV2, ST2>>;
|
using transition_t = fsm::fsm_transition_table_t<std::pair<EV1, ST1>, std::pair<EV2, ST2>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ST2 : fsm::MccFsmAbstractState {
|
struct ST2 {
|
||||||
static constexpr std::string_view ID = "ST2";
|
static constexpr std::string_view ID = "ST2";
|
||||||
using transition_t = trans_table_t<std::pair<EV2, STN>, std::pair<EV3, ST3>>;
|
using transition_t = fsm::fsm_transition_table_t<std::pair<EV2, STN>, std::pair<EV3, ST3>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ST1 : fsm::MccFsmAbstractState {
|
struct ST1 {
|
||||||
static constexpr std::string_view ID = "ST1";
|
static constexpr std::string_view ID = "ST1";
|
||||||
using transition_t = trans_table_t<std::pair<EV1, ST2>, std::pair<EV2, STN>>;
|
using transition_t = fsm::fsm_transition_table_t<std::pair<EV1, ST2>, std::pair<EV2, STN>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// using tr_t = fsm::MccFsmAbstractState::trans_table_t<std::pair<EV1, ST1>>;
|
// struct STN : fsm::MccFsmAbstractState {
|
||||||
|
// static constexpr std::string_view ID = "STN";
|
||||||
|
// using transition_t = trans_table_t<std::pair<EV1, STN>, std::pair<EV2, ST2>>;
|
||||||
|
// };
|
||||||
|
|
||||||
// static_assert(fsm::traits::fsm_trans_table_c<tr_t>, "!!!!!!!!!!!!!");
|
// struct ST3 : fsm::MccFsmAbstractState {
|
||||||
|
// static constexpr std::string_view ID = "ST3";
|
||||||
|
// using transition_t = trans_table_t<std::pair<EV1, ST1>, std::pair<EV2, ST2>>;
|
||||||
|
// };
|
||||||
|
|
||||||
fsm::MccFiniteStateMachine<ST1> fsm;
|
// struct ST2 : fsm::MccFsmAbstractState {
|
||||||
|
// static constexpr std::string_view ID = "ST2";
|
||||||
|
// using transition_t = trans_table_t<std::pair<EV2, STN>, std::pair<EV3, ST3>>;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// struct ST1 : fsm::MccFsmAbstractState {
|
||||||
|
// static constexpr std::string_view ID = "ST1";
|
||||||
|
// using transition_t = trans_table_t<std::pair<EV1, ST2>, std::pair<EV2, STN>>;
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
// fsm::MccFiniteStateMachine<ST1> fsm;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
typedef fsm::unique_tuple_t<int, float, long, int, double, char, long> ut_t;
|
typedef fsm::unique_tuple_t<int, float, long, int, double, char, long> ut_t;
|
||||||
|
|
||||||
std::cout << "type index: " << fsm::unique_tuple_type_index_t<double, ut_t>::index << " (double)\n";
|
std::cout << "type index: " << fsm::unique_tuple_type_index_t<double, ut_t>::index << " (double)\n";
|
||||||
@ -100,6 +119,11 @@ int main()
|
|||||||
|
|
||||||
aa = abi::__cxa_demangle(typeid(fsm::MccFiniteStateMachine<ST1>::states_t).name(), NULL, NULL, &status);
|
aa = abi::__cxa_demangle(typeid(fsm::MccFiniteStateMachine<ST1>::states_t).name(), NULL, NULL, &status);
|
||||||
std::cout << "states = " << aa << "\n";
|
std::cout << "states = " << aa << "\n";
|
||||||
|
free(aa);
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
fsm::MccFiniteStateMachine(ST1{});
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user