A tutorial on commons SCXML subtleties: Implicit Events

Commons SCXML provides some interesting extensions to the current W3C working draft (for commonns SCXML v0.6: http://www.w3.org/TR/2006/WD-scxml-20060124). It generates some internal events automatically which may be used to communicate between different (parallel) regions of a state machine.

Implicit .entry and .exit events

The Commons SCXML implementation generates a .entry event when any state is entered and a .exit when a state is exited. This can be useful e.g. for communication across parallel state machine regions.

Example

We show a state machine with two parallel regions. The "master" state machine triggers on (external) events "someevent" (arriving from somewhere) and changes its state. The "slave" state machine only consists of transitions. It triggers on .entry events of the "master" state machine and saves the current state name into the data model.

Note that this feature a an extension of the current W3C SCXML working draft (commons SCXML v0.6:http://www.w3.org/TR/2006/WD-scxml-20060124).

<scxml
  xmlns="http://www.w3.org/2005/07/scxml"
  version="1.0" 
  initialstate="main"
  id="demo">

  <datamodel>
    <data name="current"/>
  </datamodel>
	
  <state id="main">
    <parallel id="para">
	
      <!-- "master" state machine -->
      <state id="master">
        <initial>
          <transition target="state_1"/>
        </initial>

        <state id="state_1">
          <transition event="someevent" target="state_2"/>
        </state>
        <state id="state_2">
          <transition event="someevent" target="state_3"/>
        </state>
        <state id="state_3">
          <transition event="someevent" target="state_1"/>
        </state>
      </state> <!-- end state master -->
			
      <!-- "slave" state machine -->
      <!-- this state machine acts on .entry events of  our master state machine -->
      <state id="slave">
        <transition event="state_1.entry">
          <assign name="current" expr="'state_1'"/>
        </transition>
        <transition event="state_2.entry">
          <assign name="current" expr="'state_2'"/>
        </transition>
        <transition event="state_3.entry">
  	    <assign name="current" expr="'state_3'"/>
        </transition>
      </state> <!-- end of slave -->
    </parallel> 
  </state> <!-- end of 'main' -->
</scxml>

Implicit .change event

Similarly to the .entry and .exit event the Commons SCXML implementation generates a .change event when a piece of any data model changes, which means one can watch some part of the datamodel for an update for triggering a transition. This is quite useful for communicating across regions etc.

Example

Now we extend the first example by another parallel region "watch_changes" and send the current state to some external process.

<scxml
  xmlns="http://www.w3.org/2005/07/scxml"
  version="1.0" 
  initialstate="main"
  id="demo">

  <datamodel>
    <data name="current"/>
  </datamodel>
	
  <state id="main">
    <parallel id="para">
	
      <!-- "master" state machine -->
      <state id="master">
        <initial>
          <transition target="state_1"/>
        </initial>

        <state id="state_1">
          <transition event="someevent" target="state_2"/>
        </state>
        <state id="state_2">
          <transition event="someevent" target="state_3"/>
        </state>
        <state id="state_3">
          <transition event="someevent" target="state_1"/>
        </state>
      </state> <!-- end state master -->
			
      <!-- "slave" state machine -->
      <!-- this state machine acts on .entry events of  our master state machine -->
      <state id="slave">
        <transition event="state_1.entry">
          <assign name="current" expr="'state_1'"/>
        </transition>
        <transition event="state_2.entry">
          <assign name="current" expr="'state_2'"/>
        </transition>
        <transition event="state_3.entry">
  	    <assign name="current" expr="'state_3'"/>
        </transition>
      </state> <!-- end of slave -->
			
      <!-- watch for data model changes and report to some external component -->
      <state id="watch_changes">
        <transition event="current.change">
          <!-- send our current state name to external component -->
          <send event="state_change" target="external" targettype="sometype" namelist="current"/>
        </transition>
      </state>
    </parallel> 
  </state> <!-- end of 'main' -->
</scxml>
  • No labels