.NH
Implementation
.PP
It is now time to describe the implementation of some of the occam-specific
features such as channels and \fBNOW\fP. Also the way communication with
UNIX\(dg is performed must be described.
.FS
\(dg UNIX is a trademark of Bell Laboratories
.FE
For a thorough description of the library routines to simulate parallelism,
which are e.g. used by the channel routines and by the \fBPAR\fP construct
in Appendix B, see [6].
.NH 2
Channels
.PP
There are currently two types of channels (see Figure 1.) indicated by the type
field of a channel variable:
.IP -
An interprocess communication channel with two additional fields:
.RS
.IP -
A synchronization field to hold the state of an interprocess communication
channel.
.IP -
An integer variable to hold the value to be send.
.RE
.IP -
An outside world communication channel. This is a member of an array of
channels connected to UNIX files. Its additional fields are:
.RS
.IP -
A flags field holding a readahead flag and a flag that tells if this channel
variable is currently connected to a file.
.IP -
A preread character, if readahead is done.
.IP -
An index field to find the corresponding UNIX file.
.RE
.LP
.PS
box ht 3.0 wid 3.0
box ht 0.75 wid 0.75 with .nw at 1st box.nw + (0.5, -0.5) "Process 1"
box ht 0.75 wid 0.75 with .ne at 1st box.ne + (-0.5, -0.5) "Process 2"
box ht 0.75 wid 0.75 with .sw at 1st box.sw + (0.5, 0.5) "Process 3"
box ht 0.75 wid 0.75 with .se at 1st box.se + (-0.5, 0.5) "Process 4"
line right from 5/12 <2nd box.ne, 2nd box.se> to 5/12 <3nd box.nw, 3nd box.sw>
line right from 7/12 <2nd box.ne, 2nd box.se> to 7/12 <3nd box.nw, 3nd box.sw>
line right from 5/12 <4th box.ne, 4th box.se> to 5/12 <5nd box.nw, 5nd box.sw>
line right from 7/12 <4th box.ne, 4th box.se> to 7/12 <5nd box.nw, 5nd box.sw>
line down from 5/12 <2nd box.sw, 2nd box.se> to 5/12 <4nd box.nw, 4nd box.ne>
line down from 7/12 <2nd box.sw, 2nd box.se> to 7/12 <4nd box.nw, 4nd box.ne>
line down from 5/12 <3rd box.sw, 3rd box.se> to 5/12 <5nd box.nw, 5nd box.ne>
line down from 7/12 <3rd box.sw, 3rd box.se> to 7/12 <5nd box.nw, 5nd box.ne>
line right 1.0 from 5/12 <5th box.ne, 5th box.se> 
line right 1.0 from 7/12 <5th box.ne, 5th box.se> 
line left 1.0 from 5/12 <2nd box.nw, 2nd box.sw> 
line left 1.0 from 7/12 <2nd box.nw, 2nd box.sw> 
.PE
.DS C
\fIFigure 1. Interprocess and outside world communication channels\fP
.DE
The basic channel handling is done by \f(CWchan_in\fP and \f(CWchan_out\fP. All
other routines are based on them. The routine \f(CWchan_any\fP only checks if
there's a value available on a given channel. (It does not read this value!)
\f(CWC_init\fP initializes an array of interprocess communication channels.
.LP
The following table shows Occam statements paired with the routines used to
execute them.
.TS H
center, box;
c | c | c
lf5 | lf5 | lf5.
Occam statement	Channel handling routine	Called as
=
.sp 0.5
.TH
T{
.nf
CHAN c:
CHAN c[z]:
.fi
T}	T{
.nf
c_init(c, z) 
chan *c; unsigned z;
.fi
T}	T{
.nf
c_init(&c, 1);
c_init(&c, z);
.fi
T}
.sp 0.5
_
.sp 0.5
T{
.nf
c ? v
.fi
T}	T{
.nf
chan_in(v, c)
long *v; chan *c;
.fi
T}	T{
.nf
chan_in(&v, &c);
.fi
T}
.sp 0.5
T{
.nf
c ? b[byte i]
.fi
T}	T{
.nf
cbyte_in(b, c)
char *b; chan *c;
.fi
T}	T{
.nf
cbyte_in(&b[i], &c);
.fi
T}
.sp 0.5
T{
.nf
c ? a[i for z]
.fi
T}	T{
.nf
c_wa_in(a, z, c)
long *a; unsigned z; chan *c;
.fi
T}	T{
.nf
c_wa_in(&a[i], z, &c);
.fi
T}
.sp 0.5
T{
.nf
c ? a[byte i for z]
.fi
T}	T{
.nf
c_ba_in(a, z, c)
long *a; unsigned z; chan *c;
.fi
T}	T{
.nf
c_ba_in(&a[i], z, &c);
.fi
T}
.sp 0.5
_
.sp 0.5
T{
.nf
c ! v
.fi
T}	T{
.nf
chan_out(v, c)
long *v; chan *c;
.fi
T}	T{
.nf
chan_out(&v, &c);
.fi
T}
.sp 0.5
T{
.nf
c ! a[i for z]
.fi
T}	T{
.nf
c_wa_out(a, z, c)
long *a; unsigned z; chan *c;
.fi
T}	T{
.nf
c_wa_out(&a[i], z, &c);
.fi
T}
.sp 0.5
T{
.nf
c ! a[byte i for z]
.fi
T}	T{
.nf
c_ba_out(a, z, c)
long *a; unsigned z; chan *c;
.fi
T}	T{
.nf
c_ba_out(&a[i], z, &c);
.fi
T}
.sp 0.5
_
.sp 0.5
T{
.nf
alt
	c ? ....
		....
.fi
T}	T{
.nf
int chan_any(c)
chan *c;
.fi
T}	T{
.nf
deadlock=0;
for(;;) {
	if (chan_any(&c)) {
		....
	....
.fi
T}
.sp 0.5
.TE
The code of \f(CWc_init\fP, \f(CWchan_in\fP, \f(CWchan_out\fP and \f(CWchan_any\fP
can be found in Appendix A.
.NH 3
Synchronization on interprocess communication channels
.PP
The synchronization field can hold three different values indicating the
state the channel is in:
.IP "- \fBC\(ulS\(ulFREE\fP:" 15
Ground state, channel not in use.
.IP "- \fBC\(ulS\(ulANY\fP:" 15
Channel holds a value, the sending process is waiting for an acknowledgement
about its receipt.
.IP "- \fBC\(ulS\(ulACK\fP:" 15
Channel data has been removed by a receiving process, the sending process can
set the channel free now.
.LP
A sending process cannot simply wait until the channel changes state C\(ulS\(ulANY
to state C\(ulS\(ulFREE before it continues. There is a third state needed to prevent
a third process from using the channel before our sending process is 
acknowledged. Note, however that it is not allowed to use a channel for input
or output in more than one parallel process. This is too difficult to check
in practice, so we tried to smooth it a little.
.NH 2
NOW
.PP
\fBNOW\fP evaluates to the current time returned by the time(2) system call.
The code is simply:
.DS
.ft CW
.nf
	long now()
	{
		deadlock=0;
		return time((long *) 0);
	}
.fi
.ft
.DE
The ``deadlock=0'' prevents deadlocks while using the clock.
.NH 2
UNIX interface
.PP
To handle the communication with the outside world the following channels are
defined:
.IP -
\fBinput\fP, that corresponds with the standard input file,
.IP -
\fBoutput\fP, that corresponds with the standard output file,
.IP -
\fBerror\fP, that corresponds with the standard error file.
.IP -
\fBfile\fP, an array of channels that can be subscripted with an index
obtained by the builtin named process ``\f(CWopen\fP''. Note that
\fBinput\fP=\fBfile\fP[0], \fBoutput\fP=\fBfile\fP[1] and
\fBerror\fP=\fBfile\fP[2].
.LP
Builtin named processes to open and close files are defined as
.DS
.nf
.ft CW
proc open(var index, value name[], mode[]) = ..... :
proc close(value index) = ..... :
.fi
.ft
.DE
To open a file `junk', write nonsense onto it, and close it, goes as follows:
.DS
.ft CW
.nf
	var i:
	seq
		open(i, "junk", "w")
		file[i] ! nonsense
		close(i)
.fi
.ft
.DE
Errors opening a file are reported by a negative index, which is the
negative value of the error number (called \fIerrno\fP in UNIX).
.LP
Bytes read from or written onto these channels are taken from occam variables.
As these variables can hold more than 256 values, some negative values are used
to control channels. These values are:
.IP "- \fBEOF\fP" 9
(-1): Eof from file channel is read as -1.
.IP "- \fBTEXT\fP" 9
(-2): A -2 written onto any channel connected to a terminal puts this
terminal in the normal line oriented mode (i.e. characters typed are echoed
and lines are buffered before they are read).
.IP "- \fBRAW\fP" 9
(-3): A -3 written onto any channel connected to a terminal puts it in raw mode
(i.e. no echoing of typed characters and no line buffering).
.LP
To exit an Occam program, e.g. after an error, a builtin named process
\f(CWexit\fP is available that takes an exit code as its argument.
.NH 2
Replicators and slices
.PP
Both the base and the count of replicators like in
.DS
.ft CW
	par i = [ base for count ]
.ft
.DE
may be arbitrary expressions. The count in array slices like in
.DS
.ft CW
	c ? A[ base for count ]
.ft
.DE
must be a constant expression however, the base is again free.
