Menu

Specifying Actions

The actions an interface or component should perform when an event is received are specified within a Specifying behaviour.

Actions can be changing the value of a variable, invoking a function, generating another event or changing to another state and any combination.

In response to one event trigger, there can be different actions to be taken as long as they have non-overlapping guards. Guards are boolean expressions. The statement behind the guard is selected when the expression evaluates to true. The keyword 'otherwise' defines a catch-all guard which is true only when none of the other guard expressions in a list of guarded statements evaluates to true.

Note that the use of guards is reserved for action selection. The guards in combination with the trigger event determine which action is activated. Thus, the action is a (compound) statement inside an on event statement (optionally) behind an innermost guard.

Syntax

Declaring an action statement:

on intf1.evt1(), intf2.evt2():
{
  action-body;
}

Here 'intf1.evt1' and 'intf2.evt2' are event instances, which refer to interface variables 'intf1' and 'intf2' and to events 'evt1' and 'evt2'.

Intentionally the 'Statement' will be executed when one of the two triggers occurs.

action-body: a collection of conditions / guards and statements (function invocations, changing variable values, changing to another state, setting a reply value, generating another event, marking the event as illegal) that define what actions to perform.

Declaring a guarded action statement:

[state.State1]
on intf1.evt1(), intf2.evt2():
{
  action-body;
}

Here the action statement will only be selected when guard [state.State1] evaluates to true.

Special action statements can defined that will be performed in case no other events occur, or that optionally may be performed in case no other events occur, see Using inevitable and optional.

Examples

Simple state machine with guarded action statements

This example shows a simple state machine for a siren.

Here the value of a variable representing the state of the state machine is used as a guard to select which action statements to evaluate.

interface Siren
{
  in void TurnOn();
  in void TurnOff();

  behaviour
  {
    enum State { SirenOff, SirenOn }; // type declaration
    State state = State.SirenOff;     // variable declaration

    [state.SirenOff] // if the Siren is off, only allow to turn it on
    {
      on TurnOn:  state = State.SirenOn;
      on TurnOff: illegal;
    }
    [state.SirenOn] // if the Siren is on, only allow to turn it off
    {
      on TurnOff: state = State.SirenOff;
      on TurnOn:  illegal;
    }
  }
}

Two alternative styles to define actions based on events

This example shows an interface with two alternative styles to define the actions based on incoming events.

interface IPsm
{
  in void connect();
  in void disconnect();
  out void connected();
  out void error();

  behaviour
  {
    enum ProtocolState {Disconnected, Connected}; // type declaration
    ProtocolState state = ProtocolState.Disconnected; // variable declaration
    bool isError = false; // variable declaration
    // Alternative 1: using guards based on e.g. state value inside the action statements
    on connect:
    {
      // Select action to be performed based on state variable values.
      [state.Disconnected && !isError]
      { // Action
        connected; // Output event
        state = ProtocolState.Connected; // Assign to state variable
      }
      [otherwise]
      { // Action
        error; // Output event
        isError = true; // Assign to state variable
      }
    }

    // Alternative 2: using guards based on state variable outside the action statements
    {
      [state.Connected]
      {
        on disconnect:
        {
          [isError]
          { // Action
            isError = false;
          }
          [otherwise]
          { // Action
            state = ProtocolState.Disconnected;
          }
        }
      }
      [otherwise]
      {
        on disconnect:
        {
          error;
          isError = true;
        }
      }
    }
  }
}
Enjoy this article? Don't forget to share.