#include <goal.hh>
Public Member Functions | |
Co (handle_type handle) | |
void | operator= (Co &&) |
Co (Co &&rhs) | |
bool | await_ready () |
std::coroutine_handle | await_suspend (handle_type handle) |
void | await_resume () |
Public Attributes | |
handle_type | handle |
C++20 coroutine wrapper for use in goal logic. Coroutines are functions that use co_await
/co_return
(and co_yield
, but not supported by Co).
Co is meant to be used by methods of subclasses of Goal. The main functionality provided by Co
is
co_await Suspend{}
: Suspends the goal.co_await f()
: Waits until f()
finishes.co_return f()
: Tail-calls f()
.co_return Return{}
: Ends coroutine.The idea is that you implement the goal logic using coroutines, and do the core thing a goal can do, suspension, when you have children you're waiting for. Coroutines allow you to resume the work cleanly.
Co f()
, a std::coroutine_handle<promise_type>
is created, alongside its promise_type. There are suspension points at the beginning of the coroutine, at every co_await
, and at the final (possibly implicit) co_return
. Once suspended, you can resume the std::coroutine_handle
by doing coroutine_handle.resume()
. Suspension points are implemented by passing a struct to the compiler that implements await_sus
pend. await_suspend
can either say "cancel suspension", in which case execution resumes, "suspend", in which case control is passed back to the caller of coroutine_handle.resume()
or the place where the coroutine function is initially executed in the case of the initial suspension, or await_suspend
can specify another coroutine to jump to, which is how tail calls are implemented.std::coroutine_handle nix::Goal::Co::await_suspend | ( | handle_type | handle | ) |
When we co_await
another Co
-returning coroutine, we tell the caller of caller_coroutine.resume()
to switch to our coroutine (handle). To make sure we return to the original coroutine, we set it as the continuation of our coroutine. In promise_type::final_awaiter we check if it's set and if so we return to it.
To explain in more understandable terms: When we co_await Co_returning_function()
, this function is called on the resultant Co of the called function, and C++ automatically passes the caller in.
goal
field of promise_type is also set here by copying it from the caller.
handle_type nix::Goal::Co::handle |
The underlying handle.