Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
This PR brings support for Windows using the I/O Completion Port.
Closes #10
Notes for reviewers
Unfortunately, this is a pretty beefy PR. I tried to clean the git history so that it's kind of reviewable commit by commit though.
My approach was similar to what @mitchellh suggested me: first the backend core, then the watchers building on top of it.
I also added support for Windows tests in GH Actions as he told me he didn't have access to a Windows machine.
Please note that this work is far from perfect, it was my first time playing with IOCP so expect some weirdness/mistakes.
Known pain-points/limitations
Timers
Timings rely on
GetQueuedCompletionStatusEx
timeout parameter. I read multiple times that timings on Windows were, well, slightly inaccurate (plot twist: that's a euphemism). I'm not confident enough to deep dive into this rabbit hole, so if somebody has more knowledge on that, feel free to improve my implementation.Async
I have the feeling that there is a better way to implement the
Async
watchers compared to what I did. I couldn't come up with a better way than inspiring myself from theWASI
backend.The part I struggled the most with was the fact that
Async
can be notified before being linked to aLoop
. This requires to store the fact that it's notified inside theAsync
struct, but then it opens up a lot of other questions and failed to find a satisfying solution taking care of all of them.I'll try to come back to it with a fresh mind but I'm open to suggestions in the meantime 😁
Completion port
HANDLE
registeringIn order to be able to wait for asynchronous I/O,
HANDLE
needs to be linked to a Completion Port. However, you can only register it once otherwise, the linking call fails. I first tried to let the user handle that by giving the possibility to link a handle to aLoop
, but that ended up being unreliable and cumbersome when implementing Watchers.My final decision was to ignore the failure and suppose that it always works. Win32 documentation is not what we could call exhaustive, so I don't if it's possible for an association to fail on the first call to
CreateIoCompletionPort
with a newly createdHANDLE
. Worst scenario is that it fails silently and asynchronous wait on thisHANDLE
never completes. If anyone has an idea as to how we could properly solve that, don't hesitate 😁UDP Benchmark tweaks
This is described in #38
Process support
I didn't implement support for
Process
watchers yet. I feel like it's not required to merge this (already big) PR. I'll see if adding support is possible in the future.