Previous: , Up: Applications of ‘async'   [Contents]


6.2.3 Armour for a missing synchronous out-event

image

A Dezyne component has a requires port where a synchronous out-event is expected in response to an in-event. The type of this port is the strict interface IStrict. We armour for the situation where the foreign component that implements this interface potentially violates this requirement by defining a robust interface IRobust that is more forgiving. You can see in the code below that the IRobust interface has one additional statement to describe the situation that the in-event does not result in a synchronous out-event. The Armour component maps the IRobust on the IStrict by simply ignoring the error.

interface IStrict
{
  in void ia();
  out void oa();

  behaviour
  {
    on ia: oa;
  }
}

interface IRobust
{
  in void ia();
  out void oa();

  behaviour
  {
    on ia: oa;
    on ia: {}
  }
}

extern str $char*$;
interface ILogger
{
  in void Log(str msg);

  behaviour {
    on Log: {}
  }
}

component ArmourMSOE {
  provides IStrict pStrict;
  requires IRobust rRobust;
  requires injected ILogger iLog;

  behaviour {
    requires dzn.async p;

    on pStrict.ia(): blocking {rRobust.ia(); p.req();}
    on rRobust.oa(): {pStrict.reply(); pStrict.oa(); p.clr();}
    on p.ack(): {pStrict.reply(); pStrict.oa(); iLog.Log($"Foreign comp does not send sync out-event oa"$);}
  }
}

component Dezyne {
  provides IA pp;
  requires IStrict rStrict;

  behaviour {
    on pp.ia(): blocking {rStrict.ia();}
    on rStrict.oa(): {pp.reply(); pp.oa();}
  }
}

interface IA
{
  in void ia();
  out void oa();

  behaviour
  {
    on ia: oa;
  }
}

component Foreign {
  provides IRobust pRobust;
  requires IRobust r;
}

component ArmouredSystemMSOE {
  provides IA pp;
  requires IRobust ir;

  system {
    Dezyne re;
    ArmourMSOE am;
    Foreign n;

    pp <=> re.pp;
    re.rStrict <=> am.pStrict;
    am.rRobust <=> n.pRobust;
    n.r <=> ir;
  }
}

We use both the blocking and async keyword in this example in order to detect the situation that the synchronous out-event is missing. The blocking keyword is used to guarantee that the armour only gives control back to the caller after it is sure that a potential violation is captured and dealt with. With the async we raise an internal event req’. It fires after all processing of the current context has been completed. So before it fires, a synchronous out-event may happen. In the normal case where the synchronous out-event happens we pass it on through the IStrict interface and cancel the async event. This is the happy flow. If no such synchronous out-event fires in the armour then eventually the ‘ack’ event fires and the interface violation can be dealt with. In this example the armour simply logs the error and generates a synchronous out-event on its own to satisfy the IStrict requirement. The reply statement in both situations lifts the blocking situation so after completion of the statement block control is passed back to the caller.

image

Handling the interface violation in the Armour component


Previous: , Up: Applications of ‘async'   [Contents]