更新:由于来自Context
签名的poll()
got removed,此问题不再相关。
我正在尝试使用Future
v0.3实现一个简单的futures crate:打开File
。
我的未来目前看起来像这样:
struct OpenFuture {
options: OpenOptions,
path: PathBuf,
output: Option<io::Result<File>>,
}
要实现Future
,我想到了这一点:
impl Future for OpenFuture {
type Output = io::Result<File>;
fn poll(mut self: PinMut<Self>, cx: &mut Context) -> Poll<Self::Output> {
if let Some(file) = self.file.take() {
Poll::Ready(file)
} else {
let waker = cx.waker().clone();
cx.spawner().spawn_obj(
Box::new(lazy(move |_| {
// self.file = Some(self.options.open(&self.path));
waker.wake();
})).into(),
);
Poll::Pending
}
}
}
如果输出为Option::Some
,则可以使用它,并且将来已经准备就绪,这很简单。但是,如果还没有准备好,我不想按照文档中所述阻塞线程:
poll
的实现应努力迅速返回,并且绝不能阻塞。快速返回可防止不必要地阻塞线程或事件循环。如果提前得知对poll
的调用可能要花一点时间,则应将工作卸载到线程池(或类似的线程)中,以确保poll
可以快速返回。>
所以我想分担工作。由于我有一个Context
传递给poll
方法,因此我可以访问Spawn
和Waker
。 Spawn
应该执行一个任务,该任务会打开文件。打开文件后,它会以waker.wake()
进行通知。
由于生命周期错误,取消注释该行时,提供的代码不起作用:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
|
| Box::new(lazy(move |_| {
| _______________________________________^
| | self.file = Some(self.options.open(&self.path));
| | waker.wake();
| | })).into(),
| |_________________________^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body...
|
| fn poll(mut self: PinMut<Self>, cx: &mut Context) -> Poll<Self::Output> {
| _____________^
| | if let Some(file) = self.file.take() {
| | Poll::Ready(file)
| | } else {
... |
| | }
| | }
| |_____________^
= note: ...so that the types are compatible:
expected std::pin::PinMut<'_, _>
found std::pin::PinMut<'_, _>
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected std::future::FutureObj<'static, _>
found std::future::FutureObj<'_, _>
如何解决?
此外,Spawn::spawn_obj
返回一个Result
。如何处理此结果?建议只返回io::ErrorKind::Other
吗?