scxml

how to define a subroutine in scxml


I'm trying to figure out how a subroutine can be coded in SCXML. As soubroutine I mean a process/routine/function that can be called from different processes (states) and returns to the caller.

At first I tried with history states but on return the the caller state will restart so entering in loop. That's the sketch.

<scxml>
   <final id="Final">
      <onexit>
         <transition target="ProcA" />
         <transition target="ProcB" />
      </onexit>
   </final>
   <state id="Sub">
      <transition target="History" />
   </state>
   <state>
      <history id="History" />
      <final id="ProcA">
         <onexit>
            <transition target="Sub" />
         </onexit>
      </final>
      <final id="ProcB">
         <onexit>
            <transition target="Sub" />
         </onexit>
      </final>
   </state>
</scxml>

Solution

  • The short answer is to use SCXML’s invoke tag, which allows the interpreter to spawn a new SCXML session. Invoke is also extensible through the type attribute, so it can spawn other kinds of subprocesses, if the interpreter supports that. The semantics of invoke require the parent session to wait in the state where the invoked session was started, until the invoked session reaches a final state. You can see a short example of two sessions invoked in parallel and communicating with each other using SCXML’s send tag here:

    https://jsbin.com/hegiyuk/edit?output

     <scxml 
        datamodel="ecmascript"
        xmlns="http://www.w3.org/2005/07/scxml"
        version="1.0">
        <parallel id="p">
            <state id="1">
            <invoke id="session_1">
                <content>
                <scxml 
                  datamodel="ecmascript"
                  xmlns="http://www.w3.org/2005/07/scxml"
                  version="1.0">
                    <state id="session-1-foo">
                      <onentry>
                        <log label="here1"/>
                        <send event="ping-from-1" delay="2s" target="#_session_2"/>
                      </onentry>
                      <transition event="ping-from-2" target="session-1-bar"/>
                    </state>
                    <state id="session-1-bar">
                      <onentry>
                        <log label="here3"/>
                        <send event="pong-from-1" delay="2s"  target="#_session_2"/>
                      </onentry>    
                      <transition event="pong-from-2" target="session-1-foo"/>    
                    </state>              
                </scxml>
              </content>
            </invoke>
          </state>
          <state id="2">
            <invoke id="session_2">
                <content>
                <scxml 
                  datamodel="ecmascript"
                  xmlns="http://www.w3.org/2005/07/scxml"
                  version="1.0">
                    <state id="session-2-foo">
                      <onentry>
                        <log label="here2"/>
                        <send event="ping-from-2" delay="2s" target="#_session_1"/>
                      </onentry>
                      <transition event="ping-from-1" target="session-2-bar"/>
                    </state>
                    <state id="session-2-bar">
                      <onentry>
                        <log label="here4"/>
                        <send event="pong-from-2" delay="2s"  target="#_session_1"/>
                      </onentry>    
                      <transition event="pong-from-1" target="session-2-foo"/>    
                    </state>              
                </scxml>
              </content>
            </invoke>      
          </state>
        </parallel>
    </scxml>