gpt4 book ai didi

async-await - 具有特征的 tokio-async-await

转载 作者:行者123 更新时间:2023-11-29 08:00:11 30 4
gpt4 key购买 nike

我想在 trait 中编写异步函数,但是因为 async fn in traits 还不被支持,我试图找到等效的方法接口(interface)。这是我在 Rust nightly (2019-01-01) 中尝试过的:

playground

#![feature(await_macro, async_await, futures_api)]
#[macro_use]
extern crate tokio;
use tokio::prelude::*;

trait T {
async fn f();
}

fn main() {
}
error[E0706]: trait fns cannot be declared `async`
--> src/main.rs:7:5
|
7 | async fn f();
| ^^^^^^^^^^^^^

我在某处读到 async只是impl Future .

trait T {
fn f() -> impl futures::Future<Item = (), Error = ()>;
}
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src/lib.rs:2:15
|
2 | fn f() -> impl futures::Future<Item = (), Error = ()>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

直接返回impl trait是不允许的,所以我尝试了一个盒装特征:

trait Resource {
fn loaded(&self) -> bool;
fn init(&mut self, auth: &str) -> Box<dyn std::future::Future<Output=()>>;
fn prepare(&mut self, auth: &str) -> Box<dyn std::future::Future<Output=()>> {
Box::new(async {
if !self.loaded() {
await!(*(self.init(auth)));
}
})
}
}
[rustc] the size for values of type `dyn std::future::Future<Output=()>` cannot be known at compilation time

没有 deref,我得到的错误是没有 into_awaitable存在 Box<>.

我可以使用非尺寸 impl Future*Box<Future>await! ?什么是最适合 trait 中异步函数的接口(interface)?

最佳答案

async 函数和 impl Trait 都不允许出现在特征中。您可以使用关联类型来拉近距离。以下是一些想法:

pub trait ResourceTrait {
type FutType: Future<Output = ()>;

fn prepare(&mut self, auth: &str) -> Self::Next;
}

目前实现这个有点棘手,因为一些必需的工具尚不可用、稳定或有缺陷。

它可以实现为:

impl ResourceTrait for Resource {
type FutType = FutureObj<'static, ()>;

fn prepare(&mut self, auth: &str) -> FutureObj<'static, ()> {
FutureObj::new(Box::new(
async move {
// Do async things
// You might get a lifetime issue here if trying to access auth,
// since it's borrowed.
}
))
}
}

存在类型的替代方案可能是:

impl ResourceTrait for Resource {
// this is required since the real type of the async function
// is unnameable
existential type FutType = Future<Output = ()>;

fn prepare(&mut self, auth: &str) -> Self::FutType {
async move {
// Do async things. Might still encounter the same borrowing issues,
// since the lifetime of the returned Future isn't coupled to the
// lifetime of self.
// The workaround is to make copies of all required fields and move
// them into the Future
}
}
}

这可能有效也可能无效(因为该功能正在开发中)。为了在返回的 future 中正确借用 selfauth 等参数,我们可能还需要首先提供通用关联类型。

为了解决self 的借用问题,您可以定义

struct Resource {
inner: Arc<ResourceInner>, // carries all actual state
}

这样你就可以在prepare中复制inner并将其移动到Future中。

关于async-await - 具有特征的 tokio-async-await,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54270468/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com