Reputation: 2579
I'm willing to impl
a simple Future
counter, but smth goes decidedly wrong about it. Without any use of Context
the following programme would just block forever;
use std::future::Future;
use std::task::{Poll, Context};
use std::pin::Pin;
use futures::executor::block_on;
struct MyStruct {
counter: u32
}
impl Future for MyStruct {
type Output = String;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.counter == 5 {
Poll::Ready(self.counter.to_string())
} else {
unsafe {
Pin::get_unchecked_mut(self).counter += 1;
}
// cx.waker().wake();
Poll::Pending
}
}
}
fn main() {
let ms = MyStruct{counter: 0};
block_on(ms);
}
I imagine that I have to postpone somehow a call of Waker
, but it's not that straightforward. So I wonder, how to wake
it in the most simple form?
Upvotes: 0
Views: 110
Reputation: 60457
You can call .wake_by_ref()
. Waking the waker will tell the executor that is handling the Future
to be .poll()
'd again:
impl Future for MyStruct {
type Output = String;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.counter == 5 {
Poll::Ready(self.counter.to_string())
} else {
unsafe {
Pin::get_unchecked_mut(self).counter += 1;
}
cx.waker().wake_by_ref();
Poll::Pending
}
}
}
So your implementation will always ask to be immediately re-polled. I'll note that this is logically no different than simply returning Poll::Ready("5".to_string())
on the first invocation since there's no asynchronous work being done here. Because of that, there's no reason for it to be a Future
at all.
Upvotes: 1