Как использовать Rust async fn, который принимает ссылку в качестве обратного вызова?


10

async fnвозвращает реализованный анонимный тип Future, поэтому, если мы хотим использовать его в качестве обратного вызова, нам нужно преобразовать возвращаемое значение в объект-признак.

Я пытался написать функцию, чтобы сделать это, но у меня были некоторые проблемы на всю жизнь.

async fnвернет время жизни всех параметров, так что подпись обратного вызова также должна. Как я могу добавить время жизни к возвращаемому значению обратного вызова?

use futures::future::{Future, FutureExt, LocalBoxFuture};

type Context = ();
type AsyncCb = Box<dyn for<'r> FnOnce(&'r Context) -> LocalBoxFuture<'r, ()>>;

fn normalize_async_cb<Fut: Future<Output = ()>>(f: for<'r> fn(&'r Context) -> Fut) -> AsyncCb
//                                                    how to add 'r for Fut?  ^^^
{
    let cb = move |ctx: &Context| f(ctx).boxed_local();
    Box::new(cb)
}

Почему ввод для normalize_async_cbуказателя функции?
Кодер-256

Кроме того, что вы подразумеваете под "обратным вызовом"? Можете ли вы привести пример, показывающий, где вам понадобится этот тип обратного вызова?
Кодер-256

Ответы:


1

Rust не поддерживает полиморфизм с более высоким родом, поэтому вам нужно добавить параметр времени жизни к AsyncCbтипу:

use futures::future::{Future, FutureExt, LocalBoxFuture};

type Context = ();
type AsyncCb<'r> = Box<dyn FnOnce(&'r Context) -> LocalBoxFuture<'r, ()> + 'r>;

fn normalize_async_cb<'r, Fut: Future<Output = ()> + 'r>(f: fn(&'r Context) -> Fut) -> AsyncCb {
    let cb = move |ctx: &'r Context| f(ctx).boxed_local();
    Box::new(cb)
}

Кроме того, вы можете избежать Box, вернув implчерту:

fn normalize_async_cb<'r, Fut: Future<Output = ()> + 'r>(
    f: fn(&'r Context) -> Fut,
) -> impl FnOnce(&'r Context) -> LocalBoxFuture<'r, ()> {
    let cb = move |ctx: &'r Context| f(ctx).boxed_local();
    cb
}

(Вызывающий может затем использовать Box::new(normalize_async_cb(…))как тип AsyncCbпри желании.)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.