Como usar um fn assíncrono Rust que usa uma referência como retorno de chamada?


10

async fnretorna um tipo anônimo que implementa Future; portanto, se quisermos usá-lo como um retorno de chamada, precisamos converter o valor de retorno em um objeto de característica.

Tentei escrever uma função para fazer isso, mas tive alguns problemas durante a vida.

async fnretornará a vida útil de todos os parâmetros, portanto, a assinatura do retorno de chamada também precisará. Como posso adicionar a vida útil ao valor de retorno do retorno de chamada?

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)
}

Por que a entrada para normalize_async_cbum ponteiro de função?
Coder-256

Além disso, o que você quer dizer com "retorno de chamada"? Você pode fornecer um exemplo mostrando onde você precisaria desse tipo de retorno de chamada?
Coder-256

Respostas:


1

O Rust não suporta polimorfismo de tipo superior, portanto, você precisa adicionar um parâmetro vitalício ao AsyncCbtipo:

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)
}

Além disso, você pode evitar um Boxretornando uma implcaracterística:

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
}

(O chamador pode usar Box::new(normalize_async_cb(…))como tipo, AsyncCbse desejar.)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.