CodeBlanks Logo Icon CodeBlanks

async fn

Define async functions with async fn.

async fn

When an async fn is called, its body doesn't run; instead it returns a Future. A future is "a computation that will produce a value later", and it waits until an executor drives it:

async fn selam(ad: &str) -> String {
    format!("Merhaba {ad}")
}

let f = selam("Ece");   // nothing has run yet
// f: impl Future<Output = String>

Rust's standard library doesn't include an executor; real projects use a runtime like tokio. In the exercises we'll write a small block_on that polls the future until it completes.

The smallest executor

The core of an executor is polling the future until it returns Poll::Ready. When there's no pending work, no wake-up notification is needed, so an empty Waker is enough:

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;
        }
    }
}

Real runtimes, instead of a busy loop, put the thread to sleep until the future reports it's ready via the Waker.

Practice First async function

Write the block_on executor above and the function async fn selam(ad: &str) -> String. Print the result of block_on(selam("Ece")).

Starter code

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

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 selam(ad: &str) -> String {
    format!("Merhaba {ad}")
}

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

Expected output

Merhaba Ece

Questions and answers

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

1 What happens if the line <code>selam("Ece");</code> is written on its own?

  • The program waits
  • A future is created but never runs; the compiler warns "unused future" Correct answer
  • The text is printed
  • Compile error

Explanation: Futures are lazy; they do no work unless awaited or handed to an executor.

2 Async function

Question
____ fn selam(ad: &str) -> String {
    format!("Merhaba {ad}")
}
Answer
async fn selam(ad: &str) -> String {
    format!("Merhaba {ad}")
}

Explanation: An async fn returns a Future when called.

3 Concept and meaning

Term Meaning
async fn Returns a Future
Future A value to come later
poll Advance one step
executor Drives futures

All lessons in Advanced