on first poll of the Future , it will start a thread to emulate a background work , done will be shared by the thread
when work is done , the thread will set done to true
the code is as follow , is this the idiomatic way?
Currently , I wake up the async runtime unconditionally (line A) , I want it smarter , that is , let the thread wake up async runtime when work is done (line B) , but this line can't compile for now. So is it correct to pass Context to a thread?
struct MyFuture{
started : bool,
done : Arc<AtomicBool>,
id : u8,
}
impl Future for MyFuture {
type Output = bool;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
println!("poll {}",self.id);
if self.done.load(Ordering::Relaxed) {
Poll::Ready(true)
} else {
if !self.started {
let done = self.done.clone();
let id = self.id;
thread::spawn(move || {
thread::sleep_ms(5);
println!("work {:02} done",id);
done.store(true,Ordering::Relaxed);
// cx.waker().wake_by_ref(); // B
});
self.started = true;
}
cx.waker().wake_by_ref(); // A
Poll::Pending
}
}
}
fn simulate(id:u8)->MyFuture {
let done = Arc::new(AtomicBool::new(false));
MyFuture{started:false,done,id}
}
#[tokio::main(flavor="current_thread")]
async fn main() {
let f = (0..10).map(|x| {
tokio::spawn(simulate(x))
});
for f in f {
f.await;
}
}
Note that the impl Future itself is not a beginner topic since it's not an easy task. Usually you get the leaf futures from the libraries including the async runtime and combine them with futures crate, and/or .await it.