Previous: Component reply, Up: Component Imperative Statements   [Contents][Index]
deferdefer is a keyword that may be placed in front of an imperative
statement.
defer-statement
              ::= "defer" argument-list? imperative-statement
argument-list ::= "(" ")" | "(" expression ("," expression)* ")"
defer indicates that the execution of the corresponding statement
must be postponed at least until after returning back to the
caller. Note that in order for the deferred statement to execute, the
surrounding system must have reached an overall state where it can
accept new activating events, i.e., this state is a system wide run to
completion state.
The primary goal of defer is to decouple the execution of an
imperative statement from the caller.  This allows implementing an
asynchronous interface almost as concisely as implementing it
synchronously, as demonstrated by the example below.
interface ihelloworld
{
  in void hello ();
  out void world ();
  behavior
  {
    bool idle = true;
    on hello: world;
    [idle] on hello: idle = false;
    [!idle] on inevitable: {
      idle = true;
      world;
    }
  }
}
component synchronous_asynchronous
{
  provides ihelloworld h;
  behavior
  {
    bool synchronous = false;
    [synchronous] on h.hello (): h.world ();
    [!synchronous] on h.hello (): {
      synchronous = true;
      defer {
        synchronous = false;
        h.world ();
      }
    }
  }
}
Here we can observe the difference between synchronous and asynchronous
behavior once more.  When the synchronous boolean equals
true the world action occurs in the context, e.g. between
the hello and its return.  When synchronous equals
false the world action occurs after the return.
This behavior is clearly depicted by the following state diagram.
 
Perhaps the idle state might seem superfluous in the example
above, however it is not.  Besides resulting in component behavior which
is not compliant with its interface, removing the idle state and
the corresponding guard would allow a client to do multiple consecutive
h.hello’s, which results in an overflow of the defer queue.
Besides state playing a role in avoiding defer queue overflow,
there is another aspect related to state and the use of defer.
In order for the deferred statement to execute, the component must
remain in the same state as it was at the time of invoking defer.
Anything that changes the state of the component after invoking
defer but before the deferred statement executes will remove it
from the queue, and thereby implicitly cancel it.  This is demonstrated
by the example below.  Note that a data member variable is not part of
the component state, and changing its value does not cancel the deferred
statement.
interface ihellocruelworld
{
  in void hello ();
  in void cruel ();
  out void world ();
  behavior
  {
    bool idle = true;
    [idle] on hello: idle = false;
    [!idle] on inevitable: {
      idle = true;
      world;
    }
    on cruel: idle = true;
  }
}
component defer_cancel
{
  provides ihellocruelworld h;
  behavior
  {
    bool idle = true;
    [idle] on h.hello (): {
      idle = false;
      defer {
        idle = true;
        h.world ();
      }
    }
    on h.cruel (): idle = true;
  }
}
Here we see that the cruel event makes the component idle
again and in compliance with the interface this implies that the
world event can no longer occur.  The corresponding component
state diagram is depicted below.
 
The ability to cancel a deferred statement is not always desirable. The
way to influence the skip behavior is to add an argument list of state
variables to the defer keyword.  This limits the scope of the
state which is observed by defer in deciding when to skip the
execution.  The two extreme cases are:
defer without
an arument list.
We can see an example of a defer argument list below.
interface ihelloworld
{
  in void hello ();
  out void world ();
  behavior
  {
    bool idle = true;
    on hello: world;
    [idle] on hello: idle = false;
    [!idle] on inevitable: {
      idle = true;
      world;
    }
  }
}
interface icruel
{
  in void cruel();
  behavior
  {
    on cruel: {}
  }
}
component defer_selection
{
  provides ihelloworld h;
  provides icruel c;
  behavior
  {
    bool synchronous = false;
    bool cruel = false;
    on c.cruel(): cruel = !cruel;
    [synchronous] on h.hello (): h.world ();
    [!synchronous] on h.hello (): {
      synchronous = true;
      defer(synchronous) {
        synchronous = false;
        h.world ();
      }
    }
  }
}
Here the execution of the deferred statement must remain unaffected by
the change to the cruel state variable. We can achieve this by
only observing the state variable as the example shows or not
observing any state at all.  The latter case is left as an exercise to
the reader.
Previous: Component reply, Up: Component Imperative Statements   [Contents][Index]