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:
При возникновении исключения:
При окончании тела корутины: