Coroutine types in C++

Coroutines are a powerful feature introduced in C++20 that facilitate writing asynchronous and sequential code. They allow you to suspend and resume the execution of a function, making it easier to write code that involves tasks or operations with non-blocking behavior.

In C++, there are two types of coroutines, which define the behavior of coroutines and how they interact with other code:

1. Generator Coroutines

Generator coroutines are used to generate a sequence of values that can be iterated over. They are defined using the generator keyword and can return multiple results over time.

#include <iostream>
#include <coroutine>

std::coroutine_handle<> generator_coroutine() {
    struct generator {
        int current_value;
        
        bool move_next() {
            if (current_value < 10) {
                ++current_value;
                return true;
            }
            return false;
        }
        
        int current() {
            return current_value;
        }
    };
    
    struct promise_type {
        generator get_return_object() {
            return generator{.current_value = 0};
        }
        
        std::suspend_never initial_suspend() noexcept {
            return {};
        }
        
        std::suspend_never final_suspend() noexcept {
            return {};
        }
        
        void return_void() {}
        void unhandled_exception() {}
    };
    
    return std::coroutine_handle<promise_type>::from_promise(promise_type{});
}

int main() {
    auto coroutine = generator_coroutine();
    while (coroutine.move_next()) {
        std::cout << coroutine.promise().current() << " ";
    }
    
    return 0;
}

In this example, the generator_coroutine function returns a generator object that can be used to iterate over a sequence of values from 1 to 10. The current function returns the current value, and move_next is used to advance to the next value. The promise_type is responsible for handling the coroutine’s lifetime and behavior.

2. Async Coroutines

Async coroutines are used to perform asynchronous operations, such as waiting for I/O or network requests. They are defined using the async keyword and allow you to write code that appears to be synchronous, even though it’s executing asynchronously.

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

std::experimental::suspend_always delay_coroutine(int seconds) {
    std::this_thread::sleep_for(std::chrono::seconds(seconds));
    co_return;
}

std::experimental::suspend_never async_coroutine() {
    co_await delay_coroutine(2);
    std::cout << "Async coroutine executed after 2 seconds" << std::endl;
    co_return;
}

int main() {
    async_coroutine();
    std::cout << "Main function continues executing" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(3));
    
    return 0;
}

In this example, the delay_coroutine suspends the coroutine for a specified number of seconds before resuming execution. The async_coroutine uses co_await to wait for the delay coroutine to complete before printing a message. The main function demonstrates the asynchronous behavior by continuing execution while the async coroutine is suspended.

Coroutines in C++ provide a powerful mechanism for writing clean and efficient asynchronous code. Understanding the different types of coroutines available can help you leverage their capabilities and unlock their full potential in your applications.

#cpp #coroutines