We’re here to help you

Menu

Using 'async'

dzn.async

(since 2.3.4)

The 'dzn.async' interface represents a component implemented in the Dezyne runtime. Its purpose is to provide an out-event in a new call context without relying on an event from the environment.

interface dzn.async
{
  in void req(<data parameter declaration>...);
  in void clr();
  out void ack(<data parameter declaration>...);

  behaviour
  {
    bool armed = false;

    on clr: armed = false;
    [!armed] on req: armed = true;
    [armed]
    {
      on req: illegal;
      on inevitable: { ack; armed = false; }
    }
  }
}

'dzn.async' port instantiation must appear as a 'requires' port declaration statement inside a component 'behaviour' statement. Instances of the dzn.async interface are private to the component. The dzn.async instances do not appear in the 'system view' and 'sequence view'.

The 'req' and 'ack' events can carry data parameters. Parameter values passed into the 'req' in-event are passed into the related 'ack' out-event. The parameter types are specified as template parameters in the port declaration statement.

The 'inevitable' triggering the 'ack' out-event has priority over the 'optional' and 'inevitable' in all normal requires ports. Thus, after the 'req' call returns the 'ack' event is guaranteed to arrive before any other asynchronous requires port out-event. In case multiple 'dzn.async' instances are used the 'ack' events occur in the same order in which the respective 'req' events were called.

Components with ports of type 'requires dzn.async' must be contained in a Using a Thread-safe shell.

Syntax

requires dzn.async() p; (1)
requires dzn.async p (2)
requires dzn.async(T t) p; (3)

Explanation:

for (1): Create a requires port 'p' of type dzn.async where the 'req' and 'ack' events have no data parameters.

for (2): Short-hand notation for 1).

for (3): Create a requires port 'p' of type dzn.async where the 'req' and 'ack' events have a single data parameter 't' of type 'T'.

Examples

Basic use of 'dzn.async' with a single parameter

extern T $int$;

interface i
{
  in void e(T t);
  in void c(T t);
  out void a(T t);

  behaviour
  {
    bool idle = true;
    [idle]
    {
      on e: idle=false;
      on c: illegal;
    }
    [!idle]
    {
      on c: idle=true;
      on inevitable: { idle=true;a; }
      on e: illegal;
    }
  }
}

component async_cancel
{
  provides i p;

  behaviour
  {
    requires dzn.async(T t) defer;

    bool idle = true;

    [idle] on p.e (t): { idle=false; defer.req (t); }
    [!idle] on p.c (t): { idle=true; defer.clr (); }
    [!idle] on defer.ack (t): { idle=true;p.a (t); }
  }
}

Component relying on 'dzn.async' out-event ordering

interface IAsync
{
  in void e();
  in void c();
  out void cb1();
  out void cb2();

  behaviour
  {
    bool idle = true;
    bool first = true;

    [idle]
    {
      on e: { idle = false; first = true; }
      on c: {}
    }
    [!idle && first]
    {
      on e: illegal;
      on c: idle = true;
      on inevitable: { cb1; first = false; }
    }
    [!idle && !first]
    {
      on e: illegal;
      on c: idle = true;
      on inevitable: { cb2; idle = true; }
    }
  }
}

subint int {0..2};
extern foo $int$;

component async_order
{
  provides IAsync p;

  behaviour
  {
    requires dzn.async i1;
    requires dzn.async i2;
    int num = 0;

    [num==0]
    {
      on p.e(): { i1.req(); i2.req(); num = 2; }
      on p.c(): {}
    }
    [num>0]
    {
      on p.e: illegal;
      on p.c(): { i1.clr(); i2.clr(); num = 0; }
      on i1.ack(): { p.cb1(); num = num-1; }
      on i2.ack(): { p.cb2(); num = num-1; }
    }
  }
}

Convert synchronous requires port to asynchronous provides port

component Async
{
  provides IAsync pp;
  requires ISync rp;

  behaviour
  {
    requires dzn.async r;
    bool armed = false;

    [!armed] on pp.ia(): { armed = true; r.req(); }
    [armed] on pp.ia(): illegal;
    on r.ack(): { bool b = rp.ia(); if (b) pp.ot(); else pp.of(); armed = false; }
  }
}

interface ISync
{
  in bool ia();

  behaviour
  {
    on ia: reply(true);
    on ia: reply(false);
  }
}

interface IAsync
{
  in void ia();
  out void ot();
  out void of();

  behaviour
  {
    bool b = false;

    [!b] on ia: b = true;
    [b] on ia: illegal;
    [b] on inevitable: { b = false; ot; }
    [b] on inevitable: { b = false; of; }
  }
}

Provides port in-event triggers out-event on other provides port

An in-event on a provides port is not allowed to directly refine a modelling event on another provides port.(See Out Events On Provided Port Not Allowed)

A 'dzn.async' instance can be used to satisfy the requirement that a call context may communicate over at most one provides port.

component Async_ForkProvidesIn
{
  provides IA ppa;
  provides IA ppb;

  behaviour
  {
    requires dzn.async reflector_a;
    requires dzn.async reflector_b;

    on ppa.ia(): {reflector_b.clr(); reflector_b.req();}
    on ppb.ia(): {reflector_a.clr(); reflector_a.req();}
    on reflector_a.ack(): ppa.oa();
    on reflector_b.ack(): ppb.oa();
  }
}

interface IA
{
  in void ia();
  out void oa();
  behaviour
  {
    on ia: {}
    on optional: oa;
  }
}

Broadcast requires port out-event to multiple provides ports

A 'dzn.async' instance can be used to satisfy the requirement that a call context may communicate over at most one provides port. In this example the call context associated with a requires port modelling event is used to trigger out-events over multiple provides ports.

component Async_ForkRequiresOut
{
  provides IA ppa;
  provides IA ppb;
  requires IB rp;

  behaviour
  {
    requires dzn.async() reflector;

    on ppa.ia(): rp.ib();
    on ppb.ia(): rp.ib();
    on rp.ob(): { reflector.req(); ppb.oa(); }
    on reflector.ack(): ppa.oa();
  }
}

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

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

interface IB
{
  in void ib();
  out void ob();

  behaviour
  {
    bool is_active = false;
    on ib: is_active = true;
    [is_active] on inevitable: { ob; is_active = false; }
  }
}

If you have questions that weren’t answered by this Guide,
let our support team help you out.

Enjoy this article? Don't forget to share.
google-site-verification:google656c7703ab521151.html