CodeBlanks Logo Icon CodeBlanks

co_await

Learn await points with co_await.

What does co_await do?

co_await creates an await point inside a coroutine. The awaited object (awaitable) must be ready; until then the coroutine suspends, and when ready it continues.

An awaitable type must have three members: await_ready (is it ready?), await_suspend (how to suspend?) and await_resume (the value on resume). Example: int v = co_await Awaiter{};. Here Awaiter is an awaitable; the value returned by await_resume is assigned to v. This way asynchronous flow is written with synchronous-looking code.

Awaitable type

An awaitable is a type with await_ready, await_suspend and await_resume members. In its simplest form, a ready awaitable looks like this:

struct Awaiter { bool await_ready() { return true; } void await_suspend(std::coroutine_handle<>) { } int await_resume() { return 7; } };. Here await_ready returns true, so the coroutine is not suspended; await_resume returns 7. The expression co_await Awaiter{} yields the value 7. This structure represents the result of an asynchronous operation.

Practice Get a value with co_await

Write int v = co_await Awaiter{}; in the body of the run coroutine and print the value with std::cout << v;. In main call run();.

Starter code

main.cpp
#include <iostream>
#include <coroutine>

struct Awaiter {
    bool await_ready() { return true; }
    void await_suspend(std::coroutine_handle<>) { }
    int await_resume() { return 7; }
};

struct Task {
    struct promise_type {
        Task get_return_object() { return {std::coroutine_handle<promise_type>::from_promise(*this)}; }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_void() { }
        void unhandled_exception() { }
    };
    std::coroutine_handle<promise_type> handle;
};

Task run() {
    // Await the Awaiter with co_await and print the result
}

int main() {
    // Call run
    return 0;
}

Sample solution

main.cpp
#include <iostream>
#include <coroutine>

struct Awaiter {
    bool await_ready() { return true; }
    void await_suspend(std::coroutine_handle<>) { }
    int await_resume() { return 7; }
};

struct Task {
    struct promise_type {
        Task get_return_object() { return {std::coroutine_handle<promise_type>::from_promise(*this)}; }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_void() { }
        void unhandled_exception() { }
    };
    std::coroutine_handle<promise_type> handle;
};

Task run() {
    int v = co_await Awaiter{};
    std::cout << v;
}

int main() {
    run();
    return 0;
}

Expected output

7

Questions and answers

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

1 the co_await usage

Question
int v = ____ Awaiter{};
Answer
int v = co_await Awaiter{};

Explanation: co_await awaits the Awaiter and assigns the result to v.

2 Match each member to its role

Term Meaning
await_ready Is it ready?
await_suspend How to suspend
await_resume Resume value
co_await Await expression

3 What does co_await Awaiter{} return?

  • The Awaiter struct itself
  • A coroutine handle
  • Nothing
  • The value returned by await_resume Correct answer

Explanation: co_await yields the value returned by the awaitable's await_resume member.

All lessons in Advanced