JavaPP : ALTing with timeouts and SKIPs

Author: Peter Welch <P.H.Welch@ukc.ac.uk>

Date: Tue, 17 Jun 97 19:52:59 BST
From: phw <P.H.Welch@ukc.ac.uk>
To: java-threads@ukc.ac.uk, occam-com@ukc.ac.uk
Subject: JavaPP -- ALTing with timeout and SKIP guards
status: R
    

Dear All,

Timeout and SKIP guards have been added to the Java ALTs presented last October.
To use them, you will need this revised Alternative class. The previous Channel class is unchanged. An example showing its use is based, loosely, on the wot, no chickens? example (sample output).

Note that the given Channel class is defined to carry only integers. A version that carries Objects is obtained simply by substituting Object for int in the obvious places. These classes may be simplified for 1-1 connection (at present, they are many-1) but they cannot be extended to many-many and still used for ALTing.

The rest of this note documents occam and JavaPP equivalents for ALTing, including the timeout and SKIP guards.

(PRI) ALT on a channel array (with optional pre-conditions)

An occam prioritised ALT against an array of input guards is expressed:

      PRI ALT i = 0 FOR SIZE c
        c[i] ? x
          ...  some process (involving i)
  

A Java thread will first need to declare:

      Alternative alt = new Alternative ();
  

Then, the same prioritised ALT can be expressed:

      { int i = alt.select (c);
        x = c[i].read ();
        ...  some process (involving i)
      }
  

Notice that it is our responsibilty to read from the channel selected -- if we don't, bad things will happen. In occam, this responsibility is taken care for us by the compiler.

Often, the channel array will be small (and, if the channels are carrying Java Objects, each element can be communicating a separate protocol). In such cases, a `switch' statement may be more convenient:

      switch (alt.select (c)) {
        case 0: {
          x = c[0].read ();
          ...  some process (involving 0)
          break;
        }
        case 1: {
          x = c[1].read ();
          ...  some process (involving 1)
          break;
        }
        case 2: {
          x = c[2].read ();
          ...  some process (involving 2)
          break;
        }
      }
  

ALTing with pre-conditions is expressed in occam by:

      PRI ALT i = 0 FOR SIZE c
        guard[i] & c[i] ? x
          ...  some process (involving i)
  

where guard[i] is an array of booleans (the same size as the channel array).

In fact, the guard[i] could be any boolean expression in occam - but for Java, we need to get them into an array. The above pre-conditioned ALT is:

      { int i = alt.select (c, guard);
        x = c[i].read ();
        ...  some process (involving i)
      }
  

(PRI) ALT on a channel array and a timeout (with optional pre-conditions)

In occam, we may ALT against a (relative) timeout as follows:

    INT t:
    SEQ
      tim ? t
      PRI ALT
        ALT i = 0 FOR SIZE c
          c[i] ? x
            ...  some process (involving i)
        tim ? AFTER t PLUS (delay*msecs)
          ...  response to the timeout

where `tim' is an occam TIMER and `msecs' is a VAL INT of 1000 (or whatever number of TIMER ticks gives one millisecond). In JavaPP, this becomes:

    { int i = alt.select (c, delay);   // delay is a Java `long' type
      if (i < c.length) {
        x = c[i].read ();
        ...  some process (involving i)
      } else {
        ...  response to the timeout
      }
    }

Note: the Java `wait' methods (used in the implementation) provide relative timeouts in units of milliseconds. There is also a version of `wait' that provides timeouts in units of milliseconds plus nanoseconds (presumably the milliseconds component would normally be zero). Anyway, we provide versions of `select' that allow similar timeouts to be set.

Note: if `delay' is zero or negative, the timeout is deemed to have occured, but it is selected at lower priority than the channels (i.e. only if none of the channels were ready).

The occam ALT against an absolute timeout value:

    PRI ALT
      ALT i = 0 FOR SIZE c
        c[i] ? x
          ...  some process (involving i)
      tim ? AFTER timeout
        ...  response to the timeout

requires computing the the relative delay period for JavaPP:

    { int i = alt.select (c, timeout - System.currentTimeMillis());
      if (i < c.length) {
        x = c[i].read ();
        ...  some process (involving i)
      } else {
        ...  response to the timeout
      }
    }

where the absolute `timeout' in the Java is expressed in milliseconds (and calculated from an earlier reading the the system clock) and, again, noting that `timeout' must have type `long'.

CAVEAT: no allowance is made in the above for wrap around of the system clock! However, on our UNIX systems, time zero was in the early 1970s and these times are in milliseconds held in Java `long's (64-bit integers). I haven't done the calculation, but look out for a real mother of a Year-2000 type disaster some time around AD 1000000000 ...

Finally, we have provided pre-conditions for `select'-with-timeout in the case that both the channels and the timeout have pre-conditions. In occam:

    PRI ALT
      ALT i = 0 FOR SIZE c
        guard[i] & c[i] ? x
          ...  some process (involving i)
      timeout.condition & tim ? AFTER timeout
        ...  response to the timeout

In JavaPP, this becomes:

    { int i = alt.select (c, guard, timeout - System.currentTimeMillis(),
                          timeout_condition);
      if (i < c.length) {
        x = c[i].read ();
        ...  some process (involving i)
      } else {
        ...  response to the timeout
      }
    }

(PRI) ALT on a channel array and SKIP (with optional pre-conditions)

In occam, we may poll an array of channels by:

    PRI ALT
      ALT i = 0 FOR SIZE c
        c[i] ? x
          ...  some process (involving i)
      skip.condition & SKIP
        ...  response to no channels being ready

where `skip.condition' can be any boolean expression. If this is true, we get a poll on the channels -- i.e. we take the last branch if-and-only-if no channels are ready. If this is false, it's the same as just PRI ALTing on the channels.

In JavaPP, this becomes:

    { int i = alt.select (c, skip_condition);
      if (i < c.length) {
        x = c[i].read ();
        ...  some process (involving i)
      } else {
        ...  response to no channels being ready
      }
    }

Notice that, as in occam, the SKIP guard has to have a pre-condition -- it's the pre-condition that implies the presence of the SKIP guard!.

Finally, we can put pre-conditions on the channels as well as the SKIP guard. In occam:

    PRI ALT
      ALT i = 0 FOR SIZE c
        guard[i] & c[i] ? x
          ...  some process (involving i)
      skip.condition & SKIP
        ...  response to no channels being ready

In JavaPP, this becomes:

    { int i = alt.select (c, guard, skip_condition);
      if (i < c.length) {
        x = c[i].read ();
        ...  some process (involving i)
      } else {
        ...  response to no channels being ready
      }
    }

Peter.