CodeBlanks Logo Icon CodeBlanks

Summary - async/await

Combine async fn, await and block to await two tasks in sequence.

async/await summary

async fn and async { } produce lazy futures; .await waits for the result and is a suspension point. The Future trait consists of a single poll method: Ready(v) or Pending. A future returning Pending wakes the executor via the Waker when it's ready. Pin guarantees that self-referential state machines don't move. The standard library has no executor; real projects use tokio.

await in a loop

Async functions use normal control flow; loops, conditions and ? work the same way:

async fn adim(n: u32) -> u32 {
    n * n
}

async fn hepsi() -> Vec<u32> {
    let mut v = Vec::new();
    for i in 1..=3 {
        v.push(adim(i).await);
    }
    v
}

Practice Wait in a loop

Write the async functions adim and hepsi above. Print the result of block_on(hepsi()) with {:?}.

Starter code

main.rs
use std::future::Future;
use std::pin::pin;
use std::task::{Context, Poll, Waker};

fn block_on<F: Future>(f: F) -> F::Output {
    let mut f = pin!(f);
    let mut cx = Context::from_waker(Waker::noop());
    loop {
        if let Poll::Ready(v) = f.as_mut().poll(&mut cx) {
            return v;
        }
    }
}

fn main() {
    // buraya yaz
}

Sample solution

main.rs
use std::future::Future;
use std::pin::pin;
use std::task::{Context, Poll, Waker};

fn block_on<F: Future>(f: F) -> F::Output {
    let mut f = pin!(f);
    let mut cx = Context::from_waker(Waker::noop());
    loop {
        if let Poll::Ready(v) = f.as_mut().poll(&mut cx) {
            return v;
        }
    }
}

async fn adim(n: u32) -> u32 {
    n * n
}

async fn hepsi() -> Vec<u32> {
    let mut v = Vec::new();
    for i in 1..=3 {
        v.push(adim(i).await);
    }
    v
}

fn main() {
    println!("{:?}", block_on(hepsi()));
}

Expected output

[1, 4, 9]

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 When is async code a better fit than threads?

  • When there are many concurrent jobs mostly waiting on I/O Correct answer
  • For heavy computation
  • Always
  • Never

Explanation: Tens of thousands of connections can be handled with few threads; for CPU-heavy work, threads or rayon fit better.

2 Ready result

Question
if let Poll::____(v) = f.as_mut().poll(&mut cx) {
    return v;
}
Answer
if let Poll::Ready(v) = f.as_mut().poll(&mut cx) {
    return v;
}

Explanation: Poll::Ready carries the result.

3 Group summary

Term Meaning
async fn Lazy future
.await Suspension point
Future::poll One step
Pin Immovable

All lessons in Advanced