Oberon || Library || Module Index || Search Engine || Definition || Module
TYPE Filter = PROCEDURE (in, out: Streams.Stream); TYPE CrPipe = POINTER TO CrPipeRec; TYPE CrPipeRec = RECORD (Streams.StreamRec) END; PROCEDURE Open(VAR out, in: Streams.Stream; bufmode: Streams.BufMode); PROCEDURE Spawn(filter: Filter; in, out: Streams.Stream);
Open creates a pipeline with two streams (similar to pipe(2)). Both streams remain unconnected until they are connected to filters by Spawn. Input/output operations to unconnected pipeline streams are illegal. Transfer of control mainly depends on the buffering mode of the inner streams:
Spawn passes in and out to filter and starts the procedure as coroutine. At least one of the two streams should be a pipeline stream. Pipeline streams which are passed to Spawn are connected to filter. Pipeline constructions must be linear: cycles would cause deadlocks.
The pipeline starts working either by reading from the end or by writing to the start of the pipeline. A filter has three ways of returning/closing:
PROCEDURE UpperToLower(in, out: Streams.Stream); CONST diff = ORD("a") - ORD("A"); VAR ch: CHAR; BEGIN WHILE Streams.ReadByte(in, ch) DO IF (ch >= "A") & (ch <= "Z") THEN ch := CHR(ORD(ch) - diff); END; IF ~Streams.WriteByte(out, ch) THEN RETURN END; END; END UpperToLower; PROCEDURE Setup; VAR out, in: Streams.Stream; oldstdout: Streams.Stream; BEGIN CrPipes.Open(out, in, Streams.linebuf); oldstdout := Streams.stdout; Streams.stdout := out; CrPipes.Spawn(UpperToLower, in, oldstdout); END Setup;
Oberon || Library || Module Index || Search Engine || Definition || Module