Hi
I am using tokio runtime v1.40, and I am implementing tokio::io::AsyncRead
trait as below
pub struct MyStruct {}
impl MyStruct {
async fn wait_one(&mut self) -> bool {
// simulate some async logic
tokio::time::sleep(Duration::from_millis(100)).await
true
}
}
impl tokio::io::AsyncRead for MyStruct {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
let mut future = Box::pin(self.wait_one());
match Pin::new(&mut future).poll(cx) {
Poll::Ready(success) => {
if !success {
return Poll::Ready(Ok(()));
}
}
Poll::Pending => {
cx.waker().wake_by_ref(); // <-- why this line is needed
return Poll::Pending;
}
}
Poll::Ready(Ok(()))
}
}
So, within my AsyncRead implementation, I want to call an async method wait_one
. it is just a timer to simplify the question.
If cx.waker().wake_by_ref()
line is removed, then after Poll::Pending
is returned poll_read
will never be fired again.
So I have to add cx.waker().wake_by_ref()
in order to make poll_read
be fired again.
I thought the future
returned from wait_one
should automatically register waker but that is not true.
Is cx.waker().wake_by_ref()
efficient enough? could there be a better approach?
Thanks in advance