C++ co_await Keyword

The co_await keyword in C++ was introduced in C++20 as part of the coroutine framework. It is used to suspend the execution of a coroutine until a specific asynchronous operation is completed. The co_await keyword allows writing asynchronous code in a synchronous style, which improves readability and maintainability.

Coroutines combined with co_await, co_yield, and co_return provide an elegant way to handle asynchronous tasks, lazy evaluation, and more in modern C++ programming.


Syntax

</>
Copy
co_await expression;
co_await
The keyword used to suspend the coroutine and wait for the completion of an asynchronous operation.
expression
The asynchronous operation or awaitable object to be awaited.

Examples

Example 1: Simple Coroutine with co_await

This example demonstrates a coroutine that uses co_await to simulate waiting for an asynchronous task.

</>
Copy
#include <iostream>
#include <coroutine>
#include <chrono>
#include <thread>

// Awaitable type
struct Sleeper {
    int duration;
    bool await_ready() const noexcept { return false; } // Not ready immediately
    void await_suspend(std::coroutine_handle<>) const noexcept {
        std::this_thread::sleep_for(std::chrono::seconds(duration));
    }
    void await_resume() const noexcept {} // No result to return
};

// Custom coroutine return type
struct VoidTask {
    struct promise_type {
        VoidTask get_return_object() {
            return VoidTask{
                std::coroutine_handle<promise_type>::from_promise(*this)};
        }
        std::suspend_never initial_suspend() noexcept { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void return_void() {}
        void unhandled_exception() { std::exit(1); }
    };

    std::coroutine_handle<promise_type> handle;
    explicit VoidTask(std::coroutine_handle<promise_type> h) : handle(h) {}
    ~VoidTask() { handle.destroy(); }
};

// Coroutine function
VoidTask sleepAndPrint() {
    std::cout << "Start sleeping..." << std::endl;
    co_await Sleeper{2}; // Wait for 2 seconds
    std::cout << "Finished sleeping!" << std::endl;
}

int main() {
    auto task = sleepAndPrint(); // Start the coroutine
    return 0;
}

Output:

Start sleeping...
Finished sleeping!

Explanation:

  1. The Sleeper struct defines an awaitable type with methods await_ready, await_suspend, and await_resume.
  2. The coroutine sleepAndPrint uses co_await to suspend execution for 2 seconds.
  3. The VoidTask custom return type ensures proper coroutine lifecycle management.

Key Points about co_await Keyword

  1. The co_await keyword is used to suspend a coroutine until an asynchronous operation completes.
  2. It works with awaitable objects that define await_ready, await_suspend, and await_resume methods.
  3. Coroutines require a valid return type with an associated promise type to manage their lifecycle.
  4. Introduced in C++20, co_await enables efficient asynchronous programming with cleaner syntax.