Example 05a – Implementing coordination artifacts


Here we show an example of how to exploit structured operations to implement a coordination artifact, a simple tuple space, and its usage to solve the dining philosophers coordination problem. The in and rd operations (that corresponds to the in and rd Linda primitives) are easily implemented exploiting the await mechanism:

public class TupleSpace extends Artifact {

  TupleSet tset;

  void init(){
    tset = new TupleSet();
  }

  @OPERATION void out(String name, Object... args){
    tset.add(new Tuple(name,args));
  }

  @OPERATION void in(String name, Object... params){
    TupleTemplate tt = new TupleTemplate(name,params);
    await("foundMatch",tt);
    Tuple t = tset.removeMatching(tt);
    bind(tt,t);
  }

  @OPERATION void rd(String name, Object... params){
    TupleTemplate tt = new TupleTemplate(name,params);
    await("foundMatch",tt);
    Tuple t = tset.readMatching(tt);
    bind(tt,t);
  }

  private void bind(TupleTemplate tt, Tuple t){
    Object[] tparams = t.getContents();
    int index = 0;
    for (Object p: tt.getContents()){
      if (p instanceof OpFeedbackParam){
        ((OpFeedbackParam) p).set(tparams[index]);
      }
      index++;
    }
  }

  @GUARD boolean foundMatch(TupleTemplate tt){
    return tset.hasTupleMatching(tt);
  }
}

(The description of Tuple, TupleTemplate and TupleSet classes is omitted).

This is actually the implementation of the blackboard tuple space artifact available by default in any workspace. It follows a solution to the dining philosophers problem using a tuple space:

MAS example05a_philo {

    environment:
    c4jason.CartagoEnvironment

    agents:
    waiter agentArchClass c4jason.CAgentArch;
    philo agentArchClass c4jason.CAgentArch #5;

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

The MAS is composed by a waiter agent and five philosophers. The waiter is responsible of preparing the environment, injecting the tuples representing the forks (five fork(F) tuples) and tickets (four ticket tuples), which allow for avoiding deadlocks.

philo(0,"philo1",0,1).
philo(1,"philo2",1,2).
philo(2,"philo3",2,3).
philo(3,"philo4",3,4).
philo(4,"philo5",4,0).

!prepare_table.

+!prepare_table
  <- for ( .range(I,0,4) ) {
       out("fork",I);
       ?philo(I,Name,Left,Right);
       out("philo_init",Name,Left,Right);
     };
     for ( .range(I,1,4) ) {
       out("ticket");
     };
     println("done.").

The philosophers repeatedly get a couple of forks, use them to eat, and then release them. Before taking the forks they must get a ticket, which is released then after releasing the forks.

!start.

+!start
  <- .my_name(Me);
     in("philo_init",Me,Left,Right);
     +my_left_fork(Left);
     +my_right_fork(Right);
     println(Me," ready.");
     !!living.

+!living
 <- !thinking;
    !eating;
    !!living.

+!eating
 <- !acquireRes;
    !eat;
    !releaseRes.

+!acquireRes :
  my_left_fork(F1) & my_right_fork(F2)
  <- in("ticket");
     in("fork",F1);
     in("fork",F2).

+!releaseRes:
  my_left_fork(F1) & my_right_fork(F2)
 <-  out("fork",F1);
     out("fork",F2);
     out("ticket").

+!thinking
  <- .my_name(Me); println(Me," thinking").
+!eat
  <- .my_name(Me); println(Me," eating").

Highlights

  • no one created the tuple space artifact, since it is already available in the workspace by default.

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>