I am trying to write a simple server for a real time multiplayer and with the UdpSocket from mio.
So from all examples that I have found for mio version 0.6 the receiving part is really straight forward. But I can’t figure out a smart way to send messages. (The send function should be called from the main thread without blocking it).
In my current implementation the Poll is in a separated thread and for sending messages I use a Mutex (to_send). The send function looks like this:
Yes, i had the same idea but I am not sure if the channel will always be faster than the poll.reregister() call. If the channel has a delay, the message would not processed until the next message triggers the reregister again. Or can I somehow guarantee that this won't happen?
That’s a good question. My expectation would be that when Sender::send() returns, the message (buffer) is fully visible to any other thread that would attempt to poll/recv on the queue. To that end, waking up/notifying the mio event loop ought to work. The mio thread, upon wakeup, would keep draining the channel until there’re no more messages. If reregister is sticky in that if a reregister that happens while a mio loop isn’t waiting but when it goes to poll is immediately notified, then I think it should work. But I’d need to go read the mio docs closely to see if I can confirm that.
Yes, I have. And I have also read that it is easier to use, but I liked the simple event loop design of mio.
I think it was easier to implement than tokio with its futures, because I don’t want futures in the public API of my networking crate.
Ok, thanks for following up. I am slightly nervous about this assumption (cause I don't know mio thoroughly enough), so cc @carllerche - hopefully he'll confirm/deny that this is reasonable (and/or offer up a better suggestion). You can also try pinging the mio github and see if other, more intimately familiar with mio, people can help out.
Just discovered https://crates.io/crates/mio-extras.
Now I am using the channel from this crate to send a message to the mio thread. In the mio thread the message triggers an event and from there I register the socket-write interest. This seems safe to me. As a negative side effect there is one more iteration of the poll, until a message is actually sent.
Depending on how many messages come in at one time, this saves a lot additional reregisters.
For example with a delay of 5 milliseconds, the send (almost) never returns Wouldblock.
With no delay just throwing in ~250 messages, the send (almost) always returns Wouldblock.
(Tested on Windows)
What’s the 5ms delay? A delay you’re artificially adding?
I would send all the messages I have until WouldBlock. There’s no inherent issue with exhausting the kernel’s send buf and reregistering/deferring the remaining messages until it’s writable again. This keeps latency down and utilizes the stack better.
The 5ms are to simulate a normal game, so there are outside the networking crate. Inside the networking crate I have no delay and just sending until i get WouldBlock.
Messages that are sent are dropped immediately after this, all others go into a queue.