rust - FuturesUnordered 的终身问题
问题描述
我正在尝试将这些Readable
实例存储在Coordinator
结构上,并有一个schedule
方法可以选择其中一个readables
并将其推送到 FuturesUnordered 实例(也在内部Coordinator
)中,以便稍后拉出。问题是:由于生命周期错误而无法编译
use bytes::Bytes;
use futures::prelude::stream::FuturesUnordered;
use std::future::Future;
use std::pin::Pin;
struct Readable {}
impl Readable {
async fn read(&mut self) -> Result<Bytes, ()> {
Err(())
}
}
type Futures = FuturesUnordered<Pin<Box<dyn Future<Output = Result<Bytes, ()>> + Send>>>;
struct Coordinator {
readers: Vec<Readable>,
futures: Futures,
}
impl Coordinator {
fn schedule(&mut self) {
let reader = self.readers.get_mut(0).unwrap();
let f = Box::pin(reader.read());
self.futures.push(f);
}
}
错误
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> src/lib.rs:23:22
|
22 | fn schedule(&mut self) {
| --------- this data with an anonymous lifetime `'_`...
23 | let reader = self.readers.get_mut(0).unwrap();
| ^^^^^^^^^^^^ ...is captured here...
24 | let f = Box::pin(reader.read());
25 | self.futures.push(f);
| - ...and is required to live as long as `'static` here
error: aborting due to previous error
任何人都可以帮助我理解为什么这是一个问题?FuturesUnordered
具体来说,当我尝试推入但我没有看到 push 方法的任何生命周期界限时,它似乎在抱怨:
/// Push a future into the set.
///
/// This method adds the given future to the set. This method will not
/// call [`poll`](core::future::Future::poll) on the submitted future. The caller must
/// ensure that [`FuturesUnordered::poll_next`](Stream::poll_next) is called
/// in order to receive wake-up notifications for the given future.
pub fn push(&self, future: Fut) {...}
我认为它也可能与这个具有自我引用的特定结构有关(即:Coordinator::futures
正在引用Coordinator::readers
),但我不完全理解这是否相关。
解决方案
如果我们扩展我们的 async 函数,它将如下所示:
fn read<'a>(&'a mut self) -> impl Future<Output = Result<Bytes, ()>> + 'a
如您所见,生命周期已在返回的类型'a
中捕获,这是一个匿名生命周期,因为可以从任何位置调用此函数。Future
'a
read
这导致了我们的问题;从编译器的角度来看,您的schedule
函数创建了一个具有匿名生命周期的未来,并尝试将其存储在self
. 即使您像这样存储您的未来,它也不相关, 编译器仍然会抛出相同的错误。FuturesUnordered
self.futures = f
一种解决方案是使用专用生命周期来告诉编译器这是安全的,但我并不真正建议这样做,因为最终它可能会导致任何其他问题,因为它会强制在特定生命周期中借用 self ,如下面的代码所示。
impl<'a> Coordinator<'a> {
fn schedule(&'a mut self) {//forced
let reader = self.readers.get_mut(0).unwrap();
let f = Box::pin(reader.read());
self.futures = f;
}
}
如果您的未来不借用任何东西,其他解决方案会容易得多,您可以将没有生命周期的异步函数定义为未来的构建器。
impl Readable {
fn read(&mut self) -> impl Future<Output = Result<Bytes, ()>> {
//produce bytes from self
futures::future::err(())
}
}
也可以看看 :
推荐阅读
- aws-lambda - DyanamoDB 与 AWS Lambda 函数 Order by Desc Order with scan
- node.js - 连接到 Mongodb 的可变路由/url 参数
- android - 如何在 Android 中播放 Base 64 编码的音频
- ansible - 如何将值列表动态传递给 Ansible URI 模块
- flutter - 等效于 Javascript 的 Math.sign 但适用于 Dart
- java - 在java文件中搜索行并使用批处理脚本输出到另一个文件
- c - 在我的内核驱动程序中是“reinterpret_cast”未定义
- search - 如何在 Solr 上处理阿拉伯字符
- reactjs - 用于 Firebase 的 Ckeditor 自定义文件上传适配器不起作用
- sql - 多对多关系的两个以上表