[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Channels versus Methods

Hi Peter and Gerald,

your ideas are quite good. In fact my first ideas were similar to yours.
But the major drawback of this approach is, that you need either on the
client or on the server side a pair of corresponding read/write
statements. The compiler unfortunately cannot check their presence. If
the programmer forgets one of these, the system will hang :-( 

My approach is different. On the client side I use a "write" command
similar to the one we already have in ordinary channels, except that it
returns an object; that is straight forward and trivial:

 public Object write (Object object);

The trick is on the server side where the "read" method gets a new
interface as parameter:

 public Object read (CallChannelFunctionInterface function); 

This interface is defined as follows:

 public interface CallChannelFunctionInterface {
   public Object accept (Object in);

How does "read" work? It performs three steps:
1. "read" reads the object (call it "inObj") sent by "write" (no
difference to ordinary channels),
2. after that, the "accept" method is called with "inObj" as parameter,
3. the return object of "accept" is passed back to the "write" method.

For this the "ChannelDataStore" used in JCSP has to be extended to store
the return value. With this extention "read" and "write" could look like

  public synchronized Object read (CallChannelFunctionInterface  
                                   function) {
    if (data.getState () == ChannelDataStore.EMPTY) {
      try {
        wait ();
      catch (InterruptedException e) {
    Object value = data.get ();
    data.putReturn (function.accept(value));  // this is new
    notify ();
    return value;

  public synchronized Object write (Object value) {
    Object returnObject = null;  // this is new
    data.put (value);
    if (alt != null) {
      alt.schedule ();
    } else {
      notify ();
    try {
      wait ();
      returnObject = data.getReturn ();  // this is new
    catch (InterruptedException e) {
    return returnObject;  // this is new

May be, that there is some extra wait/sync needed. But the idea should
work (at least I hope so).
The user doesn't see the details within "read" and "write". He has only
to provide the implementation of the new interface, where the compiler
checks the details. 

With only minor modifications in "read" and "write" we can use the
One2OneChannel, Many2OneChannel, etc. in the same way as we do now (even
remote channels and  AltingInput will work). I am testing a modified
version of "Whot, no chickens":

The Phil code is like this:

 ChannelOutput request;
 Object chickens;
 int wanted = 2;
 chickens = request.write (new Integer (wanted)); // Phil wants 2

The Canteen looks like this:

 AltingChannelInput request;
 PileOfChickens pileOfChickens = new PileOfChickens ();
 switch (alt.fairSelect (preCondition)) {
   case REQUEST:
    Integer wanted = (Integer) request.read (pileOfChickens);  
      // "read" reads the input and sends the return value!
    // or if you don't need the trasmitted number simply say:
    // request.read (pileOfChickens);
   case SUPPLY:

The "PileOfChickens" is luxury version of

  class PileOfChickens implements CallChannelFunctionInterface {
    private int nChickens;
    // constructor
    PileOfChickens () { this.nChickens = 0; }
    // the return function of out CALL channel:
    public Object accept (Object input) {
      int wanted = ((Integer) input).intValue();
      int ok = min (wanted, nChickens);  // may be, not enough chickens
      nChickens -= ok;  
      return new Integer (ok);

    // get the actual size
    int size () { return nChickens; }

    // add some chickens
    void add (int incr) { nChickens += incr;}

    int min (int a, int b) { if (a < b) return a; else return b;}

What do you think of this? Have I overseen something?