diff --git a/CMakeLists.txt b/CMakeLists.txt index 0bf4cc2..e864b6b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,12 +6,6 @@ cmake_minimum_required(VERSION 3.5...3.16) project(boost_msm VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) -# Temporary settings for development, need to be cleaned up later. -# Required for testing puml frontend -# set(CMAKE_CXX_STANDARD 20) -# Required due to bug in clang19 -# add_compile_options("-Wno-missing-template-arg-list-after-template-kw") -# add_compile_options("-ftime-trace") add_library(boost_msm INTERFACE) add_library(Boost::msm ALIAS boost_msm) @@ -28,6 +22,7 @@ target_link_libraries(boost_msm Boost::core Boost::function Boost::fusion + Boost::mp11 Boost::mpl Boost::parameter Boost::phoenix diff --git a/build.jam b/build.jam index 619b840..d15ca60 100644 --- a/build.jam +++ b/build.jam @@ -14,6 +14,7 @@ constant boost_dependencies : /boost/core//boost_core /boost/function//boost_function /boost/fusion//boost_fusion + /boost/mp11//boost_mp11 /boost/mpl//boost_mpl /boost/parameter//boost_parameter /boost/phoenix//boost_phoenix diff --git a/include/boost/msm/backmp11/README.md b/include/boost/msm/backmp11/README.md index 0027a04..03ca514 100644 --- a/include/boost/msm/backmp11/README.md +++ b/include/boost/msm/backmp11/README.md @@ -30,7 +30,6 @@ When using the `favor_compile_time` policy, a different macro to generate missin Summary: - Optimized cell initialization with initializer arrays (to reduce template instantiations) - - TODO: double-check optimization - Default-initialized everything and afterwards only defer transition cells @@ -56,8 +55,3 @@ Summary: - If only a subset needs to be processed, prefer copy_if & transform over fold - Selecting a template-based function overload in Mp11 seems more efficient than using enable_if/disable_if - - -## TODOs: - -- Consider trying out the tuple impl from SML diff --git a/include/boost/msm/backmp11/dispatch_table.hpp b/include/boost/msm/backmp11/dispatch_table.hpp index 01b2df2..d8c5057 100644 --- a/include/boost/msm/backmp11/dispatch_table.hpp +++ b/include/boost/msm/backmp11/dispatch_table.hpp @@ -163,6 +163,34 @@ private: } private: + // A function object for use with mp11::mp_for_each that stuffs transitions into cells. + // Only used when C++20 is not available. + class row_init_helper + { + public: + row_init_helper(event_cell* entries) + : m_entries(entries) {} + + template + typename ::boost::disable_if::type, void>::type + operator()(Row) + { + m_entries[get_table_index::value] = + &Row::execute; + } + + template + typename ::boost::enable_if::type, void>::type + operator()(Row) + { + m_entries[get_table_index::value] = + &convert_event_and_forward::execute; + } + + private: + event_cell* m_entries; + }; + // initialize the dispatch table for a given Event and Fsm event_dispatch_table() { @@ -202,18 +230,23 @@ private: row_chainer, map_of_row_seq > chained_rows; + + // Go back and fill in cells for matching transitions. +#if __cplusplus >= 202002L typedef mp11::mp_transform< preprocess_row, chained_rows > chained_and_preprocessed_rows; - // Go back and fill in cells for matching transitions. event_cell_initializer::init( reinterpret_cast(entries), get_init_cells(), mp11::mp_size::value ); +#else + mp11::mp_for_each(row_init_helper{entries}); +#endif } - + // class used to build a chain (or sequence) of transitions for a given event and start state // (like an UML diamond). Allows transition conflicts. template< typename Seq,typename AnEvent,typename State > @@ -315,13 +348,13 @@ private: >::type type; }; - template + template struct convert_event_and_forward { static HandledEnum execute(Fsm& fsm, int region_index, int state, Event const& evt) { - typename Transition::transition_event forwarded(evt); - return Transition::execute(fsm,region_index,state,forwarded); + typename Row::transition_event forwarded(evt); + return Row::execute(fsm,region_index,state,forwarded); } }; @@ -386,25 +419,25 @@ private: // just one row, no chaining, we rebuild the row like it was before mp11::mp_front> >; - template - using preprocess_row_helper = cell_constant<&Transition::execute>; - template + template + using preprocess_row_helper = cell_constant<&Row::execute>; + template using preprocess_row = init_cell_constant< // Offset into the entries array - get_table_index::value, + get_table_index::value, // Address of the execute function mp11::mp_eval_if_c< - is_kleene_event::type::value, + is_kleene_event::type::value, cell_constant< - &convert_event_and_forward::execute + &convert_event_and_forward::execute >, preprocess_row_helper, - Transition + Row >::value >; // data members - public: + public: // max_state+1, because 0 is reserved for this fsm (internal transitions) event_cell entries[max_state+1]; }; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4c02edd..4bbafaa 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,12 +1,17 @@ file(GLOB SOURCES "*.cpp") -# list(FILTER SOURCES EXCLUDE REGEX "xyz") -# list(FILTER SOURCES INCLUDE REGEX "xyz") +if(CMAKE_CXX_STANDARD LESS 20) + message(STATUS "MSM: CXX standard is below 20, excluding puml tests") + list(FILTER SOURCES EXCLUDE REGEX "puml|Puml") +endif() -add_executable(msm_test +add_executable(boost_msm_tests + EXCLUDE_FROM_ALL ${SOURCES} main.cpp ) -target_include_directories(msm_test PRIVATE ../include) +target_include_directories(boost_msm_tests PRIVATE ../include) find_package(boost_serialization) -target_link_libraries(msm_test Boost::serialization) -target_compile_definitions(msm_test PRIVATE "BOOST_MSM_NONSTANDALONE_TEST") \ No newline at end of file +target_link_libraries(boost_msm_tests Boost::serialization) +target_compile_definitions(boost_msm_tests PRIVATE "BOOST_MSM_NONSTANDALONE_TEST") + +add_test(boost_msm_tests boost_msm_tests) diff --git a/test/CompositeEuml.cpp b/test/CompositeEuml.cpp index 67c5dae..343e33d 100644 --- a/test/CompositeEuml.cpp +++ b/test/CompositeEuml.cpp @@ -158,7 +158,6 @@ namespace BOOST_AUTO_TEST_CASE_TEMPLATE( composite_euml_test, test_machine, test_machines ) { typename test_machine::player p; - typedef typename test_machine::player_ player_; typedef typename test_machine::Playing_type Playing_type; p.start(); @@ -289,7 +288,6 @@ namespace using back0 = hierarchical_state_machine::player; using back1 = hierarchical_state_machine::Playing_type; -BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0); BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1); using backmp11_0 = hierarchical_state_machine::player; diff --git a/test/CompositeMachine.cpp b/test/CompositeMachine.cpp index 5e93962..13a2d30 100644 --- a/test/CompositeMachine.cpp +++ b/test/CompositeMachine.cpp @@ -353,7 +353,6 @@ namespace using back0 = hierarchical_state_machine::player; using back1 = hierarchical_state_machine::player_::Playing; -BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0); BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1); using backmp11_0 = hierarchical_state_machine::player; diff --git a/test/Constructor.cpp b/test/Constructor.cpp index 44f389b..48beb71 100644 --- a/test/Constructor.cpp +++ b/test/Constructor.cpp @@ -207,5 +207,4 @@ namespace } } -using backmp11_fsm = boost::msm::backmp11::state_machine; -BOOST_MSM_BACKMP11_GENERATE_DISPATCH_TABLE(backmp11_fsm); \ No newline at end of file +using backmp11_fsm = boost::msm::backmp11::state_machine; \ No newline at end of file diff --git a/test/Entries.cpp b/test/Entries.cpp index f6399d4..a493c4d 100644 --- a/test/Entries.cpp +++ b/test/Entries.cpp @@ -306,7 +306,6 @@ namespace using back0 = hierarchical_state_machine::Fsm; using back1 = hierarchical_state_machine::Fsm_::SubFsm2; -BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0); BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1); using backmp11_0 = hierarchical_state_machine::Fsm; diff --git a/test/History.cpp b/test/History.cpp index 4a3c083..642d445 100644 --- a/test/History.cpp +++ b/test/History.cpp @@ -364,7 +364,6 @@ namespace using back0 = hierarchical_state_machine::player; using back1 = hierarchical_state_machine::player_::Playing; -BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0); BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1); using backmp11_0 = hierarchical_state_machine::player; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7200253..9709a1a 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -32,68 +32,53 @@ project test-suite msm-unit-tests : [ run Anonymous.cpp ] + [ run AnonymousAndGuard.cpp ] [ run AnonymousEuml.cpp ] + [ run Back11CompositeMachine.cpp ] + [ run BigWithFunctors.cpp ] [ run CompositeEuml.cpp ] [ run CompositeMachine.cpp ] [ run Constructor.cpp ] [ run Entries.cpp ] + [ run EventQueue.cpp ] [ run History.cpp ] + [ run KleeneDeferred.cpp ] + [ run ManyDeferTransitions.cpp ] [ run OrthogonalDeferred.cpp ] [ run OrthogonalDeferred2.cpp ] [ run OrthogonalDeferred3.cpp ] [ run OrthogonalDeferredEuml.cpp ] + [ run Serialize.cpp ] + [ run SerializeSimpleEuml.cpp ] + [ run SerializeWithHistory.cpp ] + [ run SetStates.cpp ] [ run SimpleEuml.cpp ] [ run SimpleEuml2.cpp ] [ run SimpleInternal.cpp ] [ run SimpleInternalEuml.cpp ] [ run SimpleInternalFunctors.cpp ] [ run SimpleMachine.cpp ] - [ run KleeneDeferred.cpp ] [ run SimpleWithFunctors.cpp ] - [ run Serialize.cpp ] - [ run SerializeWithHistory.cpp ] - [ run SerializeSimpleEuml.cpp ] + [ run Test2RegionsAnonymous.cpp ] [ run TestConstructor.cpp ] - [ run ManyDeferTransitions.cpp ] - [ run Back11AnonymousAndGuard.cpp ] - [ run Back11Throwing.cpp ] - [ run Back11KleeneDeferred.cpp : : - : [ requires cxx11_variadic_templates ] ] - [ run Back11Anonymous.cpp : : - : [ requires cxx11_variadic_templates ] ] - [ run Back11BigWithFunctors.cpp : : - : [ requires cxx11_variadic_templates ] ] - [ run Back11CompositeMachine.cpp : : - : [ requires cxx11_variadic_templates ] ] - [ run Back11Entries.cpp : : - : [ requires cxx11_variadic_templates ] ] - [ run Back11OrthogonalDeferred3.cpp : : - : [ requires cxx11_variadic_templates ] ] - [ run Back11SimpleInternalEuml.cpp : : - : [ requires cxx11_variadic_templates ] ] - [ run Back11SimpleInternalFunctors.cpp : : - : [ requires cxx11_variadic_templates ] ] - [ run Back11SimpleMachine.cpp : : - : [ requires cxx11_variadic_templates ] ] - [ run Back11SimpleWithFunctors.cpp : : - : [ requires cxx11_variadic_templates ] ] - [ run Back11TestDeferIn2Regions.cpp : : - : [ requires cxx11_variadic_templates ] ] - [ run Back11ManyDeferTransitions.cpp : : - : [ requires cxx11_variadic_templates ] ] - [ run Back11TransitionSkipping.cpp : : - : [ requires cxx11_variadic_templates ] ] - [ run Back11SimpleWithPuml.cpp : : - : [ requires cxx20_hdr_version cxx20_hdr_barrier cxx20_hdr_compare cxx20_hdr_format cxx20_hdr_ranges cxx20_hdr_numbers ] ] - [ run Back11OnlyStringPuml.cpp : : - : [ requires cxx20_hdr_version cxx20_hdr_barrier cxx20_hdr_compare cxx20_hdr_format cxx20_hdr_ranges cxx20_hdr_numbers ] ] - [ run Back11SimpleInternalWithPuml.cpp : : - : [ requires cxx20_hdr_version cxx20_hdr_barrier cxx20_hdr_compare cxx20_hdr_format cxx20_hdr_ranges cxx20_hdr_numbers ] ] - [ run Back11OrthogonalDeferred3WithPuml.cpp : : - : [ requires cxx20_hdr_version cxx20_hdr_barrier cxx20_hdr_compare cxx20_hdr_format cxx20_hdr_ranges cxx20_hdr_numbers ] ] - [ run puml_syntax.cpp : : - : [ requires cxx20_hdr_version cxx20_hdr_barrier cxx20_hdr_compare cxx20_hdr_format cxx20_hdr_ranges cxx20_hdr_numbers ] ] - [ run puml_syntax_2.cpp : : - : [ requires cxx20_hdr_version cxx20_hdr_barrier cxx20_hdr_compare cxx20_hdr_format cxx20_hdr_ranges cxx20_hdr_numbers ] ] + [ run TestConstructorMovableOnlyTypes.cpp ] + [ run TestDeferAndMessageQueue.cpp ] + [ run TestDeferAndMessageQueue2.cpp ] + [ run TestDeferAndMessageQueue3.cpp ] + [ run TestDeferIn2Regions.cpp ] + [ run Throwing.cpp ] + [ run TransitionSkipping.cpp ] + ; + +test-suite msm-unit-tests-cxxstd20 + : + [ run Back11OrthogonalDeferred3WithPuml.cpp ] + [ run OnlyStringPuml.cpp ] + [ run puml_syntax.cpp ] + [ run puml_syntax_2.cpp ] + [ run SimpleWithPuml.cpp ] + [ run StringTerminatePuml.cpp ] + : + 20 ; diff --git a/test/OrthogonalDeferred.cpp b/test/OrthogonalDeferred.cpp index 0ecb700..5b5796e 100644 --- a/test/OrthogonalDeferred.cpp +++ b/test/OrthogonalDeferred.cpp @@ -498,7 +498,6 @@ namespace using back0 = hierarchical_state_machine::player; using back1 = hierarchical_state_machine::player_::Playing; -BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0); BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1); using backmp11_0 = hierarchical_state_machine::player; diff --git a/test/OrthogonalDeferred2.cpp b/test/OrthogonalDeferred2.cpp index 5b5d4f9..d2c2bd9 100644 --- a/test/OrthogonalDeferred2.cpp +++ b/test/OrthogonalDeferred2.cpp @@ -505,7 +505,6 @@ namespace using back0 = hierarchical_state_machine::player; using back1 = hierarchical_state_machine::player_::Playing; -BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0); BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1); using backmp11_0 = hierarchical_state_machine::player; diff --git a/test/OrthogonalDeferredEuml.cpp b/test/OrthogonalDeferredEuml.cpp index 6fbcc92..d51d2c8 100644 --- a/test/OrthogonalDeferredEuml.cpp +++ b/test/OrthogonalDeferredEuml.cpp @@ -168,7 +168,6 @@ namespace BOOST_AUTO_TEST_CASE_TEMPLATE(orthogonal_deferred_euml_test, test_machine, test_machines) { typename test_machine::player p; - typedef typename test_machine::player_ player_; typedef typename test_machine::Playing_type Playing_type; // needed to start the highest-level SM. This will call on_entry and mark the start of the SM @@ -375,7 +374,6 @@ namespace using back0 = hierarchical_state_machine::player; using back1 = hierarchical_state_machine::Playing_type; -BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0); BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1); using backmp11_0 = hierarchical_state_machine::player; diff --git a/test/SerializeWithHistory.cpp b/test/SerializeWithHistory.cpp index e1568d7..9ae88e2 100644 --- a/test/SerializeWithHistory.cpp +++ b/test/SerializeWithHistory.cpp @@ -376,7 +376,6 @@ namespace using back0 = hierarchical_state_machine::player; using back1 = hierarchical_state_machine::player_::Playing; -BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0); BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1); using backmp11_0 = hierarchical_state_machine::player; diff --git a/test/SetStates.cpp b/test/SetStates.cpp index bc11240..06cd3ea 100644 --- a/test/SetStates.cpp +++ b/test/SetStates.cpp @@ -159,7 +159,6 @@ namespace using back0 = hierarchical_state_machine::Fsm; using back1 = hierarchical_state_machine::SubFsm; -BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back0); BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(back1); using backmp11_0 = hierarchical_state_machine::Fsm; diff --git a/test/TestConstructorMovableOnlyTypes.cpp b/test/TestConstructorMovableOnlyTypes.cpp index 1072422..85a7da1 100644 --- a/test/TestConstructorMovableOnlyTypes.cpp +++ b/test/TestConstructorMovableOnlyTypes.cpp @@ -22,6 +22,7 @@ #define BOOST_TEST_MODULE test_constructor_movable_only_types #endif #include +#include namespace msm = boost::msm; namespace mpl = boost::mpl; @@ -98,7 +99,7 @@ namespace BOOST_AUTO_TEST_CASE_TEMPLATE(test_constructor_movable_only_types, bistable_switch, bistable_switches) { - auto bulp = std::make_unique(3); + auto bulp = boost::make_unique(3); bistable_switch bs(std::move(bulp), 5); BOOST_CHECK_MESSAGE(bs.bulp_->current == 10, "Wrong returned current value");