我有以下代码,试图包装一个返回 future 的函数:
use std::future::Future;
use std::pin::Pin;
pub type BoxedOperation = Box<dyn Fn() -> Pin<Box<dyn Future<Output = ()> + Send>> + Send + 'static>;
fn create_func<L, R>(func: L) -> BoxedOperation
where L: Fn() -> R + Clone + Send + 'static,
R: Future<Output = ()> + Send + 'static
{
Box::new(move || {
let func = func.clone();
Box::pin(async move {
// My logic before
(func)().await; // In the future, func will receive params
// my logic after
})
})
}
此代码无法编译-
--> src/main.rs:14:9
|
14 | / Box::pin(async move {
15 | | (func)().await;
16 | | })
| |__________^ future created by async block is not `Send`
|
note: future is not `Send` as this value is used across an await
--> src/main.rs:15:21
|
15 | (func)().await;
| ------ ^^^^^^ await occurs here, with `(func)` maybe used later
| |
| has type `&L` which is not `Send`
note: `(func)` is later dropped here
--> src/main.rs:15:27
|
15 | (func)().await;
| ^
help: consider moving this into a `let` binding to create a shorter lived borrow
--> src/main.rs:15:13
|
15 | (func)().await;
| ^^^^^^^^
= note: required for the cast from `impl Future<Output = ()>` to the object type `dyn Future<Output = ()> + Send`
help: consider further restricting this bound
|
9 | where L: Fn() -> R + Clone + Send + 'static + std::marker::Sync,
|
+++++++++++++++++++
现在,这里的 BoxedOperation 返回一个 Send
的 future 至关重要,这样我以后就可以 tokio::spawn
它,但我也不想要它同步,因为这需要 func
中使用的所有内容也都同步。我真的不明白为什么这不是首先发送。
最佳答案
这是一个棘手的案例。
当您调用func
时,编译器使用Fn::call()
通过引用来获取 self 。因此编译器借用了func
,创建了&L
,并调用了这个类型。但如 generator/async functions captures are not precise ,这种类型最终会被包含在生成的 future 中,即使不需要它,因此生成的 future 需要 &L: Send
-> L: Sync
才能发送
。
要解决此问题,您可以强制编译器在等待返回的 future 之前立即删除借用:
fn create_func<L, R>(func: L) -> BoxedOperation
where
L: Fn() -> R + Clone + Send + 'static,
R: Future<Output = ()> + Send + 'static,
{
Box::new(move || {
let func = func.clone();
Box::pin(async move {
let fut = { func() }; // Notice the block.
fut.await;
})
})
}
关于rust - 如何包装一个返回 Future 的闭包,而不是同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74920440/