Вы находитесь на странице: 1из 12

grams, three basic constructs have received widespread

recognition and use: A repetitive construct (e.g. the while


loop), an alternative construct (e.g. the conditional
if..then..else), and normal sequential program composi-
Programming S. L. Graham, R. L. Rivest tion (often denoted by a semicolon). Less agreement has
Teclmiques Editors been reached about the design of other important pro-

Communicating gram structures, and many suggestions have been made:


Subroutines (Fortran), procedures (Algol 60 [15]), entries

Sequential Processes (PL/I), coroutines (UNIX [171), classes (SIMULA 67 [5]),


processes and monitors (Concurrent Pascal [2]), clusters
(CLU [13]), forms (ALPHARD [19]), actors (Hewitt [1]).
C.A.R. Hoare The traditional stored program digital computer has
The Queen's University been designed primarily for deterministic execution of a
Belfast, Northern Ireland single sequential program. Where the desire for greater
speed has led to the introduction of parallelism, every
attempt has been made to disguise this fact from the
This paper suggests that input and output are basic programmer, either by hardware itself (as in the multiple
primitives of programming and that parallel function units of the CDC 6600) or by the software (as
composition of communicating sequential processes is a in an I/O control package, or a multiprogrammed op-
fundamental program structuring method. When erating system). However, developments of processor
combined with a development of Dijkstra's guarded technology suggest that a multiprocessor machine, con-
command, these concepts are surprisingly versatile. structed from a number of similar self-contained proc-
Their use is illustrated by sample solutions of a variety essors (each with its own store), may become more
of familiar programming exercises. powerful, capacious, reliable, and economical than a
Key Words and Phrases: programming, machine which is disguised as a monoprocessor.
programming languages, programming primitives, In order to use such a machine effectively on a single
program structures, parallel programming, concurrency, task, the component processors must be able to com-
input, output, guarded commands, nondeterminacy, municate and to synchronize with each other. Many
coroutines, procedures, multiple entries, multiple exits, methods of achieving this have been proposed. A widely
classes, data representations, recursion, conditional adopted method of communication is by inspection and
critical regions, monitors, iterative arrays updating of a common store (as in Algol 68 [18], PL/I,
CR Categories: 4.20, 4.22, 4.32 and many machine codes). However, this can create
severe problems in the construction of correct programs
and it may lead to expense (e.g. crossbar switches) and
1. Introduction unreliability (e.g. glitches) in some technologies of hard-
ware implementation. A greater variety of methods has
Among the primitive concepts of computer program- been proposed for synchronization: semaphores [6],
ming, and of the high level languages in which programs events (PL/I), conditional critical regions [10], monitors
are expressed, the action of assignment is familiar and and queues (Concurrent Pascal [2]), and path expressions
well understood. In fact, any change of the internal state [3]. Most of these are demonstrably adequate for their
of a machine executing a program can be modeled as an purpose, but there is no widely recognized criterion for
assignment of a new value to some variable part of that choosing between them.
machine. However, the operations of input and output, This paper makes an ambitious attempt to find a
which affect the external environment of a machine, are single simple solution to all these problems. The essential
not nearly so well understood. They are often added to proposals are:
a programming language only as an afterthought. (1) Dijkstra's guarded commands [8] are adopted (with
Among the structuring methods for computer pro- a slight change of notation) as sequential control struc-
General permission to make fair use in teaching or research of all tures, and as the sole means of introducing and control-
or part of this material is granted to individual readers and to nonprofit ling nondeterminism.
libraries acting for them provided that ACM's copyright notice is given (2) A parallel command, based on Dijkstra's parbegin
and that reference is made to the publication, to its date of issue, and
to the fact that reprinting privileges were granted by permission of the [6], specifies concurrent execution of its constituent se-
Association for Computing Machinery. To otherwise reprint a figure, quential commands (processes). All the processes start
table, other substantial excerpt, or the entire work requires specific simultaneously, and the parallel command ends only
permission as does republication, or systematic or multiple reproduc-
tion. when they are all finished. They may not communicate
This research was supported by a Senior Fellowship of the Science with each other by updating global variables.
Research Council.
(3) Simple forms of input and output command are
Author's present address: Programming Research Group, 45, Ban-
bury Road, Oxford, England. introduced. They are used for communication between
1978 ACM 0001-0782/78/0800-0666 $00.75 concurrent processes.
666 Communications August 1978
of Volume 21
the ACM Number 8
(4) Such communication occurs when one process tations for the most common and useful special cases;
names another as destination for output a n d the second (3) development of automatic optimization techniques;
process names the first as source for input. In this case, and (4) the design of appropriate hardware.
the value to be output is copied from the first process to Thus the concepts and notations introduced in this
the second. There is n o automatic buffeting: In general, paper (although described in the next section in the form
an input or output command is delayed until the other of a programming language fragment) should not be
process is ready with the corresponding output or input. regarded as suitable for use as a programming language,
Such delay is invisible to the delayed process. either for abstract or for concrete programming. They
(5) Input commands may appear in guards. A guarded are at best only a partial solution to the problems tackled.
command with an input guard is selected for execution Further discussion of these and other points will be
only if and when the source named in the input com- found in Section 7.
mand is ready to execute the corresponding output com-
mand. If several input guards of a set of alternatives
have ready destinations, only one is selected and the 2. Concepts and Notations
others have n o effect; but the choice between them is
arbitrary. In an efficient implementation, an output com- The style of the following description is borrowed
mand which has been ready for a long time should be from Algol 60 [15]. Types, declarations, and expressions
favored; but the defmition of a language cannot specify have not been treated; in the examples, a Pascal-like
this since the relative speed of execution of the processes notation [20] has usually been adopted. The curly braces
is undefmed. { } have been introduced into BNF to denote none or
(6) A repetitive command may have input guards. If all more repetitions of the enclosed material. (Sentences in
the sources named by them have terminated, then the parentheses refer to an implementation: they are not
repetitive command also terminates. strictly part of a language defmition.)
(7) A simple pattern-matching feature, similar to that of < c o m m a n d > :.---<simple command>l<structured command>
[16], is used to discriminate the structure of an input <simple command> :.--- <null command>l<assignment command>
message, and to access its components in a secure fash- I<input command>l<output command>
ion. This feature is used to inhibit input of messages that <structured command> :.--- <alternative command>
I<repetitive command>l<parallel command>
do not match the specified pattern.
<null command> :.--- skip
The programs expressed in the proposed language <command list> :.--- {<declaration>; I<command>;} < c o m m a n d >
are intended to be implementable.both by a conventional
machine with a single main store, and by a fixed network A command specifies the behavior of a device exe-
of processors connected by input/output channels (al- cuting the command. It may succeed or fail. Execution
though very different optimizations are appropriate in of a simple command, if successful, may have an effect
the different cases). It is consequently a rather static on the internal state of the executing device (in the case
language: The text of a program determines a fixed of assignment), or on its external environment (in the
upper bound on the number of processes operating case of output), or on both (in the case of input). Exe-
concurrently; there is no recursion and no facility for cution of a structured command involves execution of
process-valued variables. In other respects also, the lan- some or all of its constituent commands, and if any of
guage has been stripped to the barest minimum necessary these fail, so does the structured command. (In this case,
for explanation of its more novel features. whenever possible, an implementation should provide
The concept of a communicating sequential process some kind of comprehensible error diagnostic message.)
is shown in Sections 3-5 to provide a method of express- A null command has no effect and never fails.
ing solutions to many simple programming exercises A command list specifies sequential execution of its
which have previously been employed to illustrate the constituent commands in the order written. Each decla-
use of various proposed programming language features. ration introduces a fresh variable with a scope which
This suggests that the process may constitute a synthesis extends from its declaration to the end of the command
of a number of familiar and new programming ideas. list.
The reader is invited to skip the examples which do not
interest him. 2.1 Parallel Commands
However, this paper also ignores many serious prob-
<parallel command> :.--- [<process> {I I<process>} ]
lems. The most serious is that it fails to suggest any proof <process> :.---<process label> <command list>
method to assist in the development and verification of <process label> :.---<empty>l<identifier> ::
correct programs. Secondly, it pays no attention to the I<identifier>(<label subscript>{,<label subscript>}) ::
problems of efficient implementation, which may be <label subscript> :.---<integer constant>l<range>
<integer constant> :.---<numeral>l<bound variable>
particularly serious on a traditional sequential computer.
< b o u n d variable> :.---<identifier>
It is probable that a solution to these problems will < r a n g e > :.~ <bound variable>:<lower bound>..<upper bound>
require (1) imposition of restrictions in the use of the <lower bound> :.~ <integer constant>
proposed features; (2) reintroduction of distinctive no- <upper bound> :.~ <integer constant>

667 Communications August 1978


of Volume 21
the ACM Number 8
Each process of a parallel command must be disjoint An expression denotes a value which is computed by
from every other process of the command, in the sense an executing device by application of its constituent
that it does not mention any variable which occurs as a operators to the specified operands. The value of an
target variable (see Sections 2.2 and 2.3) in any other expression is undefined if any of these operations are
process. undefined. The value denoted by a simple expression
A process label without subscripts, or one whose label may be simple or structured. The value denoted by a
subscripts are all integer constants, serves as a name for structured expression is structured; its constructor is that
the command list to which it is prefixed; its scope extends of the expression, and its components are the list of
over the whole of the parallel command. A process values denoted by the constituent expressions of the
whose label subscripts include one or more ranges stands expression list.
for a series of processes, each with the same label and An assignment command specifies evaluation of its
command list, except that each has a different combi- expression, and assignment of the denoted value to the
nation of values substituted for the bound variables. target variable. A simple target variable may have as-
These values range between the lower bound and the signed to it a simple or a structured value. A structured
upper bound inclusive. For example, X(i:l..n) :: CL target variable may have assigned to it a structured value,
stands for with the same constructor. The effect of such assignment
X(l) :: CEll[X(2):: CL211...[IX(n) :: CL~
is to assign to each constituent simpler variable of the
structured target the value of the corresponding compo-
where each CLy is formed from CL by replacing every nent of the structured value. Consequently, the value
occurrence of the bound variable i by the numeral j. denoted by the target variable, if evaluated after a suc-
After all such expansions, each process label in a parallel cessful assignment, is the same as the value denoted by
command must occur only once and the processes must the expression, as evaluated before the assignment.
be well formed and disjoint. An assignment fails if the value of its expression is
A parallel command specifies concurrent execution undefined, or if that value does not match the target
of its constituent processes. They all start simultaneously variable, in the following sense: A simple target variable
and the parallel command terminates successfully only matches any value of its type. A structured target variable
if and when they have all successfully terminated. The matches a structured value, provided that: (1) they have
relative speed with which they are executed is arbitrary. the same constructor, (2) the target variable list is the
Examples: same length as the list of components of the value, (3)
(1) [cardreader?cardimage[ [lineprinter!lineimage] each target variable of the list matches the corresponding
component of the value list. A structured value with no
Performs the two constituent commands in parallel,
components is known as a "signal."
and terminates only when both operations are complete.
The time taken may be as low as the longer of the times Examples:
taken by each constituent process, i.e. the sum of its
(1) x . - - - x + 1 the value of x after the assignment
computing, waiting, and transfer times. is the same as the value o f x + 1
(2) [west :: DISASSEMBLEIlX :: SQUASH I [east :: ASSEMBLE] before.
(2) (x, y) -- (y, x) exchanges the values o f x and y.
The three processes have the names "west," "X," and (3) x .--- cons(left, right) constructs a structured value and
"east." The capitalized words stand for command lists assigns it to x.
which will be defined in later examples. (4) cons(left, right) .--- x fails if x does not have the form
cons(y, z); but if it does, then y is
(3) [room :: ROOM I Ifork(i:0..4) :: F O R K I Iphil(i:0..4) :: PHIL] assigned to left, and z is assigned
There are eleven processes. The behavior of "room" to right.
(5) insert(n) ~ insert(2,x + 1) equivalent to n .--- 2*x + l.
is specified by the command list ROOM. The behavior of assigns to c a "signal" with con-
(6) c .--- PO
the five processes fork(0), fork(l), fork(2), fork(3), structor P, and no components.
fork(4), is specified by the command list FORK, within ( 7 ) . P 0 .--- c fails if the value of c is not P 0 ;
which the bound variable i indicates the identity of the otherwise has no effect.
particular fork. Similar remarks apply to the five proc- (8) insert(n) .---has(n) fails, due to mismatch.
esses PHIL. Note: Successful execution of both (3) and (4) ensures
the truth of the postcondition x = cons(left, right); but
2.2 Assignment Commands (3) does so by changing x and (4) does so by changing
<assignment c o m m a n d > :.--- <target variable> := <expression> left and right. Example (4) will fail if there is no value of
<expression> :.-= <simple expression>l<structured expression> left and right which satisfies the postcondition.
<structured expression> : ~ <constructor>(<expression list>)
<constructor> :.--- <identifier>l<empty>
<expression list> :-- <empty>l<expression>{,<expression>} 2.3 Inimt and Output Commands
<target variable> :.--- <simple variable>l<structured target>
<structured target> :.--- <constructor>(<target variable list>) <input c o m m a n d > :.~ <source>?<target variable>
<target variable list> : ~ <empty>[<target variable> <output c o m m a n d > :.---<destination>!<expression>
{,<target variable>} <source> :.~ <process name>

668 Communications August 1978


of Volume 2 l
the ACM Number 8
<destination> :.--- <process name> 2.4 Alternative and Repetitive Commands
<process name> :.= <identifier>[<identifier>(<subscripts>)
<subscripts> ::= <integer expression>{,<integer expression>} <repetitive command> :.---,<alternative command>
<alternative command> :-- [<guarded command>
Input and output commands specify communication (13<gnarded command>} ]
between two concurrently operating sequential processes. <guarded command> : ~ <guard> ----, <command list>
I(<range>{,<range>})<guard> --, <command list>
Such a process may be implemented in hardware as a <guard> :.--- <guard list>l<guard list>;<input command>
special-purpose device (e.g. cardreader or lineprinter), or I<input command>
its behavior may be specified by one of the constituent <guard list> : ~ <guard element>(;<gnard element>}
processes of a parallel command. Communication occurs <guard element> : ~ <boolean expression>l<declaration>
between two processes of a parallel command whenever
(1) an input command in one process specifies as its
A guarded command with one or more ranges stands
source the process name of the other process; (2) an
for a series of guarded commands, each with the same
output command in the other process specifies as its
guard and command list, except that each has a different
destination the process name of the first process; and (3)
combination of values substituted for the bound varia-
the target variable of the input command matches the
bles. The values range between the lower bound and
value denoted by the expression of the output command.
upper bound inclusive. For example, (i:l..n)G --~ CL
On these conditions, the input and output commands are
stands for
said to correspond. Commands which correspond are
executed simultaneously, and their combined effect is to G1 ~ CLI[IG2 --> CL2n...[IGn ~ CLn
assign the value of the expression of the output command
where each Gj --> CLj is formed from G --, CL by
to the target variable of the input command.
replacing every occurrence of the bound variable i by the
An input command fails if its source is terminated.
numeralj.
An output command fails if its destination is terminated A guarded command is executed only if and when
or if its expression is undefined. the execution of its guard does not fail. First its guard is
(The requirement of synchronization of input and executed and then its command list. A guard is executed
output commands means that an implementation will
by execution of its constituent elements from left to right.
have to delay whichever of the two commands happens
A Boolean expression is evaluated: If it denotes false, the
to be ready first. The delay is ended when the corre-
guard fails; but an expression that denotes true has no
sponding command in the other process is also ready, or
effect. A declaration introduces a fresh variable with a
when the other process terminates. In the latter case the
scope that extends from the declaration to the end of the
first command fails. It is also possible that the delay will
guarded command. An input command at the end of a
never be ended, for example, if a group of processes are
guard is executed only if and when a corresponding
attempting communication but none of their input and
output command is executed. (An implementation may
output commands correspond with each other. This form
test whether a guard fails simply by trying to execute it,
of failure is known as a deadlock.)
and discontinuing execution if and when it fails. This is
valid because such a discontinued execution has no effect
Examples: on the state of the executing device.)
(1) cardreader?cardimage from cardreader, read a card and An alternative command specifies execution of ex-
assign its value (an array of char- actly one of its constituent guarded commands. Conse-
acters) to the variable cardimage quently, if all guards fail, the alternative command fails.
(2) lineprinter!lineimage to lineprinter, send the value of Otherwise an arbitrary one with successfully executable
lineimage for printing
(3) X?(x, y)
guard is selected and executed. (An implementation
from process named X, input a pair
of values and assign them to x should take advantage of its freedom of selection to
andy ensure efficient execution and good response. For ex-
(4) DIV!(3.a + b, 13) to process DIV, output the two ample, when input commands appear as guards, the
specified values. command which corresponds to the earliest ready and
Note: If a process named DIV issues command (3), and a process matching output command should in general be pre-
named X issues command (4), these are executed simultaneously, ferred; and certainly, no executable and ready output
and have the same effect as the assignment: ( x , y ) ~ (3*a + b, 13) command should be passed over unreasonably often.)
(mx~3*a+b;y~ 13). A repetitive command specifies as many iterations as
(5) console(0?c from the/th element of an array of possible of its constituent alternative command. Conse-
consoles, input a value and assign quently, when all guards fail, the repetitive command
it to c terminates with no effect. Otherwise, the alternative com-
(6) console(./- I)!"A" to the ( j - l)th console, output mand is executed once and then the whole repetitive
character "A"
(7) x(o?v( ) command is executed again. (Consider a repetitive com-
from the/th of an array of processes
X, input a signal V( ); refuse to mand when all its true guard lists end in an input guard.
input any other signal Such a command may have to be delayed until either (1)
(8) sem!P( ) to sem output a signal P( ) an output command corresponding to one of the input
669 Communications August 1978
of Volume 21
the ACM Number 8
guards becomes ready, or (2) all the sources named by 3. Coroutines
the input guards have terminated. In case (2), the repet-
itive command terminates. If neither event ever occurs, In parallel programming coroutines appear as a more
the process fails (in deadlock.) fundamental program structure than subroutines, which
Examples: can be regarded as a special case (treated in the next
(l) [x >_y---~ m .--- xOy_> x--~ m ~ y]
section).

If x _>y, assign x to m; i f y >_ x assign y to m; if both 3.1 COPY


x _> y and y >_ x, either assignment can be executed. Problem: Write a process X to copy characters output by
(2) i .~ 0;*[i < size; content(/) # n ~ i .~ i + 1] process west to process, east.
Solution:
The repetitive command scans the elements con-
X :: ,[c:character; west?c ~ east!c]
tent(i), for i = 0, 1. . . . . until either i >_ size, or a value
equal to n is found. Notes: (1) When west terminates, the input "west?e" will
(3) ,[c:character; west?c ~ east!c] fail, causing termination of the repetitive command, and
of process X. Any subsequent input command from east
This reads all the characters output by west, and will fail. (2) Process X acts as a single-character buffer
outputs them one by one to east. The repetition termi- between west and east. It permits west to work on
nates when the process west terminates. production of the next character, before east is ready to
(4) ,[(i:l..10)continue(t); console(i)?c-:, X!(i, c); console(0!ack(); input the previous one.
continue(i) := (c # sign off)]
3.2 S Q U A S H
This command inputs repeatedly from any of ten
Problem: Adapt the previous program to replace every
consoles, provided that the corresponding element of the
pair of consecutive asterisks "**" by an upward arrow
Boolean array continue is true. The bound variable i
identifies the originating console. Its value, together with "~". Assume that the final character input is not an
the character just input, is output to X, and an acknowl- asterisk.
edgment signal is sent back to the originating console. If Solution:
the character indicated "sign off," continue(i) is set false, X :: ,[c:character; west?c --~
to prevent further input from that console. The repetitive [c # asterisk --~ east!c
0c = asterisk ---~ wesOc;
command terminates when all ten elements of continue
[c # asterisk ~ east!asterisk; east!c
are false. (An implementation should ensure that no Dc = asterisk ~ east!upward arrow
console which is ready to provide input will be ignored 11 ]
unreasonably often.)
Notes: (l) Since west does not end with asterisk, the
(5) ,In:integer; X?insert(n) ---~ I N S E R T second "west?c" will not fail. (2) As an exercise, adapt
On:integer; X?has(n) ~ S E A R C H ; X!(i < size) this process to deal sensibly with input which ends with
]
an odd number of asterisks.
(Here, and elsewhere, capitalized words INSERT and
SEARCH stand as abbreviations for program text defined 3.3 D I S A S S E M B L E
separately.) Problem: to read cards from a cardfile and output to
On each iteration this command accepts from X either process X the stream of characters they contain. An extra
(a) a request to "insert(n)," (followed by INSERT) or (b) space should be inserted at the end of each card.
a question "has(n)," to which it outputs an answer back Solution:
to X. The choice between (a) and (b) is made by the next
[cardimage:(l..80)character; cardfile?cardimage
output command in X. The repetitive command termi- i:integer; i ~ 1;
nates when X does. If X sends a nonmatching message, [i _< 80 ~ X!cardimage(i); i .~ i + 1]
deadlock will result. X!space
]
(6) *[X?V 0 ~ val := val + 1
0val > 0; Y?PO --~ val := val - 1 Notes: (1) "(1..80)character" declares an array of 80
1 characters, with subscripts ranging between 1 and 80. (2)
On each iteration, accept either a V 0 signal from X The repetitive command terminates when the cardfile
and increment val, or a PO signal from Y, and decrement process terminates.
val. But the second alternative cannot be selected unless
val is positive (after which val will remain invariantly 3.4 A S S E M B L E
nonnegative). (When val > 0, the choice depends on the Problem: To read a stream o f characters from process X
relative speeds o f X and Y, and is not determined.) The and print them in lines o f 125 characters on a lineprinter.
repetitive command will terminate when both X and Y The last line should be completed with spaces if neces-
are terminated, or when X is terminated and val <_ 0. sary.

670 Communications August 1978


of V o l u m e 21
the A C M Number 8
Solution: ... ; subr?(results). Any commands between these two will
lineiraage:( 1.. 125)character; be executed concurrently with the subroutine.
/:integer; i ~ 1; A multiple-entry subroutine, acting as a representa-
[c:character; X?c tion for data [ 11], will also contain a repetitive command
l i n e i m a g e ( 0 ~ c; which represents each entry by an alternative input to a
[i~_ 124--~ i := i + I
structured target with the entry name as constructor. For
Ui = 125 ~ lineprinter!lineimage; i ~ 1
l 1; example,
[i = ! ~ skip [ X ? e n t r y l ( v a l u e p a r a m s ) ~ ...
0i > 1 ~ *[i _< 125 ~ l i n e i m a g e ( 0 ~ space; i ~ i + ll; I]X?entry2(value p a r a m s ) --~ ...
lineprinter!lineimage
1
1
The calling process X will determine which of the alter-
Note: (I) When X terminates, so will the first repetitive natives is activated on each repetition. When X termi-
command of this process. The last line will then be nates, so does this repetitive command. A similar tech-
printed, if it has any characters. nique in the user program can achieve the effect of
multiple exits.
3.5 Reformat A recursive subroutine can be simulated by an array
Problem: Read a sequence o f cards o f 80 characters each, o f processes, one for each level of recursion. The user
and print the characters on a linepfinter at 125 characters process is level zero. Each activation communicates its
per line. Every card should be followed by an extra parameters and results with its predecessor and calls its
space, and the last line should be completed with spaces successor if necessary:
if necessary.
Solution: [recsub(0)::USERllrecsub(i: l..reclimit)::RECSUB].

[west::DISASSEMBLEIIX::COPYIleast=ASSEMBLE] The user will call the first element of


recsub: r e c s u b ( l ) ! ( a r g u m e n t s ) ; ... ; recsub(l)?(results);.
Notes: (1) The capitalized names stand for program text
defmed in previous sections. (2) The parallel command The imposition of a fixed upper bound on recursion
is designed to terminate after the cardfile has terminated. depth is necessitated by the "static" design of the lan-
(3) This elementary problem is difficult to solve elegantly guage.
without coroutines. This clumsy simulation of recursion would be even
more clumsy for a mutually recursive algorithm. It would
3.6 Conway's Problem [4] not be recommended for conventional programming; it
Problem: Adapt the above program to replace every pair may be more suitable for an array of microprocessors
of consecutive asterisks by an upward arrow. for which the fixed upper bound is also realistic.
Solution: In this section, we assume each subroutine is used
only by a single user process (which may, of course, itself
[ w e s t = D I S A S S E M B L E [ IX=SQUASH[ least=ASSEMBLE] contain parallel commands).

4.1 Function: Division With Remainder


4. Subroutines and Data Representations Problem: Construct a process to represent a function-
type subroutine, which accepts a positive dividend and
A conventional nonrecursive subroutine can be read- divisor, and returns their integer quotient and remainder.
ily implemented as a coroutine, provided that (1) its Efficiency is o f no concern.
parameters are called "by value" and "by result," and Solution:
(2) it is disjoint from its calling program. Like a Fortran
subroutine, a coroutine may retain the values of local [DIV ::,[ x,y:integer; X?( x,y) --~
q u o t , r e m : i n t e g e r ; q u o t m 0; rein ~ x;
variables (own variables, in Algol terms) and it may use (rein _> y ~ rem ~ rem - y; q u o t ~ q u o t + 1];
input commands to achieve the effect o f "multiple entry X!(quot,rem)
points" in a safer way than PL/I. Thus a coroutine can 1
be used like a SIMULA class instance as a concrete rep- [IX=USER
resentation for abstract data. 1
A coroutine acting as a subroutine is a process oper-
ating concurrently with its user process in a parallel 4.2 Recursion: Factorial
command: [subr::SUBROUTINEI[X::uSER]. The SUBROU- Problem: Compute a factorial by the recursive method,
TINE will contain (or consist of) a repetitive command: to a given limit.
*[X?(value params) ~ ... ; X!(result params)], where ... Solution:
computes the results from the values input. The subrou- [fac( i: 1..limit)::
tine will terminate when its user does. The USER will call [n:mteger;fac(i - t)?n
the subroutine by a pair of commands: subr!(arguments); [n = 0 ~ fac(i -- 1)!1

671 Communications A u g u s t 1978


of V o l u m e 21
the A C M Number 8
fin > 0 - ~ fac(i + l ) ! n - 1; 4.5 Recursive Data Representation: Small Set of
r:knteger;fac(i + l ) ? r ; f a c ( i - i)!(n r)
Integers
II
Ilfac(O)::USER Problem: Same as above, but a.n array of processes is to
] be used to achieve a high degree of parallelism. Each
process should contain at most one number. When it
Note: This unrealistic example introduces the technique
contains no number, it should answer "false" to all
of the "iterative array" which will be used to a better
inquiries about membership. On the first insertion, it
effect: in later examples.
changes to a second phase of behavior, in which it deals
with instructions from its predecessor, passing some of
4.3 Data Representation: Small Set of Integers [11]
them on to its successor. The calling process will be
Problem: To represent a set of not more than 100 integers
named S(0). For efficiency, the set should be sorted, i.e.
as a process, S, which accepts two kinds of instruction
the ith process should contain t h e / t h largest number.
from its calling process X: (1) S!insert(n), insert the
integer n in the set, and (2) S!has(n); ... ; S?b, b is set true Solution:
if n is in the set, and false otherwise. The initial value of S(i: I.. 100)::
the set is empty. [n:integer; S ( i - l ) ? h a s ( n ) ~ S(0)!false
fin:integer; S ( i - l ) ? i n s e r t ( n ) --~
Solution: , I r a : i n t e g e r ; S(i - 1)?has(m) ---*
S:: [m _< n ~ S ( 0 ) ! ( m = n)
c o n t e n t : ( 0 . . 9 9 ) i n t e g e r ; size:integer; size .--- 0; fire > n ---* S ( i + l ) ! h a s ( m )
[ n : i n t e g e r ; X ? h a s ( n ) --* S E A R C H ; X ! ( i < size) 1
fin:integer; X ? i n s e r t ( n ) --* S E A R C H ; fire:integer; S(i - I ) ? i n s e r t ( m ) --->
[i < size --* s k i p [ m < n --* S ( i + l ) ! i n s e r t ( n ) ; n ~ m
fii = size; size < 100 --~ fire = n ~ s k i p
c o n t e n t (size) .---- n; size .--'--size + l fire > n --~ S ( i + l ) ! i n s e r t ( m )
] l III
where SEARCHis an abbreviation for: Notes: (1) The user process S(0) inquires whether n is a
member by the commands S(l)!has(n); ... ; [(i: l.. 100)S(0?
/:integer; i .--- 0;
[i < size; c o n t e n t ( 0 # n --, i .--- i + l]
b --> skip]. The appropriate process will respond to the
input command by the output command in line 2 or line
Notes: (1) The alternative command with guard "size < 5. This trick avoids passing the answer back "up the
100" will fail if an attempt is made to insert more than chain." (2) Many insertion operations can proceed in
100 elements. (2) The activity of insertion will in general parallel, yet any subsequent "has" operation will be
take place concurrently with the calling process. How- performed correctly. (3) All repetitive commands and all
ever, any subsequent instruction to S will be delayed processes of the array will terminate after the user process
until the previous insertion is complete. S(0) terminates.

4.4 Scanning a Set 4.6 Multiple Exits: Remove the Least Member
Problem: Extend the solution to 4.3 by providing a fast Exercise: Extend the above solution to respond to a
method for scanning all members of the set without command to yield the least member of the set and to
changing the value of the set. The user program will remove it from the set. The user program will invoke the
contain a repetitive command of the form: facility by a pair of commands:

S!scan( ); m o r e : b o o l e a n ; m o r e .--- true; S(1)!least( ); [ x : i n t e g e r ; S ( l ) ? x --* ... d e a l w i t h x ...


f i S ( l ) ? n o n e l e f t ( ) ---> ...
[ m o r e ; x : i n t e g e r ; S ? n e x t ( x ) --, ... d e a l w i t h x ....
fimore; S ? n o n e l e f i ( ) - - , m o r e .--- false 1
l or, if he wishes to scan and empty the set, he may write:
where S!scan( ) sets the representation into a scanning S ( l ) ! l e a s t ( ) ; m o r e : b o o l e a n ; m o r e .'= true;
mode. The repetitive command serves as a for statement, [more; x : i n t e g e r ; S ( l ) ? x - - , ... d e a l w i t h x ... ; S ( l ) ! l e a s t ( )
inputting the successive members of x from the set and fimore; S ( l ) ? n o n e l e f i ( ) ~ m o r e .--- false
inspecting them until finally the representation sends a 1
signal that there are no members left. The body of the
repetitive command is n o t permitted to communicate Hint: Introduce a Boolean variable, b, initialized to true,
with S in any way. and prefu this to all the guards of the inner loop. After
responding to a !least( ) command from its predecessor,
Solution: Add a third guarded command to the outer each process returns its contained value n, asks its suc-
repetitive command of S: cessor for its least, and stores the response in n. But if the
successor returns "noneleft( )," b is set false and the
... f i X ? s c a n ( ) ~ / : i n t e g e r ; i ~ 0;
[i < size --~ X ! n e x t ( c o n t e n t ( 0 ) ; i .--- i + l]; inner loop terminates. The process therefore returns to
X!noneleft( ) its initial state (solution due to David Gries).
672 Communications A u g u s t 1978
of V o l u m e 21
the ACM Number 8
5. Monitors and Scheduling However, after the producer has produced its next por-
tion, the consumer's request can be granted on the next
This section shows how a monitor can be regarded as iteration. (3) Similar remarks apply to the producer,
a single process which communicates with more than when in -- out + 10. (4) X is designed to terminate when
one user process. However, each user process must have out = in and the producer has terminated.
a different name (e.g. producer, consumer) or a different
subscript (e.g. X(0) and each communication with a user 5.2 Integer Semaphore
must identify its source or destination uniquely. Problem: To implement an integer semaphore, S, shared
Consequently, when a monitor is prepared to com- among an array X(i:I..100) of client processes. Each
municate with any of its user processes (i.e. whichever of process may increment the semaphore by S!V() or
them calls first) it will use a guarded command with a decrement it by S!P(), but the latter command must be
range. For example: .[(i:1.. 100)X(0?(value parameters) delayed if the value of the semaphore is not positive.
--~ ... ; X(0!(results)]. Here, the bound variable i is used Solution:
to send the results back to the calling process. If the S::val:integer; val .--- 0;
*[(i:I..100)X(0?V ( ) ~ val .--- val + 1
monitor is not prepared to accept input from some II(i:l..100)val > 0; X(0?P ( ) --, val ~ val - 1
particular user (e.g. X(j)) on a given occasion, the input ]
command may be preceded by a Boolean guard. For Notes: (1) In this process, no use is made of knowledge
example, two successive inputs from the same process of the subscript i of the calling process. (2) The sema-
are inhibited by j = 0; *[(i: 1.. 100)i # j; X(0?(values ) --, phore terminates only when all hundred processes of the
... ; j .--- i]. Any attempted outpui from X(j) will be process array X have terminated.
delayed until a subsequent iteration, after the output of
some other process X(i) has been accepted and dealt 5.3 Dining Philosophers (Problem due to E.W. Dijkstra)
with. Problem: Five philosophers spend their lives thinking
Similarly, conditions can be used to delay acceptance and eating. The philosophers share a common dining
of inputs which would violate scheduling constraints-- room where there is a circular table surrounded by five
postponing them until some later occasion when some chairs, each belonging to one philosopher. In the center
other process has brought the monitor into a state in of the table there is a large bowl of spaghetti, and the
which the input can validly be accepted. This technique table is laid with five forks (see Figure 1). On feeling
is similar to a conditional critical region [10] and it hungry, a philosopher enters the dining room, sits in his
obviates the need for special synchronizing variables own chair, and picks up the fork on the left of his place.
such as events, queues, or conditions. However, the Unfortunately, the spaghetti is so tangled that he needs
absence of these special facilities certainly makes it more to pick up and use the fork on his right as well. When he
difficult or less efficient to solve problems involving has finished, he puts down both forks, and leaves the
priorities--for example, the scheduling of head move- room. The room should keep a count of the number of
ment on a disk. philosophers in it.
Fig. 1.
5.1 Bounded Buffer
Problem: Construct a buffering process X to smooth
variations in the speed of output of portions by a pro-
ducer process and input by a consumer process. The
consumer contains pairs of commands X!more( );
X?p, and the producer contains commands of the form
X!p. The buffer should contain up to ten portions.
Solution:
(2
X::
buffer:(0..9) portion;
in,out:integer; in .--- 0; out .--- 0;
comment 0 <_ out _< in _< out + 10;
*[in < out + 10; producer?buffer(in mod 10) --* in .--- in + 1
[lout < in; consumer?more( ) --~ consumer!buffer(out rood 10); Solution: The behavior of the ith philosopher may be
out .--- out + 1 described as follows:
]
PHIL = *[... during ith lifetime ... ---,
Notes: (1) When out < in < out + 10, the selection of THINK;
the alternative in the repetitive command will depend on room!enter( );
fork(0!pickup( ); f o r k ( ( / + 1) rood 5)!pickup( );
whether the producer produces before the consumer
EAT;
consumes, or vice versa. (2) When out -- in, the buffer is fork(i)!putdown( ); f o r k ( ( / + 1) mod 5)!putdown( );
empty and the second alternative cannot be selected even room!exit( )
if the consumer is ready with its command X!more(). ]

673 Communications August 1978


of Volume 21
the A C M Number 8
The fate of the ith fork is to be picked up and put down 6.2 An Iterative Array: Matrix Multiplication
by a philosopher sitting on either side of it Problem: A square matrix A of order 3 is given. Three
streams are to be input, each stream representing a
FORK =
*[phil(0?pickup( )--* phil(0?putdown( ) column of an array IN. Three streams are to be output,
0phil((i - 1)rood 5)?pickup( ) --* p h i l ( ( / - l) raod 5)?putdown( ) each representing a column of" the product matrix IN
1 A. After an initial delay, the results are to be produced
The story of the room may be simply told: at the same rate as the input is consumed. Consequently,
a high degree of parallelism is required. The solution
R O O M = occupancy:integer; occupancy .--- 0; should take the form shown in Figure 2. Each of the nine
,[(i:0..4)phil(0?enter ( ) --* occupancy .--- occupancy + l
nonborder nodes inputs a vector component from the
11(i:0..4)phil(0?exit ( ) --~ occupancy .--- occupancy - l
] west and a partial sum from the north. Each node outputs
the vector component to its east, and an updated partial
All these components operate in parallel: sum to the south. The input data is produced by the west
[room::ROOM I [fork( i:0..4)::FORK IIphil( i:0..4)::PHIL]. border nodes, and the desired results are consumed by
south border nodes. The north border is a constant
Notes: (1) The solution given above does not prevent all
source of zeros and the east border is just a sink. No
five philosophers from entering the room, each picking
provision need be made for termination nor for changing
up his left fork, and starving to death because he cannot
the values of the array A.
pick up his right fork. (2) Exercise: Adapt the above
program to avert this sad possibility. Hint: Prevent more
Fig. 2.
than four philosophers from entering the room. (Solution
due to E. W. Dijkstra).

0 0 0

6. M i s c e l l a n e o u s
~111 ~12x A13x
This section contains further examples of the use of
communicating sequential processes for the solution of
some less familiar problems; a parallel version o f the A11x*Azly A12x*A22y A13x*A23y
sieve o f Eratosthenes, and the design of an iterative
array. The proposed solutions are even more speculative
than those of the previous sections, and in the second A11x*A21y,A~ AlzX.A22Y.A3~AoX.A23y.A~z
example, even the question of termination is ignored.

6.1 Prime Numbers: The Sieve of Eratosthenes [14] S

Problem: To print in ascending order all primes less than


10000. Use an array of processes, SIEVE, in which each Solution: There are twenty-one nodes, in five groups,
process inputs a prime from its predecessor and prints it. comprising the central square and the four borders:
The process then inputs an ascending stream of numbers
[M(i: 1..3,0)::WEST
from its predecessor and passes them on to its successor, IIM(0d:I..3)::NORTH
suppressing any that are multiples of the original prime. IIM(i:I..3,4)::EAST
Solution: IIM(4j:I..3)::SOUTH
IIM(i:I..3d:I..3)::CENTER
[SIEVE(i: 1 100)::
1
. .

p,rap:integer;
SIEVE(i- l)?p; The WEST and SOUTH borders are processes of the user
print!p; program; the remaining processes are:
rap .---p; c o m m e n t rap is a multiple o f p;
,[re:integer; S I E V E ( / - l)?m ---* N O R T H = .[true --* M(Id)!0 ]
*[m > mp ~ mp .--'- m p + p]; E A S T = .Ix:real; M(i,3)?x---> skip]
[m = rap --* skip C E N T E R = .[x:real; M(id - l)?x --*
nra < rap --* SIEVE(i + l)!ra M ( i , j + l)!x; sum:real;
] ] M ( i - l,j)?sum; M(i + l d ) ! ( A ( i , j ) * x + sum)
HSIEVE(0)::print!2; n:integer; n .--- 3; ]
* I n < 10000--* SIEVE(I)!n; n .--- n + 2]
IISIEVE(101)::*[n:integer;SIEVE(100)?n --~ print!n]
Hprint::,[(i:0.. 101) n:integer; SIEVE(0?n --> ...]
1 7. D i s c u s s i o n
Note: (1) This beautiful solution was contributed by
David Giles. (2) It is algorithmically similar to the A design for a programming language must neces-
program developed in [7, pp. 27-32]. sarily involve a number o f decisions which seem to be
674 Communications August 1978
of Volume 2 I
the A C M Number 8
fairly arbitrary. The discussion of this section is intended printed text which should describe the execution of the
to explain some of the underlying motivation and to program, independent of which parts were drawn from
mention some unresolved questions. a library.
Since I did not intend to design a complete language,
7.1 Notations I have ignored the problem of libraries in order to
I have chosen single-character notations (e.g. !,?) to concentrate on the essential semantic concepts of the
express the primitive concepts, rather than the more program which is actually executed.
traditional boldface or underlined English words. As a
result, the examples have an APL-like brevity, which 7.3 Port Names
some readers fred distasteful. My excuse is that (in An alternative to explicit naming of source and des-
contrast to APL) there are only a very few primitive tination would be to name a port through which com-
concepts and that it is standard practice of mathematics munication is to take place. The port names would be
(and also good coding practice) to denote common prim- local to the processes, and the manner in which pairs of
itive concepts by brief notations (e.g. +,x). When read ports are to be connected by channels could be declared
aloud, these are replaced by words (e.g. plus, times). in the head of a parallel command.
Some readers have suggested the use of assignment This is an attractive alternative which could be de-
notation for input and output: signed to introduce a useful degree of syntactically check-
able redundancy. But it is semantically equivalent to the
<target variable> := <source> present proposal, provided that each port is connected to
<destination> .---<expression>
exactly one other port in another process. In this case
I fend this suggestion misleading: it is better to regard each channel can be identified with a tag, together with
input and output as distinct primitives, justifying distinct the name of the process at the other end. Since I wish to
notations. concentrate on semantics, I preferred in this paper to use
I have used the same pair of brackets ([...]) to bracket the simplest and most direct notation, and to avoid
all program structures, instead of the more familiar raising questions about the possibility of connecting more
variety of brackets (if..fi, begin..end, case...esac, etc.). In than two ports by a single channel.
this I follow normal mathematical practice, but I must
also confess to a distaste for the pronunciation of words 7.4 Automatic Buffering
like fi, od, or esac. As an alternative to synchronization of input and
I am dissatisfied with the fact that my notation gives output, it is often proposed that an outputting process
the same syntax for a structured expression and a sub- should be allowed to proceed even when the inputting
scripted variable. Perhaps tags should be distinguished process is not yet ready to accept the output. An imple-
from other identifiers by a special symbol (say #). mentation would be expected automatically to interpose
I was tempted to introduce an abbreviation for com- a chain of buffers to hold output messages that have not
bined declaration and input, e.g. X?(n:integer) for yet been input.
n:integer; X?n. I have deliberately rejected this alternative, for two
reasons: (1) It is less realistic to implement in multiple
7.2 Expficit Naming disjoint processors, and (2) when buffering is required
My design insists that every input or output com- on a particular channel, it can readily be specified using
mand must name its source or destination explicitly. This the given primitives. Of course, it could be argued
makes it inconvenient to write a library of processes equally well that synchronization can be specified when
which can be included in subsequent programs, inde- required by using a pair of buffered input and output
pendent of the process names used in that program. A commands.
partial solution to this problem is to allow one process
(the main process) of a parallel command to have an 7.5 Unbounded Process Activation
empty label, and to allow the other processes in the The notation for an array of processes permits the
command to use the empty process name as source or same program text (like an Algol recursive procedure) to
destination of input or output. have many simultaneous "activations"; however, the
For construction of large programs, some more gen- exact number must be specified in advance. In a conven-
eral technique will also be necessary. This should at least tional single-processor implementation, this can lead to
permit substitution of program text for names defined inconvenience and wastefulness, similar to the fixed-
elsewhere--a technique which has been used informally length array of Fortran. It would therefore be attractive
throughout this paper. The Cobol coPY verb also permits to allow a process array with no a priori bound on the
a substitution for formal parameters within the copied number of elements; and to specify that the exact number
text. But whatever facility is introduced, I would rec- of elements required for a particular execution of the
ommend the following principle: Every program, after program should be determined dynamically, like the
assembly with its library routines, should be printable as maximum depth of recursion of an Algol procedure or
a text expressed wholly in the language, and it is this the number of iterations of a repetitive command.

675 Communications August 1978


of Volume 21
the ACM Number 8
However, it is a good principle that every actual run striking. There, coroutines are strictly deterministic: No
of a program with unbounded arrays should be identical choice is given between alternative sources of input. The
to the run of some program with all its arrays bounded output commands are automatically buffered to any
in advance. Thus the unbounded program should be required degree. The output of one process can be au-
defined as the "limit" (in some sense) of a series of tomatically fanned out to any :number of processes (in-
bounded programs with increasing bounds. I have cho- cluding itself!) which can consume it at differing rates.
sen to concentrate on the semantics of the bounded Finally, the processes there are designed to run forever,
case--which is necessary anyway and which is more whereas my proposed parallel command is normally
realistic for implementation on multiple microprocessors. intended to terminate. The design in [12] is based on an
elegant theory which permits proof of the properties of
7.6 Fairness programs. These differences are not accidental--they
Consider the parallel command: seem to be natural consequences of the difference be-
[X::Y!stop( )ll Y::continue:boolean; continue .--- true; tween the more abstract applicative (or functional) ap-
.[continue; X?stop( ) ~ continue .---false proach to programming and the more machine-oriented
Ilcontinue ---, n .--- n + 1 imperative (or procedural) approach, which is taken by
1 communicating sequential processes.
1.
If the implementation always prefers the second alter- 7.8 Output Guards
native in the repetitive command of Y, it is said to be Since input commands may appear in guards, it
unfair, because although the output command in X could seems more symmetric to permit output commands as
have been executed on an infinite number of occasions, well. This would allow an obvious and useful simplifi-
it is in fact always passed over. cation in some of the example programs, for example, in
The question arises: Should a programming language the bounded buffer (5.1). Perhaps a more convincing
definition specify that an implementation must be fair?. reason would be to ensure that the externally visible
Here, I am fairly sure that the answer is NO. Otherwise, effect and behavior of every parallel command can be
the implementation would be obliged to successfully modeled by some sequential command. In order to
complete the example program shown above, in spite of model the parallel command
the fact that its nondeterminism is unbounded. I would
Z :: [X!211Y!3l
therefore suggest that it is the programmer's responsibil-
ity to prove that his program terminates correctly--with- we need to be able to write the sequential alternative
out relying on the assumption of fairness in the imple- command:
mentation. Thus the program shown above is incorrect,
Z :: [X!2 ~ Y!31IY!3 ~ X!2]
since its termination cannot be proved.
Nevertheless, I suggest that an efficient implementa- Note that this cannot be done by the command
tion should try to be reasonably fair and should ensure Z :: [true ~ X!2; Y!31]true ~ Y!3; X!2]
that an output command is not delayed unreasonably
often after it first becomes executable. But a proof of which can fail if the process Z happens to choose the
correctness must not rely on this property of an efficient first alternative, but the processes Y and X are synchro-
implementation. Consider the following analogy with a nized with each other in such a way that Y must input
sequential program: An efficient implementation of an from Z before X does, e.g.
alternative command will tend to favor the alternative Y :: Z?y; X ! g o ( )
which can be most efficiently executed, but the program- IIX:: Y?go(); Z?x
mer must ensure that the logical correctness of his pro-
gram does not depend on this property of his implemen- 7.9 Restriction: Repetitive Command With Input Guard
tation. In proposing an unfamiliar programming language
This method of avoiding the problem of fairness does feature, it seems wiser at first to specify a highly restric-
not apply to programs such as operating systems which tive version rather than to propose extensions--
are intended to run forever because in this case termi- especially when the language feature claims to be prim-
nation proofs are not relevant. But I wonder whether it itive. For example, it is clear that the multidimensional
is ever advisable to write or to execute such programs. process array is not primitive, since it can readily be
Even an operating system should be designed to bring constructed in a language which permits only single-
itself to an orderly conclusion reasonably soon after it dimensional arrays. But I have a rather more serious
inputs a message instructing it to do so. Otherwise, the misgiving about the repetitive command with input
only way to stop it is to "crash" it. guards.
The automatic termination of a repetitive command
7.7 Functional Coroutines on termination of the sources of all its input guards is an
It is interesting to compare the processes described extremely powerful and convenient feature but it also
here with those proposed in [12]; the differences are most involves some subtlety of specification to ensure that it
676 Communications August 1978
of Volume 21
the A C M Number 8
is implementable; and it is certainly not primitive, since 5. Dahl, O-J., et al. SIMULA 67, common base language.
the required effect can be achieved (with considerable Norwegian Computing Centre, Forskningveien, Oslo, 1967.
6. Dijkstra, E.W. Co-operating sequential processes. In
inconvenience) by explicit exchange of "end()" signals. Programming Languages, F. Genuys, Ed., Academic Press, New
For example, the subroutine DIV(4.l) could be rewritten: York, 1968, pp. 43-112.
7. Dijkstra, E.W. Notes on structured programming. In Structured
[DIV :: continue:boolean; continue .----true; Programming, Academic Press, New York 1972, pp. 1-82.
*[continue; X?endO--, continue .--- false 8. Dijkstra, E.W. Guarded commands, nondeterminacy, and formal
[Icontinue; x,y:integer; X?(x,y) --->... ; X!(quot,rem) derivation of programs. Comm. A CM 18, 8 (Aug. 1975), 453-457.
[IX :: USER PROG; DIV!endO 9. Dijkstra, E.W. Verbal communication, Marktoberdorf, Aug.
] 1975.
10. Hoare, C.A.R. Towards a theory of parallel programming. In
Other examples would be even more inconvenient. Operating Systems Techniques, Academic Press, New York, 1972, pp.
61-71.
But the dangers of convenient facilities are notorious. 11. Hoare, C.A.R. Proof of correctness of data representations..4cta
For example, the repetitive commands with input guards Informatica 1, 4 (1972), 271-281.
may tempt the programmer to write them without mak- 12. Kahn, G. The semantics of a simple language for parallel
programming. In Proc. IFIP Congress 74, North Holland, 1974.
ing adequate plans for their termination; and if it turns 13. Liskov, B.H. A note on CLU. Computation Structures Group
out that the automatic termination is unsatisfactory, Memo. 112, M.I.T., Cambridge, Mass, 1974.
reprogramming for explicit termination will involve se- 14. Mcllroy, M.D. Coroutines. Bell Laboratories, Murray Hill, N.J.,
1968.
vere changes, affecting even the interfaces between the 15. Naur, P., Ed. Report on the algorithmic language ALGOL 60.
processes. Comm. ACM 3, 5 (May 1960), 299-314.
16. Reynolds, J.C. COGENT. ANL-7022, Argonne Nat. Lab.,
Argonne, II1., 1965.
17. Thompson, K. The UNIX command language. In Structured
8. Conclusion Programming, Infotech, Nicholson House, Maidenhead. England,
1976, pp. 375-384.
18. van Wijngaarden, A. Ed. Report on the algorithmic language
This paper has suggested that input, output, and ALGOL 68. Numer. Math. 14 (1969), 79-218.
concurrency should be regarded as primitives of pro- 19. Wulf, W.A., London, R.L., and Shaw, M. Abstraction and
gramming, which underlie many familiar and less famil- verification in ALPHARD. Dept. of Comptr. Sci., Carnegie-MeUon
U., Pittsburgh, Pa., June 1976.
iar programming concepts. However, it would be unjus- 20. Wirth, N. The programming language PASCAL. Acta
tified to conclude that these primitives can wholly replace Informatica 1, 1 (1971), 35-63.
the other concepts in a programming language. Where
a more elaborate construction (such as a procedure or a
monitor) is frequently useful, has properties which are
more simply provable, and can also be implemented
more efficiently than the general case, there is a strong
reason for including in a programming language a special
notation for that construction. The fact that the construc-
tion can be defined in terms of simpler underlying prim-
itives is a useful guarantee that its inclusion is logically
consistent with the remainder of the language.

Acknowledgments. The research reported in this pa-


per has been encouraged and supported by a Senior
Fellowship of the Science Research Council of Great
Britain. The technical inspiration was due to Edsger W.
Dijkstra [9], and the paper has been improved in pres-
entation and content by valuable and painstaking advice
from D. Gries, D. Q. M. Fay, Edsger W. Dijkstra, N.
Wirth, Robert Milne, M. K. Harper, and its referees.
The role of IFIP W.G.2.3 as a forum for presentation
and discussion is acknowledged with pleasure and grat-
itude.
Received March 1977; revised August 1977
References
1. Atkinson, R., and Hewitt, C. Synchronisation in actor systems.
Working Paper 83, M.I.T., Cambridge, Mass., Nov. 1976.
2. Brinch Hansen, P. The programming language Concurrent
Pascal. IEEE Trans. Software Eng. 1, 2 (June 1975), 199-207.
3. Campbell, R.H., and Habermann, A.N. The specification of
process synchronisation by path expressions. Lecture Notes in
Computer Science 16, Springer, 1974, pp. 89-102.
4. Conway, M.E. Design of a separable transition-diagram
compiler. Comm. ACM 6, 7 (July 1963), 396-408.

677 Communications August 1978


of Volume 21
the ACM Number 8

Вам также может понравиться