Ticket #6951: fix_pseudo_entry_and_none_event.patch

File fix_pseudo_entry_and_none_event.patch, 15.4 KB (added by Takatoshi Kondo <redboltz@…>, 10 years ago)

patch

  • boost/msm/back/state_machine.hpp

     
    25262526             // given region starts with the entry pseudo state as active state
    25272527             self->m_states[find_region_id<typename EventType::active_state::wrapped_entry>::region_index] = state_id;
    25282528             self->internal_start(evt.m_event);
    2529              // and we process the transition in the zone of the newly active state
    2530              // (entry pseudo states are, according to UML, a state connecting 1 transition outside to 1 inside
    2531              self->process_event(evt.m_event);
     2529             if (self->m_events_queue.m_events_queue.empty())
     2530             {
     2531                 // and we process the transition in the zone of the newly active state
     2532                 // (entry pseudo states are, according to UML, a state connecting 1 transition outside to 1 inside
     2533                 self->process_event(evt.m_event);
     2534             }
    25322535         }
    25332536     private:
    25342537         // helper for the fork case, does almost like the direct entry
  • libs/msm/test/Jamfile.v2

     
    3434    [ run OrthogonalDeferred.cpp ]
    3535    [ run OrthogonalDeferred2.cpp ]
    3636    [ run OrthogonalDeferredEuml.cpp ]
     37    [ run PseudoEntry.cpp ]
    3738    [ run SimpleEuml.cpp ]
    3839    [ run SimpleEuml2.cpp ]
    3940    [ run SimpleInternal.cpp ]
  • libs/msm/test/PseudoEntry.cpp

     
     1// Copyright 2012 Christophe Henry, Takatoshi Kondo
     2// henry UNDERSCORE christophe AT hotmail DOT com, redboltz AT gmail DOT com
     3// This is an extended version of the state machine available in the boost::mpl library
     4// Distributed under the same license as the original.
     5// Copyright for the original version:
     6// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
     7// under the Boost Software License, Version 1.0. (See accompanying
     8// file LICENSE_1_0.txt or copy at
     9// http://www.boost.org/LICENSE_1_0.txt)
     10
     11#include <iostream>
     12// back-end
     13#include <boost/msm/back/state_machine.hpp>
     14//front-end
     15#include <boost/msm/front/state_machine_def.hpp>
     16#include <boost/msm/front/functor_row.hpp>
     17
     18#define BOOST_TEST_MODULE MyTest
     19#include <boost/test/unit_test.hpp>
     20
     21namespace msm = boost::msm;
     22namespace mpl = boost::mpl;
     23using namespace boost::msm::front;
     24
     25namespace
     26{
     27    // events
     28    struct event1 {};
     29    struct event2 {};
     30
     31    // front-end: define the FSM structure
     32    struct L0Fsm_ : public state_machine_def<L0Fsm_>
     33    {
     34        // The list of FSM states
     35        struct L1State1 : public state<>
     36        {
     37            template <class Event,class FSM>
     38            void on_entry(Event const&,FSM& ) {++entry_counter;}
     39            template <class Event,class FSM>
     40            void on_exit(Event const&,FSM& ) {++exit_counter;}
     41            int entry_counter;
     42            int exit_counter;
     43        };
     44        struct L1Fsm_ : public state_machine_def<L1Fsm_>
     45        {
     46            unsigned int entry_action_counter;
     47
     48            template <class Event,class FSM>
     49            void on_entry(Event const&,FSM& ) {++entry_counter;}
     50            template <class Event,class FSM>
     51            void on_exit(Event const&,FSM& ) {++exit_counter;}
     52            int entry_counter;
     53            int exit_counter;
     54
     55            // test with a pseudo entry
     56            struct L2PseudoEntry : public msm::front::entry_pseudo_state<0>
     57            {
     58                template <class Event,class FSM>
     59                void on_entry(Event const&,FSM& ) {++entry_counter;}
     60                template <class Event,class FSM>
     61                void on_exit(Event const&,FSM& ) {++exit_counter;}
     62                int entry_counter;
     63                int exit_counter;
     64            };
     65            struct L2Fsm_ : public state_machine_def<L2Fsm_>
     66            {
     67                unsigned int entry_action_counter;
     68                unsigned int deferred_action_counter;
     69
     70                template <class Event,class FSM>
     71                void on_entry(Event const&,FSM& ) {++entry_counter;}
     72                template <class Event,class FSM>
     73                void on_exit(Event const&,FSM& ) {++exit_counter;}
     74                int entry_counter;
     75                int exit_counter;
     76
     77                // test with a pseudo entry
     78                struct L3PseudoEntry : public entry_pseudo_state<0>
     79                {
     80                    template <class Event,class FSM>
     81                    void on_entry(Event const&,FSM& ) {++entry_counter;}
     82                    template <class Event,class FSM>
     83                    void on_exit(Event const&,FSM& ) {++exit_counter;}
     84                    int entry_counter;
     85                    int exit_counter;
     86                };
     87                struct L3State1 : public state<>
     88                {
     89                    template <class Event,class FSM>
     90                    void on_entry(Event const&,FSM& ) {++entry_counter;}
     91                    template <class Event,class FSM>
     92                    void on_exit(Event const&,FSM& ) {++exit_counter;}
     93                    int entry_counter;
     94                    int exit_counter;
     95                };
     96                struct L3State2 : public state<>
     97                {
     98                    template <class Event,class FSM>
     99                    void on_entry(Event const&,FSM& ) {++entry_counter;}
     100                    template <class Event,class FSM>
     101                    void on_exit(Event const&,FSM& ) {++exit_counter;}
     102                    int entry_counter;
     103                    int exit_counter;
     104                };
     105
     106                struct EntryAction {
     107                    template <class Event, class Fsm, class SourceState, class TargetState>
     108                    void operator()(Event const&, Fsm& f, SourceState&, TargetState&) {
     109                        ++f.entry_action_counter;
     110                    }
     111                };
     112                struct DeferredAction {
     113                    template <class Event, class Fsm, class SourceState, class TargetState>
     114                    void operator()(Event const&, Fsm& f, SourceState&, TargetState&) {
     115                        ++f.deferred_action_counter;
     116                    }
     117                };
     118
     119                // the initial state. Must be defined
     120                typedef L3State1 initial_state;
     121
     122                // Transition table for SubSubFsm2
     123                struct transition_table : mpl::vector<
     124                    //     Start           Event    Next       Action          Guard
     125                    //   +---------------+--------+----------+----------------+-------+
     126                    Row  < L3PseudoEntry , none   , L3State1 , EntryAction    , none  >,
     127                    Row  < L3State1      , none   , L3State2 , none           , none  >,
     128                    Row  < L3State2      , event2 , none     , DeferredAction , none  >
     129                    //   +---------------+--------+----------+----------------+-------+
     130                > {};
     131
     132                // Replaces the default no-transition response.
     133                template <class FSM,class Event>
     134                void no_transition(Event const& e, FSM&,int state)
     135                {
     136                    BOOST_FAIL("no_transition called!");
     137                }
     138            };
     139            typedef msm::back::state_machine<L2Fsm_> L2Fsm;
     140           
     141            struct EntryAction {
     142                template <class Event, class Fsm, class SourceState, class TargetState>
     143                void operator()(Event const&, Fsm& f, SourceState&, TargetState&) {
     144                    ++f.entry_action_counter;
     145                }
     146            };
     147
     148            // the initial state. Must be defined
     149            typedef L2Fsm_ initial_state;
     150
     151            // Transition table for SubFsm2
     152            struct transition_table : mpl::vector<
     153                //     Start           Event   Next                      Action        Guard
     154                //   +---------------+-------+-------------------------+-------------+-------+
     155                Row  < L2PseudoEntry , none  , L2Fsm::entry_pt
     156                                               <L2Fsm_::L3PseudoEntry> , EntryAction , none  >
     157                //   +---------------+-------+-------------------------+-------------+-------+
     158            > {};
     159
     160            // Replaces the default no-transition response.
     161            template <class FSM,class Event>
     162            void no_transition(Event const& e, FSM&,int state)
     163            {
     164                BOOST_FAIL("no_transition called!");
     165            }
     166        };
     167        typedef msm::back::state_machine<L1Fsm_> L1Fsm;
     168
     169        // the initial state of the player SM. Must be defined
     170        typedef L1State1 initial_state;
     171
     172        // Enable deferred capability
     173        typedef int activate_deferred_events;
     174
     175        // transition actions
     176        // guard conditions
     177
     178        // Transition table for Fsm
     179        struct transition_table : mpl::vector<
     180            //     Start      Event    Next                      Action   Guard
     181            //   +----------+--------+-------------------------+--------+-------+
     182            Row  < L1State1 , event1 , L1Fsm::entry_pt
     183                                       <L1Fsm_::L2PseudoEntry> , none   , none  >,
     184            Row  < L1State1 , event2 , none                    , Defer  , none  >
     185            //   +----------+--------+-------------------------+--------+-------+
     186        > {};
     187
     188        // Replaces the default no-transition response.
     189        template <class FSM,class Event>
     190        void no_transition(Event const& e, FSM&,int state)
     191        {
     192            BOOST_FAIL("no_transition called!");
     193        }
     194
     195        // init counters
     196        template <class Event,class FSM>
     197        void on_entry(Event const&,FSM& fsm)
     198        {
     199            fsm.template get_state<L0Fsm_::L1State1&>().entry_counter=0;
     200            fsm.template get_state<L0Fsm_::L1State1&>().exit_counter=0;
     201            fsm.template get_state<L0Fsm_::L1Fsm&>().entry_counter=0;
     202            fsm.template get_state<L0Fsm_::L1Fsm&>().exit_counter=0;
     203            fsm.template get_state<L0Fsm_::L1Fsm&>().entry_action_counter=0;
     204            fsm.template get_state<L0Fsm_::L1Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm&>().entry_counter=0;
     205            fsm.template get_state<L0Fsm_::L1Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm&>().exit_counter=0;
     206            fsm.template get_state<L0Fsm_::L1Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm&>().entry_action_counter=0;
     207            fsm.template get_state<L0Fsm_::L1Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm&>().deferred_action_counter=0;
     208            fsm.template get_state<L0Fsm_::L1Fsm&>().template get_state<L0Fsm_::L1Fsm::L2PseudoEntry&>().entry_counter=0;
     209            fsm.template get_state<L0Fsm_::L1Fsm&>().template get_state<L0Fsm_::L1Fsm::L2PseudoEntry&>().exit_counter=0;
     210            fsm.template get_state<L0Fsm_::L1Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm::L3PseudoEntry&>().entry_counter=0;
     211            fsm.template get_state<L0Fsm_::L1Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm::L3PseudoEntry&>().exit_counter=0;
     212            fsm.template get_state<L0Fsm_::L1Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm::L3State1&>().entry_counter=0;
     213            fsm.template get_state<L0Fsm_::L1Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm::L3State1&>().exit_counter=0;
     214            fsm.template get_state<L0Fsm_::L1Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm::L3State2&>().entry_counter=0;
     215            fsm.template get_state<L0Fsm_::L1Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm&>().template get_state<L0Fsm_::L1Fsm::L2Fsm::L3State2&>().exit_counter=0;
     216           
     217        }
     218    };
     219    typedef msm::back::state_machine<L0Fsm_> L0Fsm;
     220
     221
     222    BOOST_AUTO_TEST_CASE( my_test )
     223    {     
     224        L0Fsm p;
     225
     226        p.start();
     227        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1State1&>().entry_counter == 1,"L1State1 entry not called correctly");
     228        BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"L1State1 should be active");
     229
     230        p.process_event(event2()); // Deferred
     231        BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"L1State1 should be active");
     232        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1State1&>().entry_counter == 1,"L1State1 entry not called correctly");
     233        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1State1&>().exit_counter == 0,"L1State1 exit not called correctly");
     234
     235        p.process_event(event1());
     236        BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"L1Fsm should be active");
     237        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1State1&>().exit_counter == 1,"L1State1 exit not called correctly");
     238        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1Fsm&>().entry_counter == 1,"L1Fsm entry not called correctly");
     239        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1Fsm&>().entry_action_counter == 1,"L1Fsm entry action not called correctly");
     240        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1Fsm&>().get_state<L0Fsm_::L1Fsm::L2PseudoEntry&>().entry_counter == 1,"L2EntryPoint entry not called correctly");
     241        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1Fsm&>().get_state<L0Fsm_::L1Fsm::L2PseudoEntry&>().exit_counter == 1,"L2EntryPoint exit not called correctly");
     242        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm&>().entry_counter == 1,"L2Fsm entry not called correctly");
     243        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm&>().entry_action_counter == 1,"L2Fsm entry action not called correctly");
     244        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm&>().exit_counter == 0,"L2Fsm exit not called correctly");
     245        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm::L3PseudoEntry&>().entry_counter == 1,"L3PseudoEntry entry not called correctly");
     246        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm::L3PseudoEntry&>().exit_counter == 1,"L3PseudoEntry exit not called correctly");
     247        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm::L3State1&>().entry_counter == 1,"L3State1 entry not called correctly");
     248        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm::L3State1&>().exit_counter == 1,"L3State1 exit not called correctly");
     249        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm::L3State2&>().entry_counter == 1,"L3State2 entry not called correctly");
     250        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm::L3State2&>().exit_counter == 0,"L3State2 exit not called correctly");
     251        BOOST_CHECK_MESSAGE(p.get_state<L0Fsm_::L1Fsm&>().get_state<L0Fsm_::L1Fsm::L2Fsm&>().deferred_action_counter == 1,"L2Fsm deferred action not called correctly");
     252    }
     253}
     254