Boost logo

Boost :

Subject: Re: [boost] [msm] on_entry must be implemented for every initial events for every states in substatemachines.
From: Christophe Henry (christophe.j.henry_at_[hidden])
Date: 2010-09-02 15:50:12


> Hi All
>
> In the following little example see attachment,
> I have a problem that in the RunningStateMachine::State2 the on_entry
> function must be implemented with event1 and with event3 as well
> but from the logic point of view there is no possibility to call
> on_entry in RunningStateMachine::State2 with event1.
>
> actually at runtime there is no call is happening to to the function :
> void on_entry(event1 const&,FSM& ) {std::cout << "entering:
> State2:Event1" << std::endl;}

> but it must be defined and even implemented ( if no implementation
> provided linker error occurs).

> Is it a restriction/bug or I'm missing something ?
> It is only happening with initial events for substatemachines ?
> Or is there a kind of pattern to know what events can enter exit a
> state in a top of the ones present in the transition tables ?.

Hi,
Well, we don't want to go into the implementation details (we really
don't ;-) ) but to make it short, msm tries the entry event with every
state to see which state is active at run-time.
And this means that every state's entry and exit behavior must be able
to process this event.
Of course it'd be possible to know in advance that some states are
wrong candidates but this requires some compile-time graph analysis.
And I do plan to start working on this using the metagraph library
which is in construction.
But for the moment I don't have this tool in msm. And even when I do,
there will be a compile-time cost.

Back to the example, when you write:

        template <class FSM>
        void on_entry(event3 const&,FSM& ) {std::cout << "entering:
State2:Event3" << std::endl;}

You are hiding the default on_entry, which provides you with an empty
implementation for all events.
The solution is not incredibly beautiful but will save us some
compile-time. We need to tell the compiler we have a version for
event3 and one for all others:

        template <class Event,class FSM>
        typename boost::enable_if<
            typename boost::is_same<Event,event3>::type,void >::type
// version for event3
        on_entry(Event const&,FSM& ) {std::cout << "entering:
State2:Event3" << std::endl;}

        template <class Event,class FSM>
        typename boost::disable_if<
            typename boost::is_same<Event,event3>::type,void >::type
// version for events != event3
        on_entry(Event const&,FSM& ) {std::cout << "entering:
State2:Event1" << std::endl;}

Now it compiles :)

HTH,
Christophe


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk