FSM ...
This commit is contained in:
parent
4244f76041
commit
156dfb13ba
@ -125,7 +125,8 @@ add_library(${CNTR_PROTO_LIB} STATIC ${CNTR_PROTO_LIB_SRC})
|
||||
set(MOUNT_SERVER_APP_SRC mount.h mount_state.h mount_server.cpp comm_server.h comm_server_endpoint.h comm_server_configfile.h mount_astrom.h
|
||||
mount_astrom_default.h mcc_coord.h mount_pz.h)
|
||||
set(MOUNT_SERVER_APP mount_server)
|
||||
add_executable(${MOUNT_SERVER_APP} ${MOUNT_SERVER_APP_SRC})
|
||||
add_executable(${MOUNT_SERVER_APP} ${MOUNT_SERVER_APP_SRC}
|
||||
mcc_fsm.h)
|
||||
# target_include_directories(${MOUNT_SERVER_APP} PUBLIC ${ERFA_INCLUDE_DIR})
|
||||
target_link_libraries(${MOUNT_SERVER_APP} ${CNTR_PROTO_LIB} spdlog::spdlog_header_only ERFA_LIB)
|
||||
|
||||
@ -147,5 +148,9 @@ if (WITH_TESTS)
|
||||
add_executable(${FITPACK_TEST_APP} tests/fitpack_test.cpp)
|
||||
target_link_libraries(${FITPACK_TEST_APP} fitpack)
|
||||
target_include_directories(${FITPACK_TEST_APP} PRIVATE ${FITPACK_INCLUDE_DIR})
|
||||
message(STATUS "INC UP: " ${FITPACK_INCLUDE_DIR})
|
||||
# message(STATUS "INC UP: " ${FITPACK_INCLUDE_DIR})
|
||||
|
||||
set(FSM_TEST_APP fsm_test)
|
||||
add_executable(${FSM_TEST_APP} tests/fsm_test.cpp)
|
||||
|
||||
endif()
|
||||
|
||||
243
cxx/mcc_fsm.h
Normal file
243
cxx/mcc_fsm.h
Normal file
@ -0,0 +1,243 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
||||
|
||||
/* FINITE-STATE MACHINE IMPLEMENTATION */
|
||||
|
||||
|
||||
#include <limits>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
namespace traits
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
concept std_pair_c = requires(T t) {
|
||||
[]<typename T1, typename T2>(std::type_identity<std::pair<T1, T2>>) {
|
||||
|
||||
}(std::type_identity<std::remove_cvref_t<T>>());
|
||||
};
|
||||
|
||||
|
||||
} // namespace traits
|
||||
|
||||
|
||||
namespace fsm
|
||||
{
|
||||
|
||||
/* A TYPE TO HOLD COMPILE-TIME SEQUENCE OF std::pair */
|
||||
template <traits::std_pair_c... pairs>
|
||||
struct pair_holder_t;
|
||||
|
||||
template <traits::std_pair_c head, traits::std_pair_c... tail>
|
||||
struct pair_holder_t<head, tail...> {
|
||||
// using self_t = pair_holder_t<head, tail...>;
|
||||
// using self_data_t = std::tuple<head, tail...>;
|
||||
typedef pair_holder_t<head, tail...> self_t;
|
||||
typedef std::tuple<head, tail...> sequence_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct pair_holder_t<> {
|
||||
// using self_data_t = std::tuple<>;
|
||||
typedef std::tuple<> sequence_t;
|
||||
constexpr static bool valid = true;
|
||||
};
|
||||
|
||||
} // namespace fsm
|
||||
|
||||
|
||||
namespace traits
|
||||
{
|
||||
template <typename T>
|
||||
concept pair_holder_c = requires {
|
||||
[]<mcc::traits::std_pair_c... Ts>(std::type_identity<fsm::pair_holder_t<Ts...>>) {
|
||||
//
|
||||
}(std::type_identity<std::remove_cvref_t<T>>());
|
||||
};
|
||||
|
||||
} // namespace traits
|
||||
|
||||
|
||||
namespace fsm
|
||||
{
|
||||
|
||||
/* A CLASS TO FIND TYPE OF pair.second ELEMENT BY ITS pair.first one IN PAIR-SEQUENCE */
|
||||
|
||||
template <typename FirstT, traits::pair_holder_c PHLDT>
|
||||
struct pair_holder_find_t;
|
||||
|
||||
template <typename FirstT, typename CurrentFirstT, typename SecondT, mcc::traits::std_pair_c... tail>
|
||||
struct pair_holder_find_t<FirstT, pair_holder_t<std::pair<CurrentFirstT, SecondT>, tail...>>
|
||||
: pair_holder_find_t<FirstT, pair_holder_t<tail...>> {
|
||||
};
|
||||
|
||||
template <typename FirstT>
|
||||
struct pair_holder_find_t<FirstT, pair_holder_t<>> {
|
||||
typedef std::nullptr_t result_t;
|
||||
};
|
||||
|
||||
template <typename FirstT, typename SecondT, mcc::traits::std_pair_c... tail>
|
||||
struct pair_holder_find_t<FirstT, pair_holder_t<std::pair<FirstT, SecondT>, tail...>> {
|
||||
typedef SecondT result_t;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* A CLASS TO GET ALL pair.first TYPES IN PAIR-SEQUENCE */
|
||||
|
||||
template <traits::pair_holder_c PHLDT>
|
||||
struct pair_holder_first_t;
|
||||
|
||||
template <typename FirstT, typename SecondT, mcc::traits::std_pair_c... tail>
|
||||
struct pair_holder_first_t<pair_holder_t<std::pair<FirstT, SecondT>, tail...>> {
|
||||
typedef decltype(std::tuple_cat(
|
||||
std::declval<std::tuple<FirstT>>(),
|
||||
std::declval<typename pair_holder_first_t<pair_holder_t<tail...>>::first_t>())) first_t;
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct pair_holder_first_t<pair_holder_t<>> {
|
||||
typedef std::tuple<> first_t;
|
||||
};
|
||||
|
||||
|
||||
/* A CLASS TO GET ALL pair.second TYPES IN PAIR-SEQUENCE */
|
||||
|
||||
template <traits::pair_holder_c PHLDT>
|
||||
struct pair_holder_second_t;
|
||||
|
||||
template <typename FirstT, typename SecondT, mcc::traits::std_pair_c... tail>
|
||||
struct pair_holder_second_t<pair_holder_t<std::pair<FirstT, SecondT>, tail...>> {
|
||||
typedef decltype(std::tuple_cat(
|
||||
std::declval<std::tuple<SecondT>>(),
|
||||
std::declval<typename pair_holder_second_t<pair_holder_t<tail...>>::second_t>())) second_t;
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct pair_holder_second_t<pair_holder_t<>> {
|
||||
typedef std::tuple<> second_t;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* A TYPE TO IMPLEMENT TUPLE OF UNIQUE TYPES */
|
||||
|
||||
template <typename... TYPEs>
|
||||
class unique_tuple_t
|
||||
{
|
||||
template <typename IT, typename UniqTupleT>
|
||||
struct in_tuple : in_tuple<IT, typename UniqTupleT::tuple_t> {
|
||||
};
|
||||
|
||||
template <typename IT, typename... Ts>
|
||||
struct in_tuple<IT, std::tuple<Ts...>> : std::disjunction<std::is_same<IT, Ts>...> {
|
||||
};
|
||||
|
||||
// insert
|
||||
template <typename IT, typename UniqTupleT, bool = in_tuple<IT, UniqTupleT>::value>
|
||||
struct insert;
|
||||
|
||||
template <typename IT, typename... Ts>
|
||||
struct insert<IT, std::tuple<Ts...>, false> {
|
||||
typedef std::tuple<IT, Ts...> tuple_t;
|
||||
typedef std::tuple<> non_unique_t;
|
||||
};
|
||||
|
||||
template <typename IT, typename... Ts>
|
||||
struct insert<IT, std::tuple<Ts...>, true> {
|
||||
typedef std::tuple<Ts...> tuple_t;
|
||||
typedef std::tuple<IT> non_unique_t;
|
||||
};
|
||||
|
||||
|
||||
// merge
|
||||
template <typename ITupleT, typename OTupleT>
|
||||
struct merge;
|
||||
|
||||
template <typename MT, typename... MTs, typename... OTs>
|
||||
struct merge<std::tuple<MT, MTs...>, std::tuple<OTs...>> {
|
||||
typedef merge<std::tuple<MTs...>, std::tuple<OTs...>> tail_t;
|
||||
typedef insert<MT, typename tail_t::tuple_t> curr_tuple_t;
|
||||
|
||||
typedef typename curr_tuple_t::tuple_t tuple_t;
|
||||
typedef decltype(std::tuple_cat(std::declval<typename curr_tuple_t::non_unique_t>(),
|
||||
std::declval<typename tail_t::non_unique_t>())) non_unique_t;
|
||||
};
|
||||
|
||||
template <typename... MTs>
|
||||
struct merge<std::tuple<>, std::tuple<MTs...>> {
|
||||
typedef std::tuple<MTs...> tuple_t;
|
||||
typedef std::tuple<> non_unique_t;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename merge<std::tuple<TYPEs...>, std::tuple<>>::tuple_t tuple_t;
|
||||
typedef typename merge<std::tuple<TYPEs...>, std::tuple<>>::non_unique_t non_unique_t;
|
||||
};
|
||||
|
||||
} // namespace fsm
|
||||
|
||||
|
||||
namespace traits
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
concept unique_tuple_c = requires {
|
||||
[]<typename... Ts>(std::type_identity<fsm::unique_tuple_t<Ts...>>) {}(std::type_identity<std::remove_cvref_t<T>>());
|
||||
};
|
||||
|
||||
} // namespace traits
|
||||
|
||||
|
||||
namespace fsm
|
||||
{
|
||||
|
||||
// GET INDEX OF GIVEN TYPE IN UNIQUE TUPLE
|
||||
namespace details
|
||||
{
|
||||
|
||||
// template <typename T, mcc::traits::unique_tuple_c UT, std::size_t I = 0>
|
||||
template <typename T, typename TupleT, std::size_t I = 0>
|
||||
struct unique_tuple_type_index_helper_t;
|
||||
|
||||
|
||||
template <typename T, typename HeadT, typename... TailT, std::size_t I>
|
||||
struct unique_tuple_type_index_helper_t<T, std::tuple<HeadT, TailT...>, I> {
|
||||
constexpr static std::size_t index = unique_tuple_type_index_helper_t<T, std::tuple<TailT...>, I + 1>::index;
|
||||
};
|
||||
|
||||
|
||||
template <typename T, typename... TailT, std::size_t I>
|
||||
struct unique_tuple_type_index_helper_t<T, std::tuple<T, TailT...>, I> {
|
||||
constexpr static std::size_t index = I;
|
||||
};
|
||||
|
||||
template <typename T, std::size_t I>
|
||||
struct unique_tuple_type_index_helper_t<T, std::tuple<>, I> {
|
||||
constexpr static std::size_t index = std::numeric_limits<std::size_t>::max();
|
||||
static_assert(false, "INVALID INPUT TYPE!");
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
|
||||
template <typename T, mcc::traits::unique_tuple_c UT>
|
||||
struct unique_tuple_type_index_t : details::unique_tuple_type_index_helper_t<T, typename UT::tuple_t, 0> {
|
||||
};
|
||||
|
||||
template <typename T, mcc::traits::unique_tuple_c UT>
|
||||
constexpr static std::size_t unique_tuple_type_index_v = unique_tuple_type_index_t<T, typename UT::tuple_t>::index;
|
||||
|
||||
} // namespace fsm
|
||||
|
||||
|
||||
} // namespace mcc
|
||||
@ -278,7 +278,7 @@ public:
|
||||
|
||||
virtual ~MccMountState()
|
||||
{
|
||||
_mount.logTrace("Delete MccMountState instance: {}", (void)this);
|
||||
_mount.logTrace("Delete MccMountState instance: {}", (void*)this);
|
||||
};
|
||||
|
||||
|
||||
|
||||
41
cxx/tests/fsm_test.cpp
Normal file
41
cxx/tests/fsm_test.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include <iostream>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "../mcc_fsm.h"
|
||||
|
||||
struct S {
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace mcc;
|
||||
|
||||
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<int, ut_t>::index << " (int)\n";
|
||||
std::cout << "type index: " << fsm::unique_tuple_type_index_t<long, ut_t>::index << " (long)\n";
|
||||
// std::cout << "type index: " << fsm::unique_tuple_type_index_t<S, ut_t>::index << " (struct S)\n";
|
||||
|
||||
std::cout << typeid(ut_t::tuple_t).name() << "\n";
|
||||
std::cout << typeid(ut_t::non_unique_t).name() << "\n";
|
||||
|
||||
|
||||
typedef fsm::pair_holder_t<std::pair<int, long>, std::pair<float, double>, std::pair<char, char*>> ph_t;
|
||||
|
||||
// using s_t = fsm::pair_holder_find_t<float, ph_t>::result_t;
|
||||
using s_t = fsm::pair_holder_find_t<S, ph_t>::result_t;
|
||||
if constexpr (std::is_null_pointer_v<s_t>) {
|
||||
std::cout << "second type: invalid input type!\n";
|
||||
} else {
|
||||
std::cout << "second type: " << typeid(s_t).name() << "\n";
|
||||
}
|
||||
|
||||
using t1_t = fsm::pair_holder_first_t<ph_t>::first_t;
|
||||
std::cout << "first types: " << typeid(t1_t).name() << "\n";
|
||||
|
||||
using t2_t = fsm::pair_holder_second_t<ph_t>::second_t;
|
||||
std::cout << "second types: " << typeid(t2_t).name() << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user