Package org.jcsp.lang

# Class AltingBarrier

java.lang.Object
org.jcsp.lang.Guard
org.jcsp.lang.AltingBarrier

public class AltingBarrier extends Guard
This is the front-end for a barrier that can be used as a `Guard` in an `Alternative`.

## Description

An alting barrier is represented by a family of `AltingBarrier` front-ends. Each process using the barrier must do so via its own front-end. A new alting barrier is created by the static `create` method, which returns an array of front-ends. If new processes need to be enrolled, further front-ends may be made from an existing one (see `expand` and `contract`). A process may temporarilly `resign` from a barrier and, later, re-`enroll`.

To use this barrier, a process simply includes its given `AltingBarrier` front-end in a `Guard` array associated with an `Alternative`. Its index will be selected if and only if all parties (processes) to the barrier similarly select it (using their own front-ends).

If a process wishes to commit to this barrier (i.e. not offer it as a choice in an `Alternative`), it may `sync` on it. However, if all parties only do this, a non-alting `Barrier` would be more efficient. A further shortcut (over using an `Alternative`) is provided to `poll` this barrier for completion.

An `AltingBarrier` front-end may only be used by one process at a time (and this is checked at run-time). A process may communicate a non-resigned front-end to another process; but the receiving process must `mark` it before using it and, of course, the sending process must not continue to use it. If a process terminates holding a front-end, it may be recycled for use by another process via `reset`.

### Priorities

These do not -- and cannot -- apply to selection between barriers. The `priSelect()` method works locally for the process making the offer. If this were allowed, one process might offer barrier `x` with higher priority than barrier `y` ... and another process might offer them with its priorities the other way around. In which case, it would be impossible to resolve a choice in favour of `x` or `y` in any way that satisfied the conflicting priorities of both processes.

However, the `priSelect()` method is allowed for choices including barrier guards. It honours the respective priorities defined between non-barrier guards ... and those between a barrier guard and non-barrier guards (which guarantees, for example, immediate response to a timeout from ever-active barriers). Relative priorities between barrier guards are inoperative.

### Misuse

The implementation defends against misuse, throwing an `AltingBarrierError` error when riled. See the documentation for `AltingBarrierError` for circumstances.

## Example 0 (a single alting barrier)

Here is a simple gadget with two modes of operation, switched by a click event (operated externally by a button in the application below). Initially, it is in individual mode -- represented here by incrementing a number and outputting it (as a `String` to change the label on its controlling button) as often as it can. Its other mode is group, in which it can only work if all associated gadgets are also in this mode. Group work consists of a single decrement and output of the number (to its button's label). It performs group work as often as the group will allow (i.e. until it, or one of its partner gadgets, is clicked back to individual mode).

     import org.jcsp.lang.*;

     public class AltingBarrierGadget0 implements CSProcess {

       private final AltingChannelInput click;
       private final AltingBarrier group;
       private final ChannelOutput configure;

       public AltingBarrierGadget0 (
         AltingChannelInput click, AltingBarrier group, ChannelOutput configure
       ) {
         this.click = click;
         this.group = group;
         this.configure = configure;
       }

       public void run () {

         final Alternative clickGroup =
           new Alternative (new Guard[] {click, group});

         final int CLICK = 0, GROUP = 1;

         int n = 0;
         configure.write (String.valueOf (n));

         while (true) {

           configure.write (Color.green)                // pretty

           while (!click.pending ()) {                  // individual work mode
             n++;                                       // work on our own
             configure.write (String.valueOf (n));      // work on our own
           }
           click.read ();                               // must consume the click

           configure.write (Color.red);                 // pretty

           boolean group = true;                        // group work mode
           while (group) {
             switch (clickGroup.priSelect ()) {         // offer to work with the group
               case CLICK:
                 click.read ();                         // must consume the click
                 group = false;                         // back to individual work mode
               break;
               case GROUP:
                 n--;                                   // work with the group
                 configure.write (String.valueOf (n));  // work with the group
               break;
             }
           }

         }

       }

     }

Here is code for a system of buttons and gadgets, synchronised by an alting barrier. Note that this single event needs an array of `AltingBarrier` front-ends to operate -- one for each gadget:

     import org.jcsp.lang.*;
     import org.jcsp.plugNplay.*;

     public class AltingBarrierGadget0Demo0 {

       public static void main (String[] argv) {

         final int nUnits = 8;

         // make the buttons

         final One2OneChannel[] event = Channel.one2oneArray (nUnits);

         final One2OneChannel[] configure = Channel.one2oneArray (nUnits);

         final boolean horizontal = true;

         final FramedButtonArray buttons =
           new FramedButtonArray (
             "AltingBarrier: Gadget 0, Demo 0", nUnits, 120, nUnits*100,
              horizontal, configure, event
           );

         // construct an array of front-ends to a single alting barrier

         final AltingBarrier[] group = AltingBarrier.create (nUnits);

         // make the gadgets

         final AltingBarrierGadget0[] gadgets = new AltingBarrierGadget0[nUnits];
         for (int i = 0; i invalid input: '<' gadgets.length; i++) {
           gadgets[i] = new AltingBarrierGadget0 (event[i], group[i], configure[i]);
         }

         // run everything

         new Parallel (
           new CSProcess[] {
             buttons, new Parallel (gadgets)
           }
         ).run ();

       }

     }

The very simple "group" work in the above example consists of actions performed independently by each gadget (decrementing the number on its button's label). The (alting) barrier synchronisation ensures that these decrements keep in step with each other.

A more interesting gadget would work with other gadgets for group work that really did require them all to be engaged. For example, they resume operation of a machine that would be dangerous if some gadgets (perhaps those responsible for safety aspects) were doing their individual work.

## Example 1 (lots of alting barriers)

This example derives from a pathological challenge to the management of choice between multiway synchronisations raised by Michael Goldsmith (Formal Systems Europe). There are three processes (`P`, `Q` and `R`) and theee events (`a`, `b` and `c`). `P` offers events `a` and `b`; `Q` offers events `b` and `c`; and `R` offers events `c` and `a`. If `P` and `Q` synchronise on `b`, they do something (possibly together) then start again. Similarly if `Q` and `R` synchronise on `c` or if `R` and `P` synchronise on `a`. In CSP, the expression is trivial:

      P = ((a -> P0); P) [] ((b -> P1); P), and where c is not in the alphabet of P
      Q = ((b -> Q0); Q) [] ((c -> Q1); Q), and where a is not in the alphabet of Q
      R = ((c -> R0); R) [] ((a -> R1); R), and where b is not in the alphabet of R

      SYSTEM = (P || Q || R) \ {a, b, c}

To impact their environment (and avoid divergence), the sub-processes `P0`, `P1`, `Q0`, `Q1`, `R0` and `R1` will engage in external events (i.e. not just `a`, `b` or `c`). Additionally, `P1` and `Q0` (triggered by `b`) may engage in other hidden events, not given in the above. The same for `Q1` and `R0` (triggered by `c`) and for `R1` and `P0` (triggered by `a`).

In our version, there are `N` processes and events arranged (logically) around a circle. Each process is either off or on standby, switching between these states on random timeouts. Each process is also attached to a personal button that it uses to indicate its state. When off, it colours its button black; when on standby, light gray.

When on standby, each process offers `(span+1)` events: a timeout, the event with it on the circle and the next `(span-1)` events going (say) clockwise. It the timeout occurs, it switches to its off state. If one of the events (`AltingBarrier`) occurs, it must have occured for a consecutive block of `span` processes (including this one ... somewhere) around the circle. This group now go into a playing state.

Not mentioned before is a rail track, made of channels, running round the circle. When playing, the process furthest uptrack choses a colour and sends this to its partners down the track (to which the mulitway synchronisation ensures this group has exclusive access). Each process in the playing group then flashes its button with that colour a fixed (parametrised) number of times. The rate of flashing is coordinated by the `AltingBarrier` multiway synchronisation event common to the group -- the furthest uptrack process only keeping time for this. After playing, the process switches to its off state.

[Note: the above `SYSTEM` has `N` equal to `3`, `span` equal to `2`, no off state and no timeout on standby. The channels used to flash the buttons are the external events mentioned and the rail track channels are the hidden extras.]

Here is the code for these processes. As usual, the constructor just saves all parameters:

     import org.jcsp.lang.*;
     import org.jcsp.awt.*;

     import java.awt.Color;
     import java.util.Random;

     public class AltingBarrierGadget1 implements CSProcess {

       private final AltingBarrier[] barrier;
       private final AltingChannelInput in, click;
       private final ChannelOutput out, configure;
       private final Color offColour, standbyColour;
       private final int offInterval, standbyInterval;
       private final int playInterval, flashInterval;

       public AltingBarrierGadget1 (
         AltingBarrier[] barrier,
         AltingChannelInput in, ChannelOutput out,
         AltingChannelInput click, ChannelOutput configure,
         Color offColour, Color standbyColour,
         int offInterval, int standbyInterval,
         int playInterval, int flashInterval
       ) {
         this.barrier = barrier;
         this.in = in;  this.out = out;
         this.click = click;  this.configure = configure;
         this.offColour = offColour;  this.standbyColour = standbyColour;
         this.offInterval = offInterval;  this.standbyInterval = standbyInterval;
         this.playInterval = playInterval;  this.flashInterval = flashInterval;
       }

The `barrier` array gives this gadget access to the multiway events shared with adjacent siblings. The `in` and `out` channel ends are part of the rail track this gadget uses later (when playing). The `click` and `configure` channels attach this gadget to its button. The `click` channel is never used by this gadget -- it's included for completeness should anyone wish to enhance its behaviour. The other parameters are just data.

The `run()` method controls switching between off, standby and playing states. The latter is the choice between all the multiway syncs (and the timeout). It is handled by a fair select on the `Alternative`, constructed just once (before loop entry):

       public void run () {

         CSTimer tim = new CSTimer ();

         final Random random = new Random ();

         final Guard[] standbyGuard = new Guard[barrier.length + 1];
         for (int i = 0; i invalid input: '<' barrier.length; i++) {
           standbyGuard[i] = barrier[i];
         }
         standbyGuard[barrier.length] = tim;
         final int TIMEOUT = barrier.length;
         Alternative standbyAlt = new Alternative (standbyGuard);

         configure.write (Boolean.FALSE);               // disable mouse clicks
                                                        // (not used by this gadget)
         while (true) {

           configure.write (offColour);
           tim.sleep (random.nextInt (offInterval));

           configure.write (standbyColour);
           tim.setAlarm (tim.read () + random.nextInt (standbyInterval));

           int choice = standbyAlt.fairSelect ();       // magic synchronisation

           if (choice != TIMEOUT) {
             play (choice, random, tim);
           }

         }

       }

Here is the playing code. Initially, a colour is chosen and passed down the playing group's section of rail track, to which it has exclusive access. The flashing group is coordinated through the group's common event, with just one of them keeping time.

       private void play (int choice, Random random, CSTimer tim) {

         final boolean RIGHTMOST = (choice == 0);
         final boolean LEFTMOST = (choice == (barrier.length - 1));

         Color colour = null;
         if (RIGHTMOST) {
           colour = new Color (random.nextInt ());
         } else {
           colour = (Color) in.read ();
         }
         Color bright = colour.brighter ();

         if (!LEFTMOST) out.write (colour);             // pass it on

         final AltingBarrier focus = barrier[choice];

         final int count = playInterval/flashInterval;

         long timeout = tim.read () + flashInterval;

         boolean bright = true;

         for (int i = 0; i invalid input: '<' count; i++) {
           configure.write (bright ? brighter : colour);
           bright = !bright;
           if (RIGHTMOST) {
             tim.after (timeout);
             timeout += flashInterval;
           }
           focus.sync ();
         }

       }

     }

Here is code setting up a "circle" of these gadgets, buttons and alting barriers. The buttons are laid out in a row, so that the rightmost button is actually on the "left" of the leftmost button. Care needs to be taken to distribute the `span` front-ends for each `AltingBarrier` to the correct gadgets -- see the re-arrangement below:

     import org.jcsp.lang.*;
     import org.jcsp.util.*;
     import org.jcsp.plugNplay.*;

     import java.awt.Color;
     import java.util.Random;

     public class AltingBarrierGadget1Demo0 {

       public static void main (String[] argv) {

         final int nUnits = 30, span = 6;

         final int offInterval = 800, standbyInterval = 1000;    // milliseconds

         final int playInterval = 10000, flashInterval = 500;    // milliseconds

         final Color offColour = Color.black, standbyColour = Color.lightGray;

         // make the buttons

         final One2OneChannel[] click =
           Channel.one2oneArray (nUnits, new OverWriteOldestBuffer (1));

         final One2OneChannel[] configure = Channel.one2oneArray (nUnits);

         final boolean horizontal = true;

         final FramedButtonArray buttons =
           new FramedButtonArray (
             "AltingBarrier: Gadget 1, Demo 0", nUnits, 100, nUnits*50,
              horizontal, configure, click
           );

         // construct nUnits barriers, each with span front-ends ...

         AltingBarrier[][] ab = new AltingBarrier[nUnits][];
         for (int i = 0; i invalid input: '<' nUnits; i++) {
           ab[i] = AltingBarrier.create (span);
         }

         // re-arrange front-ends, ready for distribution to processes ...

         AltingBarrier[][]barrier = new AltingBarrier[nUnits][span];
         for (int i = 0; i invalid input: '<' nUnits; i++) {
           for (int j = 0; j invalid input: '<' span; j++) {
             barrier[i][j] = ab[(i + j) % nUnits][j];
           }
         }

         // make the track and the gadgets

         One2OneChannel[] track = Channel.one2oneArray (nUnits);

         AltingBarrierGadget1[] gadgets = new AltingBarrierGadget1[nUnits];
         for (int i = 0; i invalid input: '<' nUnits; i++) {
           gadgets[i] =
             new AltingBarrierGadget1 (
               barrier[i],
               track[(i + 1)%nUnits], track[i],
               click[i], configure[i],
               offColour, standbyColour,
               offInterval, standbyInterval,
               playInterval, flashInterval
             );
         }

         // run everything

         new Parallel (
           new CSProcess[] {
             buttons, new Parallel (gadgets)
           }
         ).run ();

       }

     }

For fun, here is another application program for the same gadget. It allows a much larger system to be built, laying out the circle of buttons in a grid, row by row. The rightmost button on each row is to the left of the leftmost button on the next row down. The next row down from the bottom row is the top row. The buttons and its `click` and `configure` channels are now two dimensional structures. The barriers, gadgets and rail track are still one dimensional. Only code differences from the above are shown:

     import org.jcsp.lang.*;
     import org.jcsp.util.*;
     import org.jcsp.plugNplay.*;

     import java.awt.Color;
     import java.util.Random;

     public class AltingBarrierGadget1Demo1 {

       public static void main (String[] argv) {

         final int width = 30, depth = 20;
         final int nUnits = width*depth;

         ...  the other system parameters (final ints and Colors)

         final One2OneChannel[][] click = new One2OneChannel[depth][];
         for (int i = 0; i invalid input: '<' depth; i++) {
           click[i] = Channel.one2oneArray (width, new OverWriteOldestBuffer (1));
         }

         final One2OneChannel[][] configure = new One2OneChannel[depth][];
         for (int i = 0; i invalid input: '<' depth; i++) {
           configure[i] = Channel.one2oneArray (width);
         }

         final FramedButtonGrid buttons =
           new FramedButtonGrid (
             "AltingBarrier: Gadget 1, Demo 1", depth, width,
             20 + (depth*50), width*50, configure, click
           );

         ...  construct nUnits barriers and the track exactly as before

         AltingBarrierGadget1[] gadgets = new AltingBarrierGadget1[nUnits];
         for (int i = 0; i invalid input: '<' nUnits; i++) {
           gadgets[i] =
             new AltingBarrierGadget1 (
               barrier[i],
               track[(i + 1)%nUnits], track[i],
               click[i/width][i%width],
               configure[i/width][i%width],
               offColour, standbyColour,
               offInterval, standbyInterval,
               playInterval, flashInterval
             );
         }

         ...  build and run the buttons and gadgets in parallel

       }

     }

### Other Examples

The `alting-barriers` directory in `jcsp-demos` contains other gadgets in a similar vein.

#### `AltingBarrierGadget2`

These are similar to `AltingBarrierGadget1`, but sit on a 2-way circular railtrack offering to synchronise in the same `span`-groups. Their difference is the game they play when synchronised: pass-the-parcel up and down their section of track, with the parcel's (rapid) progress indicated by writing on the button labels. These gadgets also enable their buttons when playing and finish their game when any one, or more, of their buttons is clicked -- or they get bored and timeout.

#### `AltingBarrierGadget3`

Along with their attached buttons, these form a two dimensional structure covering the surface of a torus. The gadgets on the top row are adjacent to the gadgets on the bottom row. The gadgets on the left column are adjacent to the gadgets on the right column. The demonstration program, `AltingBarrierGadget3Demo0`, asks the user to choose between various shapes and sizes for the synchronisation groups (pluses, crosses and circles) -- but all groups have the same shape and size.

Creation and distribution of the barriers is not done by the demonstration program but, more simply, by the gadgets themselves. Each `AltingBarrierGadget3` belongs to many synchronisation groups, but has lead responsibility for one. It services the input end of a single channel and is given the (shared) output ends of the service channels to the other gadgets in the group it is leading. [Note: the giver of those output ends is the demonstration program.] It creates the alting barrier (and some other things -- see below) for its lead group. Distribution is by I/O-PAR exchange over their service channels as the gadgets initialise. Each gadget sends the things it made to the gadgets in the group it is leading and receives the same from the leaders of its other synchronisation groups. This is the only use they make of these channels.

A synchronised group plays a simple counting game until one of its buttons is clicked or the countdown reaches zero. Termination of the game is, and has to be, simultaneous. This is managed by a shared termination flag, safely operated through phased barrier synchronisation (which lets any process in the group set it in an even phase, with all processes acting on it in the odd phases). Shared label and colour variables (for the group's buttons) are operated similarly. The shared variables are distributed (as fields of a shared object) by the leader gadget, along with the group's alting barrier front-ends, during initialisation.

The group's `AltingBarrier` is used to separate the phases. Alting capability on this barrier enables rapid response to any button click on the group to end the game. The lead gadget controls timing: it alts between a countdown timeout, its button click and a cancel message from the rest of the group (should any of their buttons be clicked) -- following any of these with the barrier sync, scheduling the next phase. The other gadgets alt between their button click and the barrier: response to a click being the (timeout) cancel message to the leader then wait for the barrier; response to the barrier being the next phase.

The `Any2One` cancel channel is a mulitplexing relay from the non-lead buttons to the leader gadget. It is constructed by the lead gadget and distributed to its team alongside the shared variables. The cancel channel must be overwriting buffered to avoid deadlock -- the same as the click channels from buttons. The cancel channel must be cleared at the start of each game -- same as the click channels.

USER GAME: run the demo program on a 30x20 grid (expand to full screen), with circle shapes (say), a radius of 3, off and standBy intervals of 1000 (millisecs), play interval of 10000 (millisecs) and a count interfavl of 200 (millisecs). Your challenge is to zap all the coloured shapes away before any of their counts reach zero and the end of the world happens, :). How long can you survive?!!

#### `AltingBarrierGadget4`

These are the same as the previous (`AltingBarrierGadget3`) gadgets, except that they do not assume that all the synchronisation groups to which they belong have the same shape or size. While they do know the size of the group they lead (from the length of the channel of output ends they are given), that is all they know. In particular, they do not know how many items (barriers etc.) to expect from the leaders of their other groups in the opening exchange.

This is solved by giving each gadget a global barrier on which their parallel outputting processes synchronise when they finish their distribution. After this synchronisation, all exchanges must have finished and they can tell their gadgets to proceed.

The demonstration program for these gadgets just asks for a size for synchronisation groups and allocates (lead) shapes randomly. It could randomise the sizes as well, but the smaller patterns would always emerge dominant in the synchronisations achieved (simply because they require fewer gadgets to be simultaneously on standby -- i.e. offering mode) and the consequent games.

USER GAME: same as before, except with a span (rather than radius) of 3.

#### `AltingBarrierGadget5`

These are the same as `AltingBarrierGadget4`, except for the technique used to signal the end of the initial exchange of information amongst the synchronisation groups. They use a global alting barrier on which both the outputting and inputting partners in the exchange offer to synchronise -- the former when finished outputting and the latter as an alternative to inputting. This is, perhaps, more elegant than the conventional barrier and channel used by the `AltingBarrierGadget4` gadgets and exercises the `expand()` and `contract()` methods.

USER GAME: same as before, except with a span (rather than radius) of 3.

#### `AltingBarrierGadget6`

The unbuffered service channels used by `AltingBarrierGadget3`, `AltingBarrierGadget4` and `AltingBarrierGadget5` (in the opening I/O-PAR exchange of information amongst each playing group) force the leaders to synchronise with each of their team members. This is no problem for `AltingBarrierGadget3`, since all groups have the same size and it receives as many messages as it sends; knowing how many messages it is sending, it knows how large its reception arrays should be. This is not the case for `AltingBarrierGadget4` and `AltingBarrierGadget5`, which must first receive into collection objects that can expand to any size.

`AltingBarrierGadget6` performs an asynchronous opening exchange of information, using the collection objects directly to buffer the communication messages and no channels. Further, no internal parallelism is needed for this exchange: the gadgets first add all their messages to the collections held by the rest of their team; then, they synchronise on the global barrier (a non-alting one, the same as used by `AltingBarrierGadget4`s); finally, they extract the information sent by the leaders of the other teams to which they belong. As before, the barrier synchronisation is crucial for the correctness of this exchange, ensuring that all messages are in place before they are gathered.

USER GAME: same as before, except with a span (rather than radius) of 3.

Author:
  P.H. Welch
See Also:
  - `Barrier`
  - `

    `

## Method Summary

Modifier and Type
Method
Description
`void`
`contract()`
This contracts by one the number of processes enrolled in this alting barrier.
`void`
`contract(AltingBarrier[] ab)`
This contracts the number of processes enrolled in this alting barrier.
`static AltingBarrier`
`create()`
This creates a new alting barrier with an (initial) enrollment count of `1`.
`static AltingBarrier[]`
`create(int n)`
This creates a new alting barrier with an (initial) enrollment count of `n`.
`void`
`enroll()`
A process may enroll only if it is resigned.
`AltingBarrier`
`expand()`
This expands by one the number of processes enrolled in this alting barrier.
`AltingBarrier[]`
`expand(int n)`
This expands the number of processes enrolled in this alting barrier.
`void`
`mark()`
A process may hand its barrier front-end over to another process, but the receiving process must invoke this method before using it.
`boolean`
`poll(long offerTime)`
This is a simple way to poll for synchonisation on an `AltingBarrier` without having to set up an `Alternative`.
`void`
`reset()`
This resets a front-end for reuse.
`void`
`resign()`
A process may resign only if it is enrolled.
`void`
`sync()`
This is a simple way to perform a committed synchonisation on an `AltingBarrier` without having to set up an `Alternative`.

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

## Method Details

### create

public static AltingBarrier[] create(int n)
This creates a new alting barrier with an (initial) enrollment count of `n`. It provides an array of `n` front-ends to this barrier. It is the invoker's responsibility to install one of these (by constructor or `set` method) in each process that will be synchronising on the barrier, before firing up those processes.

Note: each process must use a different front-end to the barrier. Usually, a process retains an `AltingBarrier` front-end throughout its lifetime -- however, see `mark`.

Parameters:
  `n` - the number of processes enrolled (initially) on this barrier.

Returns:
  an array of `n` front-ends to this barrier.

Throws:
  `IllegalArgumentException` - if `n` invalid input: '<'= `0`.

### create

public static AltingBarrier create()
This creates a new alting barrier with an (initial) enrollment count of `1`. It provides a single front-end to the barrier, from which others may be generated (see `expand()`) -- usually one-at-a-time to feed processes individually forked (by a `ProcessManager`). It is the invoker's responsibility to install each one (by constructor or `set` method) in the process that will be synchronising on the barrier, before firing up that process. Usually, a process retains an `AltingBarrier` front-end throughout its lifetime -- however, see `mark`.

Note: if a known number of processes needing the barrier are to be run (e.g. by a `Parallel`), creating the barrier with an array of front-ends using `create(n)` would be more convenient.

Returns:
  a single front-end for this barrier.

### expand

public AltingBarrier[] expand(int n)
This expands the number of processes enrolled in this alting barrier.

Use it when an enrolled process is about to go `Parallel` itself and some/all of those sub-processes also need to be enrolled. It returns an array new front-ends for this barrier. It is the invoker's responsibility to pass these on to those sub-processes.

Note that if there are `x` sub-processes to be enrolled, this method must be invoked with an argument of `(x - 1)`. Pass the returned `AltingBarrier`s to any `(x - 1)` of those sub-processes. Pass this `AltingBarrier` to the last one.

Before using its given front-end to this barrier, each sub-process must `mark` it to take ownership. [Actually, only the sub-process given the original front-end (which may be running in a different thread) really has to do this.]

Following termination of the `Parallel`, the original process must take back ownership of its original `AltingBarrier` (loaned to one of the sub-processes, which may have been running on a different thread) by `mark`ing it again.

Also following termination of the `Parallel`, the original process must contract the number of processes enrolled on the barrier. To do this, it must have retained the front-end array returned by this method and pass it to `contract`.

Parameters:
  `n` - the number of processes to be added to this barrier.

Returns:
  an array of new front-ends for this barrier.

Throws:
  `IllegalArgumentException` - if `n` invalid input: '<'= `0`.

  `AltingBarrierError` - if currently resigned or not owner of this front-end.

### expand

public AltingBarrier expand()
This expands by one the number of processes enrolled in this alting barrier.

Use it when an enrolled process is about to fork a new process (using `ProcessManager`) that also needs to be enrolled. It returns an new front-end for this barrier. It is the invoker's responsibility to pass it to the new process.

Before terminating, the forked process should `contract` (by one) the number of processes enrolled in this barrier. Otherwise, no further synchronisations on this barrier would be able to complete.

Returns:
  a new front-end for this barrier.

Throws:
  `AltingBarrierError` - if currently resigned or not owner of this front-end.

### contract

public void contract(AltingBarrier[] ab)
This contracts the number of processes enrolled in this alting barrier. The given front-ends are discarded.

Use it following termination of a `Parallel`, some/all of whose sub-processes were enrolled by being given front-ends returned by `expand`. See the documentation for `expand`.

Warning: only the process that went `Parallel` should invoke this method -- never one of the sub-processes.

Warning: never invoke this method whilst processes using its argument's front-ends are running.

Warning: do not attempt to reuse any of the argument elements afterwards -- they front-end nothing.

Parameters:
  `ab` - the front-ends being discarded from this barrier. This array must be unaltered from one previously delivered by an `expand`.

Throws:
  `IllegalArgumentException` - if `ab` is `null` or zero length.

  `AltingBarrierError` - if the given array is not one previously delivered by an `expand(n)`, or the invoking process is currently resigned or not the owner of this front-end.

### contract

public void contract()
This contracts by one the number of processes enrolled in this alting barrier. This front-end cannot not be used subsequently.

This method should be used on individually created front-ends (see `expand()`) when, and only when, the process holding it is about to terminate. Normally, that process would have been forked by the process creating this barrier.

Warning: do not try to use this front-end following invocation of this method -- it no longer fronts anything.

Throws:
  `AltingBarrierError` - if currently resigned or not the owner of this front-end.

### resign

public void resign()
A process may resign only if it is enrolled. A resigned process may not offer to synchronise on this barrier (until a subsequent `enroll`). Other processes can complete the barrier (represented by this front-end) without participation by the resigned process.

Unless all processes synchronising on this barrier terminate in the same phase, it is usually appropriate for a terminating process to resign first. Otherwise, its sibling processes will never be able to complete another synchronisation.

Note: a process must not transfer its front-end to another process whilst resigned from the barrier -- see `mark`.

Throws:
  `AltingBarrierError` - if currently resigned.

### enroll

public void enroll()
A process may enroll only if it is resigned. A re-enrolled process may resume offering to synchronise on this barrier (until a subsequent `resign`). Other processes cannot complete the barrier (represented by this front-end) without participation by the re-enrolled process.

Note: timing re-enrollment on a barrier usually needs some care. If the barrier is being used for synchronising phases of execution between a set of processes, it is crucial that re-enrollment occurs in an appropriate (not arbitrary) phase. If the trigger for re-enrollment comes from another enrolled process, that process should be in such an appropriate phase. The resigned process should re-enroll and, then, acknowledge the trigger. The triggering process should wait for that acknowledgement. If the decision to re-enroll is internal (e.g. following a timeout), a buddy process, enrolled on the barrier, should be asked to provide that trigger when in an appropriate phase. The buddy process, perhaps specially built just for this purpose, polls a service channel for that question when in that phase.

Throws:
  `AltingBarrierError` - if currently enrolled.

### mark

public void mark()
A process may hand its barrier front-end over to another process, but the receiving process must invoke this method before using it. Beware that the process that handed it over must no longer use it.

Note: a process must not transfer its front-end to another process whilst resigned from the barrier -- see `resign`. The receiving process assumes this is the case. This mark will fail if it is not so.

See `expand(n)` for an example pattern of use.

Throws:
  `AltingBarrierError` - if the front-end is resigned.

### reset

public void reset()
This resets a front-end for reuse. It still fronts the same barrier. Following this method, this front-end is enrolled on the barrier and not owned by any process.

Warning: this should only be used to recycle a front-end whose process has terminated. It should not be used to transfer a front-end between running processes (for which `mark` should be used).

Example:

       AltingBarrier[] action = AltingBarrier.create (n);

       Parallel[] system = new Parallel[n];
       for (int i = 0; i invalid input: '<' system.length; i++) {
         system[i] = new Something (action[i], ...);
       }

       while (true) {
         // invariant: all 'action' front-ends are enrolled on the barrier.
         // invariant: all 'action' front-ends are not yet owned by any process.
         system.run ();
         // assume: no 'system' process discards (contracts) its 'action' front-end.
         // note: some 'system' processes may have resigned their 'action' front-ends.
         // note: in the next run of 'system', its processes may be different
         //       from the point of view of the 'action' front-ends.
         for (int i = 0; i invalid input: '<' action.length; i++) {
           action[i].reset ();
         }
         // deduce: loop invariant re-established.
       }

### sync

public void sync()
This is a simple way to perform a committed synchonisation on an `AltingBarrier` without having to set up an `Alternative`. For example, if `group` is an `AltingBarrier`, then:

         group.sync ();

saves first having to construct the single guarded:

         Alternative groupCommit = new Alternative (new Guard[] {group});

and then:

         groupCommit.select ();

If this is the only method of synchronisation performed by all parties to this barrier, a non-alting `Barrier` would be more efficient.

Important note: following a `select`, `priSelect` or `fairSelect` on an `Alternative` that returns the index of an `AltingBarrier`, that barrier synchronisation has happened. Do not proceed to invoke this `sync` method -- unless, of course, you want to wait for a second synchronisation.

### poll

public boolean poll(long offerTime)
This is a simple way to poll for synchonisation on an `AltingBarrier` without having to set up an `Alternative`. The parameter specifies how long this poll should leave its offer to synchronise on the table. If `true` is returned, the barrier has completed. If `false`, the barrier was unable to complete within the time specified (i.e. at no time were all parties making an offer).

For example, if `group` is an `AltingBarrier`, then:

         if (group.poll (offerTime)) {
           ...  group synchronisation achieved
         } else {
           ...  group synchronisation failed (within offerTime millisecs)
         }

is equivalent to:

         groupTimer.setAlarm (groupTimer.read () + offerTime);
         if (groupPoll.priSelect () == 0) {
           ...  group synchronisation achieved
         } else {
           ...  group synchronisation failed (within offerTime millisecs)
         }

where first would have to have been constructed:

         CSTimer groupTimer = new CSTimer ();
         Alternative groupPoll =
           new Alternative (new Guard[] {group, groupTimer});

Note: polling algorithms should generally be a last resort! If all parties to this barrier only use this method, synchronisation depends on all their poll periods coinciding. An `offerTime` of zero is allowed: if all other parties are offering, the barrier will complete -- otherwise, the poll returns immediately. However, if more than one party only ever polls like this, no synchronisation will ever take place.

Parameters:
  `offerTime` - the time (in milliseconds) that this offer to synchronise should be left on the table.

Returns:
  `true` if and only if the barrier completes within time specifed.