[MSM] exit_ps stuks in case of outer state machine uses Row with event to event base class

Hi Christophe and All after splitting our complicated several level deep contained state machines to small run-time instances. I have to use feature Event Hierarchy (http://svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/ch03s02.html#d0e1176) which is really cool. But this feature in combination with pseudo exits state, breaks the pseudo exit state functionality and the pseudo exit state is entered but never left. I have made a small example where the problem is reproduced see attachment. (the file name is misleading was just lazy to rename it something more appropriate) Here is the output of the execution : entering: Idle MS1_ leaving: Idle Action: MS1::onEvent1 entering: RunningStateMachine MS1_ entering: RunningStateMachine::PseudoEntry1 leaving: RunningStateMachine::PseudoEntry1 entering: Inner1 RunningStateMachine_ entering: InnerState11 leaving: InnerState11 leaving: Inner1 entering: RunningStateMachine::PseudoEntry1 I have tried it in our host test environment only so VC9 compiler and with boost trunk from Friday last week. Cheers Richard.

Hi Christophe and All
after splitting our complicated several level deep contained state machines to small run-time instances. I have to use feature Event Hierarchy (http://svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/ch03s02.html#d0e1176) which is really cool.
Great :)
But this feature in combination with pseudo exits state, breaks the pseudo exit state functionality and the pseudo exit state is entered but never left.
I have made a small example where the problem is reproduced see attachment. (the file name is misleading was just lazy to rename it something more appropriate)
Here is the output of the execution :
entering: Idle MS1_ leaving: Idle Action: MS1::onEvent1 entering: RunningStateMachine MS1_ entering: RunningStateMachine::PseudoEntry1 leaving: RunningStateMachine::PseudoEntry1 entering: Inner1 RunningStateMachine_ entering: InnerState11 leaving: InnerState11 leaving: Inner1
----> look here, PseudoEntry1
entering: RunningStateMachine::PseudoEntry1
Hi Richard, I think it's because there are a few mistakes in your state machine: 1. You are in PseudoEntry1, not PseudoExit1, so it won't work: _row < Inner1 , event3 , PseudoEntry1
should probably be: _row < Inner1 , event3 , PseudoExit1
2. The outside event (event4) must be constructible from the inside event (event3). As stated there(http://svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/ch03s02.html#d0e942), it requires a copy-constructor to build an event4 from event3. You need to change event4 to: struct event4 : public baseEvent { event4(){} template <class Event> event4(Event const&){} }; Why it compiles is still a mystery to me, to be honest. I would expect the compiler to complain about not being able to construct event4 from event3. I need to have a look at this. 3. This one is my fault and might be a problem for you as you seek performance. I think we discussed this but I forgot it in the doc. Pseudo exits require the message queue and you deactivated it with: typedef int no_message_queue; 4. It's probably just the example here but just in case you created a transition conflict which is unlikely to please you between: _row < RunningStateMachine::exit_pt< RunningStateMachine::PseudoExit1
, event4 , Idle > and: Row < RunningStateMachine, baseEvent, RunningStateMachine >
In this case, event4 is a baseEvent and both transitions are conflicting. MSM will take the latest defined, which is correct but probably not what you want. Now it should work. I tried to replace event4 with baseEvent (and add the constructor) and all works as advertised. Regards, Christophe

3. This one is my fault and might be a problem for you as you seek performance. I think we discussed this but I forgot it in the doc. Pseudo exits require the message queue and you deactivated it with: typedef int no_message_queue;
Thinking again about it, as you have the newest MSM version (time for a bit of advertisement for the new version ;-) ), there is now a way around the queue. The exit point needs the queue because it will process an event4 during processing of event3, so that MSM has time to update its current state before processing event4. But this is only because MSM does this after the transition (the UML standard "forgot" to specify this point). The newest version allows you to override this and decide that this updating job will be done for example before the transition is taken (after the guard chooses the transition of course), or after the exit action, etc. To do this, add into every state machine: typedef msm::active_state_switch_before_transition active_state_switch_policy; Now you don't need the queue. Doc is there: http://svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/ch03s05.html#backend-... Regards, Christophe
participants (2)
-
Christophe Henry
-
Richard Szabo