Is there a way to use Io.net.Reader in a non-blocking way?
I wanted to try out the new Io interface by implementing a wayland client myself but ran into the following obstacle:
I have the following function:
pub fn receive(io: Io) void {
var buff: [256]u8 = undefined;
var r = stream.reader(io, &buff);
var reader = &r.interface;
while (true) {
const header = reader.takeStruct(wl.MessageHeader, native_endianess) catch |err| switch (err) {
Io.Reader.Error.EndOfStream => break,
else => @panic(@errorName(err)),
};
processMessage(io, header, reader);
// if (reader.seek == reader.end) break;
}
}
The stream is created using
std.Io.UnixAddress.connect()
This code blocks at reader.takeStruct if there is nothing else to receive. Is there a non blocking way of doing this using the reader?
If I uncomment the line:
// if (reader.seek == reader.end) break;
It will work but but than not all messages are processed in one call, that would be fine but in order to process all messages I would need to call it in a loop as new messages can come in during process message so again I get stuck at takeStruct.
This is some new territory for me so if itâs a logical error please let me know!
You arenât expressing asynchrony in this code because you are not using the std.Io.async call. Andrew wrote an excellent article explaining the exact meaning of that and how to use std.Io.Threaded at a basic level: here
Not sure how async is going to help me here? if takeStruct keeps blocking until new data arrives the await call will never return as the last takeStruct call will always block until new data arrives. All I am looking for is for a way to use the reader so that Iâm able to read if data is available if not return.
It might be that Reader is not meant for this use case though and I would need to call stream.socket.receive() instead.
The point is that you cannot assume any asynchronous properties of the Reader. The design of std.Io is such that asynchrony is expressed explicitly; therefore, there is no ânon-blockingâ read.
It sounds like you are running into some issue with your assumptions about your input stream, but it is hard to know without knowing more about the usage. If your issue is that you want to continue processing while the reader blocks, use std.Io.async. If your issue is that your reader is essentially hanging, check your assumptions about your input.
Io.Threaded doesnât do non-blocking reads, even if it did, you still wouldnât get the behaviour you are asking for, as @minkatter said, your understanding/expectations of Io is incorrect.
The Reader/Writer interfaces have no concept of nonblocking I/O, even an Io that implements non-blocking I/O it will still block the readers âthreadâ (for lack of a better term) as the reader has no way to return in a nonblocking context.
So to take advantage of nonblocking with a reader, you need to put it on a separate âthreadâ so that when it blocks, it doesnât block your âthreadâ. This is what io.async/concurrent are for.
The correct term for whatever âthreadâ is depends on the Io implementation, for the case of Threaded it is an actual OS thread. For the even less completed Evented it will be âfibreâ/âgreen threadâ
This is how it works in other languages, they just do it implicitly and forcefully. Zig gives you the choice.