صفات Async

متدهای Async در traitها اخیراً در انتشار 1.75 تثبیت شده‌اند. این نیاز به پشتیبانی برای استفاده از موقعیت بازگشتی impl Trait (RPIT) در traitها را داشت، زیرا شیرین‌زدایی (desugaring) برای async fn شامل -> impl Future<Output = ...> است.

با این‌حال، حتی با پشتیبانی native امروز، برخی از مشکلات در مورد async fn و RPIT در ویژگی‌ها وجود دارد:

  • ‏Return-position impl Trait تمام طول عمرهای درون محدوده را ثبت می کند (بنابراین برخی از الگوهای قرض کردن (borrowing) نمی توانند بیان شوند)

  • ویژگی‌هایی که متد‌های آن‌ها از موقعیت بازگشتی impl trait یا async استفاده می‌کنند با dyn سازگار نیستند.

If we do need dyn support, the crate async_trait provides a workaround through a macro, with some caveats:

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!("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 آسان است، اما توجه داشته باشید که برای رسیدن به این هدف از heap allocationها استفاده می‌کند. این heap allocation دارای سربار عملکرد است.

  • چالش‌های پشتیبانی برای async trait در زبان Rust بسیار عمیق هستند و احتمالاً ارزش توصیف عمیق در اینجا را ندارند. Niko Matsakis در این پست آنها را به خوبی توضیح داده است. به خصوص اگر شما به این موضوع علاقه‌مند هستید.

  • سعی کنید یک sleep خواب جدید ایجاد کنید که برای مدت زمان تصادفی می‌خوابد و آن را به Vec اضافه کنید.