Re: [scxml] sixth WD of SCXML is published

Jim Barnett wrote:
> Greg,
>   We will reply to the rest of your comments as we have time to review
> them.  Here are responses to a few of them:

Yes, sorry about that. I admit it was a bit of a brain dump. No rush.

> 5. Section 9 on IDs does not specify the scope of uniqueness
>>> The section states:  "The values of all attributes of type "id" MUST
> be unique within the session."  

Sorry, yes; my mistake. I guess what I really meant was "Is there any 
context in which uniqueness of IDs over types of objects that are 
effectively disjoint (such as states vs. data model fields) is 
important, or is this mainly just for general readability and ambiguity 
prevention?" (If you had something like "typeof('abc')=='state'" and 
"typeof('def')=='datafield'", for example, then this would be a clear 
situation where two different types of object should not be able to have 
the same ID).

Or is it just that it's simpler for a parser to validate a document 
using ID/IDREF than one with a bunch of different schema keys?

> 7. The algorithm seems to potentially run into infinite recursion on
> default history state transitions if multiple default history state
> transition targets create a circuit
>>>  We will look at this more closely, but in general SCXML and all
> other state machine languages are so rich in possibilities for infinite
> loops that we can never hope to eliminate all of them.

Of course. This one in particular just seemed to be something that was 
easily detectable or preventable with a rule change.

>>> yes, the intent was 'descendant', so we would like to hear about the
> issues with <initial> and <parallel>

OK. First off is just a little inconsistency between section 3.5.2 and 
the sections which describe @initial (3.1.1 and 3.2.1). Section 3.5.2 
says "must be a descendant", but with @initial being of type IDREFS, I'm 
guessing this should be "must be one or more descendants" (or however 
you want to word it to work in a mention of <parallel> -- maybe even 
just copying the text from the descriptions of @initial).

Now, more importantly: <parallel> does not currently allow <initial>, 
but given the definition of <initial>, it seems like it could 
potentially serve a valid purpose.

The first such reason would be executable content. You might say that 
parallel/onentry could already handle this, but remember that <onentry> 
cannot be skipped by transitions, whereas transitions that directly 
target child states will skip the initial/transition executable content 
of those states' ancestors.

The second reason is a little more involved, but it's along those same 
lines. As you've confirmed for me, initial transition targets must be 
descendants of the <initial> parent's element -- not necessarily direct 
children:

<state name="S1" initial="S3">
   <state name="S2">
     <initial>
       <transition target="S3">
         <log expr="'Passed through S2'" />
       </transition>
     </initial>

     <state name="S3" />
   </state>
</state>

In other words, in the case above, entering S1 directly would mean 
entering S3 directly, skipping over S2's initial transition (i.e. S2 is 
not added to statesForDefaultEntry in the algorithm), and the <log> 
would not be executed.

Now, presumably (and please correct me if I'm wrong on this) <parallel> 
does not allow <initial> because when a parallel state is entered, all 
of its children are entered as well. But this means all children trigger 
their initial transition (because they're all added to 
statesForDefaultEntry). True, there is no difference in functionality if 
you were to have an @initial that specified only direct child states, 
but as above, specifying one or more states at the grandchild level or 
deeper WOULD have an effect:

<parallel state="P1" initial="S3">
   <state name="S1" />
   <state name="S2">
     <initial>
       <transition target="S3">
         <log expr="'Passed through S2'" />
       </transition>
     </initial>

     <state name="S3" />
   </state>
</parallel>

In this case above, upon entering P1, S1 and S3 would be entered, and 
again S2's initial transition would be skipped over. (This also means 
initial="S3" is the same as initial="S1 S3", and not specifying an 
initial transition is the same as "S1 S2").

Of course, the same effect could be achieved by wrapping the <parallel> 
in a <state initial="S3">, but this seems like an unnecessary extra 
step. It also means that if you're making use of parallel/state/final, 
the "done.state.*" event does not have the same ID as the wrapper <state>.

> 4. What are the semantics of the in() predicate in any of the
> intermediate places where executable content is used? What I mean by
> this is that just about everywhere that executable content is used
> except for transition/@cond, the current state configuration is in the
> middle of being modified (onentry, onexit, (state |
> parallel)/transition, initial/transition).
> If the answer here is "add/remove states in the configuration when the
> algorithm says so," then OK. I just wanted to make sure, since 8.1,
> 10.2.5.1, and 10.3.4.1 don't say anything about this.
> 
>>> Yes, the intent is to add/remove states following the algorithm.

OK. With that in mind, would you see any benefit to pre- and 
post-microstep versions of in()? That is, during <transition>, 
<onentry>, or <onexit>, the former would enable access to the state 
configuration from before the microstep began, and the latter would 
enable access to what the state configuration will be when the microstep 
completes. I say that for reasons of parallel states such as the following:

<parallel>
   <state id="SA">
     <state id="SA1">
       <transition event="move" target="SA2" />
     </state>
     <state id="SA2" />
   </state>
   <state id="SB">
     <state id="SB1">
       <onexit>
         <if cond="in('SA1')"><log expr="'In SA1'"/></if>
         <if cond="in('SA2')"><log expr="'In SB1'"/></if>
         <if cond="in('SB1')"><log expr="'In SB1'"/></if>
         <if cond="in('SB2')"><log expr="'In SB2'"/></if>
         <if cond="in('SC1')"><log expr="'In SC1'"/></if>
         <if cond="in('SC2')"><log expr="'In SC2'"/></if>
       </onexit>
       <transition event="move" target="SB2" />
     </state>
     <state id="SB2" />
   </state>
   <state id="SC">
     <state id="SC1">
       <transition event="move" target="SC2" />
     </state>
     <state id="SC2" />
   </state>
</parallel>

Assuming a configuration containing "SA1 SB1 SC1", the "move" event will 
trigger all three transitions. However, in SB1's <onexit>, we get the 
log entries "In SB1" and "In SC1" -- SA1 has already been exited, 
leaving no trace that we used to be there, whereas SC1 gives no 
indication that it is also about to be exited. This means In() has a 
dependency on document order that I believe could be eliminated.

> 9. Are there any plans for state machine instance serialization? i.e. I 
> want to take a running instance, save its configuration, history states,
> 
> event queue, etc. to a byte array, and then restore it at a later time
> 
>>> We have discussed this and think it's out of scope, at least for the
> first version of the spec. We expect that most implementations will
> support something like this, and are interested in suggestions for
> things that we could add to the spec to make serialization easier, but
> we don't see the need for a standard serialization format at the moment.

I figured as much. No complaints here; an extension is just fine. I am 
interested myself in what other implementations have done with this (if 
anything).

> = Jim Barnett

Thanks for your reply.

-- Greg

Received on Thursday, 12 November 2009 01:24:10 UTC