The co_await operator makes the current coroutine suspended, and the compiler must save where the coroutine should continue execution when it's resumed, so there is a location information somewhere. Is it possible to obtain this location information and convert it to file and line numbers to help debugging coroutines and trace back asynchronous calls?
I guess if such feature exists, it must be compiler specific, I'm interested in both GCC and MSVC compilers.
My current workaround is having an ugly AWAIT macro that's declared like this in debug builds:
#define AWAIT(x) (co_await (x).passLocation(__PRETTY_FUNCTION__, __FILE__, __LINE__))
Where x is the return type of a coroutine that has a passLocation method which passes the info into the promise, then returns *this. And I'm using AWAIT(x) instead of co_await x.
If there is a way to let obtain location infromation from the handle, then I can avoid using this hack.
The first part of evaluating the
co_await x;expression callse.await_ready(), whereeis eitherxor a derivative ofx. Theawait_readyfunction is called with no parameters. However, the overload ofawait_readycan have default parameters; it just needs to be callable with no parameters.So you can use the standard C++20 mechanism for capturing program location:
std::source_location::current()as a default parameter toawait_ready.However, this is part of the awaitable type, not a part of the promise. If you need to get this to the promise, then it needs to go into
await_suspend, which gets acoroutine_handle<P>to the promise object via the expressione.await_suspend(h), wherehis acoroutine_handle<P>.That being said, such direct coupling between an awaitable and a promise isn't the most ideal situation.
coroutine_handle<>erases the type of the promise, so you have to explicitly have yourawait_suspendoverload usecoroutine_handle<P>, wherePis the particular promise type of your current function. You can have a different overload for different promise types (or<>if you don't care):You would need a generic overload (using
coroutine_promise<>) to handle promises that aren't of typeP.