Thanks links:
cppreference.com - Coroutines (C++20)
Coroutine - "это магия компилятора".
"нужные места" - это примерно так:
{ co_await promise.initial_suspend(); try { // код корутины } catch (...) { promise.unhandled_exception(); } FinalSuspend: co_await promise.final_suspend(); }
CASE1: Определение типа promise_type через using:
struct promise; struct coroutine : std::coroutine_handle<promise> { using promise_type = ::promise; }; struct promise { coroutine get_return_object() { return {coroutine::from_promise(*this)}; } std::suspend_always initial_suspend() noexcept { return {}; } std::suspend_always final_suspend() noexcept { return {}; } void return_void() {} void unhandled_exception() {} }; // Использование void good() { // h - это корутина, потому что содержит co_return // и возвращает структуру coroutine, содержащую promise_type coroutine h = [](int i) -> coroutine // make i a coroutine parameter { std::cout << i; co_return; }(0); // lambda destroyed h.resume(); // no problem, i has been copied to the coroutine // frame as a by-value parameter h.destroy(); }
CASE2: Здесь компилятора сам найдет promise_type в возвращаемой структуре task:
struct task { struct promise_type { task get_return_object() { return {}; } std::suspend_never initial_suspend() { return {}; } std::suspend_never final_suspend() noexcept { return {}; } void return_void() {} void unhandled_exception() {} }; }; // resuming_on_new_thread - это корутина, потому что содержит co_await // и возвращает структуру task, содержащую promise_type task resuming_on_new_thread(std::jthread& out) { std::cout << "Coroutine started on thread: " << std::this_thread::get_id() << '\n'; co_await switch_to_new_thread(out); // awaiter destroyed here std::cout << "Coroutine resumed on thread: " << std::this_thread::get_id() << '\n'; }
В месте вызова корутины, перед выполнением самого кода корутины, компилятор закладывает выполнение следующих шагов:
При достижении co_return:
При возникновении исключения:
При окончании тела корутины: