[msm] internal/external conflicting transitions

Hi Michael, Looks like you are thoroughly testing MSM and I find it great :)
The docs have a section on "Conflicting Transitions". It has two conflicts described:
1. an event enables multiple transitions because multiple guards test valid,
2. an internal and external transition are both enabled
I see a clear definition for the behavior of #1 in the discussion; however, it is not clear that #2 will follow the same rule.
I was maybe unclear with "internal" so let's see if we can converge. With internal, I mean internal to a composite. Suppose we have a fsm named Top containing a state State and a composite Sub. Top has a transition on Event from Sub to State. Sub has 2 states, SubState1 and SubState2 and a transition on Event from SubState2 to SubState1. If the fsm is in the state Sub::SubState2 and Event is detected, we now have a conflict between Sub->State and SubState2->SubState1. UML defines this as a conflict and orders that SubState2->SubState1 wins. It also surprised me a bit until I implemented exit points, which are in themselves a conflict (they are defined as a connection between a transition inside a composite and one outside, triggered by the same event). So, if SubState1 were an exit point, it would still work.
It was actually a little surprising to me that the order <of the transition definitions affected #2. (Well, maybe not surprising ... but not what I wanted). I used the SimpleTutorial to test the behavior with:
a_row < Stopped , play , Stopped , &p::test_conflict >, a_row < Stopped , play , Playing , &p::start_playback >, a_row < Stopped , open_close , Open , &p::open_drawer >,
and
a_row < Stopped , play , Playing , &p::start_playback >, a_row < Stopped , play , Stopped , &p::test_conflict >, a_row < Stopped , open_close , Open , &p::open_drawer >,
The last transition defined "wins" in a conflict.
This is were I'm unsure if I follow you. SimpleTutorial has no composite, so no internal transition so we must be talking about different things. I can, however, still answer about the order of evaluation. UML orders that conflicts be solved by guards which are mutually exclusive, so your machine is currently ill-formed (no guards) and UML says the behavior is undefined and I, as implementer, am allowed to punish you like I wish ;-) Seriously, if you have guards and they are mutually exclusive, your machine is correct and all will work as expected, no matter the order of evaluation. If you still want to know how it works, with pleasure (this is where normal users could stop reading ;-) ). First, for every event used inside a composite, MSM adds a forwarding row at the end of your table (at the end, so they have no influence on the state index calculation system). Then, for a given event, MSM iterates at compile-time through the STT, from back to front and replaces the conflicts by a new row containing all of the conflicts (this is were your compiler suffers). Thus, transitions internal to a composite are given higher priority in the evaluation. This also means that for "normal" conflicts, the last transition wins. I was already asked if I would change it. It is implementation-specific so you should not rely on it, but it is very unlikely that I will ever want to change it. I hope I brought enough elements to bring clarity. If not, please let me know. Christophe

Christophe Henry wrote:
Hi Michael,
Looks like you are thoroughly testing MSM and I find it great :)
I'm hoping to test it thoroughly. I'm an HFSM geek and ROOM/UML implementations are part of my livelihood. I'm enjoying getting to know your library.
2. an internal and external transition are both enabled
I see a clear definition for the behavior of #1 in the discussion; however, it is not clear that #2 will follow the same rule.
<snip>
I was maybe unclear with "internal" so let's see if we can converge. With internal, I mean internal to a composite. Suppose we have a fsm
Ok. So I think this is part of the issue. As you know, UML defines three types of states: simple, composite and submachines. It appears that MSM implements simple and maybe submachines. I'm still unclear on what MSM exactly has and will write another email on the subject after I have sorted it all out. For our purposes... lets just talk about simple states. Transitions can be either internal or external. Even for simple states. An internal transition in a simple state will never execute exit or entry code. <snip>
This is were I'm unsure if I follow you. SimpleTutorial has no composite, so no internal transition so we must be talking about different things.
And this is where I was unclear. A better question would be: For a simple state, how do I create an internal transition?
I can, however, still answer about the order of evaluation. UML orders that conflicts be solved by guards which are mutually exclusive, so your machine is currently ill-formed (no guards) and UML says the behavior is undefined and I, as implementer, am allowed to punish you like I wish ;-)
Indeed. I was trying to determine what the punishment was going to be (o; Specifically I was wanting to know the behavior when there was an internal/external transition conflict. Though that was not what I had implemented in my test (my mistake). This also disturbs me a bit... though it isn't your problem. Bran Selic for some reason changed this behavior in UML. It used to be much more well defined. Internal transitions were always evaluated before external transitions.
If you still want to know how it works, with pleasure (this is where normal users could stop reading ;-) ). First, for every event used inside a composite, MSM adds a forwarding row at the end of your table (at the end, so they have no influence on the state index calculation system). Then, for a given event, MSM iterates at compile-time through the STT, from back to front and replaces the conflicts by a new row containing all of the conflicts (this is were your compiler suffers). Thus, transitions internal to a composite are given higher priority in the evaluation. This also means that for "normal" conflicts, the last transition wins. I was already asked if I would change it. It is implementation-specific so you should not rely on it, but it is very unlikely that I will ever want to change it.
I hope I brought enough elements to bring clarity. If not, please let me know.
Perfect! This is what I wanted to know. I think it would be helpful to describe the run-to-completion semantics (including the ordering) in the documentation as well as a summary of rules for conflict resolution. I do like the "last transition wins" rule you have created. I also understand defining it as undefined (implementation-specific) behavior. michael -- ---------------------------------- Michael Caisse Object Modeling Designs www.objectmodelingdesigns.com
participants (2)
-
Christophe Henry
-
Michael Caisse