[英]How to restrict async_trait function's return value to implement Sync?
I'm using the async_trait
crate to define an async
method on a trait.我正在使用
async_trait
板条箱在 trait 上定义async
方法。 I intend to transform the Future
it returns into a Stream
, wrap the Stream
in an Arc
and send the Arc
over to multiple threads.我打算将它返回的
Future
转换为Stream
,将Stream
包装在Arc
中并将Arc
发送到多个线程。 Minimal reproducible code is as follows:最小可重现代码如下:
use async_trait::async_trait;
use futures::stream::{unfold, Stream};
use std::sync::Arc;
use tokio::runtime::Runtime;
#[async_trait]
trait Trait: Send + Sync {
async fn do_something(&self) -> i32;
}
async fn use_trait<T: Trait>(x: &T) {
let boxed: Arc<Box<dyn Stream<Item = i32> + Send + Sync>>;
let lazy_poller = unfold(None, move |state| async move {
if let Some(value) = state {
Some((value, Some(value)))
} else {
let value = x.do_something().await;
Some((value, Some(value)))
}
});
boxed = Arc::new(Box::new(lazy_poller));
let boxed_clone = boxed.clone();
let rt = Runtime::new().unwrap();
rt.block_on(async {
let _moved = boxed_clone;
// Do something with `_moved.next()`
});
}
However it compiled with the following error:但是它编译时出现以下错误:
error: future cannot be shared between threads safely
--> src/main.rs:21:22
|
21 | boxed = Arc::new(Box::new(lazy_poller));
| ^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Sync`
|
= help: the trait `Sync` is not implemented for `dyn futures::Future<Output = i32> + std::marker::Send`
note: future is not `Sync` as it awaits another future which is not `Sync`
--> src/main.rs:17:25
|
17 | let value = x.do_something().await;
| ^^^^^^^^^^^^^^^^ await occurs here on type `Pin<Box<dyn futures::Future<Output = i32> + std::marker::Send>>`, which is not `Sync`
= note: required for the cast to the object type `dyn Stream<Item = i32> + Sync + std::marker::Send`
It seems that async_trait
desugars the async methods' return types as Pin<Box<dyn Future<...> + Send>>
, without specifying Sync
.似乎
async_trait
将异步方法的返回类型脱糖为Pin<Box<dyn Future<...> + Send>>
,而没有指定Sync
。 However I thought it would also be fairly common to require Future
s to be Sync
, in addition to Send
.但是,我认为除了
Send
之外,要求Future
s 是Sync
也是相当普遍的。
My questions are:我的问题是:
Sync
, andSync
,以及async_trait
not specify Sync
for the return types automatically?async_trait
不自动为返回类型指定Sync
? As already mentioned in the comments, Future
s do not need to be Sync
for most of the use cases;正如评论中已经提到的,对于大多数用例,
Future
不需要是Sync
; and when it may be polled from different tasks, FutureExt::shared
is the way to go, which is exactly what I needed for my use case.当可以从不同的任务中轮询它时,
FutureExt::shared
是通往 go 的方式,这正是我的用例所需要的。 I did not have to transform it into a Stream
.我不必将其转换为
Stream
。
As for my example, it would be:至于我的例子,它将是:
use async_trait::async_trait;
use futures::future::FutureExt;
use tokio::runtime::Runtime;
#[async_trait]
trait Trait: Send + Sync {
async fn do_something(&self) -> i32;
}
async fn use_trait<T: Trait>(x: &T) {
let shared = x.do_something().shared();
let shared_clone = shared.clone();
let rt = Runtime::new().unwrap();
rt.block_on(async {
let _moved = shared_clone;
// Do something with `_moved.await`
});
println!("{}", shared.await)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.