Suppose I want an async fn that checks a condvar. This async fn gets polled, and ought to return a result with Some when ready. I am calling this from another function. What is the general syntax for returning a future in a poll-like style?
I think that as currently designed, async fn
is only intended to be a tool for polling existing Future
implementations (from tokio
, hyper
, etc).
If you want to implement the Future
trait yourself by defining what happens when the future is polled and how completion is signalled to the runtime, then you still need to write down the impl Future
explicitly.
In addition, note that Rust's async runtimes do not continuously poll the futures. The runtime polls them once, and if they are busy it waits for a readiness notification before polling them again. You can emulate continuous polling by sending such a readiness notification on every poll, but that is likely to be quite inefficient due to the underlying synchronization machinery.
In this particular case, you will probably end up facing the fact that CondVar
is fundamentally an async-unfriendly blocking abstraction, and needing to set up a dedicated thread for blocking on it and signalling the async runtime when it does something.
The alternative would be to replace the CondVar
with some kind of message queue that sends readiness notifications to the async runtime in a nonblocking way. In the new async design, Waker
can play this role.
What do you want to use it for? Note that futures always need something to notify them when they're ready to continue, and a condvar won't notify the future.
Thank you everyone for your responses.
I was mistaken Hadrien, I meant "conditional variable" like a boolean. I want something like the below code, but I want to know the simplest way to do it without having to use someone else's library (lots of annoying compat issues and needing to go through cargo.toml's and switching out dependency versions to match in the current transition phase. I would rather just make my own)
fn main(){
block_on(alert_in_2s(Instant::now().add(Duration::from_ms(2000))));
}
async fn alert_in_2s(instant_2s: Instant) -> bool {
if Instant::now() < instant_2s {
false
} else {
println!("done waiting");
true
}
}
If you wish to do it without using any libraries, you could do this.
Note that this can be done much more efficiently than starting a full thread for every sleeping future, and if you use a dependency like tokio, their timer will use that method.
use std::time::Instant;
use std::task::{Poll, Context};
use std::future::Future;
use std::pin::Pin;
struct WaitFuture {
thread_started: bool,
until: Instant,
}
impl Future for WaitFuture {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
if self.until <= Instant::now() {
Poll::Ready(())
} else {
if !self.thread_started {
let wait = cx.waker().clone();
let until = self.until;
std::thread::spawn(move || {
let now = Instant::now();
if now < until {
std::thread::sleep(until - now);
}
wait.wake();
});
self.thread_started = true;
}
Poll::Pending
}
}
}
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.