Example 06 – Internal operations and timed await: implementing a clock


Sometimes it is useful to implement operations that trigger the asynchronous execution of other operations inside the artifact, which are typically long-term. For instance: a clock artifact can have the start operation, triggering the execution of a long-term counting operation. Such operations are typically internal, i.e. not (necessarily) part of the usage interface, and are annotated with @INTERNAL_OPERATION. To trigger the execution of an internal operation the execInternalOp primitive is provided.

In the following example, an agent creates a clock and uses it.

MAS example06_clock {

  environment:
  c4jason.CartagoEnvironment

  agents:
  clock_user agentArchClass c4jason.CAgentArch;

  classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}

The clock artifact has two usage interface operations – start and stop – and an internal operation count, triggered by start:

public class Clock extends Artifact {

  boolean counting;
  final static long TICK_TIME = 100;

  void init(){
    counting = false;
  }

  @OPERATION void start(){
    if (!counting){
      counting = true;
      execInternalOp("count");
    } else {
      failed("already_counting");
    }
  }

  @OPERATION void stop(){
    counting = false;
  }

  @INTERNAL_OPERATION void count(){
    while (counting){
      signal("tick");
      await_time(TICK_TIME);
    }
  }
}

Highlights:

  • Timed await: await_time primitive belongs to the await primitives: it suspends the execution of the operation until the specified time (in milliseconds) has elapsed (from now). Like in the await case, by suspending the operation, the artifact is made accessible to agents for executing operations and possible changes to its observable state are committed and made observable.

The agent starts a clock, then reacts to ticks generated by it for a certain number of times, and finally stopping it.

!test_clock.

+!test_clock
  <- makeArtifact("myClock","c4jexamples.Clock",[],Id);
     focus(Id);
     +n_ticks(0);
     start;
     println("clock started.").

@plan1
+tick: n_ticks(10)
  <- stop;
     println("clock stopped.").

@plan2 [atomic]
+tick: n_ticks(N)
  <- -+n_ticks(N+1);
     println("tick perceived!").

Highlights:

  • Controllable processes: these features make it possible to exploit artifacts also to implement controllable
    long-term processes, without the need to use agents for this purpose (e.g. clock agent).

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>