Here we describe how to implement objects handling IO.
The example is a concurrent object, keyboard, that reads characters from a keyboard, but without blocking. The keyboard object may be used as in the following example
KBprocess: = LIB.BasicSystem.BasicSystem
P1: = BasicProcess("P1")
ch := keyboard.get(P1)
"P1 read: ".print;
P2: = BasicProcess("P2")
i := i + 1
%if (i /% 1000) = 0 %then%
The object KBprocess is subclassed from BasicSystem - part of the qBeta library.
It defines two active object, P1 and P2.
P1 constantly reads a character on the keyboard using ch := keyboard.get(P1). If a character has been typed, keyboard.get returns with that character. If no character has been typed, P1 is suspended. The next time P1 is resumed, keyboard.get again test if a character has been typed, etc.
The object P2 constantly writes a message on the console and then suspends.
The KBprocess constantly - using cycle - resumes the object keyboard, P1, and P2. In this example the three object are cooperatively scheduled - they might as well bee scheduled pre-emptively using e.g. P1.attach(100), etc.
The important property of this example is that P1 does not block if there is no input on the keyboard.
The output from a an execution may look as follows:
P1 read: a
P1 read: b
P1 read: c
P1 read: d
P1 read: e
P2 constantly writes the text P2 here - when a character has been typed, P1 writes a text like P1 read: a, where a is the character that has been typed.
The keyboard object
The keyboard object may be defined as follows:
keyboard: = BasicProcess("Keyboard")
B: = Indexed(100,integer)
%if _kbhit %then%
top := top + 1
B.%put _iget %at% top
get(caller: ?BasicProcess) -> ch: ?char:
%if next < top %then%
next := next + 1
ch := B.%get next
The keyboard object is subclassed from BasicProcess as is P1 and P2.
It defines an Indexed object B with index variables next and top. B is used to buffer input from the keyboard until read by get. Note that the example does not handle more than 100 chars - the program will simply fail with an index error if more than 100 chars have been typed - this is, however easy to fix.
The scan pattern, constantly checks if a character has been typed - using the primitive operation _kbhit. If a character has been typed it is read - using _iget and inserted into B. Then the keyboard suspends.
The get operation checks if there is a character in the buffer B, and if so, returns the next one. If B is empty, then it suspends the caller - using caller.suspend.
Note that in this version of qBeta, the called of get is passed as a parameter in order to be suspended. This is needed since it is to possible to suspend the active coroutine without having a reference to it. This is possible in Beta and SIMULA and may bed added to qBeta. The first versions of SIMULA and Beta did not have the R.suspend operation - but this was later added to SIMULA and Beta.
IO in general
The example example may be generalized - at least we think so - to handle input from other sources like ports, but also hardware devices om embedded platfroms (boards). But only for devices/ports where it is necessary to scan memory locations in order to detect if there is new data. An example of non-blocking sockets is described here.
For devices controlled by interrupts, something else has to be done. The plan is to support this.