Come usare un fn asincrono Rust che accetta un riferimento come callback?


10

async fnrestituisce un tipo anonimo che implementa Future, quindi se vogliamo usarlo come callback, dobbiamo convertire il valore restituito in un oggetto tratto.

Ho provato a scrivere una funzione per fare questo, ma ho avuto alcuni problemi a vita.

async fnrestituirà la durata di tutti i parametri, quindi è necessario anche la firma del callback. Come posso aggiungere la durata al valore restituito del callback?

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

Perché l'input è normalize_async_cbun puntatore a funzione?
Coder-256

Inoltre, cosa intendi per "richiamata"? Potete fornire un esempio che mostri dove sarebbe necessario questo tipo di callback?
Coder-256

Risposte:


1

La ruggine non supporta il polimorfismo di tipo superiore, quindi è necessario aggiungere un parametro a vita al 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)
}

Adizionale, puoi evitare a Boxrestituendo il impltratto:

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
}

(Il chiamante può quindi utilizzare Box::new(normalize_async_cb(…))come tipo AsyncCbse lo si desidera.)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.