Contents of the PWC.DOC file
When programming a transputer network, it is useful to
distinguish the different forms of parallelism that are possible.
The most obvious form of concurrency occurs when we have multiple
transputers executing code simultaneously. However, concurrency
is also possible on a single transputer.
On a single transputer, we can start up a number of
processes using TCC's par construct or the runtime startp()
function. Running multiple processes on a single transputer
compares to the kind of multitasking that operating systems such
as UNIX perform. In this case, we do not have true concurrency
but rather what is best termed "virtual concurrency".
One can achieve true concurrency on a single transputer with
programs that make use of channel I/O. In such a case, it is
possible to employ one or more of the transputer's links even as
the MPU is executing code.
On a single transputer, we can begin to exploit the
transputer's parallel nature if we create separate processes: one
to perform some sort of fundamental calculation or data massaging
and one or two additional processes to read data on and off the
transputer node via its links.
The TCC program PWC.C (see listing) demonstrates this point.
The strategy employed is pretty straightforward. It uses a
calculation process, main(), that counts words from a file as
they are read in with fgets(). main() is also responsible for
initializing channels and starting up the I/O process, IOProc().
fgets() is modified slightly for pwc: instead of obtaining its
buffers directly by a function call to read(), buffers are
obtained via channel communications with IOProc().
IOProc() acts as a go between between the host system and
the process, main(). Once it obtains a valid file descriptor from
main(), it proceeds to read buffers into a two-way linked list.
Two channels, CommOne and CommTwo, are used to pass messages with
main(). CommOne is used to send buffer pointers to main whenever
fgets() requires a buffer. CommTwo is used to receive string
pointers from main whenever main wishs to display a string on
After each read, IOProc() checks, using an alt construct,
these two channels. If either channel is "selected" by the alt
construct, the appropriate action is taken. Each time fgets()
exhausts its current buffer, it attempts to read a new buffer
pointer in on the channel, CommOne. IOProc(), seeing that this
channel is ready for, takes a buffer pointer off the tail of its
linked list and sends it to fgets().
main() maps its console output through IOProc() and never
attempts to communicate with the links directly. IOProc()
"masters" the links. This detail is critical since it insures
that there will never be any more than one process attempting to
use the links at a time.
IOProc() represents a rudimentary form of a message passer.
IOProc is a sort of a state machine; it is either waiting for
input, waiting for output, outputting data or inputting data. The
overhead for message passers is minimal. In any one of these
states it is either using a link device or waiting on a
communications event, leaving the MPU almost entirely free for
some other task.
Most concurrent transputer applications will want a message
passer of some kind. They make efficient use of the transputer's
facilities, insure stable and unified use of the links and
cleanly separate the communications task into a module. A message
passer can be revised and expanded upon independently of the rest
of the program. A revision of a message passer, for example,
might implement error checking capabilities or the ability to
select alternative message routes.