Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Асинхронные трейты

Асинхронные методы в трейтах были стабилизированы в релизе 1.75. Для этого потребовалась поддержка impl Trait в возвращаемой позиции внутри трейтов, так как десахаризация async fn включает -> impl Future<Output = ...>.

Однако даже при нативной поддержке есть особые подводные камни, связанные с async fn:

  • impl Trait в возвращаемой позиции захватывает все времена жизни из области видимости (поэтому некоторые шаблоны заимствования нельзя выразить).

  • Асинхронные трейты нельзя использовать с объектами трейтов (нет поддержки dyn Trait).

Крейт async_trait предоставляет обходной путь для поддержки dyn через макрос, с определёнными оговорками:

// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0

use async_trait::async_trait;
use std::time::Instant;
use tokio::time::{Duration, sleep};

#[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!("Running all sleepers...");
        for sleeper in &sleepers {
            let start = Instant::now();
            sleeper.sleep().await;
            println!("Slept for {} 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;
}
This slide should take about 5 minutes.
  • async_trait легко использовать, но обратите внимание, что для этого он использует выделения памяти в куче. Эти выделения создают накладные расходы на производительность.

  • Сложности поддержки языком async trait слишком глубоки, чтобы подробно описывать их на этом занятии. Если хотите разобраться глубже, см. эту запись в блоге Ники Мацакиса. Также см. эти ключевые слова:

  • Попробуйте создать новую структуру «спящего», которая будет спать случайное время, и добавить её в Vec.