Package org.jcsp.lang

# Class Any2AnyCallChannel

java.lang.Object
org.jcsp.lang.Any2AnyCallChannel

All Implemented Interfaces:
  `Serializable`, `ChannelAccept`

public abstract class Any2AnyCallChannel extends Object implements ChannelAccept, Serializable
This is the super-class for any-to-any `interface`-specific CALL channels, safe for use by many clients and many servers.

Shortcut to the Constructor and Method Summaries.

## Description

Please see `One2OneCallChannel` for general information about CALL channels. Documented here is information specific to this any-any version.

### Converting a Method Interface into a Variant CALL Channel

Constructing a any-any CALL channel for a specific `interface` follows exactly the same pattern as in the 1-1 case. Of course, it must extend `Any2AnyCallChannel` rather than `One2OneCallChannel`.

For example, using the same `Foo` interface as before, we derive:

     import org.jcsp.lang.*;

     public class Any2AnyFooChannel extends Any2AnyCallChannel implements Foo {

       ...  same body as One2OneFooChannel

     }

### Calling a CALL Channel

All the client needs to see is the method `interface` implemented by the CALL channel. So far as the client is concerned, therefore, there is no difference between any of the varieties of CALL channel - it just makes the call.

### Accepting a CALL Channel

The mechanics of accepting a CALL channel are the same for all varieties. However, the server should declare which kind (or kinds) it allows to be attached:

     import org.jcsp.lang.*;

     class B implements CSProcess, Foo {

       private final ChannelAccept in;

       public B (final One2OneFooChannel in) {         // original constructor
         this.in = in;
       }

       public B (final Any2AnyFooChannel in) {       // additional constructor
         this.in = in;
       }

       ...  rest as before

     }

When wrapping the above to hide its raw method interface, don't forget to include the extra constructor(s):

     import org.jcsp.lang.*;

     public class B2 implements CSProcess {            // no Foo interface

       private final B b;

       public B2 (final One2OneFooChannel in) {        // original constructor
         b = new B (in);
       }

       public B2 (final Any2AnyFooChannel in) {      // additional constructor
         b = new B (in);
       }

       public void run () {
         b.run ();
       }

     }

### ALTing on a CALL Channel

As for ordinary channels, ALTing over 1-any or any-any versions is not supported. Hence, a server can only choose to ``accept`` or not to `accept` a `Any2AnyFooChannel` - it cannot back off because of some other event.

### Building a CALL Channel Network

Network building with CALL channels is the same as building with ordinary channels. First construct the channels and, then, construct the processes - plugging in the channels as required and running them in `Parallel`.

For example, the network consisting of several clients and several servers:

where `A` is unchanged from its definition in `One2OneCallChannel`, is implemented by:

         Any2AnyFooChannel c = new Any2AnyFooChannel ();

         final A[] aClients = new A[n_aClients];
         for (int i = 0; i invalid input: '<' aClients.length; i++) {
           aClients[i] = new A (c);
         }

         final B2[] bServers = new B2[n_bClients];
         for (int i = 0; i invalid input: '<' bServers.length; i++) {
           bServers[i] = new B2 (c);
         }

         new Parallel (
           new CSProcess[] {
             new Parallel (aClients),
             new Parallel (bServers)
           }
         ).run ();

The clients compete with each other to find a server and the servers compete with each other to find a client. A client must not care which server it gets and vice-versa. The any-any CALL channel strictly serialises client-server transactions - only one at a time can actually take place.

It is a good idea, therefore, to restrict the duration of the CALL to as short a period as possible, so that other clients and servers are not unnecessarilly delayed. For instance, the any-any CALL can be used just to enable a client and server find one another. During the CALL, the client could give the server a private direct line (e.g. a 1-1 CALL channel) on which it promises to call back after hanging up on the shared one. The server could reply with special information (such as how long it is prepared to wait for that call back). In this way, multiple client-server transactions could proceed concurrently. An example is given below.

## Example

This further develops the CALL channel version of the Wot-no-Chickens example, introduced in `Any2OneCallChannel`.

The college authorities have decided to charge its philosophers for all the chickens they are consuming. Unfortunately, getting the canteen to collect money from the customers would mean that its `serviceTime` would have to be increased from its present zero to one second. Since the canteen can only do one thing at a time, a new form of delay would be introduced into the system. Since the philosophers only think for a maximum of three seconds in between trying to eat, having them wait around (possibly for several seconds) while their colleagues make their purchases is deemed unacceptable.

The college has decided, therefore, to make some new investments. Students are to be employed to sell the chickens from the canteen. Each student is equipped with a hot-plate on which can be (indefinitely) stored one hot chicken, straight from the canteen. The student can get a chicken from the canteen (if the canteen has some available) still with the same zero `serviceTime` as before - the canteen has not changed. Students that have chickens compete with each other to service any customers. Servicing a customer means collecting some money and giving change, which takes one second, as well as handing over the chicken.

Hungry philosophers compete with each other to find any student who is ready for a customer. Students and philosophers find each other through a any-any CALL channel. However, if the full transaction (which includes a delay of one second) were to take place over that shared channel, the college would be no better off! The canteen-students system would still only be dealing with one customer at a time.

Therefore, the good idea mentioned at the end of the previous section is employed to enable student-philosopher transactions to proceed in parallel. The any-any shared channel is used only for a philosopher to pass over a private direct 1-1 line to a student and to exchange names (out of politeness). The bulk of all transactions takes place in parallel over unshared lines.

Here is the fixed part of the network diagram for the new college. The 1-1 channels for private communication between a philosopher (`Prof`) and a student (`Student`) are dynamically connected, continually changing and, therefore, not shown:

For this new system, the `Canteen`, `Chef` and `Clock` processes are unchanged. The philosophers' behaviour has changed as described above and, so, we have chosen a new name for their class - `Prof`. But first, we describe the new player on the block - the `Student`.

### The Student

Each student process is a server on its `studentService` channel and a client on its `canteenService`. As with the `Canteen` server, we have chosen to define the `Student` service interface and associated CALL channel class as inner declarations:

     import org.jcsp.lang.*;

     class Student implements CSProcess {

       public static interface Service {
         public String hello (String profId,
                Canteen.One2OneServiceChannel service);
       }

       public static class Any2AnyServiceChannel
        extends Any2AnyCallChannel implements Service {
         public String hello (String profId,
                Canteen.One2OneServiceChannel service) {
           join ();
           String n = ((Service) server).hello (profId, service);
           fork ();
           return n;
         }
       }

Note that the `hello` CALL offers the caller's name and private 1-1 channel. These will be saved and the student's name returned when the student accepts the CALL. Notice also that that private channel instances the 1-1 `Service` channel exported by the `Canteen`. This is not surprising since the student, who will accept the CALL on that line, will be acting on behalf of the canteen - one of many proxies set up by the college to reduce the service bottleneck caused by the newly introduced charges.

Following the same pattern as for the `Canteen`, we next set up the constructor and the local fields for saving its parameters:

       private final String id;
       private final ChannelAccept studentService;
       // provide service on this line
       private final Canteen.Service canteenService;
       // act as a client on this line
       private final int serviceTime;

       public Student (String id, Any2AnyServiceChannel studentService,
                       Canteen.Service canteenService, int serviceTime) {
         this.id = id;
         this.studentService = studentService;
         this.canteenService = canteenService;
         this.serviceTime = serviceTime;
       }

Now, we need to combine the exported interfaces into a single one so that the inner process can be created (anonymously) by this wrapper's run method:

       private interface inner extends CSProcess, Service, Canteen.Service {};

       public void run () {

         new inner () {

           private AltingChannelAccept service;
           // place holder for the private line
           private int nServed = 0;

           private final CSTimer tim = new CSTimer ();

Impementations of the required CALL interfaces (including the one for the channel privately supplied) come next:

           public String hello (String profId,
                  Canteen.One2OneServiceChannel service) {
             this.service = service;
             System.out.println ("   Student " + id + " -> Prof " +
                                 profId + " : hello ... ");
             return id;
           }

           public int takeChicken (String profId) {
             System.out.println ("   Student " + id + " -> Prof +"
                                 profId + " : that'll be 1-95 please ... ");
             tim.sleep (serviceTime);          // take the money and give any change
             nServed++;
             System.out.println ("   Student " + id + " -> Prof "
                                 + profId + " : thank you - have a nice day ["
                                 + nServed + " served]");
             return 1;
           }

and the run method that conducts everything:

           public void run () {
             System.out.println ("   Student " + id + " : starting ... ");
             while (true) {
               canteenService.takeChicken (id);
               // make a client CALL on the canteen
               System.out.println ("   Student " + id +
                                   " : got chicken ... ready to serve ...");
               studentService.accept (this);     // customer makes contact
               service.accept (this);            // deal with customer
             }
           }

Finally, don't forget to run this inner process:

         }.run ();
       }
     }

### The Professor

Professors behave in pretty much the same way as philosophers. The only difference is that they communicate with the student proxies, rather than directly with the canteen. For this, each needs to keep a private channel up its sleeve:

     import org.jcsp.lang.*;

     class Prof implements CSProcess {

       private final String id;
       private final Student.Service studentService;
       private final int thinkTime;
       private final int eatTime;
       private final boolean greedy;

       public Prof (String id, Student.Service studentService,
                    int thinkTime, int eatTime, boolean greedy) {
         this.id = id;
         this.studentService = studentService;
         this.thinkTime = thinkTime;
         this.eatTime = eatTime;
         this.greedy = greedy;
       }

       public void run () {
         final CSTimer tim = new CSTimer ();
         final Canteen.One2OneServiceChannel service =
               new Canteen.One2OneServiceChannel ();
         // This is the private channel for
         // direct communication with a student
         int nEaten = 0;
         while (true) {
           if (! greedy) {
             System.out.println ("   Prof " + id + " : thinking ...");
             tim.sleep (thinkTime);  // thinking
           }
           System.out.println ("   Prof " + id + " : gotta eat ...");
           String student = studentService.hello (id, service);
                            // find a student
           System.out.println ("   Prof " + id + " -> Student "
                                + student +
                                " : hi, can I have a chicken please?");
           int chicken = service.takeChicken (id);
                         // and pay up ...
           nEaten++;
           System.out.println ("   Prof " + id +
                               " : mmm ... that's good [" +
                               nEaten + " so far]");
           tim.sleep (eatTime);      // eating
         }
       }

     }

### The New College

The new charges slow down the speed with which the professors can get their chickens (although not their eating of them). Most affected are the greedy ones who can no longer consume at a rate approaching 10 per second (whilst supplies hold out) but now have to wait a whole second simply to make a purchase. Bill, therefore, should not get quite so sick. Notice that, so long as supplies hold out and there are enough students, philosophers are not delayed by each other - their purchases will be made in parallel.

For convenience, the college network diagram is reproduced here - naming some more of the characters. The new college seems to have attracted some good students:

Here is the code:

     import org.jcsp.lang.*;

     class NewCollege implements CSProcess {

       public void run () {

         final String[] profId = {"Bill", "Hilary", "Gennifer",
                                  "Paula", "Monica"};
         final String[] studentId = {"Occam", "Babbage",
                                     "Einstein", "Turing"};

         final int thinkTime = 3000;             // 3 seconds
         final int eatTime = 100;                // 100 milliseconds

         final int studentServiceTime = 1000;    // 1 second

         final int canteenServiceTime = 0;       // 0 seconds
         final int canteenSupplyTime = 3000;     // 3 seconds
         final int maxChickens = 50;

         final Student.Any2AnyServiceChannel studentService
           = new Student.Any2AnyServiceChannel ();
         final Canteen.Any2OneServiceChannel canteenService
           = new Canteen.Any2OneServiceChannel ();
         final Canteen.Any2OneSupplyChannel supply
           = new Canteen.Any2OneSupplyChannel ();

         final Student[] students = new Student[studentId.length];
         for (int i = 0; i invalid input: '<' students.length; i++) {
           students[i] = new Student (studentId[i], studentService,
                                      canteenService, studentServiceTime);
         }

         final Prof[] profs = new Prof[profId.length];
         for (int i = 0; i invalid input: '<' profs.length; i++) {
           profs[i] = new Prof (profId[i], studentService,
                                thinkTime, eatTime, i == 0);
         }

         new Parallel (
           new CSProcess[] {
             new Clock (),
             new Canteen (canteenService, supply,
                          canteenServiceTime, canteenSupplyTime, maxChickens),
             new Parallel (students),
             new Parallel (profs),
             new Chef ("Pierre", 4, 2000, supply),
             // chefId, batchSize, batchTime
             new Chef ("Henri", 10, 20000, supply),
             new Chef ("Sid", 100, 150000, supply)
           }
         ).run ();

       }
       public static void main (String argv[]) {
         new NewCollege ().run ();
       }
     }

Author:
  P.H. Welch
See Also:
  - `One2OneCallChannel`
  - `Any2OneCallChannel`
  - `One2AnyCallChannel`
  - `Alternative`
  - Serialized Form

## Field Summary

Fields
Modifier and Type
Field
Description
`protected int`
`selected`
This may be set during the standard calling sequence to record which method was invoked by a client.
`protected CSProcess`
`server`
This holds a reference to a server process so that a client may make the call.

## Constructor Summary

Constructors
Constructor
Description
`Any2AnyCallChannel()`

## Method Summary

Modifier and Type
Method
Description
`int`
`accept(CSProcess server)`
This is invoked by a server when it commits to accepting a CALL from a client.
`protected void`
`fork()`
This is invoked by a client during the standard calling sequence.
`protected void`
`join()`
This is invoked by a client during the standard calling sequence.

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

## Field Details

### server

protected CSProcess server
This holds a reference to a server process so that a client may make the call. The reference is only valid between the ``join`` and ``fork`` elements of the standard calling sequence. As shown in that sequence, it will need casting up to the relevant interface supported by the specific CALL channel derived from this class.

### selected

protected int selected
This may be set during the standard calling sequence to record which method was invoked by a client. It is only safe to do this between the ``join`` and ``fork`` elements of that sequence. Either all the CALL channel methods should do this or none - in the latter case, its default value remains as zero. Its value is returned to a server as the result the server's invocation of ``accept``.

## Constructor Details

### Any2AnyCallChannel

public Any2AnyCallChannel()

## Method Details

### accept

public int accept(CSProcess server)
This is invoked by a server when it commits to accepting a CALL from a client. The parameter supplied must be a reference to this server - see the example from `One2OneCallChannel`. It will not complete until a CALL has been made. If the derived CALL channel has set the `selected` field in the way defined by the standard calling sequence, the value returned by this method will indicate which method was called.

Specified by:
  `accept` in interface `ChannelAccept`
Parameters:
  `server` - the server process receiving the CALL.

### join

protected void join()
This is invoked by a client during the standard calling sequence. It will not complete until a server invokes an ``accept`` on this channel. In turn, that `accept` will not complete until the client invokes a ``fork``, after having made its CALL on the server.

### fork

protected void fork()
This is invoked by a client during the standard calling sequence. A server must have invoked an ``accept`` for the client to have got this far in the sequence - see the ``join``. This call unblocks that `accept`, releasing the server and client to resume separate lives.