State variables and guard expressions enable specification of protocols in a behaviour section. They specify the selection of one of multiple different actions (see Specifying actions) for an input event.

The state of an interface is composed of the values of all state variables.

The state diagram of an interface takes only the first variable declared into account.

State variable declarations can refer to public types (e.g. defined for use as event return values) or to private type declarations local to the 'behaviour' section. Types can be boolean, integer with limited contiguous range or enumerated.

Guards are boolean expressions based on state variables. 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.

Syntax

Declaring a state variable type based on an enum.

enum State {State1, State2};

Declaring a state variable based on the above type and initialising it:

State state = State.State1;

Declaring a guarded action statement

[state.State1]
{
  action-statement ;
}

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

See Specifying actions for how to declare action statements.

Examples

Simple state machine

This example shows a simple state machine for a siren.

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
      }
    }
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 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;
        }
      }
    }
  }
}

See also: