CSP for Java
(JCSP) 1.1-rc4

org.jcsp.lang
Interface CSProcess

All Known Implementing Classes:
ActiveApplet, ActiveButton, ActiveButtonControl, ActiveCanvas, ActiveCheckbox, ActiveCheckboxMenuItem, ActiveChoice, ActiveClosingFrame, ActiveComponent, ActiveContainer, ActiveDialog, ActiveFileDialog, ActiveFrame, ActiveLabel, ActiveList, ActiveMenu, ActiveMenuItem, ActivePanel, ActiveScrollbar, ActiveScrollPane, ActiveTextArea, ActiveTextEnterArea, ActiveTextEnterField, ActiveTextField, ActiveWindow, And, AndInt, BlackHole, BlackHoleInt, CNS, Delta, Delta2, Delta2Int, DeltaInt, Demultiplex, DemultiplexInt, Deparaplex, DeparaplexInt, DynamicDelta, DynamicDeltaInt, Fibonacci, FibonacciInt, FixedDelay, FixedDelayInt, FramedButton, FramedButtonArray, FramedButtonGrid, FramedScrollbar, Generate, GenerateInt, Identity, IdentityInt, Integrate, IntegrateInt, Link, Merge, Merge2, Merge2Int, MergeInt, Mult, MultInt, Multiplex, MultiplexInt, Nand, NandInt, Nor, NorInt, Numbers, NumbersInt, Or, OrInt, Pairs, PairsInt, Parallel, Paraplex, ParaplexInt, Plex, Plex2, Plex2Int, PlexInt, Plus, PlusInt, Prefix, PrefixInt, Printer, PrinterInt, PriParallel, ProcessManager, ProcessRead, ProcessReadInt, ProcessWrite, ProcessWriteInt, Regular, RegularInt, Regulate, RegulateInt, RemoteProcess, Sequence, Sign, SignInt, Skip, SpawnerService, Squares, SquaresInt, Stop, Substitute, SubstituteInt, Successor, SuccessorInt, Tail, TailInt, Times, TimesInt, Xor, XorInt

public interface CSProcess

This is the JCSP interface for a process - an active component that encapsulates the data structures on which it operates.

Description

A CSP process is a component that encapsulates data structures and algorithms for manipulating that data. Both its data and algorithms are private. The outside world can neither see that data nor execute those algorithms. Each process is alive, executing its own algorithms on its own data. Processes interact solely via CSP synchronising primitives, such as channels, events or other well-defined modes of access to shared passive objects.

In this JCSP binding of the CSP model into Java, a process is an instance of a class implementing this CSProcess interface. Its actions are defined by the run method.

Running processes interact solely via CSP channels, events or carefully synchronised access to shared objects -- not by calling each other's methods. These passive objects form the CSP interface to a process. They are not present in the Java interface and must be configured into each process via public constructors and/or mutators when it is not running (i.e. before and in between runs). It is safe to extract information from the process via accessor methods, but only after (or in between) runs.

For other general information, see the JCSP overview.

Process Oriented Design

A process-oriented design consists of layered networks of processes. A network is simply a parallel composition of processes connected through a set of passive synchronisation objects (wires) and is itself a process. Each process fulfills a contract with its environment that specifies not only what functions it performs, but how it is prepared to synchronise with that environment to obtain information and deliver results. Note that a process does not interact directly with other processes, only with the wires to which it is connected. This is a very familiar form of component interface -- certainly to hardware engineers -- and is one that allows considerable flexibility and reuse.

Implementation Pattern

The structure of a JCSP process should follow the outline:
 import org.jcsp.lang.*;
 ...  other imports
  
 class ProcessExample implements CSProcess {
  
   ...  private/protected shared synchronisation objects (channels etc.)
   ...  private/protected state information
  
   ...  public constructors
   ...  public configuration/inspection methods (when not running)
  
   ...  private/protected support methods (part of a run)
   ...  public run method (the process starts here)
  
 }
 
The pattern of use for these methods is simple and well-disciplined. The public constructors and configuration methods must install the shared synchronisation objects into their private/protected fields. They may also initialise other private/protected state information. The public configuration/inspection methods (simple sets and gets) may be invoked only when this process is not running and are the responsibility of a single process only -- usually the process that constructed it. That process is also responsible for invoking the public run method that kicks this one into life (usually, via a Parallel or ProcessManager intermediary). The private support methods are triggered only by the run method and express the live behaviour of this process.

A process instance may have several lives but these must, of course, be consecutive. Different instances of the same process class may, also of course, be alive concurrently. Reconfiguration of a process via its configuration/inspection methods may only take place between lives. Dynamic reconfiguration of a live process may take place -- but only with the active cooperation of the process (for example, through channel communication).

Motivation

Like any object, a process should encapsulate a coherent set of data and algorithms for managing that data. The discipline outlined in the above implementation pattern has the following broad aims: These properties mean that processes make excellent building blocks for complex systems -- their semantics compose cleanly and predictably as they are plugged together.

This is not to say that the semantics of processes connected in parallel are simply the sum of the semantics of each individual process -- just that those semantics should contain no surprises. Value can added just through the nature of the parallel composition itself. For example, connect simple stateless processes into a channel feedback-loop, give them some external wires and we get a component that contains state.

Discussion

The public methods of an arbitrary object are at the mercy of any other object that has a reference to it. Further, invocations of those methods may be part of any thread of control. Object designers, implementors and users need to have this under well-documented control. This control is not easy to achieve without any rules.

The process design pattern defines some powerful simplifications that bring us that control. Backed up with the theory of CSP, it also addresses and offers solutions to some fundamental issues in concurrency and multi-threading.

In unconstrained OO, threads and objects are orthogonal notions -- sometimes dangerously competitive. Threads have no internal structure and can cross object boundaries in spaghetti-like trails that relate objects together in a way that has little correspondence to the original OO design. A process combines these ideas into a single concept, gives it structure and maintains strong encapsulation by guarding the distribution and use of references with some strict (and checkable) design rules. A process may be wired up in parallel with other processes to form a network -- which is itself a process. So, a process may have sub-processes that have sub-sub-processes ad infinitum. This is the way the world works ...

The simplicity of the process design pattern is that each process can be considered individually as an independent serial program, interacting with external I/O devices (the synchronisation objects -- channels etc.). At the other end of those devices may lie other processes, but that is of no concern to the consideration of this process. All our past skills and intuition about serial programming can safely be applied. The new skills needed to design and use parallel process networks sit alongside those earlier skills and no cross-interference takes place.

Examples

Numerous examples are scattered throughout the documentation of this library. Good starting ponts are in the Parallel and Alternative classes. Here is another very simple one:
 import org.jcsp.lang.*;
 
 // LaunchControl is a process to control the launch of a space rocket.
 
 // It is configured with a countdown time in seconds -- this must be above
 // a minimum threshold, MIN_COUNTDOWN, else the launch is immediately aborted.
 
 // There are two control lines, abort and hold, that respectively abort
 // or hold the launch if signalled.  The hold is released by a second
 // signal on the same line.
 
 // During countdown, the count is reported by outputting on the countdown
 // channel.
 
 // If not aborted, LaunchControl fires the rocket (by outputting on its fire
 // channel) when the countdown reaches zero.  An ABORTED launch is also
 // reported on this fire channel.
 
 // After a successful or aborted launch, LaunchControl terminates.
 // The status attribute records whether the launch was FIRED or ABORTED
 // and may then be inspected.
 
 public class LaunchControl implements CSProcess {
 
   public static final int MIN_COUNTDOWN = 10;
 
   public static final int FIRED = 0;
   public static final int HOLDING = 1;
   public static final int COUNTING = 2;
   public static final int ABORTED = 3;
   public static final int UNDEDFINED = 4;
 
   private final int start;
   private final AltingChannelInputInt abort;
   private final AltingChannelInputInt hold;
   private final ChannelOutputInt countdown;
   private final ChannelOutputInt fire;
 
   private int status = UNDEDFINED;
 
   public LaunchControl (final int start,
                         final AltingChannelInputInt abort,
                         final AltingChannelInputInt hold,
                         final ChannelOutputInt countdown,
                         final ChannelOutputInt fire) {
     this.start = start;
     this.abort = abort;
     this.hold = hold;
     this.countdown = countdown;
     this.fire = fire;
   }
 
   public int getStatus () {                   // inspection method
     return status;                            // (can only be used in between runs)
   }
 
   public void run () {
 
     final CSTimer tim = new CSTimer ();        // JCSP timers have
     final long oneSecond = 1000;               // millisecond granularity
 
     long timeout = tim.read () + oneSecond;    // compute first timeout
 
     final Alternative alt =
       new Alternative (new Guard[] {abort, hold, tim});
     final int ABORT = 0;
     final int HOLD = 1;
     final int TICK = 2;
 
     int count = start;
     boolean counting = (start >= MIN_COUNTDOWN); // abort if bad start
 
     while ((count > 0) && counting) {
       countdown.write (count);                   // public address system
       tim.setAlarm (timeout);                    // set next timeout
       switch (alt.priSelect ()) {
         case ABORT:                              // abort signalled
           abort.read ();                         // clear the signal
           counting = false;
         break;
         case HOLD:                               // hold signalled
           long timeLeft = timeout - tim.read (); // time till next tick
           hold.read ();                          // clear the signal
           fire.write (HOLDING);                  // signal rocket
           hold.read ();                          // wait for the release
           timeout = tim.read () + timeLeft;      // recompute next timeout
           fire.write (COUNTING);                 // signal rocket
         break;
         case TICK:                               // timeout expired
           count--;
           timeout += oneSecond;                  // compute next timeout
         break;
       }
     }
 
     status = (counting) ? FIRED : ABORTED;       // set status attribute
     fire.write (status);                         // signal rocket (go/nogo)
     if (counting) countdown.write (0);           // complete countdown
   }
 }
 

Author:
P.D. Austin, P.H. Welch
See Also:
Parallel, PriParallel, Alternative, ChannelInput, ChannelOutput, One2OneChannel, Any2OneChannel, One2AnyChannel, Any2AnyChannel, ChannelInputInt, ChannelOutputInt, One2OneChannelInt, Any2OneChannelInt, One2AnyChannelInt, Any2AnyChannelInt, ProcessManager

Method Summary
 void run()
          This defines the actions of the process.
 

Method Detail

run

void run()
This defines the actions of the process.


CSP for Java
(JCSP) 1.1-rc4

Submit a bug or feature to jcsp-team@kent.ac.uk
Version 1.1-rc4 of the JCSP API Specification (Copyright 1997-2008 P.D.Austin and P.H.Welch - All Rights Reserved)
Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.