diff --git a/include/boost/msm/back11/dispatch_table.hpp b/include/boost/msm/back11/dispatch_table.hpp index 1506152..f5a7644 100644 --- a/include/boost/msm/back11/dispatch_table.hpp +++ b/include/boost/msm/back11/dispatch_table.hpp @@ -21,7 +21,11 @@ #include #include #include + #include +#include +#include +#include #include #include @@ -199,20 +203,18 @@ struct dispatch_table { typedef typename boost::fusion::result_of::as_map< - typename boost::fusion::result_of::insert< - Map, - typename ::boost::fusion::result_of::end::type, - typename ::boost::fusion::result_of::make_pair< - typename transition_source_type::type, - typename ::boost::mpl::push_back< - typename ::boost::fusion::result_of::value_at_key< - Map, - typename transition_source_type::type - >::type, - typename change_frow_event::type - >::type - >::type - >::type + typename boost::fusion::result_of::make_vector< + typename ::boost::fusion::result_of::make_pair< + typename transition_source_type::type, + typename ::boost::mpl::push_back< + typename ::boost::fusion::result_of::value_at_key< + Map, + typename transition_source_type::type + >::type, + typename change_frow_event::type + >::type + >::type + >::type >::type type; }; @@ -440,25 +442,15 @@ struct dispatch_table ::boost::fusion::map<>, ::boost::mpl::if_< // if we already have a row on this source state - ::boost::mpl::has_key< ::boost::mpl::placeholders::_1, + ::boost::fusion::result_of::has_key< ::boost::mpl::placeholders::_1, transition_source_type< ::boost::mpl::placeholders::_2> >, // insert a new element in the value type -// push_to_map_of_vec<::boost::mpl::placeholders::_2, ::boost::mpl::placeholders::_1>, - boost::fusion::result_of::as_map, - ::boost::fusion::result_of::make_pair, - ::boost::mpl::push_back< - ::boost::fusion::result_of::value_at_key< ::boost::mpl::placeholders::_1, - transition_source_type< ::boost::mpl::placeholders::_2> >, - change_frow_event< ::boost::mpl::placeholders::_2 > > - > > >, + push_to_map_of_vec<::boost::mpl::placeholders::_2, ::boost::mpl::placeholders::_1>, // first row on this source state, make a vector with 1 element - boost::fusion::result_of::as_map, ::boost::fusion::result_of::make_pair, - make_vector< change_frow_event< ::boost::mpl::placeholders::_2> > > > > + boost::msm::back11::make_vector< change_frow_event< ::boost::mpl::placeholders::_2> > > > > > >::type map_of_row_seq; diff --git a/test/Back11TransitionSkipping.cpp b/test/Back11TransitionSkipping.cpp new file mode 100644 index 0000000..77f7562 --- /dev/null +++ b/test/Back11TransitionSkipping.cpp @@ -0,0 +1,160 @@ +// Copyright 2010 Christophe Henry +// henry UNDERSCORE christophe AT hotmail DOT com +// This is an extended version of the state machine available in the boost::mpl library +// Distributed under the same license as the original. +// Copyright for the original version: +// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed +// under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#ifndef BOOST_MSM_NONSTANDALONE_TEST +#define BOOST_TEST_MODULE back11_transition_skipping +#endif +#include +#include +//#define USE_PRE11_MSM_BACKEND // <- toggle this to switch between back vs back11 + +// back-end +#if defined(USE_PRE11_MSM_BACKEND) +#include +namespace msm_back = boost::msm::back; +#else +#include +namespace msm_back = boost::msm::back11; +#endif + +// front-end +#include +#include +#include +#include + + +template +using msm_flags = boost::mpl::vector; +template +using msm_transition_table = boost::mpl::vector; + + + +namespace msmf = boost::msm::front; +namespace euml = boost::msm::front::euml; + +struct evt1 {}; +struct evt2 {}; +struct evt3 {}; + +struct top_ : public msmf::state_machine_def { + int count_guard_false = 0; + int count_guard_true = 0; + + + struct nested : public msmf::state<> { + template + void on_entry(Event const&, FSM&) { ++entry_counter; } + template + void on_exit(Event const&, FSM&) { ++exit_counter; } + int entry_counter=0; + int exit_counter=0; + }; + + struct other1 : public msmf::state<> { + template + void on_entry(Event const&, FSM&) { ++entry_counter; } + template + void on_exit(Event const&, FSM&) { ++exit_counter; } + int entry_counter = 0; + int exit_counter = 0; + }; + + struct other2 : public msmf::state<> { + template + void on_entry(Event const&, FSM&) { ++entry_counter; } + template + void on_exit(Event const&, FSM&) { ++exit_counter; } + int entry_counter = 0; + int exit_counter = 0; + }; + + struct other3 : public msmf::state<> { + template + void on_entry(Event const&, FSM&) { ++entry_counter; } + template + void on_exit(Event const&, FSM&) { ++exit_counter; } + int entry_counter = 0; + int exit_counter = 0; + }; + + struct other4 : public msmf::state<> { + template + void on_entry(Event const&, FSM&) { ++entry_counter; } + template + void on_exit(Event const&, FSM&) { ++exit_counter; } + int entry_counter = 0; + int exit_counter = 0; + }; + struct other5 : public msmf::state<> { + template + void on_entry(Event const&, FSM&) { ++entry_counter; } + template + void on_exit(Event const&, FSM&) { ++exit_counter; } + int entry_counter = 0; + int exit_counter = 0; + }; + + struct guard_true { + template + bool operator()(EVT const&, FSM& fsm, SourceState&, TargetState&) const { + ++fsm.count_guard_true; + return true; + } + }; + + struct guard_false { + template + bool operator()(EVT const&, FSM& fsm, SourceState&, TargetState&) const { + ++fsm.count_guard_false; + return false; + } + }; + + + typedef nested initial_state; + + using transition_table = msm_transition_table< + // Start Event Next Action Guard + //--------+------------+---------+------------+-----------+-------------- + msmf::Row < nested, msmf::none, other1, msmf::none, guard_false>, + msmf::Row < nested, msmf::none, other2, msmf::none, guard_true >, // <- this transition is not executed with back11 + msmf::Row < nested, msmf::none, other3, msmf::none, guard_false>, + msmf::Row < nested, msmf::none, other4, msmf::none, guard_false>, + msmf::Row < other1, evt3, nested, msmf::none, msmf::none > + >; +}; + +using top = msm_back::state_machine; + + +BOOST_AUTO_TEST_CASE(back11_transition_skipping) +{ + top msm; + msm.start(); + BOOST_CHECK_MESSAGE(msm.count_guard_true == 1, "guard_true should be called once"); + BOOST_CHECK_MESSAGE(msm.count_guard_false == 2, "guard_false should be called once"); + + BOOST_CHECK_MESSAGE(msm.get_state().exit_counter == 1, "nested exit not called correctly"); + BOOST_CHECK_MESSAGE(msm.get_state().entry_counter == 1, "nested entry not called correctly"); + BOOST_CHECK_MESSAGE(msm.get_state().exit_counter == 0, "other2 exit not called correctly"); + BOOST_CHECK_MESSAGE(msm.get_state().entry_counter == 1, "other2 entry not called correctly"); + BOOST_CHECK_MESSAGE(msm.get_state().exit_counter == 0, "other1 exit not called correctly"); + BOOST_CHECK_MESSAGE(msm.get_state().entry_counter == 0, "other1 entry not called correctly"); + BOOST_CHECK_MESSAGE(msm.get_state().exit_counter == 0, "other3 exit not called correctly"); + BOOST_CHECK_MESSAGE(msm.get_state().entry_counter == 0, "other3 entry not called correctly"); + BOOST_CHECK_MESSAGE(msm.get_state().exit_counter == 0, "other4 exit not called correctly"); + BOOST_CHECK_MESSAGE(msm.get_state().entry_counter == 0, "other4 entry not called correctly"); + BOOST_CHECK_MESSAGE(msm.current_state()[0] == 2, "other2 should be active"); //Open + +} diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c012ce1..7200253 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -81,6 +81,8 @@ test-suite msm-unit-tests : [ 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 : :