Member-only story
Painless C++ Coroutines-Part 2

As promised, I continue the journey of demistifying coroutines from where we left off, i.e. Painless Coroutines-Part 1 where we covered sections 1 till 4. If you still haven’t looked at the first part, I strongly encourage you to do so before getting on with the second part. In this part, I resume the journey with the section that is somewhat a tautology, i.e., Resuming the coroutine ;) .
5. Resuming the coroutine
With most of the details about coroutine creation and suspension out of the way, we can finally look at more details of coroutine implementation that sheds a light on how a coroutine can be resumed after suspension.
5.1 The coroutine handle
What I did not mention about co_await
operator that apart from co awaiting the result of the awaiter object, it also saves the execution state of the coroutine on heap and creates a callable object also known as the coroutine handle which when invoked resumes the coroutine from its suspension state.
The standard provides the coroutine handle that we’re interested in and is a template object which can have two template parameters
std::coroutine_handle<>
: i.e., empty orvoid
template parameterstd::coroutine_handle<promise_type>
Another important aspect of these two types is that the first type can be implicitly converted from the second type. We will look into this in detail later but for now we are going to work mostly with the empty template version of the coroutine handle, except for briefly using the templated version once in the next subsection.
5.2 coroutine handle and the promise_type
The coroutine handle is associated with promise_type
object for every coroutine execution and is of the type with template parameter mentioned in section 5.1, i.e., std::coroutine_handle<promise_type>
.
Secondly the coroutine handle provides a static method from_promise
to access the coroutine handle associated with the promise_type
, i.e.
struct ReturnObject { struct promise_type {
...
auto getHandle()
{
return…