
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