Package org.jcsp.lang

# Class One2OneCallChannel

java.lang.Object
org.jcsp.lang.Guard
org.jcsp.lang.AltingChannelAccept
org.jcsp.lang.One2OneCallChannel

All Implemented Interfaces:
  `Serializable`, `ChannelAccept`

public abstract class One2OneCallChannel extends AltingChannelAccept implements Serializable
This is the super-class for one-to-one `interface`-specific CALL channels.

Shortcut to the Constructor and Method Summaries.

## Description

Normal method invocation between objects is sometimes refered to as message-passing between a client (the invoker of the method) object and a server object (the invoked). Information flows from the client (the method name and parameter values) to the server, which reacts in some way (possibly changing state) and may return information back to the client (via the method result or, indirectly, by changing values referenced by the method parameters).

This corresponds loosely with the client-server communication pattern between active processes, but where information flows over a pair of channels connecting them. However, there are major semantic differences between the two mechanisms. A server process is in charge of its own life, can act spontaenously and can refuse to accept a client call. A server object is passive, never does anything unless invoked and, then, has no choice but to obey. We must be careful, therefore, not to become confused by the same words computer scientists have chosen to mean very different things.

CALL channels risk deepening this confusion. They provide a method interface for client-server communication between active processes, yet their semantics remain those of a synchronising zero-buffered channel. However, the attraction of replacing a sequence of channel `write`(s) and `read` (matched at the other end of the channel-pair by a sequence of channel `read`(s) and `write`) with a single method invocation (and a single matching ``accept``) makes this risk worthwhile.

[Note: CALL channels were part of the occam3 language specification. They provide an extended rendezvous in the sense of an Ada `entry`, but are considerably more flexible and lightweight.]

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

A CALL channel must be individually constructed to support a specific method `interface`. This is done by extending this class to implement that `interface` in the manner outlined below. The calling (i.e. client) process just sees that `interface` and invokes its methods. The callee (i.e. server) process just sees the ``accept`` method of the CALL channel and invokes that (supplying itself as argument). Both actions are voluntary and have to occur for the communication to take place.

Consider the following:

     interface Foo {

       public Bar calculate (...);
       public void processQuery (...);
       public boolean closeValve (...);

     }

Deriving the corresponding CALL channel is mechanical and could easilly be automated:

     import org.jcsp.lang.*;

     public class One2OneFooChannel extends One2OneCallChannel implements Foo {

       public static final int CALCULATE = 0;           // optional
       public static final int PROCESS_QUERY = 1;       // optional
       public static final int CLOSE_VALVE = 2;         // optional

       public Bar calculate (...) {
         join ();                                       // ready to make the CALL
         Bar result = ((Foo) server).calculate (...);
         selected = CALCULATE;                          // optional
         fork ();                                       // call finished
         return result;
       }

       public void processQuery (...) {
         join ();                                       // ready to make the CALL
         ((Foo) server).processQuery (...);
         selected = PROCESS_QUERY;                      // optional
         fork ();                                       // call finished
       }

       public boolean closeValve (...) {
         join ();                                       // ready to make the CALL
         boolean result = ((Foo) server).closeValve (...);
         selected = CLOSE_VALVE;                        // optional
         fork ();                                       // call finished
         return result;
       }

     }

The above methods will be called by the client process. The ``join`` will not complete until the server invokes an ``accept`` on this channel. That `accept` will not complete until the client reaches the ``fork``. This gives the zero-buffered fully synchronised semantics of CSP channel communication.

In between the `join` and the `fork`, the client and server processes are locked together in extended rendezvous, commonly executing the chosen method in the server environment. [Actually, it is the client that invokes the method on the server, temporarilly referenced by the ``server`` field from this `One2OneCallChannel` super-class and blocked waiting for its `accept` to complete.] Setting the ``selected`` field is optional. However, its value is returned to the server by the ``accept`` method and can be used (as in the above) to let the server know which of its methods the client invoked.

[Note: a `One2OneFooChannel` is only safe to use between a single client and a single server. Any-1, 1-Any and Any-Any versions may be derived from `Any2OneCallChannel`, `One2AnyCallChannel` and `Any2AnyCallChannel` (respectively) using exactly the same pattern as above.]

### Calling a CALL Channel

All the client needs to see is the method `interface` implemented by the CALL channel. For example:

     import org.jcsp.lang.*;

     public class A implements CSProcess {

       private final Foo out;

       public A (final Foo out) {
         this.out = out;
       }

       public void run () {
         ...
         Bar t = out.calculate (...);
         ...
         out.processQuery (...);
         ...
         if (! out.closeValve (...)) ...;
         ...
       }

     }

[Note: this means, of course, that a client is blind to the variety of CALL channel it is calling. It may be connected to its server(s) via a 1-1, Any-1, 1-Any or Any-Any link without any change in its coding.]

### Accepting a CALL Channel

To receive the calls forwarded by the CALL channel, the server needs to implement the same `interface`. To accept a call, it invokes the ``accept`` method of the CALL channel, passing itself (usually `this`) as the argument. All it needs to see, therefore, is the `ChannelAccept` interface implemented by the channel. For example:

     import org.jcsp.lang.*;

     class B implements CSProcess, Foo {

       private final ChannelAccept in;

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

       ...  other fields, methods etc.

       ...  implementation of Foo methods

       public void run () {        // controls when Foo invocations are acceptable
         ...
         in.accept (this);                   // don't care which method was called
         ...
         switch (in.accept (this)) {         // care which method was called
           case One2OneFooChannel.CALCULATE:
             ...
           break;
           case One2OneFooChannel.PROCESS_QUERY:
             ...
           break;
           case One2OneFooChannel.CLOSE_VALVE:
             ...
           break;
         }]
         ...
         in.accept (this);                   // don't care which method was called
         ...
       }

     }

However, it is not very secure for a server process (like `B`) to advertise a standard method interface (like `Foo`). In the above example, there is the danger that someone might try to invoke one of the `Foo` methods directly on an instance of `B` (e.g. by plugging an instance of `B`, instead of the CALL channel, into an instance of `A`). That would not be a good idea!

It is also semantically misleading - `B`'s interface is through the CALL channel passed to its constructor, not through its (necessarilly `public`) `Foo` methods.

So, `B` should not be the public server process - we need to hide its directly invocable methods. A simple way to do this is to wrap it up in another process that simply omits the public declaration of the relevant interface:

     import org.jcsp.lang.*;

     public class B2 implements CSProcess {            // no Foo interface

       private final B b;

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

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

     }

Notice that this wrapper imposes no run-time overhead, apart from a small start-up cost. The hidden inner process does all the work and has direct access to the CALL channel and, hence, to the client.

[Note: the only difference needed in the server code to support Any-1, 1-Any and Any-Any CALL channels is in the parameter declaration that specifies the variety to be used. For complete flexibility, constructors (or `setFooChannel` methods) for each kind (i.e. `One2OneFooChannel`, `Any2OneFooChannel`, `One2AnyFooChannel` and `Any2AnyFooChannel` may be provided.]

### ALTing on a CALL Channel

This class is a sub-class of `Guard` and, therefore, its derived CALL channels may be included in a `Guard` array associated with an `Alternative`. Hence, the server may ALT between any mixture of CALL channels, ordinary channels, `timeouts` and `Skips`.

However, when implementing the server, the CALL channel field needs to be declared as an `AltingChannelAccept`, rather than a `ChannelAccept`. So, in the above example, the first field declaration of `B` needs to become:

       private final AltingChannelAccept in;

See `Any2OneCallChannel` for an example of `ALT`ing between CALL channels.

[Note: a server may ALT on a Any-1 CALL channel with this same change. However, as for ordinary channels, ALTing over 1-Any or Any-Any versions is not supported.]

### 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 simple two process network:

is implemented by:

         One2OneFooChannel c = new One2OneFooChannel ();

         new Parallel (
           new CSProcess[] {
             new A (c),
             new B2 (c)
           }
         ).run ();

[Note: simple network examples using Any-1, 1-Any and Any-Any CALL channels are given in their respective classes.]

## Example

Please see `Any2OneCallChannel` for an example that includes one server, ALTing between two (Any-1) CALL channels, and lots of clients.

Author:
  P.H. Welch
See Also:
  - `Any2OneCallChannel`
  - `One2AnyCallChannel`
  - `Any2AnyCallChannel`
  - `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
`One2OneCallChannel()`

## 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 org.jcsp.lang.Guard

`schedule`

### 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

### One2OneCallChannel

public One2OneCallChannel()

## 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 above. 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.