4 ms·
> A bigger problem in my opinion is that Rust has chosen to follow the poll-based model This is an inaccurate simplification that, admittedly, their own litera
by zamalek 6y ago
> A bigger problem in my opinion is that Rust has chosen to follow the poll-based model
This is an inaccurate simplification that, admittedly, their own literature has perpetuated. Rust uses informed polling: the resource can wake the scheduler at any time and tell it to poll. When this occurs it is virtually identical to completion-based async (sans some small implementation details).
What informed polling brings to the picture is opportunistic sync: a scheduler may choose to poll before suspending a task. This helps when e.g. there is data already in IO buffers (there often is).
There's also some fancy stuff you can do with informed polling, that you can't with completion (such as stateless informed polling).
Everything else I agree with, especially Pin, but informed polling is really elegant.
- pas 6y agoCould you explain what is informed and stateless informed polling? I haven't really found anything on the web. Thanks!
- Diggsey 6y agoI believe they mean that when you poll a future, you pass in a context. The future derives a "waker" object from this context which it can store, and use to later trigger itself to be re-polled. By using a context with a custom "waker" implementation, you can learn which future specifically needs to be re-polled. Normally only the executor would provide the waker implementation, so you only learn which top-level future (task) needs to be re-polled, but not what specific future within that task is ready to proceed. However, some future combinators also use a custom waker so they can be more precise about which specific future within the task should be re-polled.
- zamalek 6y agoSo stateful async would be writing IO. You've passed in a buffer, the length to copy from the buffer. In the continuation, you'd need to know which original call you were working with so that you can correlate it with those parameters you passed through. var state = socket.read(buffer); while (!state.poll()) {} state.bytesRead... Stateless async is accepting a connection. In 95% of servers, you just care that a connection was accepted; you don't have any state that persists across the continuation: while (!listeningSocket.poll()) {} var socket = listeningSocket.accept(); Stateless async skirts around many of the issues that Rust async can have (because Pin etc. has to happen because of state).
- amelius 6y ago> the resource can wake the scheduler at any time and tell it to poll Isn't that called interrupting? The terminology seems a little off here, but perhaps that is only my perception.
- marcosdumay 6y agoNo, it's not. Interrupting is when you call the scheduler at any time, even when it's doing some other work. When it's idle, it can not be interrupted. Interruptions are something one really tries to restrict to the hardware - kernel layers. Because when people write interruption handlers, they almost always write them wrong.
- cormacrelf 6y agoTo elaborate on what it is rather than what it is not, when implementing poll based IO with rust async, typically you have code like “select(); waker.wake()” on a worker thread. Select blocks. Waking tells the executor to poll the related future again, from the top of its tree. The waker implementation may indeed cause an executor thread to stop waiting, it depends on the implementation. It could also be the case that the executor is already awake and the future is simply added to a synchronised queue. Etc. You can implement waking however you like, and technically this could involve an interruptible scheduler, if you really wanted. But you would kinda have to write that.