[msm]exit pseudo state and event

Hello, Boost.Msm supports the UML2.0 feature "exit pseudo state". Here is a description about exit pseudo state in the document.
exit_pseudo_state
Basic type for exit pseudo states. Exit pseudo states are an predefined exit from a submachine and connect two transitions. The first argument is the name of the event which will be "thrown" out of the exit point. This event does not need to be the same as the one sent by the inner region but must be convertible from it. The second argument is needed if you want your state (and all others used in a concrete state machine) to inherit a basic type for logging or providing a common behavior.
template<class Event,class Base = default_base_state, { } class SMPtrPolicy = no_sm_ptr> exit_pseudo_state { }
Why the 1st template parameter "Event" is needed? Consider the attached diagram "11_ExitPointEvent.png". IMHO, the Exit2 is typical usecase of exit pseudo state. Outgoing transition from exit pseudo state shouldn't have any events and guards. The point is how to divide the concerns. When we design the Sm1, we can depend only State1, State1::Exit1, State1::Exit2 and State2. And we shouldn't depend on which event triggers the transition to pseudo exit state. It's State1's concern. To implement that, I pass the "none" as 1st template parameter. namespace msmf = boost::msm::front; struct Exit2:public msm::front::exit_pseudo_state<msmf::none> {}; (See the attached file 11_ExitPointEvent.cpp) I think it is suitable for the default template parameter. The example in the Boost.Msm tutorial document, the usage of exit pseudo state is similar as Exit1 in "11_ExitPointEvent.png". The behavior that I understand is below. In State1 1. Event1 is occurred, 2. Transition to Exit1. 3. Event1 is converted to Event2 (Exit1's template argument). In Sm1 4. Dispatch Event2. 5. Transition to State2. (Entry, Exit action is omitted) Is that right? I'd like to know why such complicated mechanism is needed? Is the purpose to propagate the event parameter? Thanks, Takatoshi

Hello,
Boost.Msm supports the UML2.0 feature "exit pseudo state". Here is a description about exit pseudo state in the document.
exit_pseudo_state
Basic type for exit pseudo states. Exit pseudo states are an predefined exit from a submachine and connect two transitions. The first argument is the name of the event which will be "thrown" out of the exit point. This event does not need to be the same as the one sent by the inner region but must be convertible from it. The second argument is needed if you want your state (and all others used in a concrete state machine) to inherit a basic type for logging or providing a common behavior.
template<class Event,class Base = default_base_state, { } class SMPtrPolicy = no_sm_ptr> exit_pseudo_state { }
Why the 1st template parameter "Event" is needed?
It is needed for implementation reasons. Actually it might not be needed if I decided to hardcode an event (like "none" as you later suggest).
Consider the attached diagram "11_ExitPointEvent.png".
IMHO, the Exit2 is typical usecase of exit pseudo state. Outgoing transition from exit pseudo state shouldn't have any events and guards. The point is how to divide the concerns. When we design the Sm1, we can depend only State1, State1::Exit1, State1::Exit2 and State2. And we shouldn't depend on which event triggers the transition to pseudo exit state. It's State1's concern.
True. OTOH, letting a submachine decide which event is exiting this submachine creates a constraint on the main state machine. The goal of the implementation is to remove this constraint.
To implement that, I pass the "none" as 1st template parameter.
It is acceptable to msm and probably in the spirit of the Standard.
namespace msmf = boost::msm::front; struct Exit2:public msm::front::exit_pseudo_state<msmf::none> {}; (See the attached file 11_ExitPointEvent.cpp)
I think it is suitable for the default template parameter.
Maybe (see below).
The example in the Boost.Msm tutorial document, the usage of exit pseudo state is similar as Exit1 in "11_ExitPointEvent.png".
The behavior that I understand is below. In State1 1. Event1 is occurred, 2. Transition to Exit1. 3. Event1 is converted to Event2 (Exit1's template argument). In Sm1 4. Dispatch Event2. 5. Transition to State2. (Entry, Exit action is omitted)
Is that right?
Yes.
I'd like to know why such complicated mechanism is needed? Is the purpose to propagate the event parameter?
As implementer, I allow myself from time to time to ignore the standard (implementer's privilege ;-) ) where I feel it forces unacceptable constraints on me. This is such a case. There are several reasons. One is as you noticed, not to lose the event type and even more, data. If an event has some attributes, converting it to "none" will lose them. Slicing and subtle bugs in waiting. The second reason is this extra constraint. It is a constraint coming from down in your design. This simply feels wrong to me. The implementation of msm allows the writer of the main machine to have less constraints. He can decide to write an event convertible from any other event, or to take over only data from the inner event. Consider event6 from the tutorial. I could write: struct event6 { event6(){} template <class Event> event6(Event const& e) { some_id_ = e.id(); } int some_id_; }; The dependency to the submachine is only a weak one. The third reason is that we would have in our main machine a second-class transition. No event, no guard. Which implies no possible transition conflict resolution. What if I want to implement an "if/else" mechanism in the main machine? Not possible. I will be forced to add a state as target of this transition whose sole purpose would be to provide me with a set of outgoing transitions implementing my "if/else". But without event data (as we would only have "none"), I would not be able to implement every case and I will be forced to resort to lesser solutions (like adding attributes to the submachine to store event data). This is a personal choice but these reasons matter to me more than the extra complexity added by a template parameter. If your taste is the Standard one, it is fine with me, just define "none" as event parameter. The next point to consider is whether to make "none" a default parameter. One one hand, it would make the pseudo exit almost Standard-conform (if we ignore the possible on_entry/on_exit handlers which are not foreseen by the Standard), on the other hand, someone not knowing this finesse of the Standard and providing no event parameter and a normal outer transition with an event will be quite surprised to get no_transition handler calls. I do not favor forcing bugs on msm users (which qualifies as a "complicated mechanism") only to please the Standard.
Thanks, Takatoshi
Regards, Christophe PS: I just realize this post would be a good addition to a Rationale section ;-)

On Sat, Jul 2, 2011 at 1:55 AM, Christophe Henry <christophe.j.henry@googlemail.com> wrote:
Hello,
Boost.Msm supports the UML2.0 feature "exit pseudo state". Here is a description about exit pseudo state in the document.
exit_pseudo_state
Basic type for exit pseudo states. Exit pseudo states are an predefined exit from a submachine and connect two transitions. The first argument is the name of the event which will be "thrown" out of the exit point. This event does not need to be the same as the one sent by the inner region but must be convertible from it. The second argument is needed if you want your state (and all others used in a concrete state machine) to inherit a basic type for logging or providing a common behavior.
template<class Event,class Base = default_base_state, { } class SMPtrPolicy = no_sm_ptr> exit_pseudo_state { }
Why the 1st template parameter "Event" is needed?
It is needed for implementation reasons. Actually it might not be needed if I decided to hardcode an event (like "none" as you later suggest).
OK.
Consider the attached diagram "11_ExitPointEvent.png".
IMHO, the Exit2 is typical usecase of exit pseudo state. Outgoing transition from exit pseudo state shouldn't have any events and guards. The point is how to divide the concerns. When we design the Sm1, we can depend only State1, State1::Exit1, State1::Exit2 and State2. And we shouldn't depend on which event triggers the transition to pseudo exit state. It's State1's concern.
True. OTOH, letting a submachine decide which event is exiting this submachine creates a constraint on the main state machine. The goal of the implementation is to remove this constraint.
I agree.
To implement that, I pass the "none" as 1st template parameter.
It is acceptable to msm and probably in the spirit of the Standard.
namespace msmf = boost::msm::front; struct Exit2:public msm::front::exit_pseudo_state<msmf::none> {}; (See the attached file 11_ExitPointEvent.cpp)
I think it is suitable for the default template parameter.
Maybe (see below).
The example in the Boost.Msm tutorial document, the usage of exit pseudo state is similar as Exit1 in "11_ExitPointEvent.png".
The behavior that I understand is below. In State1 1. Event1 is occurred, 2. Transition to Exit1. 3. Event1 is converted to Event2 (Exit1's template argument). In Sm1 4. Dispatch Event2. 5. Transition to State2. (Entry, Exit action is omitted)
Is that right?
Yes.
I'd like to know why such complicated mechanism is needed? Is the purpose to propagate the event parameter?
As implementer, I allow myself from time to time to ignore the standard (implementer's privilege ;-) ) where I feel it forces unacceptable constraints on me. This is such a case. There are several reasons. One is as you noticed, not to lose the event type and even more, data. If an event has some attributes, converting it to "none" will lose them. Slicing and subtle bugs in waiting.
The second reason is this extra constraint. It is a constraint coming from down in your design. This simply feels wrong to me. The implementation of msm allows the writer of the main machine to have less constraints. He can decide to write an event convertible from any other event, or to take over only data from the inner event. Consider event6 from the tutorial. I could write:
struct event6 { event6(){} template <class Event> event6(Event const& e) { some_id_ = e.id(); } int some_id_; };
The dependency to the submachine is only a weak one.
The third reason is that we would have in our main machine a second-class transition. No event, no guard. Which implies no possible transition conflict resolution. What if I want to implement an "if/else" mechanism in the main machine? Not possible. I will be forced to add a state as target of this transition whose sole purpose would be to provide me with a set of outgoing transitions implementing my "if/else". But without event data (as we would only have "none"), I would not be able to implement every case and I will be forced to resort to lesser solutions (like adding attributes to the submachine to store event data).
This is a personal choice but these reasons matter to me more than the extra complexity added by a template parameter. If your taste is the Standard one, it is fine with me, just define "none" as event parameter.
In my approach (using none), it is also possible to implement that "if/else" mechanism. See the attached file. We can access the "stored" event parameter in guard functor. (Use the get_param() instead of get_result().) Of course some public interface is required in State1_. There are two different ways of thinking about dependency. A. The event that occurs in the sub state machine is submachine’s concern. If outside state machine want to know which event is occurred in submachine, submachine should provide the proper interface. Of course we can know not only events but also everything occurs in submachine. For example action result in submachine.(See 12_InsideOutsideInfo.cpp) B. Events are the concept separate from state machine (and sub machine). They exist independent. Hence the mechanism should treat events exceptionally. My opinion is A. But I can understand B. What do you think?
The next point to consider is whether to make "none" a default parameter. One one hand, it would make the pseudo exit almost Standard-conform (if we ignore the possible on_entry/on_exit handlers which are not foreseen by the Standard), on the other hand, someone not knowing this finesse of the Standard and providing no event parameter and a normal outer transition with an event will be quite surprised to get no_transition handler calls. I do not favor forcing bugs on msm users (which qualifies as a "complicated mechanism") only to please the Standard.
Thanks, Takatoshi
Regards, Christophe
PS: I just realize this post would be a good addition to a Rationale section ;-)
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Regards, Takatoshi

This is a personal choice but these reasons matter to me more than the extra complexity added by a template parameter. If your taste is the Standard one, it is fine with me, just define "none" as event parameter.
In my approach (using none), it is also possible to implement that "if/else" mechanism. See the attached file.
I think you might have forgotten the file. I'll try to answer without it. Please correct me if I get it wrong. If your plan is to add some guards to the transitions starting from the pseudo exit, this is not UML conform as guards are not allowed there (not that it matters to msm, I usually have great pleasure to ignore the Standard's restrictions ;-) But other tools might care).
We can access the "stored" event parameter in guard functor. (Use the get_param() instead of get_result().) Of course some public interface is required in State1_.
Sure but I'd prefer to avoid this. It means attributes in State1_ which are only valid when the pseudo exit is used.
There are two different ways of thinking about dependency.
A. The event that occurs in the sub state machine is submachine’s concern. If outside state machine want to know which event is occurred in submachine, submachine should provide the proper interface.
I understand but it's not my programming style because, as stated above, it means attributes in the submachine, which are only valid in a certain scenario, meaning in a certain... state of the submachine. These attributes will need a default value, will need to be reset after the call, could be called at a point where they are invalid, will need some special work of the submachine (ex: when to reset them? Just after the transition? When is it? How will the caller know whether they are valid?). Quite some work. I prefer going generic. The main machine has no idea about the event type, only that it provides a certain method. Of course I understand that templates are not everybody's stuff. Luckily, msm allows both ways :) If you feel more comfortable with submachine methods, it's fine.
Of course we can know not only events but also everything occurs in submachine. For example action result in submachine.(See 12_InsideOutsideInfo.cpp)
Sure you can. Whether you want this or not is a matter of taste.
B. Events are the concept separate from state machine (and sub machine). They exist independent. Hence the mechanism should treat events exceptionally.
My opinion is A. But I can understand B. What do you think?
I think I'll need your example to understand this question. Generally, my opinion is that I want the weakest dependency I can get away with. And a dependency to a template method of an event seems to me a weaker one than a dependency to a submachine class. Both ways because the submachine would also have to make some assumptions about the main machine's behaviour. Regards, Christophe

On Mon, 4 Jul 2011 21:42:38 +0200 "Christophe Henry" <christophe.j.henry@googlemail.com> wrote:
This is a personal choice but these reasons matter to me more than the extra complexity added by a template parameter. If your taste is the Standard one, it is fine with me, just define "none" as event parameter.
In my approach (using none), it is also possible to implement that "if/else" mechanism. See the attached file.
I think you might have forgotten the file. I'll try to answer without it. Please correct me if I get it wrong. If your plan is to add some guards to the transitions starting from the pseudo exit, this is not UML conform as guards are not allowed there (not that it matters to msm, I usually have great pleasure to ignore the Standard's restrictions ;-) But other tools might care).
Same here. I completely agree with your stance that overcome the lack of UML standards.
We can access the "stored" event parameter in guard functor. (Use the get_param() instead of get_result().) Of course some public interface is required in State1_.
Sure but I'd prefer to avoid this. It means attributes in State1_ which are only valid when the pseudo exit is used.
Yes. The attributes lifetime is mismatch the valid value. It's an ugly point of this approach.
There are two different ways of thinking about dependency.
A. The event that occurs in the sub state machine is submachine’s concern. If outside state machine want to know which event is occurred in submachine, submachine should provide the proper interface.
I understand but it's not my programming style because, as stated above, it means attributes in the submachine, which are only valid in a certain scenario, meaning in a certain... state of the submachine. These attributes will need a default value, will need to be reset after the call, could be called at a point where they are invalid, will need some special work of the submachine (ex: when to reset them? Just after the transition? When is it? How will the caller know whether they are valid?). Quite some work. I prefer going generic. The main machine has no idea about the event type, only that it provides a certain method. Of course I understand that templates are not everybody's stuff. Luckily, msm allows both ways :) If you feel more comfortable with submachine methods, it's fine.
Of course we can know not only events but also everything occurs in submachine. For example action result in submachine.(See 12_InsideOutsideInfo.cpp)
Sure you can. Whether you want this or not is a matter of taste.
B. Events are the concept separate from state machine (and sub machine). They exist independent. Hence the mechanism should treat events exceptionally.
My opinion is A. But I can understand B. What do you think?
I think I'll need your example to understand this question. Generally, my opinion is that I want the weakest dependency I can get away with. And a dependency to a template method of an event seems to me a weaker one than a dependency to a submachine class. Both ways because the submachine would also have to make some assumptions about the main machine's behaviour.
In the case of event parameter, I completely agree with you. But I'm not sure how to propagate the sub-machine's action result to main-machine without adding the interface to sub-machine. I have two ideas. 1. Using the internal transition. (See 13_PropagateActionResult.cpp Event2) Can I call the member function "process_event" inside the action functor?? (See Line 69) More generally, does the msm provide interfaces that send events to their own state machine? 2. Add the mutable variable to event classes, and modify the variable in action functor. I think it is ugly. If there are no good ideas to do that, your approach solves only event parameter. I think it's too partial. I hope 1 is OK. Or do you have any better ideas?
Regards, Christophe
Thanks, Takatoshi

I think I'll need your example to understand this question. Generally, my opinion is that I want the weakest dependency I can get away with. And a dependency to a template method of an event seems to me a weaker one than a dependency to a submachine class. Both ways because the submachine would also have to make some assumptions about the main machine's behaviour.
In the case of event parameter, I completely agree with you. But I'm not sure how to propagate the sub-machine's action result to main-machine without adding the interface to sub-machine.
I have two ideas. 1. Using the internal transition. (See 13_PropagateActionResult.cpp Event2) Can I call the member function "process_event" inside the action functor?? (See Line 69)
Yes. I didn't try your example out but it looks good.
More generally, does the msm provide interfaces that send events to their own state machine?
Sure. That's one of the main reasons to pass the fsm as parameter to the action.
2. Add the mutable variable to event classes, and modify the variable in action functor. I think it is ugly.
I agree :)
If there are no good ideas to do that, your approach solves only event parameter. I think it's too partial.
I hope 1 is OK. Or do you have any better ideas?
What you are doing should work without problems. As a side note, I like the Guard1 / Not_<Guard1> construct. It's the best way to ensure that guards are mutually exclusive. Regards, Christophe

On Wed, 6 Jul 2011 23:09:37 +0200 "Christophe Henry" <christophe.j.henry@googlemail.com> wrote:
I think I'll need your example to understand this question. Generally, my opinion is that I want the weakest dependency I can get away with. And a dependency to a template method of an event seems to me a weaker one than a dependency to a submachine class. Both ways because the submachine would also have to make some assumptions about the main machine's behaviour.
In the case of event parameter, I completely agree with you. But I'm not sure how to propagate the sub-machine's action result to main-machine without adding the interface to sub-machine.
I have two ideas. 1. Using the internal transition. (See 13_PropagateActionResult.cpp Event2) Can I call the member function "process_event" inside the action functor?? (See Line 69)
Yes. I didn't try your example out but it looks good.
Great! I think it's a typical pattern that propagate sub-machine's information to outside state machine via event mechanism.
More generally, does the msm provide interfaces that send events to their own state machine?
Sure. That's one of the main reasons to pass the fsm as parameter to the action.
2. Add the mutable variable to event classes, and modify the variable in action functor. I think it is ugly.
I agree :)
If there are no good ideas to do that, your approach solves only event parameter. I think it's too partial.
I hope 1 is OK. Or do you have any better ideas?
What you are doing should work without problems.
At first, I was not sure it is correct or not that calling process_event recursively. process_event() -> operator()() -> process_event() But you pointed out it's no problem. I can use the msm mechanism flexibly!
As a side note, I like the Guard1 / Not_<Guard1> construct. It's the best way to ensure that guards are mutually exclusive.
Thanks. I think that your euml functor is also useful outside of euml as DESL. The functor Not_ is suitable for "else". But if we have much more guards, We have to use Or_ functor like this. msme::Not_< msme::Or_< msme::Or_<Guard1, Guard2>, Guard3> > Off the top of my head, how about the functor Else_ below? Else_ <Guard1, Guard2, Guard3, ... >
Regards, Christophe
Thanks, Takatoshi

At first, I was not sure it is correct or not that calling process_event recursively.
process_event() -> operator()() -> process_event()
But you pointed out it's no problem. I can use the msm mechanism flexibly!
It's not really recursive, the second process_event just gets queued until the first completes, but it's just an implementation detail.
I think that your euml functor is also useful outside of euml as DESL.
Right now no, because it can handle only 3 or 4 arguments. But this is going to change soon, I'm working on it.
The functor Not_ is suitable for "else". But if we have much more guards, We have to use Or_ functor like this. msme::Not_< msme::Or_< msme::Or_<Guard1, Guard2>, Guard3> >
Off the top of my head, how about the functor Else_ below? Else_ <Guard1, Guard2, Guard3, ... >
Do you mean a transition with some "if " as guard, followed by a transition with Else_? Hmmm this will be hard to get right but it's an idea. What I have is If_Else_<Condition,Action1,Action2> but only as guard of a single transition. Regards, Christophe

The functor Not_ is suitable for "else". But if we have much more guards, We have to use Or_ functor like this. msme::Not_< msme::Or_< msme::Or_<Guard1, Guard2>, Guard3> >
Off the top of my head, how about the functor Else_ below? Else_ <Guard1, Guard2, Guard3, ... >
For else, we can use the fact that msm tries guards from the bottom of the table to the top: // else clause Row< state1, ev, state2, none, none>, // if clause Row< state1, ev, state2, none, Or_<...> > // more if clauses ... It's not UML-conform, but well ;-) HTH, Christophe

On Mon, 11 Jul 2011 21:31:43 +0200 "Christophe Henry" <christophe.j.henry@googlemail.com> wrote:
The functor Not_ is suitable for "else". But if we have much more guards, We have to use Or_ functor like this. msme::Not_< msme::Or_< msme::Or_<Guard1, Guard2>, Guard3> >
Off the top of my head, how about the functor Else_ below? Else_ <Guard1, Guard2, Guard3, ... >
For else, we can use the fact that msm tries guards from the bottom of the table to the top:
// else clause Row< state1, ev, state2, none, none>, // if clause Row< state1, ev, state2, none, Or_<...> > // more if clauses ...
Fantastic! This has 2 advantages and 1 disadvantage. Advantages: One is simple enough. The other is good performance. It doesn't need evaluating the guard functor twice. I was about to consider how to cache the functor's result. Disadvantage: As you might expect, the evaluating direction is opposite of my intuition. Are there any reasons of this implementation? Modifying to the opposite direction is easy?
It's not UML-conform, but well ;-)
HTH,
Christophe
Regards, Takatoshi

Off the top of my head, how about the functor Else_ below? Else_ <Guard1, Guard2, Guard3, ... >
For else, we can use the fact that msm tries guards from the bottom of the table to the top:
// else clause Row< state1, ev, state2, none, none>, // if clause Row< state1, ev, state2, none, Or_<...> > // more if clauses ...
Fantastic! This has 2 advantages and 1 disadvantage.
Advantages: One is simple enough. The other is good performance. It doesn't need evaluating the guard functor twice. I was about to consider how to cache the functor's result.
Disadvantage: As you might expect, the evaluating direction is opposite of my intuition.
Are there any reasons of this implementation?
There are. It's an implementation detail which dates back to the early phases of the library (start + 3 months). The reason is that msm adds, for performance, rows for submachines at the end of the table (one for every event found in the submachine), then starts processing from the bottom to give these rows a higher priority (UML rule). At the same time, the library also uses the table to generate state ids (http://svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/ch06s03.html). I could do the opposite (extra rows at the beginning) but it'd be pretty hard to guess after this what the state id you get in no_transition means (it's already hard enough to explain the current order, imagine if I had to explain you have to count in reverse order...). And as the else feature is not in the Standard, it seemed ok. In these early phases I didn't have, like now, different steps of transition table processing. This old decision could deserve some revisiting, but: - there are a few corner cases which could make a change pretty tricky (pseudo entry/exit states) - some people already use the current implementation state, so it'd break their code, I'd need some compile-time configuration, which would get hidden deep in the already big doc. The default would still be the current order.
Modifying to the opposite direction is easy?
Unfortunately not, so considering the gain and the time it'd cost, it's unlikely to change until I have nothing else to implement in the library, which could take some time ;-) Regards, Christophe

On Thu, Jul 14, 2011 at 4:48 AM, Christophe Henry <christophe.j.henry@googlemail.com> wrote:
Off the top of my head, how about the functor Else_ below? Else_ <Guard1, Guard2, Guard3, ... >
For else, we can use the fact that msm tries guards from the bottom of the table to the top:
// else clause Row< state1, ev, state2, none, none>, // if clause Row< state1, ev, state2, none, Or_<...> > // more if clauses ...
Fantastic! This has 2 advantages and 1 disadvantage.
Advantages: One is simple enough. The other is good performance. It doesn't need evaluating the guard functor twice. I was about to consider how to cache the functor's result.
Disadvantage: As you might expect, the evaluating direction is opposite of my intuition.
Are there any reasons of this implementation?
There are. It's an implementation detail which dates back to the early phases of the library (start + 3 months). The reason is that msm adds, for performance, rows for submachines at the end of the table (one for every event found in the submachine), then starts processing from the bottom to give these rows a higher priority (UML rule).
I agree. But this UML rule should only apply the submachine structure. I describe more details below.
At the same time, the library also uses the table to generate state ids (http://svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/ch06s03.html). I could do the opposite (extra rows at the beginning) but it'd be pretty hard to guess after this what the state id you get in no_transition means (it's already hard enough to explain the current order, imagine if I had to explain you have to count in reverse order...).
I agree. State id ordering shouldn't be changed.
And as the else feature is not in the Standard, it seemed ok. In these early phases I didn't have, like now, different steps of transition table processing. This old decision could deserve some revisiting, but: - there are a few corner cases which could make a change pretty tricky (pseudo entry/exit states)
I think it isn't corner case. Consider else_usecase.png.(attached file) When we implement choice pseudo state, we often use the else guard. And when we implement this statemachine using msm, we use extra event like the substatemachine case. See else_usecase_converted.png. IMHO, we often meet with this case.
- some people already use the current implementation state, so it'd break their code, I'd need some compile-time configuration, which would get hidden deep in the already big doc. The default would still be the current order.
Current documents refer to only state id order. http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch06s03.html They don't refer to reverse transition evaluation. I believe it's still implement detail. This meas we have a chance to change the evaluation order. Here is my solution. See forward_eval.patch. In dispatch_table.hpp, If the state is submachine state then front_row and Fsm::frow<State, Event> are same. And it appears only front element. The evaluating direction changes by this information. After applying this patch, 14_GuardEvalOrder.cpp(attached file) outputs the result below. Guard1_1 Guard1_2 Guard1_3 Guard1_4 Guard1 Guard2 Guard3 Guard4 Both evaluation priority and order are OK :) But there is another problem that relate to internal transitions. http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch03s02.html#d0e807 The document said internal transitions have the highest priority(as mandated by the UML standard). I checked UML standard. But I couldn't find this rule. (OMG Unified Modeling LanguageTM (OMG UML) Superstructure Version 2.3) I'm guessing you mean below. 15.3.12 StateMachine (from BehaviorStateMachines) === begin quotation === Conflicting transitions It was already noted that it is possible for more than one transition to be enabled within a state machine. If that happens, then such transitions may be in conflict with each other. For example, consider the case of two transitions originating from the same state, triggered by the same event, but with different guards. If that event occurs and both guard conditions are true, then only one transition will fire. In other words, in case of conflicting transitions, only one of them will fire in a single run-to-completion step. Two transitions are said to conflict if they both exit the same state, or, more precisely, that the intersection of the set of states they exit is non-empty. Only transitions that occur in mutually orthogonal regions may be fired simultaneously. This constraint guarantees that the new active state configuration resulting from executing the set of transitions is well-formed. An internal transition in a state conflicts only with transitions that cause an exit from that state. Firing priorities In situations where there are conflicting transitions, the selection of which transitions will fire is based in part on an implicit priority. These priorities resolve some transition conflicts, but not all of them. The priorities of conflicting transitions are based on their relative position in the state hierarchy. By definition, a transition originating from a substate has higher priority than a conflicting transition originating from any of its containing states. The priority of a transition is defined based on its source state. The priority of joined transitions is based on the priority of the transition with the most transitively nested source state. In general, if t1 is a transition whose source state is s1, and t2 has source s2, then: * If s1 is a direct or transitively nested substate of s2, then t1 has higher priority than t2. * If s1 and s2 are not in the same state configuration, then there is no priority difference between t1 and t2. Transition selection algorithm The set of transitions that will fire is a maximal set of transitions that satisfies the following conditions: * All transitions in the set are enabled. * There are no conflicting transitions within the set. * There is no transition outside the set that has higher priority than a transition in the set (that is, enabled transitions with highest priorities are in the set while conflicting transitions with lower priorities are left out). This can be easily implemented by a greedy selection algorithm, with a straightforward traversal of the active state configuration. States in the active state configuration are traversed starting with the innermost nested simple states and working outwards. For each state at a given level, all originating transitions are evaluated to determine if they are enabled. This traversal guarantees that the priority principle is not violated. The only non-trivial issue is resolving transition conflicts across orthogonal states on all levels. This is resolved by terminating the search in each orthogonal state once a transition inside any one of its components is fired. === end quotation === See smd1.png , smd2.png and smd3.png. These are my understanding. And I wrote internal_continue.patch. This modification is to continue evaluating process if evaluated row is internal transition. If my understanding is right, we don't need the following expression. struct Empty : public msm::front::state<> { struct internal_transition_table : mpl::vector< a_internal < cd_detected , Empty, &Empty::internal_action > > {}; }; You can check this behavior using 15_MultiInternalTransition.cpp.
Modifying to the opposite direction is easy?
Unfortunately not, so considering the gain and the time it'd cost, it's unlikely to change until I have nothing else to implement in the library, which could take some time ;-)
I also did the tests. To pass the all tests, it requires some changes. See msm_test.patch. The changes are only ordering of rows. Internal transitions move up in the same start state group. These changes doesn't effect the state ids. After 3 patches are applied, all tests passed. I tested on the following environments. g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3 Microsoft Visual C++ 2008 Express Edition SP1 Could you check my patches?
Regards, Christophe
Thanks, Takatoshi

Off the top of my head, how about the functor Else_ below? Else_ <Guard1, Guard2, Guard3, ... >
For else, we can use the fact that msm tries guards from the bottom of the table to the top:
// else clause Row< state1, ev, state2, none, none>, // if clause Row< state1, ev, state2, none, Or_<...> > // more if clauses ...
Fantastic! This has 2 advantages and 1 disadvantage.
Advantages: One is simple enough. The other is good performance. It doesn't need evaluating the guard functor twice. I was about to consider how to cache the functor's result.
Disadvantage: As you might expect, the evaluating direction is opposite of my intuition.
Are there any reasons of this implementation?
There are. It's an implementation detail which dates back to the early phases of the library (start + 3 months). The reason is that msm adds, for performance, rows for submachines at the end of the table (one for every event found in the submachine), then starts processing from the bottom to give these rows a higher priority (UML rule).
I agree. But this UML rule should only apply the submachine structure. I describe more details below.
Sure but msm implements all those cases.
At the same time, the library also uses the table to generate state ids (http://svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/ch06s03.html). I could do the opposite (extra rows at the beginning) but it'd be pretty hard to guess after this what the state id you get in no_transition means (it's already hard enough to explain the current order, imagine if I had to explain you have to count in reverse order...).
I agree. State id ordering shouldn't be changed.
And as the else feature is not in the Standard, it seemed ok. In these early phases I didn't have, like now, different steps of transition table processing. This old decision could deserve some revisiting, but: - there are a few corner cases which could make a change pretty tricky (pseudo entry/exit states)
I think it isn't corner case. Consider else_usecase.png.(attached file) When we implement choice pseudo state, we often use the else guard. And when we implement this statemachine using msm, we use extra event like the substatemachine case. See else_usecase_converted.png.
IMHO, we often meet with this case.
I'm afraid you misunderstood me. I didn't write that a choice pseudo-state is a corner case but that the change you request has a few corner cases to consider if the implementation is to work.
- some people already use the current implementation state, so it'd break their code, I'd need some compile-time configuration, which would get hidden deep in the already big doc. The default would still be the current order.
Current documents refer to only state id order. http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch06s03.html
They don't refer to reverse transition evaluation. I believe it's still implement detail. This meas we have a chance to change the evaluation order.
No, this is documented (http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch06.html): "the guard conditions are tried in reverse order of their transition definition in the transition table" and I know of a few people using this.
Here is my solution.
See forward_eval.patch.
In dispatch_table.hpp, If the state is submachine state then front_row and Fsm::frow<State, Event> are same. And it appears only front element. The evaluating direction changes by this information. After applying this patch, 14_GuardEvalOrder.cpp(attached file) outputs the result below.
Guard1_1 Guard1_2 Guard1_3 Guard1_4 Guard1 Guard2 Guard3 Guard4
Both evaluation priority and order are OK :)
But there is another problem that relate to internal transitions. http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch03s02.html#d0e807
The document said internal transitions have the highest priority(as mandated by the UML standard). I checked UML standard. But I couldn't find this rule. (OMG Unified Modeling LanguageTM (OMG UML) Superstructure Version 2.3)
I'm guessing you mean below.
15.3.12 StateMachine (from BehaviorStateMachines)
=== begin quotation === Conflicting transitions It was already noted that it is possible for more than one transition to be enabled within a state machine. If that happens, then such transitions may be in conflict with each other. For example, consider the case of two transitions originating from the same state, triggered by the same event, but with different guards. If that event occurs and both guard conditions are true, then only one transition will fire. In other words, in case of conflicting transitions, only one of them will fire in a single run-to-completion step. Two transitions are said to conflict if they both exit the same state, or, more precisely, that the intersection of the set of states they exit is non-empty. Only transitions that occur in mutually orthogonal regions may be fired simultaneously. This constraint guarantees that the new active state configuration resulting from executing the set of transitions is well-formed. An internal transition in a state conflicts only with transitions that cause an exit from that state.
Firing priorities In situations where there are conflicting transitions, the selection of which transitions will fire is based in part on an implicit priority. These priorities resolve some transition conflicts, but not all of them. The priorities of conflicting transitions are based on their relative position in the state hierarchy. By definition, a transition originating from a substate has higher priority than a conflicting transition originating from any of its containing states. The priority of a transition is defined based on its source state. The priority of joined transitions is based on the priority of the transition with the most transitively nested source state. In general, if t1 is a transition whose source state is s1, and t2 has source s2, then: * If s1 is a direct or transitively nested substate of s2, then t1 has higher priority than t2. * If s1 and s2 are not in the same state configuration, then there is no priority difference between t1 and t2. Transition selection algorithm The set of transitions that will fire is a maximal set of transitions that satisfies the following conditions: * All transitions in the set are enabled. * There are no conflicting transitions within the set. * There is no transition outside the set that has higher priority than a transition in the set (that is, enabled transitions with highest priorities are in the set while conflicting transitions with lower priorities are left out). This can be easily implemented by a greedy selection algorithm, with a straightforward traversal of the active state configuration. States in the active state configuration are traversed starting with the innermost nested simple states and working outwards. For each state at a given level, all originating transitions are evaluated to determine if they are enabled. This traversal guarantees that the priority principle is not violated. The only non-trivial issue is resolving transition conflicts across orthogonal states on all levels. This is resolved by terminating the search in each orthogonal state once a transition inside any one of its components is fired. === end quotation ===
Yes, it is probably this.
See smd1.png , smd2.png and smd3.png. These are my understanding. And I wrote internal_continue.patch. This modification is to continue evaluating process if evaluated row is internal transition.
If my understanding is right, we don't need the following expression.
struct Empty : public msm::front::state<> { struct internal_transition_table : mpl::vector< a_internal < cd_detected , Empty, &Empty::internal_action >
{}; };
Are you saying we don't need internal transitions? I'd disagree then. They're the best way to implement taking action without changing state.
You can check this behavior using 15_MultiInternalTransition.cpp.
Modifying to the opposite direction is easy?
Unfortunately not, so considering the gain and the time it'd cost, it's unlikely to change until I have nothing else to implement in the library, which could take some time ;-)
I also did the tests. To pass the all tests, it requires some changes. See msm_test.patch. The changes are only ordering of rows. Internal transitions move up in the same start state group. These changes doesn't effect the state ids.
After 3 patches are applied, all tests passed.
Well, yes, if you change the test, of course it will work ;-)
I tested on the following environments. g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3 Microsoft Visual C++ 2008 Express Edition SP1
Unfortunately my tests are not sufficient, it's something I want to take care of soon.
Could you check my patches?
I did. I'm not sure I fully get what you're trying but I don't think it will work. Again, there are quite some cases to think about. Let's take one, to show why the priority given to inner is important. See conflict_and_exit. If I believe your example in smd1, there is no priority. Then, the exit points cannot work any more (yes, transitions leading to exit points are inner transitions). Frankly, I don't see the point in doing such change: - it will break people's code - it will break a documented implementation - I doubt it will work in all cases - it is likely to be slower (more if statements) - it will not be Standard-conform. To do this, I need a really good reason And this for no bugfix and no added feature, simply to be able to write: // else clause Row< state1, ev, state2, none, none> // if clause Row< state1, ev, state2, none, Or_<...> > instead of: // if clause Row< state1, ev, state2, none, Or_<...> > // else clause Row< state1, ev, state2, none, none> No, this does not look appealing to me. If you're at implementing stuff for msm, I might consider another solution: - a typedef in the front-end, which will change the reading order of the table, no to break other's code - replacing in dispatch_table reverse_fold by fold to change the reading order if typedef is requesting it. - adding rows (frows) at the top instead of bottom. This leaves us with the hard part, reading the ids in the correct order. For this, we need to find out which one of the transition table transformations is the correct one. I didn't look at it yet, but I imagine it could be tricky. Then use it to read the id from up to down. I understand you like this feature, but I need to also consider the wishes of those who requested me very useful features some time ago and are waiting for them. So it's also my job to allocate my scarce development time (my evenings) where I think it will be the most useful. For example, the junction pseudo-state you requested seems to me to have a much higher gain for all of us. Regards, Christophe

On Wed, 20 Jul 2011 00:30:03 +0200 "Christophe Henry" <christophe.j.henry@googlemail.com> wrote:
Off the top of my head, how about the functor Else_ below? Else_ <Guard1, Guard2, Guard3, ... >
For else, we can use the fact that msm tries guards from the bottom of the table to the top:
// else clause Row< state1, ev, state2, none, none>, // if clause Row< state1, ev, state2, none, Or_<...> > // more if clauses ...
Fantastic! This has 2 advantages and 1 disadvantage.
Advantages: One is simple enough. The other is good performance. It doesn't need evaluating the guard functor twice. I was about to consider how to cache the functor's result.
Disadvantage: As you might expect, the evaluating direction is opposite of my intuition.
Are there any reasons of this implementation?
There are. It's an implementation detail which dates back to the early phases of the library (start + 3 months). The reason is that msm adds, for performance, rows for submachines at the end of the table (one for every event found in the submachine), then starts processing from the bottom to give these rows a higher priority (UML rule).
I agree. But this UML rule should only apply the submachine structure. I describe more details below.
Sure but msm implements all those cases.
Yes.
At the same time, the library also uses the table to generate state ids (http://svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/ch06s03.html). I could do the opposite (extra rows at the beginning) but it'd be pretty hard to guess after this what the state id you get in no_transition means (it's already hard enough to explain the current order, imagine if I had to explain you have to count in reverse order...).
I agree. State id ordering shouldn't be changed.
And as the else feature is not in the Standard, it seemed ok. In these early phases I didn't have, like now, different steps of transition table processing. This old decision could deserve some revisiting, but: - there are a few corner cases which could make a change pretty tricky (pseudo entry/exit states)
I think it isn't corner case. Consider else_usecase.png.(attached file) When we implement choice pseudo state, we often use the else guard. And when we implement this statemachine using msm, we use extra event like the substatemachine case. See else_usecase_converted.png.
IMHO, we often meet with this case.
I'm afraid you misunderstood me. I didn't write that a choice pseudo-state is a corner case but that the change you request has a few corner cases to consider if the implementation is to work.
I'm sorry. I omitted too much information. Please let me explain step by step. 1.When the transition process exiting the substatemachine, We sometimes need if/else transition outside of substatemachine. 2.In the case above, we can use the anonymous transitions for else transitions. But we have to write it the top of same start state group in transition table. I think it isn't natural description. And I asked you to change the evaluation order reverse. And then, you said it's difficult. And you showed me some reasons. At that time I didn't know the evaluation order was already documented. Hence, I thought changing the order was not big problem, I thought it's only implementation problem. 3.I consider that anonymous transitions for else transition have wider usage. e.g. For implement choice pseudo states using msm. This is why I said it's not corner case. Sorry for less description.
- some people already use the current implementation state, so it'd break their code, I'd need some compile-time configuration, which would get hidden deep in the already big doc. The default would still be the current order.
Current documents refer to only state id order. http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch06s03.html
They don't refer to reverse transition evaluation. I believe it's still implement detail. This meas we have a chance to change the evaluation order.
No, this is documented (http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch06.html): "the guard conditions are tried in reverse order of their transition definition in the transition table" and I know of a few people using this.
Oh.. I missed it.
Here is my solution.
See forward_eval.patch.
In dispatch_table.hpp, If the state is submachine state then front_row and Fsm::frow<State, Event> are same. And it appears only front element. The evaluating direction changes by this information. After applying this patch, 14_GuardEvalOrder.cpp(attached file) outputs the result below.
Guard1_1 Guard1_2 Guard1_3 Guard1_4 Guard1 Guard2 Guard3 Guard4
Both evaluation priority and order are OK :)
But there is another problem that relate to internal transitions. http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch03s02.html#d0e807
The document said internal transitions have the highest priority(as mandated by the UML standard). I checked UML standard. But I couldn't find this rule. (OMG Unified Modeling LanguageTM (OMG UML) Superstructure Version 2.3)
I'm guessing you mean below.
15.3.12 StateMachine (from BehaviorStateMachines)
=== begin quotation === Conflicting transitions It was already noted that it is possible for more than one transition to be enabled within a state machine. If that happens, then such transitions may be in conflict with each other. For example, consider the case of two transitions originating from the same state, triggered by the same event, but with different guards. If that event occurs and both guard conditions are true, then only one transition will fire. In other words, in case of conflicting transitions, only one of them will fire in a single run-to-completion step. Two transitions are said to conflict if they both exit the same state, or, more precisely, that the intersection of the set of states they exit is non-empty. Only transitions that occur in mutually orthogonal regions may be fired simultaneously. This constraint guarantees that the new active state configuration resulting from executing the set of transitions is well-formed. An internal transition in a state conflicts only with transitions that cause an exit from that state.
Firing priorities In situations where there are conflicting transitions, the selection of which transitions will fire is based in part on an implicit priority. These priorities resolve some transition conflicts, but not all of them. The priorities of conflicting transitions are based on their relative position in the state hierarchy. By definition, a transition originating from a substate has higher priority than a conflicting transition originating from any of its containing states. The priority of a transition is defined based on its source state. The priority of joined transitions is based on the priority of the transition with the most transitively nested source state. In general, if t1 is a transition whose source state is s1, and t2 has source s2, then: * If s1 is a direct or transitively nested substate of s2, then t1 has higher priority than t2. * If s1 and s2 are not in the same state configuration, then there is no priority difference between t1 and t2. Transition selection algorithm The set of transitions that will fire is a maximal set of transitions that satisfies the following conditions: * All transitions in the set are enabled. * There are no conflicting transitions within the set. * There is no transition outside the set that has higher priority than a transition in the set (that is, enabled transitions with highest priorities are in the set while conflicting transitions with lower priorities are left out). This can be easily implemented by a greedy selection algorithm, with a straightforward traversal of the active state configuration. States in the active state configuration are traversed starting with the innermost nested simple states and working outwards. For each state at a given level, all originating transitions are evaluated to determine if they are enabled. This traversal guarantees that the priority principle is not violated. The only non-trivial issue is resolving transition conflicts across orthogonal states on all levels. This is resolved by terminating the search in each orthogonal state once a transition inside any one of its components is fired. === end quotation ===
Yes, it is probably this.
See smd1.png , smd2.png and smd3.png. These are my understanding. And I wrote internal_continue.patch. This modification is to continue evaluating process if evaluated row is internal transition.
If my understanding is right, we don't need the following expression.
struct Empty : public msm::front::state<> { struct internal_transition_table : mpl::vector< a_internal < cd_detected , Empty, &Empty::internal_action >
{}; };
Are you saying we don't need internal transitions? I'd disagree then. They're the best way to implement taking action without changing state.
No. UML's internal transitions are important. Msm provides some options to implement it. Without eUML, functor front-end is preferred. http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch03s03.html#d0e1396 // Start Event Next Action Guard Row < Empty , cd_detected , none , none , internal_guard >, We can describe internal transitions to set Next to none. Is it right? g_irow is almost same. // Start Event Guard g_irow < Empty , cd_detected ,&p::internal_guard> I think they are needed. I only mean internal_transition_table is not mandatory. http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch03s02.html#internal... Because we already have the machanism that controls the evaluation order from inside substatemachine to outside. And UML standard said that internal transitions are not relate to priority. There are no guaranty that internal transitions are evaluated faster than another (non internal) transitions if they have same start state. Consider fig1.png. Thease two transitions have same priority. At least in UML specification, we don't have a guaranty that which transition would be handled. But one of them would be handled. If we want to give the internal transition higher priority, we should write the statemachine like fig2.png. In the case of fig2, only the internal transition would be handled. Do you agree? But we can control the evaluating order using the Row's sequence. (I think it is out of UML standard.) e.g. // Start Event Next Action Guard Row < Empty , cd_detected , none , none , internal_guard >, Row < Empty , cd_detected , State1 , none , another_guard >, or // Start Event Next Action Guard Row < Empty , cd_detected , State1 , none , another_guard >, Row < Empty , cd_detected , none , none , internal_guard >, I'd like to know why internal_transition_table is needed. I think transition_table is enough.
You can check this behavior using 15_MultiInternalTransition.cpp.
Modifying to the opposite direction is easy?
Unfortunately not, so considering the gain and the time it'd cost, it's unlikely to change until I have nothing else to implement in the library, which could take some time ;-)
I also did the tests. To pass the all tests, it requires some changes. See msm_test.patch. The changes are only ordering of rows. Internal transitions move up in the same start state group. These changes doesn't effect the state ids.
After 3 patches are applied, all tests passed.
Well, yes, if you change the test, of course it will work ;-)
Sorry, I was misunderstanding UML specification. My internal_continue.patch is wrong. I misunderstood the sentence that "An internal transition in a state conflicts only with transitions that cause an exit from that state." I thought we could execute multiple internal transitions on one event. But it's not true. I found the sentence below. "In the presence of orthogonal regions it is possible to fire multiple transi tions as a result of the same event occurrence -- as many as one transition in each region in the current state configuration." I pull back internal_continue.patch.
I tested on the following environments. g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3 Microsoft Visual C++ 2008 Express Edition SP1
Unfortunately my tests are not sufficient, it's something I want to take care of soon.
OK.
Could you check my patches?
I did. I'm not sure I fully get what you're trying but I don't think it will work. Again, there are quite some cases to think about. Let's take one, to show why the priority given to inner is important. See conflict_and_exit. If I believe your example in smd1, there is no priority. Then, the exit points cannot work any more (yes, transitions leading to exit points are inner transitions).
Sorry smd1 is based on my misunderstanding of UML specification.
Frankly, I don't see the point in doing such change: - it will break people's code - it will break a documented implementation
I agree.
- I doubt it will work in all cases - it is likely to be slower (more if statements) - it will not be Standard-conform. To do this, I need a really good reason
And this for no bugfix and no added feature, simply to be able to write:
// else clause Row< state1, ev, state2, none, none> // if clause Row< state1, ev, state2, none, Or_<...> >
instead of:
// if clause Row< state1, ev, state2, none, Or_<...> > // else clause Row< state1, ev, state2, none, none>
No, this does not look appealing to me. If you're at implementing stuff for msm, I might consider another solution: - a typedef in the front-end, which will change the reading order of the table, no to break other's code
Thanks for good suggestion. I'd like to consider a little more:)
- replacing in dispatch_table reverse_fold by fold to change the reading order if typedef is requesting it. - adding rows (frows) at the top instead of bottom.
This leaves us with the hard part, reading the ids in the correct order. For this, we need to find out which one of the transition table transformations is the correct one. I didn't look at it yet, but I imagine it could be tricky. Then use it to read the id from up to down.
I understand you like this feature, but I need to also consider the wishes of those who requested me very useful features some time ago and are waiting for them. So it's also my job to allocate my scarce development time (my evenings) where I think it will be the most useful. For example, the junction pseudo-state you requested seems to me to have a much higher gain for all of us.
Yes. I understand your situation. I agree this request is not high priority. And the request is not reasonable enough at this time. Also I'd like to know your design philosophy of msm. I would ask you some questions.
Regards, Christophe
Thanks, Takatoshi

I'm sorry. I omitted too much information. Please let me explain step by step.
1.When the transition process exiting the substatemachine, We sometimes need if/else transition outside of substatemachine. 2.In the case above, we can use the anonymous transitions for else transitions. But we have to write it the top of same start state group in transition table. I think it isn't natural description. And I asked you to change the evaluation order reverse.
And then, you said it's difficult. And you showed me some reasons. At that time I didn't know the evaluation order was already documented. Hence, I thought changing the order was not big problem, I thought it's only implementation problem.
3.I consider that anonymous transitions for else transition have wider usage. e.g. For implement choice pseudo states using msm.
This is why I said it's not corner case. Sorry for less description.
I get it now. Clearly, it is not a corner case. It's even surprising the Standard foresees "else" only for junctions / choices. This would make sense for other cases.
If my understanding is right, we don't need the following expression.
struct Empty : public msm::front::state<> { struct internal_transition_table : mpl::vector< a_internal < cd_detected , Empty, &Empty::internal_action >
{}; };
Are you saying we don't need internal transitions? I'd disagree then. They're the best way to implement taking action without changing state.
No. UML's internal transitions are important. Msm provides some options to implement it.
Without eUML, functor front-end is preferred. http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch03s03.html#d0e1396 // Start Event Next Action Guard Row < Empty , cd_detected , none , none , internal_guard >,
We can describe internal transitions to set Next to none. Is it right?
g_irow is almost same. // Start Event Guard g_irow < Empty , cd_detected ,&p::internal_guard>
I think they are needed.
I only mean internal_transition_table is not mandatory. http://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch03s02.html#internal...
Because we already have the machanism that controls the evaluation order from inside substatemachine to outside.
Strictly speaking, no, it's not mandatory. The goals of internal_transition_table are: - ensure the transitions withing it have a higher priority - make the state more reusable and more useful when reused.
And UML standard said that internal transitions are not relate to priority. There are no guaranty that internal transitions are evaluated faster than another (non internal) transitions if they have same start state.
Consider fig1.png. Thease two transitions have same priority. At least in UML specification, we don't have a guaranty that which transition would be handled. But one of them would be handled.
True, the Standard is vague about this, which caused me some headaches ;-) My decision on this matter is discussable, so please allow me to explain. After thinking hard about it, I came to the conclusion that this was just another variation of the Liskov substitution principle (I do use other sources than the Standard ;-) ). In your fig2, State1 is a submachine. Then its internal transitions have a higher priority, right? Now imagine I redesign it and make it a simple state (your fig1). Then if I follow your interpretation, the priority will change, thus breaking the implicit contract I had with the state machine which State1 was and my behaviour would silently change. This would lead to subtle bugs. In this spirit of this principle, I decided the only logical solution was to treat internal transitions as "more internal" and having a higher priority. Of course I also edged my bets and allowed the variation with transition_table ;-)
If we want to give the internal transition higher priority, we should write the statemachine like fig2.png. In the case of fig2, only the internal transition would be handled.
Do you agree?
No for the reasons I wrote above, but I can't prove you wrong.
But we can control the evaluating order using the Row's sequence. (I think it is out of UML standard.)
It is, but we won't care too much, right? :)
e.g.
// Start Event Next Action Guard Row < Empty , cd_detected , none , none , internal_guard >, Row < Empty , cd_detected , State1 , none , another_guard >, or // Start Event Next Action Guard Row < Empty , cd_detected , State1 , none , another_guard >, Row < Empty , cd_detected , none , none , internal_guard >,
I'd like to know why internal_transition_table is needed. I think transition_table is enough.
See above. Yes it's not needed but I find it pretty useful in everyday's life. This is of course a matter of taste.
If you're at implementing stuff for msm, I might consider another solution: - a typedef in the front-end, which will change the reading order of the table, no to break other's code
Thanks for good suggestion. I'd like to consider a little more:)
Sure :)
- replacing in dispatch_table reverse_fold by fold to change the reading order if typedef is requesting it. - adding rows (frows) at the top instead of bottom.
This leaves us with the hard part, reading the ids in the correct order. For this, we need to find out which one of the transition table transformations is the correct one. I didn't look at it yet, but I imagine it could be tricky. Then use it to read the id from up to down.
I understand you like this feature, but I need to also consider the wishes of those who requested me very useful features some time ago and are waiting for them. So it's also my job to allocate my scarce development time (my evenings) where I think it will be the most useful. For example, the junction pseudo-state you requested seems to me to have a much higher gain for all of us.
Yes. I understand your situation. I agree this request is not high priority. And the request is not reasonable enough at this time.
Oh it is reasonable, I'm just trying to build first what will make the most people happy. To show my point, I am working on: - a rewrite of the ugliest parts of eUML, the current state is not satisfactory - support for thread-safe usage, asio usage, etc. - improving my test coverage I think we all agree that is is badly needed...
Also I'd like to know your design philosophy of msm. I would ask you some questions.
Sure, but for the record, a big part of it is not from me but from a chapter from Dave and Aleksey's book (http://boostpro.com/mplbook). This is the base for MSM. Regards, Christophe

Hi, Christophe <...snip...>
Strictly speaking, no, it's not mandatory. The goals of internal_transition_table are: - ensure the transitions withing it have a higher priority - make the state more reusable and more useful when reused.
I understand your design decision. <...snip...>
And UML standard said that internal transitions are not relate to priority. There are no guaranty that internal transitions are evaluated faster than another (non internal) transitions if they have same start state.
Consider fig1.png. Thease two transitions have same priority. At least in UML specification, we don't have a guaranty that which transition would be handled. But one of them would be handled.
True, the Standard is vague about this, which caused me some headaches ;-) My decision on this matter is discussable, so please allow me to explain. After thinking hard about it, I came to the conclusion that this was just another variation of the Liskov substitution principle (I do use other sources than the Standard ;-) ). In your fig2, State1 is a submachine. Then its internal transitions have a higher priority, right? Now imagine I redesign it and make it a simple state (your fig1). Then if I follow your interpretation, the priority will change, thus breaking the implicit contract I had with the state machine which State1 was and my behaviour would silently change. This would lead to subtle bugs. In this spirit of this principle, I decided the only logical solution was to treat internal transitions as "more internal" and having a higher priority. Of course I also edged my bets and allowed the variation with transition_table ;-)
You introduced new priority rule below. Internal transitions have higher priority than normal(outer) transitions which have same state state. I agree with your additional rule. It's reasonable. BTW, I often want to another expansion below. When internal transitions are invoked, the trigger event isn't consumed and evaluating process continues. But it is another story. <...snip...>
Yes. I understand your situation. I agree this request is not high priority. And the request is not reasonable enough at this time.
Oh it is reasonable, I'm just trying to build first what will make the most people happy. To show my point, I am working on: - a rewrite of the ugliest parts of eUML, the current state is not satisfactory - support for thread-safe usage, asio usage, etc. - improving my test coverage I think we all agree that is is badly needed...
Also I'd like to know your design philosophy of msm. I would ask you some questions.
Sure, but for the record, a big part of it is not from me but from a chapter from Dave and Aleksey's book (http://boostpro.com/mplbook). This is the base for MSM.
Yeah! I have this book. It's translated in Japanese. And on the front of the book, Dave's autograph is exist!! I understand the basic concept of msm, Now I'm digging deeper area.
Regards, Christophe
Thanks, Takatoshi

Hi, Maybe I solved the problem. And of course it keeps your policy. On Wed, 20 Jul 2011 23:01:53 +0200 "Christophe Henry" <christophe.j.henry@googlemail.com> wrote: <...snip...>
And UML standard said that internal transitions are not relate to priority. There are no guaranty that internal transitions are evaluated faster than another (non internal) transitions if they have same start state.
Consider fig1.png. Thease two transitions have same priority. At least in UML specification, we don't have a guaranty that which transition would be handled. But one of them would be handled.
True, the Standard is vague about this, which caused me some headaches ;-) My decision on this matter is discussable, so please allow me to explain. After thinking hard about it, I came to the conclusion that this was just another variation of the Liskov substitution principle (I do use other sources than the Standard ;-) ). In your fig2, State1 is a submachine. Then its internal transitions have a higher priority, right? Now imagine I redesign it and make it a simple state (your fig1). Then if I follow your interpretation, the priority will change, thus breaking the implicit contract I had with the state machine which State1 was and my behaviour would silently change. This would lead to subtle bugs. In this spirit of this principle, I decided the only logical solution was to treat internal transitions as "more internal" and having a higher priority. Of course I also edged my bets and allowed the variation with transition_table ;-)
If we want to give the internal transition higher priority, we should write the statemachine like fig2.png. In the case of fig2, only the internal transition would be handled.
Do you agree?
No for the reasons I wrote above, but I can't prove you wrong.
But we can control the evaluating order using the Row's sequence. (I think it is out of UML standard.)
It is, but we won't care too much, right? :)
e.g.
// Start Event Next Action Guard Row < Empty , cd_detected , none , none , internal_guard >, Row < Empty , cd_detected , State1 , none , another_guard >, or // Start Event Next Action Guard Row < Empty , cd_detected , State1 , none , another_guard >, Row < Empty , cd_detected , none , none , internal_guard >,
I'd like to know why internal_transition_table is needed. I think transition_table is enough.
See above. Yes it's not needed but I find it pretty useful in everyday's life. This is of course a matter of taste.
If you're at implementing stuff for msm, I might consider another solution: - a typedef in the front-end, which will change the reading order of the table, no to break other's code
Thanks for good suggestion. I'd like to consider a little more:)
Sure :)
I introduced new typedef to statemachine class in front-end. See 14_GuardEvalOrder.cpp. (Attached file) class Sm1_ and class State1_ have this new typedef named evaluation_forward. (Line 72 and 171) It's a modifier of evaluation order. If and only if evaluation_forward is defined, the transition table's evaluation order becomes from top to bottom. For your convenience, I prepared two patches. One is for trunk, and the other is for version1.47.0. Before applying patch or evaluation_forward is not defined, the output is below. -----------------
Send Event1 Guard1_1_i_2 Guard1_1_i_1 Guard1_4 Guard1_3 Guard1_2 Guard1_1 Guard1_i_1 Guard1_i_2 Guard1 Guard2 Guard3 Guard4 0
After applyng patch and evaluation_forward is defined, the output is below. -----------------
Send Event1 Guard1_1_i_1 Guard1_1_i_2 Guard1_1 Guard1_2 Guard1_3 Guard1_4 Guard1_i_1 Guard1_i_2 Guard1 Guard2 Guard3 Guard4 0
Of course, state id numbering policy is not changed. Christophe, after your vacation, could you check it? Regards, Takatoshi
participants (3)
-
Christophe Henry
-
Takatoshi Kondo
-
Takatoshi Kondo