Checking if sockets are ready for reading, writing, or both
Summary
Inko should provide an API that allows you to check if one or more sockets are ready for reading, writing, or both reading and writing. This is necessary to implement HTTP keep-alive supports, as you have to periodically check (with a timeout of sorts) if a socket can be used again.
Motivation
Socket servers that want to reuse sockets need to be able to check when this is possible. Currently there's no way of doing so, as all socket operations use a blocking-like API (built on top of non-blocking APIs).
Implementation
To be decided. An interesting solution would be to expose the VM's network poller as a first class object. This would allow you to do something like this:
import std::net::poll::Poller
import std::net::socket::TcpListener
let listener = try! TcpListener.new(ip: '0.0.0.0', port: 40_000)
let poller = Poller.new
let client = try! listener.accept
poller.register(client, read: True, write: True)
let ready = poller.poll
Here ready
would then be an Array of the objects that are ready, [client]
in this case.
The downside here is that if poll
were to block, it would also block the current thread.
This could be worked around by using std::process.blocking
.
The benefit of this approach is that we already have polling functionality baked in, meaning
we don't need to build wrappers around select(2)
or poll(2)
. It would also support polling
for many sockets at once in an efficient way, something select(2)
and poll(2)
can't do.
Drawbacks
We probably can not reuse epoll/wepoll/kqueue for this, as our current implementation is not built with timeouts in mind. Extending this would require additional data structures to keep track of the timeouts, which would require synchronisation.
Related work
- Ruby provides a binding to
select(2)
usingIO.select()