Boost logo

Boost Users :

Subject: [Boost-users] [MSM] event type change while using a direct entry
From: Steckmann, Sven (sven.steckmann_at_[hidden])
Date: 2011-05-11 09:04:12


Dear list,

while writing a state machine, I added an explicit_entry to my machine. My problem now is, if I want to write different function for different event types for the entry action like this:
template < class FSM>
void on_entry(event2 const& ev,FSM&fsm ){ … }
not all events were catched by it. After some compiling and generating an example, I know when the problem occurs. I am not sure if this is a bug or a feature ☺. The event for the explicit entry is wrapped with a direct_entry_event. If the transition is from outside the statemachine this is quite ok (I got the original event, not the direct_entry_event), but if transition is inside the machine, the direct_entry_event is not removed and I got this to my on_entry.

The example and the console output from the listing below show this effect. Is this a compiler problem or a problem/bug/feature coming from the msm?

I am using a gcc 4.3.4 and boost 1.46.1 (trunk also shows this)

Kind regards,
    Sven Steckmann
 
// 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 <vector>
#include <iostream>
// back-end
#include <boost/msm/back/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>

#include <boost/msm/front/functor_row.hpp>

namespace msm = boost::msm;
namespace mpl = boost::mpl;

namespace
{
    // events
    struct event1 {};
    struct event2 {};

    struct SubFsm2_ : public msm::front::state_machine_def<SubFsm2_>
    {

        template <class Event,class FSM>
        void on_entry(Event const&,FSM& ) {std::cout << "entering: SubFsm2" << std::endl;}
        template <class Event,class FSM>
        void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2" << std::endl;}

        struct SubState2 : public msm::front::state<> , public msm::front::explicit_entry<0>
        {
            template <class Event,class FSM>
            void on_entry(Event const&ev,FSM&fsm )
            {
              std::cout << "entering: SubFsm2::SubState2 with event type: " << typeid(Event).name() << std::endl;
            }
            template <class Event,class FSM>
            void on_exit(Event const&,FSM& ) {std::cout << "leaving: SubFsm2::SubState2" << std::endl;}
        };

        // the initial state. Must be defined
        typedef SubState2 initial_state;

        // Transition table for SubFsm2
        struct transition_table : mpl::vector<
            // Start Event Next Action Guard
            // +--------------+-------------+------------+------------------------+----------------------+
            _row < SubState2 , event2 , SubState2 >
            // +--------------+-------------+------------+------------------------+----------------------+
> {};
        // Replaces the default no-transition response.
        template <class FSM,class Event>
        void no_transition(Event const& e, FSM&,int state)
        {
            std::cout << "no transition from state " << state
                << " on event " << typeid(e).name() << std::endl;
        }
    };
    typedef msm::back::state_machine<SubFsm2_> SubFsm2;

     // front-end: define the FSM structure
    struct Fsm_ : public msm::front::state_machine_def<Fsm_>
    {
        // The list of FSM states
        struct State1 : public msm::front::state<>
        {
            // every (optional) entry/exit methods get the event passed.
            template <class Event,class FSM>
            void on_entry(Event const&ev,FSM&fsm )
            {
              std::cout << "entering: State1" << std::endl;
            }
            template <class Event,class FSM>
            void on_exit(Event const&,FSM& ) {std::cout << "leaving: State1" << std::endl;}
        };
        struct State2 : public msm::front::state<>
        {
            // every (optional) entry/exit methods get the event passed.
            template <class Event,class FSM>
            void on_entry(Event const&,FSM& ) {std::cout << "entering: State2" << std::endl;}
            template <class Event,class FSM>
            void on_exit(Event const&,FSM& ) {std::cout << "leaving: State2" << std::endl;}
        };


        // the initial state of the player SM. Must be defined
        typedef SubFsm2 initial_state;


        // Transition table for Fsm
        struct transition_table : mpl::vector<
            // Start Event Next Action Guard
            // +---------------------+--------+------------------------------------+-------+--------+
            _row < State1 , event1 , SubFsm2 >,
            _row < SubFsm2 , event1 , State1 >
            // +---------------------+--------+------------------------------------+-------+--------+
> {};

        // Replaces the default no-transition response.
        template <class FSM,class Event>
        void no_transition(Event const& e, FSM&,int state)
        {
            std::cout << "no transition from state " << state
                << " on event " << typeid(e).name() << std::endl;
        }
    };
    typedef msm::back::state_machine<Fsm_> Fsm;

    void test()
    {
        Fsm p;
        p.start();

        p.process_event(event2());
        p.process_event(event1());
        p.process_event(event1());
    }
}

--------------------------------------------- OUTPUT to console ------------------------------------------------------
entering: SubFsm2
entering: SubFsm2::SubState2 with event type: N5boost3msm4back13state_machineIN12_GLOBAL__N_14Fsm_ENS_9parameter5void_ES6_S6_S6_E9InitEventE
leaving: SubFsm2::SubState2
////// Comment: Now the transition is inside the submachine, the direct_entry_event is not removed
entering: SubFsm2::SubState2 with event type: N5boost3msm4back18direct_entry_eventIN12_GLOBAL__N_18SubFsm2_9SubState2ENS3_6event2EEE
leaving: SubFsm2::SubState2
leaving: SubFsm2
entering: State1
leaving: State1
entering: SubFsm2
////// Comment: Her the right event will be passed to
entering: SubFsm2::SubState2 with event type: N12_GLOBAL__N_16event1E


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net