async 연습 문서의 문제 1 풀이 코드다.

//! async 연습 p1: 퓨처를 만드는 순간, await하는 순간, spawn하는 순간 중 언제 일이 시작되는지 시간으로 확인한다.
//! 의존성: tokio = { version = "1", features = ["full"] }
//! 실행: python3 "_시스템/Rust 계획/rs_check.py" "Rust/4.연습문제/40_async-practice_p1.rs"

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

async fn fetch(id: u32) -> u32 {
    sleep(Duration::from_millis(100)).await;
    id * 10
}

/// 걸린 시간을 100ms 단위로 반올림한다(작은 흔들림을 지운다).
fn rounded(t: Instant) -> u128 {
    (t.elapsed().as_millis() + 50) / 100 * 100
}

#[tokio::main]
async fn main() {
    // (가) 만들어 두고 차례로 await
    let t = Instant::now();
    let a = fetch(1);
    let b = fetch(2);
    let sum = a.await + b.await;
    let ga = rounded(t);
    println!("(가) 합 {sum}, 약 {ga}ms");

    // (나) join!으로 같이 기다리기
    let t = Instant::now();
    let (x, y) = tokio::join!(fetch(1), fetch(2));
    let gb = rounded(t);
    println!("(나) 합 {}, 약 {gb}ms", x + y);

    // (다) spawn한 뒤 다른 일을 하고 나서 await
    let t = Instant::now();
    let h1 = tokio::spawn(fetch(1));
    let h2 = tokio::spawn(fetch(2));
    sleep(Duration::from_millis(100)).await; // 다른 일 100ms
    let s = h1.await.unwrap() + h2.await.unwrap();
    let gc = rounded(t);
    println!("(다) 합 {s}, 약 {gc}ms");

    // (라) 퓨처를 만들고 다른 일을 한 뒤 await
    let t = Instant::now();
    let f = fetch(1);
    sleep(Duration::from_millis(100)).await; // 다른 일 100ms
    let v = f.await;
    let gd = rounded(t);
    println!("(라) 값 {v}, 약 {gd}ms");

    // (마) 둘 다 만들어 둔 뒤 join!에 넘기기
    let t = Instant::now();
    let (a, b) = (fetch(1), fetch(2));
    let (x, y) = tokio::join!(a, b);
    let ge = rounded(t);
    println!("(마) 합 {}, 약 {ge}ms", x + y);

    // (바) 변형: (라)를 spawn으로 바꾸기
    let t = Instant::now();
    let f = tokio::spawn(fetch(1));
    sleep(Duration::from_millis(100)).await; // 다른 일 100ms
    let v2 = f.await.unwrap();
    let gf = rounded(t);
    println!("(바) 값 {v2}, 약 {gf}ms");

    assert_eq!((ga, gb, gc, gd, ge, gf), (200, 100, 100, 200, 100, 100));
    println!("ALL CHECKS PASSED");
}