User guide
86 CHAPTER 3. THE LIBRARY
MAIN
BUF1 TEE1
X2 X3 X5
MER1 MER2
BUF2 TEE2 BUF3
w w w w w
w
w
w
ww
w
w c c c c
w
c
cc
c c
cc
c c
Figure 3.10: Coroutine data flow
This problem is attributed to R.W.Hamming. Th e solut i on gi ven here shows how data
can flow round a network of coroutines. It i s illustrated in figure 3.10 in which each
box represents a coroutine and the edges represent callco/cowait connections. The
end of a connec t i on corresponding to callco is marked by c, and an end corresponding
to cowait is marked by w. The arrows on the connections show the direction in which
data moves. Notice that, in tee1, callco is sometimes used for i nput and sometimes
for output.
The coroutine BUF1 controls a queue of integers. Non-zero values can be in-
serted into the queue using callco(BUF1,val), and values c an be extracted using
callco(BUF1,0). The coroutines BUF2 and BUF3 are similar. The corouti ne TEE1 is
connected to BUF1 and BUF2 and is d es i gne d so that callco(TEE1) ex e cu te d in cor ou-
tine X2 will yield a value that TEE1 extracted from BUF1, after sending a copy to BUF2.
TEE2 similarly takes val ue s from BUF2 passing them to BUF3 and X3. Values passing
through X2, X3 and X5 are multiplied by 2, 3 and 5, respectively. MER1 merges two
monotonically inc r e asi ng streams of numbers produced by X2 and X3. The resulting
monotonic stream is then merged by MER2 with the str eam produced by X5. The stream
produced by MER2 is the required Hamming sequence, each value of which is printed
by MAIN and t he n inserted into BUF1.
The BCPL code for this solution is as follows:
GET "libhdr"
LET buf(args) BE // Body of BUF1, BUF2 and BUF3
{ LET p, q, val = 0, 0, 0
LET v = VEC 200
{ val := cowait(val)
TEST val=0 THEN { IF p=q DO writef("Buffer empty*n")
val := v!(q REM 201)
q := q+1
}
ELSE { IF p=q+201 DO writef("Buffer full*n")
v!(p REM 201) := val
p := p+1
}
} REPEAT
}