Traits Assíncronos
Métodos async em traits foram estabilizados apenas recentemente, no lançamento 1.75. Isso exigiu suporte para o uso de impl Trait em posição de retorno em traits, pois a “desaçucarização” para async fn inclui -> impl Future<Output = ...>.
No entanto, mesmo com o suporte nativo hoje, existem algumas armadilhas em torno de async fn e RPIT em _traits:
-
O
impl Traitem posição de retorno captura todos os tempos de vida em escopo (portanto, alguns padrões de empréstimo não podem ser expressos) -
Os métodos de traits que usam
impl traitem posição de retorno ouasyncnão são compatíveis comdyn.
Se precisarmos de suporte dyn, o crate async_trait fornece uma solução alternativa por meio de um macro, com algumas ressalvas:
use async_trait::async_trait;
use std::time::Instant;
use tokio::time::{sleep, Duration};
#[async_trait]
trait Sleeper {
async fn sleep(&self);
}
struct FixedSleeper {
sleep_ms: u64,
}
#[async_trait]
impl Sleeper for FixedSleeper {
async fn sleep(&self) {
sleep(Duration::from_millis(self.sleep_ms)).await;
}
}
async fn run_all_sleepers_multiple_times(
sleepers: Vec<Box<dyn Sleeper>>,
n_times: usize,
) {
for _ in 0..n_times {
println!("executando todos os dormentes..");
for sleeper in &sleepers {
let start = Instant::now();
sleeper.sleep().await;
println!("dormiu por {}ms", start.elapsed().as_millis());
}
}
}
#[tokio::main]
async fn main() {
let sleepers: Vec<Box<dyn Sleeper>> = vec![
Box::new(FixedSleeper { sleep_ms: 50 }),
Box::new(FixedSleeper { sleep_ms: 100 }),
];
run_all_sleepers_multiple_times(sleepers, 5).await;
}
-
async_traité fácil de usar, mas observe que ele está usando alocações de pilha para alcançar isso. Essa alocação de pilha impacta o desempenho. -
Os desafios no suporte da linguagem para
async traitsão profundos em Rust e provavelmente não valem a pena descrever em detalhes. Niko Matsakis fez um bom trabalho ao explicá-los neste post se você estiver interessado em aprofundar. -
Tente criar uma nova estrutura sleeper que dormirá por uma quantidade aleatória de tempo e adicioná-la ao Vec.