Асинхронні трейти
Асинхронні методи у трейтах було стабілізовано у випуску 1.75. Це вимагало підтримки використання impl Trait з позицією повернення у трейтах, оскільки десигнування для async fn включає -> impl Future<Output = ...>.
Однак, навіть з нативною підтримкою, існують деякі підводні камені навколо async fn:
-
Позиція повернення
impl Traitфіксує всі терміни життя в межах області застосування (тому деякі моделі запозичення не можуть бути виражені). -
Асинхронні трейти не можна використовувати з об’єктами трейтів (підтримка
dyn Trait).
Крейт async_trait надає обхідний шлях за допомогою макросу, з деякими застереженнями:
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!("Запуск всіх сплячих..");
for sleeper in &sleepers {
let start = Instant::now();
sleeper.sleep().await;
println!("Проспав {}мс", 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простий у використанні, але зауважте, що для цього він використовує виділення в купі. Цей розподіл купи має накладні витрати на продуктивність. -
Проблеми мовної підтримки
async traitє надто глибокими, щоб детально описати їх у цьому уроці. Якщо ви зацікавлені у глибшому вивченні, перегляньте цей запис у блозі Ніко Мацакіса. Дивіться також ці ключові слова:- RPIT: скорочення від return-position
impl Trait. - RPITIT: скорочення від return-position
impl Traitу трейті (RPIT у трейті).
- RPIT: скорочення від return-position
-
Спробуйте створити нову сплячу структуру, яка буде спати протягом випадкового періоду часу, і додайте її до
Vec.