I'm looking for some way to get a signal on an I/O completion port when a socket becomes readable/writeable (i.e. the next send/recv will complete immediately). Basically I want an overlapped version of WSASelect
.
(Yes, I know that for many applications, this is unnecessary, and you can just keep issuing overlapped send
calls. But in other applications you want to delay generating the message to send until the last moment possible, as discussed e.g. here. In these cases it's useful to do (a) wait for socket to be writeable, (b) generate the next message, (c) send the next message.)
So far the best solution I've been able to come up with is to spawn a thread just to call select
and then PostQueuedCompletionStatus
, which is awful and not particularly scalable... is there any better way?
It turns out that this is possible!
Basically the trick is:
WSAIoctl
SIO_BASE_HANDLE
to peek through any "layered service providers"DeviceIoControl
to submit anAFD_POLL
request for the base handle, to the AFD driver (this is whatselect
does internally)There are many, many complications that are probably worth understanding, but at the end of the day the above should just work in practice. This is supposed to be a private API, but libuv uses it, and MS's compatibility policies mean that they will never break libuv, so you're fine. For details, read the thread starting from this message: https://github.com/python-trio/trio/issues/52#issuecomment-424591743