Any function that calls
co_return
co_await
co_yield
That's it.
Suspend function execution
Resume it from the same place
Automatically handle saving/restoring underlying state
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() {}
};
// When coroutine gets called, what to return
coroutine get_return_object()
{
return {coroutine::from_promise(*this)};
}
// When coroutine gets called, what to do
std::suspend_always initial_suspend() noexcept
{
return {};
}
// When coroutine ends (or co_returns), what to do
std::suspend_always final_suspend() noexcept
{
return {};
}
// What to do if we return `void`
void return_void() {}
// What to do if there's an unhandled exception
void unhandled_exception() {}
coroutine foo() // Can have reference parameters, whatever, it'll work
{
for (int i = 0; i < 10; ++i)
{
std::cout << i << '\n';
co_await std::suspend_always{};
}
}
\\ ...
coroutine handle = foo();
while (!handle.done())
handle.resume();
handle.destroy();
coroutine handle = foo(); // finish running foo
assert (handle.done());
handle.destroy(); // Destroy (suspended) handle, freeing coroutine memory
// handle still exists!
assert (handle);
handle.done(); // UB, dereferencing pointer
handle.destroy(); // Crash
// can be reassigned to 'nullptr' coroutine
handle = coroutine();
// Does not work like a pointer though!
assert (!handle);
handle.destroy(); // Crash
Many more customization points
yield_value
awaitable
definition
get_return_object_on_allocation_failure