CodeBlanks Logo Icon CodeBlanks

await

Wait for a future with .await.

await

.await waits for a future to complete and gives its result. It can only be used in an async context. While waiting, the thread isn't blocked: the runtime can run other tasks on the same thread:

async fn fiyat(id: u32) -> u32 {
    id * 10                       // in reality: a database query
}

async fn toplam() -> u32 {
    let a = fiyat(1).await;
    let b = fiyat(2).await;
    a + b
}

Here the two calls run sequentially. Running them concurrently needs tools like join!.

await is a suspension point

The compiler turns an async function into a state machine; each .await is a state. If the future isn't ready yet, the function pauses at that point and its local variables are kept inside the state machine. That's why, in async functions, the future itself carries the variables instead of the stack.

// conceptually:
enum Toplam {
    Basla,
    BirinciBekliyor { f: FiyatFuture },
    IkinciBekliyor { a: u32, f: FiyatFuture },
    Bitti,
}

Practice Chained await

Write the async functions fiyat and toplam above. Print the result of toplam() with block_on.

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 fiyat(id: u32) -> u32 {
    id * 10
}

async fn toplam() -> u32 {
    let a = fiyat(1).await;
    let b = fiyat(2).await;
    a + b
}

fn main() {
    println!("{}", block_on(toplam()));
}

Expected output

30

Questions and answers

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

1 What happens if <code>.await</code> is written in a normal (non-async) function?

  • E0728: await only inside async functions and blocks Correct answer
  • It works
  • The thread blocks
  • It warns

Explanation: To run a future from synchronous code, an executor entry point like block_on is used.

2 Wait for the result

Question
async fn toplam() -> u32 {
    let a = fiyat(1).____;
    a
}
Answer
async fn toplam() -> u32 {
    let a = fiyat(1).await;
    a
}

Explanation: .await gives the future's result.

3 Expression and type

Term Meaning
fiyat(1) impl Future<Output = u32>
fiyat(1).await u32
toplam() A future not yet run
block_on(toplam()) 30

All lessons in Advanced