Limbo channels are unbuffered; a sender blocks until there is a receiver. This example shows a way to make a buffered channel of strings from an unbuffered channel. It is written as a module whose bufchan
function takes a chan of string
and a size as argument, and returns a new channel; it creates an asynchronous task that accepts input from the argument channel and saves up to size
strings, meanwhile trying to send them to its user.
implement Bufchan; Bufchan : module { bufchan: fn(c: chan of string, size: int): chan of string; }; xfer(oldchan, newchan: chan of string, size: int) { temp := array[size] of string; fp := 0; # first string in buffer n := 0; # number of strings in buffer dummy := chan of string; sendch, recvch: chan of string; s: string; for (;;) { sendch = recvch = dummy; if (n > 0) sendch = newchan; if (n < size) recvch = oldchan; alt { s = <-recvch => temp[(fp+n)%size] = s; n++; sendch <- = temp[fp] => temp[fp++] = nil; n--; if (fp>=size) fp -= size; } } } bufchan(oldchan:chan of string, size:int): chan of string { newchan := chan of string; spawn xfer(oldchan, newchan, size); return newchan; }The module is somewhat specialized, but it illustrates useful programming techniques. The most interesting computation occurs in
xfer
, which does the work. The problem xfer
faces is that it does not want to receive input when its buffer is full, nor to try to send when it has nothing to transmit. The solution here is to use a dummy channel on which nothing is ever sent or received; in the alt
statement, that channel substitutes for the real input channel when the buffer is full, and for the output channel when the buffer is empty.
The module could be used in the following way:
Bufchan : module { PATH : con "/appl/lib/bufchan.dis"; bufchan : fn (c : chan of string; size : int) : chan of string; }; . . . bufc := load Bufchan Bufchan->PATH; sourcech := chan of string; # ... here, hand off sourcech to a process that # ... reads strings from it and copies them to ch ch : chan of string = bufc->bufchan(sourcech, 10); . . . s := <- ch; . . .