Example 05 – Structured Operations

In order to realise complex operations, a family of primitives (called await) is provided to suspend the execution of an operation until some specified condition is met, breaking the execution of an operation in multiple transactional steps. By suspending the execution of an operation, other operations can be invoked before the current one is terminated. When the specified condition holds and no operations are in execution, the suspended operation is resumed. Complex operations which can be implemented by using this mechanism include:

  • long-term operations which need not to block the use of the artifact;
  • concurrent operations i.e. operations whose execution must overlap, which are essential for realising coordination mechanisms and functionalities.

In the following example, two agents share and concurrently use an artifact, which provides an operation using this mechanism.

MAS example05_complexop {


    complexop_userA agentArchClass c4jason.CAgentArch;
    complexop_userB agentArchClass c4jason.CAgentArch;

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

The artifact used by the two agents has the following code:

public class ArtifactWithComplexOp extends Artifact {

  int internalCount;

  void init(){
    internalCount = 0;

  @OPERATION void complexOp(int ntimes){
    await("myCondition", ntimes);

  @GUARD boolean myCondition(int ntimes){
    return internalCount >= ntimes;

  @OPERATION void update(int delta){

  private void doSomeWork(){}


In complexOp first we do some work, then we generate a signal step1_completed, and after that, by means of await, we suspend the execution of the operation until the condition defined by the guard method myCondition – whose name (and parameters, if needed) are specified as parameters of the await primitive – holds.

The effect is to suspend the execution of the operation until the value of internalCount is greater than or equal to the value specified by the complexOp ntimes parameter. Besides complexOp, the update operation is provided to increment the internal counter. In the example one agent – complexop_userA – executes a complexOp and the other agent - complexop_userB – repeatedly execute update. The action and plan of the first agent is suspended until the second agent has executed a number of updates which is sufficient to resume the complexOp operation. Here it is the complexop_userA source code:


  <- println("[userA] creating the artifact...");
     println("[userA] executing the action...");
     println("[userA] action completed."). 

  <- println("[userA] first step completed.").

  <- println("[userA] second step completed: ",C).

It is worth noting that the agent reacts to step1_completed signal generated by the artifact, printing a message on the console, even if the do_test plan execution is suspended waiting for complexOp(10) action completion. complexop_userB source code:


  <- !discover("a0");      !use_it(10).            +!use_it(NTimes) : NTimes > 0
  <- update(3);
     println("[userB] updated.");
     !use_it(NTimes - 1).

  <- println("[userB] completed.").

  <- lookupArtifact(ArtName,_).
  <- .wait(10);

The agent simply executes for 10 times the update operation. By running the example it is possible to see the interleaving of the agent actions.


  • Concurrency: the execution of the operations overlaps in time: however always only one operation step is in execution at a time, so no interferences can occur in accessing and modifying artifact state
  • Transactionality and Observability: by executing await, all the changes to the observable properties done so far by the operation are committed.

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>