简体   繁体   English

如何限制 async_trait 函数的返回值来实现同步?

[英]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:我的问题是:

  • How should I specify the async method's return type to be Sync , and我应该如何将异步方法的返回类型指定为Sync ,以及
  • Why does 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM