考虑以下代码
extern crate futures;
use std::sync::{atomic, Arc};
use futures::*;
struct F(Arc<atomic::AtomicBool>);
impl Future for F {
type Item = ();
type Error = ();
fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
println!("Check if flag is set");
if self.0.load(atomic::Ordering::Relaxed) {
Ok(Async::Ready(()))
} else {
Ok(Async::NotReady)
}
}
}
fn main() {
let flag = Arc::new(atomic::AtomicBool::new(false));
let future = F(flag.clone());
::std::thread::spawn(move || {
::std::thread::sleep_ms(10);
println!("set flag");
flag.store(true, atomic::Ordering::Relaxed);
});
// ::std::thread::sleep_ms(20);
let result = future.wait();
println!("result: {:?}", result);
}
生成的线程设置了一个未来等待的标志。
我们还会睡眠生成的线程,因此来自.poll()
的初始.wait()
调用是在设置标志之前。这会导致.wait()
无限制地阻塞(看似)。如果我们取消注释其他thread::sleep_ms
,.wait()
会返回,并打印出结果(()
)。
我希望当前线程多次调用poll
来尝试解决未来问题,因为我们正在阻止当前线程。但是,这种情况并没有发生。
我试过阅读some docs,问题似乎是第一次从park
获取NotReady
后线程poll
。但是,我不清楚为什么这是什么,或者如何解决这个问题。
我错过了什么?
答案 0 :(得分:7)
为什么你需要停下等待的未来而不是反复轮询?答案很明显,恕我直言。因为在一天结束时它会更快更有效!
要重复轮询未来(可能被称为“忙碌等待”),图书馆必须决定是经常做还是很少做,而且回答都不令人满意。经常做,你浪费CPU周期,很少做,代码反应迟钝。
所以是的,你需要在等待某事时停放任务,然后在等待时取消停放。像这样:
#![allow(deprecated)]
extern crate futures;
use std::sync::{Arc, Mutex};
use futures::*;
use futures::task::{park, Task};
struct Status {
ready: bool,
task: Option<Task>,
}
#[allow(dead_code)]
struct F(Arc<Mutex<Status>>);
impl Future for F {
type Item = ();
type Error = ();
fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
println!("Check if flag is set");
let mut status = self.0.lock().expect("!lock");
if status.ready {
Ok(Async::Ready(()))
} else {
status.task = Some(park());
Ok(Async::NotReady)
}
}
}
#[test]
fn test() {
let flag = Arc::new(Mutex::new(Status {
ready: false,
task: None,
}));
let future = F(flag.clone());
::std::thread::spawn(move || {
::std::thread::sleep_ms(10);
println!("set flag");
let mut status = flag.lock().expect("!lock");
status.ready = true;
if let Some(ref task) = status.task {
task.unpark()
}
});
let result = future.wait();
println!("result: {:?}", result);
}
请注意Future::poll
在这里做了几件事:它正在检查一个外部条件,它正在停止任务,所以可以进行比赛,比如: