The curious case of the coroutine that couldn't be killed
Coroutines are a C++20 feature I've fallen in love with recently, especially in the context of asynchronous programming. They certainly take a lot of boilerplate to initially set up, but once you've got that working, async code can be written in a style that looks very similar to synchronous blocking code, making it easier to read and reason about. It's not a perfect honeymoon though, there are some hidden gotchas that can ruin your day, but they can be worked around. People are often surprised at how coroutines and lambdas interact for example, but that's really the only outcome that makes sense given lambdas can be invoked multiple times.
Today though we're going to look at how coroutines and C++ exceptions interact, and what that means for our behind-the-scenes code. Let's start with this basic minimal template, which we'll be making repeated changes to throughout this post:
#include <array> | |
#include <cassert> | |
#include <coroutine> | |
#include <cstdint> | |
#include <exception> | |
#include <initializer_list> | |
#include <new> | |
#include <print> | |
#include <stdexcept> | |
#include <utility> | |
{ | |
std::uintptr_t addr() const | |
{ | |
| |
} | |
char const* name() const | |
{ | |
| |
} | |
LifetimeDebugger() | |
{ | |
std::println(stderr, | |
} | |
LifetimeDebugger(LifetimeDebugger const& l) | |
{ | |
std::println(stderr, | |
} | |
LifetimeDebugger& operator=(LifetimeDebugger const& l) | |
{ | |
std::println(stderr, | |
| |
} | |
LifetimeDebugger(LifetimeDebugger&& l) | |
{ | |
std::println(stderr, | |
} | |
LifetimeDebugger& operator=(LifetimeDebugger&& l) | |
{ | |
std::println(stderr, | |
| |
} | |
~LifetimeDebugger() | |
{ | |
std::println(stderr, | |
} | |
}; | |
#if defined(_MSC_VER) && !defined(__clang__) | |
#define DEBUG_LIFETIME(name) LifetimeDebugger<std::array{#name}> debugLifetime##name | |
#else | |
#define DEBUG_LIFETIME(name) | |
#endif | |
DEBUG_LIFETIME(global); | |
{ | |
~ThrowOnDestruct() | |
{ | |
std::println(stderr, | |
if(std::uncaught_exceptions() <= 0) | |
{ | |
| |
} | |
} | |
}; | |
: char | |
{ | |
Return = 'R', | |
Await = 'A', | |
Throw = 'T', | |
}; | |
: char | |
{ | |
AwaitReadyTrue = 'R', | |
AwaitSuspendTrue = 'S', | |
AwaitSuspendFalse = 'U', | |
}; | |
AwaitBehavior initialSuspendBehavior; | |
AwaitBehavior middleSuspendBehavior; | |
AwaitBehavior finalSuspendBehavior; | |
{ | |
Operation o; | |
AwaitBehavior i, m, f; | |
}; | |
{ | |
| |
| |
std::size_t index{}; | |
| |
{ | |
| |
{ | |
| |
{ | |
| |
{ | |
((cases[index] = {o, i, m, f}), ...); | |
++index; | |
} | |
} | |
} | |
} | |
| |
} | |
{ | |
std::array<TestCase, NUM_TEST_CASES> cases; | |
buildTestCasesImpl(cases); | |
| |
} | |
{ | |
| |
{ | |
DEBUG_LIFETIME(promise_type); | |
void* | |
{ | |
std::println(stderr, | |
| |
} | |
void | |
{ | |
std::println(stderr, | |
| |
} | |
Task get_return_object() | |
{ | |
std::println(stderr, | |
| |
} | |
| |
| |
{ | |
DEBUG_LIFETIME(InitialSuspend); | |
bool await_ready() | |
{ | |
std::println(stderr, | |
| |
} | |
bool await_suspend(std::coroutine_handle<promise_type>) | |
{ | |
std::println(stderr, | |
| |
} | |
void await_resume() | |
{ | |
std::println(stderr, | |
} | |
}; | |
| |
{ | |
DEBUG_LIFETIME(MiddleSuspend); | |
bool await_ready() | |
{ | |
std::println(stderr, | |
| |
} | |
bool await_suspend(std::coroutine_handle<promise_type>) | |
{ | |
std::println(stderr, | |
| |
} | |
void await_resume() | |
{ | |
std::println(stderr, | |
} | |
}; | |
| |
{ | |
DEBUG_LIFETIME(FinalSuspend); | |
bool await_ready() | |
{ | |
std::println(stderr, | |
| |
} | |
bool await_suspend(std::coroutine_handle<promise_type>) | |
{ | |
std::println(stderr, | |
| |
} | |
void await_resume() | |
{ | |
std::println(stderr, | |
} | |
}; | |
InitialSuspend initial_suspend() | |
{ | |
std::println(stderr, | |
| |
} | |
FinalSuspend final_suspend() | |
{ | |
std::println(stderr, | |
| |
} | |
void return_void() | |
{ | |
std::println(stderr, | |
} | |
void unhandled_exception() | |
{ | |
std::println(stderr, | |
try | |
{ | |
std::rethrow_exception(std::current_exception()); | |
} | |
catch(std::exception const& e) | |
{ | |
std::println(stderr, | |
} | |
catch(...) | |
{ | |
std::println(stderr, | |
} | |
} | |
MiddleSuspend await_transform(std::suspend_always) | |
{ | |
std::println(stderr, | |
| |
} | |
}; | |
std::coroutine_handle<promise_type> h; | |
DEBUG_LIFETIME(Task); | |
}; | |
Task makeTask(Operation | |
{ | |
DEBUG_LIFETIME(coroutine_local); | |
| |
{ | |
DEBUG_LIFETIME(coroutine_try); | |
| |
{ | |
| |
| |
| |
} | |
std::println(stderr, | |
} | |
| |
{ | |
std::println(stderr, | |
| |
} | |
std::println(stderr, | |
} | |
int main() | |
{ | |
DEBUG_LIFETIME(main); | |
std::println(stderr, | |
| |
| |
| |
{ | |
std::println(stderr, | |
| |
| |
| |
| |
{ | |
Task t(makeTask(o)); | |
std::println(stderr, | |
| |
{ | |
std::println(stderr, | |
t.h.resume(); | |
} | |
| |
{ | |
std::println(stderr, | |
t.h.destroy(); | |
} | |
} | |
| |
{ | |
std::println(stderr, | |
} | |
| |
{ | |
std::println(stderr, | |
} | |
std::println(stderr, | |
} | |
std::println(stderr, | |
} | |
Nothing especially asynchronous happens in this code, since we're not focusing on things like synchronization today.
We just output some debug messages using C++23's std::println
to get a quick picture of the program flow when we run.
Already though, we can see that we are required to mark some functions as
in order for the code to be accepted by the compiler, because the standard says that the final_suspend
operations must not be potentially-throwing.
Everything else is apparently fair-game.
Anyway, here's the output for our starting template:
Operation
:
Initial suspend
AwaitBehavior
:
Middle suspend
AwaitBehavior
:
Final suspend
AwaitBehavior
:
[00007ff769fb7863] construct `global` default | |
[000000bf916fec74] construct `main` default | |
main start | |
main test start R|RRR | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|RRR | |
main test start R|RRS | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|RRS | |
main test start R|RRU | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|RRU | |
main test start R|RSR | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|RSR | |
main test start R|RSS | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|RSS | |
main test start R|RSU | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|RSU | |
main test start R|RUR | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|RUR | |
main test start R|RUS | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|RUS | |
main test start R|RUU | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|RUU | |
main test start R|SRR | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|SRR | |
main test start R|SRS | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main destroy | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|SRS | |
main test start R|SRU | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|SRU | |
main test start R|SSR | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|SSR | |
main test start R|SSS | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main destroy | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|SSS | |
main test start R|SSU | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|SSU | |
main test start R|SUR | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|SUR | |
main test start R|SUS | |
operator new(272) | |
[000002b53a242130] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a242131] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a242131] ~destruct `InitialSuspend` | |
[000002b53a242138] construct `coroutine_local` default | |
[000002b53a242139] construct `coroutine_try` default | |
return_void | |
[000002b53a242139] ~destruct `coroutine_try` | |
[000002b53a242138] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a242168] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main destroy | |
[000002b53a242168] ~destruct `FinalSuspend` | |
[000002b53a242130] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|SUS | |
main test start R|SUU | |
operator new(272) | |
[000002b53a2469e0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2469e1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a2469e1] ~destruct `InitialSuspend` | |
[000002b53a2469e8] construct `coroutine_local` default | |
[000002b53a2469e9] construct `coroutine_try` default | |
return_void | |
[000002b53a2469e9] ~destruct `coroutine_try` | |
[000002b53a2469e8] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a246a18] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a246a18] ~destruct `FinalSuspend` | |
[000002b53a2469e0] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|SUU | |
main test start R|URR | |
operator new(272) | |
[000002b53a2465f0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2465f1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a2465f1] ~destruct `InitialSuspend` | |
[000002b53a2465f8] construct `coroutine_local` default | |
[000002b53a2465f9] construct `coroutine_try` default | |
return_void | |
[000002b53a2465f9] ~destruct `coroutine_try` | |
[000002b53a2465f8] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a246628] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246628] ~destruct `FinalSuspend` | |
[000002b53a2465f0] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|URR | |
main test start R|URS | |
operator new(272) | |
[000002b53a246890] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246891] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246891] ~destruct `InitialSuspend` | |
[000002b53a246898] construct `coroutine_local` default | |
[000002b53a246899] construct `coroutine_try` default | |
return_void | |
[000002b53a246899] ~destruct `coroutine_try` | |
[000002b53a246898] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a2468c8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a2468c8] ~destruct `FinalSuspend` | |
[000002b53a246890] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|URS | |
main test start R|URU | |
operator new(272) | |
[000002b53a246350] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246351] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246351] ~destruct `InitialSuspend` | |
[000002b53a246358] construct `coroutine_local` default | |
[000002b53a246359] construct `coroutine_try` default | |
return_void | |
[000002b53a246359] ~destruct `coroutine_try` | |
[000002b53a246358] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a246388] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a246388] ~destruct `FinalSuspend` | |
[000002b53a246350] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|URU | |
main test start R|USR | |
operator new(272) | |
[000002b53a2469e0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2469e1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a2469e1] ~destruct `InitialSuspend` | |
[000002b53a2469e8] construct `coroutine_local` default | |
[000002b53a2469e9] construct `coroutine_try` default | |
return_void | |
[000002b53a2469e9] ~destruct `coroutine_try` | |
[000002b53a2469e8] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a246a18] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246a18] ~destruct `FinalSuspend` | |
[000002b53a2469e0] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|USR | |
main test start R|USS | |
operator new(272) | |
[000002b53a246740] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246741] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246741] ~destruct `InitialSuspend` | |
[000002b53a246748] construct `coroutine_local` default | |
[000002b53a246749] construct `coroutine_try` default | |
return_void | |
[000002b53a246749] ~destruct `coroutine_try` | |
[000002b53a246748] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a246778] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a246778] ~destruct `FinalSuspend` | |
[000002b53a246740] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|USS | |
main test start R|USU | |
operator new(272) | |
[000002b53a2469e0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2469e1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a2469e1] ~destruct `InitialSuspend` | |
[000002b53a2469e8] construct `coroutine_local` default | |
[000002b53a2469e9] construct `coroutine_try` default | |
return_void | |
[000002b53a2469e9] ~destruct `coroutine_try` | |
[000002b53a2469e8] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a246a18] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a246a18] ~destruct `FinalSuspend` | |
[000002b53a2469e0] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|USU | |
main test start R|UUR | |
operator new(272) | |
[000002b53a246dd0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246dd1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246dd1] ~destruct `InitialSuspend` | |
[000002b53a246dd8] construct `coroutine_local` default | |
[000002b53a246dd9] construct `coroutine_try` default | |
return_void | |
[000002b53a246dd9] ~destruct `coroutine_try` | |
[000002b53a246dd8] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a246e08] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246e08] ~destruct `FinalSuspend` | |
[000002b53a246dd0] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|UUR | |
main test start R|UUS | |
operator new(272) | |
[000002b53a2469e0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2469e1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a2469e1] ~destruct `InitialSuspend` | |
[000002b53a2469e8] construct `coroutine_local` default | |
[000002b53a2469e9] construct `coroutine_try` default | |
return_void | |
[000002b53a2469e9] ~destruct `coroutine_try` | |
[000002b53a2469e8] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a246a18] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a246a18] ~destruct `FinalSuspend` | |
[000002b53a2469e0] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|UUS | |
main test start R|UUU | |
operator new(272) | |
[000002b53a2464a0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2464a1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a2464a1] ~destruct `InitialSuspend` | |
[000002b53a2464a8] construct `coroutine_local` default | |
[000002b53a2464a9] construct `coroutine_try` default | |
return_void | |
[000002b53a2464a9] ~destruct `coroutine_try` | |
[000002b53a2464a8] ~destruct `coroutine_local` | |
final_suspend | |
[000002b53a2464d8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a2464d8] ~destruct `FinalSuspend` | |
[000002b53a2464a0] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end R|UUU | |
main test start A|RRR | |
operator new(272) | |
[000002b53a246200] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246201] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a246201] ~destruct `InitialSuspend` | |
[000002b53a246208] construct `coroutine_local` default | |
[000002b53a246209] construct `coroutine_try` default | |
await_transform | |
[000002b53a246219] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_resume | |
[000002b53a246219] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a246209] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a246208] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a246238] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246238] ~destruct `FinalSuspend` | |
[000002b53a246200] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|RRR | |
main test start A|RRS | |
operator new(272) | |
[000002b53a246b30] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246b31] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a246b31] ~destruct `InitialSuspend` | |
[000002b53a246b38] construct `coroutine_local` default | |
[000002b53a246b39] construct `coroutine_try` default | |
await_transform | |
[000002b53a246b49] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_resume | |
[000002b53a246b49] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a246b39] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a246b38] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a246b68] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a246b68] ~destruct `FinalSuspend` | |
[000002b53a246b30] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|RRS | |
main test start A|RRU | |
operator new(272) | |
[000002b53a246c80] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246c81] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a246c81] ~destruct `InitialSuspend` | |
[000002b53a246c88] construct `coroutine_local` default | |
[000002b53a246c89] construct `coroutine_try` default | |
await_transform | |
[000002b53a246c99] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_resume | |
[000002b53a246c99] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a246c89] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a246c88] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a246cb8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a246cb8] ~destruct `FinalSuspend` | |
[000002b53a246c80] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|RRU | |
main test start A|RSR | |
operator new(272) | |
[000002b53a2469e0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2469e1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a2469e1] ~destruct `InitialSuspend` | |
[000002b53a2469e8] construct `coroutine_local` default | |
[000002b53a2469e9] construct `coroutine_try` default | |
await_transform | |
[000002b53a2469f9] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a2469f9] ~destruct `MiddleSuspend` | |
[000002b53a2469e9] ~destruct `coroutine_try` | |
[000002b53a2469e8] ~destruct `coroutine_local` | |
[000002b53a2469e0] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|RSR | |
main test start A|RSS | |
operator new(272) | |
[000002b53a246890] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246891] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a246891] ~destruct `InitialSuspend` | |
[000002b53a246898] construct `coroutine_local` default | |
[000002b53a246899] construct `coroutine_try` default | |
await_transform | |
[000002b53a2468a9] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a2468a9] ~destruct `MiddleSuspend` | |
[000002b53a246899] ~destruct `coroutine_try` | |
[000002b53a246898] ~destruct `coroutine_local` | |
[000002b53a246890] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|RSS | |
main test start A|RSU | |
operator new(272) | |
[000002b53a246740] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246741] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a246741] ~destruct `InitialSuspend` | |
[000002b53a246748] construct `coroutine_local` default | |
[000002b53a246749] construct `coroutine_try` default | |
await_transform | |
[000002b53a246759] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a246759] ~destruct `MiddleSuspend` | |
[000002b53a246749] ~destruct `coroutine_try` | |
[000002b53a246748] ~destruct `coroutine_local` | |
[000002b53a246740] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|RSU | |
main test start A|RUR | |
operator new(272) | |
[000002b53a246c80] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246c81] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a246c81] ~destruct `InitialSuspend` | |
[000002b53a246c88] construct `coroutine_local` default | |
[000002b53a246c89] construct `coroutine_try` default | |
await_transform | |
[000002b53a246c99] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
MiddleSuspend::await_resume | |
[000002b53a246c99] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a246c89] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a246c88] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a246cb8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246cb8] ~destruct `FinalSuspend` | |
[000002b53a246c80] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|RUR | |
main test start A|RUS | |
operator new(272) | |
[000002b53a2465f0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2465f1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a2465f1] ~destruct `InitialSuspend` | |
[000002b53a2465f8] construct `coroutine_local` default | |
[000002b53a2465f9] construct `coroutine_try` default | |
await_transform | |
[000002b53a246609] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
MiddleSuspend::await_resume | |
[000002b53a246609] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a2465f9] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a2465f8] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a246628] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a246628] ~destruct `FinalSuspend` | |
[000002b53a2465f0] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|RUS | |
main test start A|RUU | |
operator new(272) | |
[000002b53a246350] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246351] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a246351] ~destruct `InitialSuspend` | |
[000002b53a246358] construct `coroutine_local` default | |
[000002b53a246359] construct `coroutine_try` default | |
await_transform | |
[000002b53a246369] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
MiddleSuspend::await_resume | |
[000002b53a246369] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a246359] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a246358] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a246388] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a246388] ~destruct `FinalSuspend` | |
[000002b53a246350] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|RUU | |
main test start A|SRR | |
operator new(272) | |
[000002b53a246dd0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246dd1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246dd1] ~destruct `InitialSuspend` | |
[000002b53a246dd8] construct `coroutine_local` default | |
[000002b53a246dd9] construct `coroutine_try` default | |
await_transform | |
[000002b53a246de9] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_resume | |
[000002b53a246de9] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a246dd9] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a246dd8] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a246e08] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246e08] ~destruct `FinalSuspend` | |
[000002b53a246dd0] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|SRR | |
main test start A|SRS | |
operator new(272) | |
[000002b53a246c80] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246c81] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246c81] ~destruct `InitialSuspend` | |
[000002b53a246c88] construct `coroutine_local` default | |
[000002b53a246c89] construct `coroutine_try` default | |
await_transform | |
[000002b53a246c99] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_resume | |
[000002b53a246c99] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a246c89] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a246c88] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a246cb8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main destroy | |
[000002b53a246cb8] ~destruct `FinalSuspend` | |
[000002b53a246c80] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|SRS | |
main test start A|SRU | |
operator new(272) | |
[000002b53a246c80] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246c81] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246c81] ~destruct `InitialSuspend` | |
[000002b53a246c88] construct `coroutine_local` default | |
[000002b53a246c89] construct `coroutine_try` default | |
await_transform | |
[000002b53a246c99] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_resume | |
[000002b53a246c99] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a246c89] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a246c88] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a246cb8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a246cb8] ~destruct `FinalSuspend` | |
[000002b53a246c80] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|SRU | |
main test start A|SSR | |
operator new(272) | |
[000002b53a2465f0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2465f1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a2465f1] ~destruct `InitialSuspend` | |
[000002b53a2465f8] construct `coroutine_local` default | |
[000002b53a2465f9] construct `coroutine_try` default | |
await_transform | |
[000002b53a246609] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
main destroy | |
[000002b53a246609] ~destruct `MiddleSuspend` | |
[000002b53a2465f9] ~destruct `coroutine_try` | |
[000002b53a2465f8] ~destruct `coroutine_local` | |
[000002b53a2465f0] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|SSR | |
main test start A|SSS | |
operator new(272) | |
[000002b53a246b30] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246b31] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246b31] ~destruct `InitialSuspend` | |
[000002b53a246b38] construct `coroutine_local` default | |
[000002b53a246b39] construct `coroutine_try` default | |
await_transform | |
[000002b53a246b49] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
main destroy | |
[000002b53a246b49] ~destruct `MiddleSuspend` | |
[000002b53a246b39] ~destruct `coroutine_try` | |
[000002b53a246b38] ~destruct `coroutine_local` | |
[000002b53a246b30] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|SSS | |
main test start A|SSU | |
operator new(272) | |
[000002b53a246350] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246351] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246351] ~destruct `InitialSuspend` | |
[000002b53a246358] construct `coroutine_local` default | |
[000002b53a246359] construct `coroutine_try` default | |
await_transform | |
[000002b53a246369] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
main destroy | |
[000002b53a246369] ~destruct `MiddleSuspend` | |
[000002b53a246359] ~destruct `coroutine_try` | |
[000002b53a246358] ~destruct `coroutine_local` | |
[000002b53a246350] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|SSU | |
main test start A|SUR | |
operator new(272) | |
[000002b53a246740] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246741] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246741] ~destruct `InitialSuspend` | |
[000002b53a246748] construct `coroutine_local` default | |
[000002b53a246749] construct `coroutine_try` default | |
await_transform | |
[000002b53a246759] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
MiddleSuspend::await_resume | |
[000002b53a246759] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a246749] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a246748] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a246778] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246778] ~destruct `FinalSuspend` | |
[000002b53a246740] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|SUR | |
main test start A|SUS | |
operator new(272) | |
[000002b53a2469e0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2469e1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a2469e1] ~destruct `InitialSuspend` | |
[000002b53a2469e8] construct `coroutine_local` default | |
[000002b53a2469e9] construct `coroutine_try` default | |
await_transform | |
[000002b53a2469f9] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
MiddleSuspend::await_resume | |
[000002b53a2469f9] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a2469e9] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a2469e8] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a246a18] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main destroy | |
[000002b53a246a18] ~destruct `FinalSuspend` | |
[000002b53a2469e0] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|SUS | |
main test start A|SUU | |
operator new(272) | |
[000002b53a246200] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246201] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246201] ~destruct `InitialSuspend` | |
[000002b53a246208] construct `coroutine_local` default | |
[000002b53a246209] construct `coroutine_try` default | |
await_transform | |
[000002b53a246219] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
MiddleSuspend::await_resume | |
[000002b53a246219] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a246209] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a246208] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a246238] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a246238] ~destruct `FinalSuspend` | |
[000002b53a246200] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|SUU | |
main test start A|URR | |
operator new(272) | |
[000002b53a246350] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246351] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246351] ~destruct `InitialSuspend` | |
[000002b53a246358] construct `coroutine_local` default | |
[000002b53a246359] construct `coroutine_try` default | |
await_transform | |
[000002b53a246369] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_resume | |
[000002b53a246369] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a246359] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a246358] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a246388] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246388] ~destruct `FinalSuspend` | |
[000002b53a246350] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|URR | |
main test start A|URS | |
operator new(272) | |
[000002b53a246b30] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246b31] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246b31] ~destruct `InitialSuspend` | |
[000002b53a246b38] construct `coroutine_local` default | |
[000002b53a246b39] construct `coroutine_try` default | |
await_transform | |
[000002b53a246b49] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_resume | |
[000002b53a246b49] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a246b39] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a246b38] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a246b68] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a246b68] ~destruct `FinalSuspend` | |
[000002b53a246b30] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|URS | |
main test start A|URU | |
operator new(272) | |
[000002b53a2460b0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2460b1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a2460b1] ~destruct `InitialSuspend` | |
[000002b53a2460b8] construct `coroutine_local` default | |
[000002b53a2460b9] construct `coroutine_try` default | |
await_transform | |
[000002b53a2460c9] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_resume | |
[000002b53a2460c9] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a2460b9] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a2460b8] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a2460e8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a2460e8] ~destruct `FinalSuspend` | |
[000002b53a2460b0] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|URU | |
main test start A|USR | |
operator new(272) | |
[000002b53a246200] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246201] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246201] ~destruct `InitialSuspend` | |
[000002b53a246208] construct `coroutine_local` default | |
[000002b53a246209] construct `coroutine_try` default | |
await_transform | |
[000002b53a246219] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a246219] ~destruct `MiddleSuspend` | |
[000002b53a246209] ~destruct `coroutine_try` | |
[000002b53a246208] ~destruct `coroutine_local` | |
[000002b53a246200] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|USR | |
main test start A|USS | |
operator new(272) | |
[000002b53a246c80] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246c81] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246c81] ~destruct `InitialSuspend` | |
[000002b53a246c88] construct `coroutine_local` default | |
[000002b53a246c89] construct `coroutine_try` default | |
await_transform | |
[000002b53a246c99] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a246c99] ~destruct `MiddleSuspend` | |
[000002b53a246c89] ~destruct `coroutine_try` | |
[000002b53a246c88] ~destruct `coroutine_local` | |
[000002b53a246c80] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|USS | |
main test start A|USU | |
operator new(272) | |
[000002b53a246b30] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246b31] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246b31] ~destruct `InitialSuspend` | |
[000002b53a246b38] construct `coroutine_local` default | |
[000002b53a246b39] construct `coroutine_try` default | |
await_transform | |
[000002b53a246b49] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a246b49] ~destruct `MiddleSuspend` | |
[000002b53a246b39] ~destruct `coroutine_try` | |
[000002b53a246b38] ~destruct `coroutine_local` | |
[000002b53a246b30] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|USU | |
main test start A|UUR | |
operator new(272) | |
[000002b53a2460b0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2460b1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a2460b1] ~destruct `InitialSuspend` | |
[000002b53a2460b8] construct `coroutine_local` default | |
[000002b53a2460b9] construct `coroutine_try` default | |
await_transform | |
[000002b53a2460c9] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
MiddleSuspend::await_resume | |
[000002b53a2460c9] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a2460b9] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a2460b8] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a2460e8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a2460e8] ~destruct `FinalSuspend` | |
[000002b53a2460b0] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|UUR | |
main test start A|UUS | |
operator new(272) | |
[000002b53a246890] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246891] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246891] ~destruct `InitialSuspend` | |
[000002b53a246898] construct `coroutine_local` default | |
[000002b53a246899] construct `coroutine_try` default | |
await_transform | |
[000002b53a2468a9] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
MiddleSuspend::await_resume | |
[000002b53a2468a9] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a246899] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a246898] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a2468c8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a2468c8] ~destruct `FinalSuspend` | |
[000002b53a246890] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|UUS | |
main test start A|UUU | |
operator new(272) | |
[000002b53a2460b0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2460b1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a2460b1] ~destruct `InitialSuspend` | |
[000002b53a2460b8] construct `coroutine_local` default | |
[000002b53a2460b9] construct `coroutine_try` default | |
await_transform | |
[000002b53a2460c9] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
MiddleSuspend::await_resume | |
[000002b53a2460c9] ~destruct `MiddleSuspend` | |
coroutine try end | |
[000002b53a2460b9] ~destruct `coroutine_try` | |
coroutine function end | |
[000002b53a2460b8] ~destruct `coroutine_local` | |
return_void | |
final_suspend | |
[000002b53a2460e8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a2460e8] ~destruct `FinalSuspend` | |
[000002b53a2460b0] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end A|UUU | |
main test start T|RRR | |
operator new(272) | |
[000002b53a246c80] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246c81] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a246c81] ~destruct `InitialSuspend` | |
[000002b53a246c88] construct `coroutine_local` default | |
[000002b53a246c89] construct `coroutine_try` default | |
[000002b53a246c89] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246c88] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246cb8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246cb8] ~destruct `FinalSuspend` | |
[000002b53a246c80] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|RRR | |
main test start T|RRS | |
operator new(272) | |
[000002b53a246740] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246741] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a246741] ~destruct `InitialSuspend` | |
[000002b53a246748] construct `coroutine_local` default | |
[000002b53a246749] construct `coroutine_try` default | |
[000002b53a246749] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246748] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246778] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a246778] ~destruct `FinalSuspend` | |
[000002b53a246740] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|RRS | |
main test start T|RRU | |
operator new(272) | |
[000002b53a2469e0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2469e1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a2469e1] ~destruct `InitialSuspend` | |
[000002b53a2469e8] construct `coroutine_local` default | |
[000002b53a2469e9] construct `coroutine_try` default | |
[000002b53a2469e9] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a2469e8] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246a18] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a246a18] ~destruct `FinalSuspend` | |
[000002b53a2469e0] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|RRU | |
main test start T|RSR | |
operator new(272) | |
[000002b53a2464a0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2464a1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a2464a1] ~destruct `InitialSuspend` | |
[000002b53a2464a8] construct `coroutine_local` default | |
[000002b53a2464a9] construct `coroutine_try` default | |
[000002b53a2464a9] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a2464a8] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a2464d8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a2464d8] ~destruct `FinalSuspend` | |
[000002b53a2464a0] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|RSR | |
main test start T|RSS | |
operator new(272) | |
[000002b53a246200] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246201] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a246201] ~destruct `InitialSuspend` | |
[000002b53a246208] construct `coroutine_local` default | |
[000002b53a246209] construct `coroutine_try` default | |
[000002b53a246209] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246208] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246238] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a246238] ~destruct `FinalSuspend` | |
[000002b53a246200] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|RSS | |
main test start T|RSU | |
operator new(272) | |
[000002b53a2464a0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2464a1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a2464a1] ~destruct `InitialSuspend` | |
[000002b53a2464a8] construct `coroutine_local` default | |
[000002b53a2464a9] construct `coroutine_try` default | |
[000002b53a2464a9] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a2464a8] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a2464d8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a2464d8] ~destruct `FinalSuspend` | |
[000002b53a2464a0] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|RSU | |
main test start T|RUR | |
operator new(272) | |
[000002b53a246740] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246741] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a246741] ~destruct `InitialSuspend` | |
[000002b53a246748] construct `coroutine_local` default | |
[000002b53a246749] construct `coroutine_try` default | |
[000002b53a246749] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246748] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246778] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246778] ~destruct `FinalSuspend` | |
[000002b53a246740] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|RUR | |
main test start T|RUS | |
operator new(272) | |
[000002b53a2465f0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2465f1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a2465f1] ~destruct `InitialSuspend` | |
[000002b53a2465f8] construct `coroutine_local` default | |
[000002b53a2465f9] construct `coroutine_try` default | |
[000002b53a2465f9] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a2465f8] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246628] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a246628] ~destruct `FinalSuspend` | |
[000002b53a2465f0] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|RUS | |
main test start T|RUU | |
operator new(272) | |
[000002b53a2469e0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2469e1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002b53a2469e1] ~destruct `InitialSuspend` | |
[000002b53a2469e8] construct `coroutine_local` default | |
[000002b53a2469e9] construct `coroutine_try` default | |
[000002b53a2469e9] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a2469e8] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246a18] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a246a18] ~destruct `FinalSuspend` | |
[000002b53a2469e0] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|RUU | |
main test start T|SRR | |
operator new(272) | |
[000002b53a2464a0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2464a1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a2464a1] ~destruct `InitialSuspend` | |
[000002b53a2464a8] construct `coroutine_local` default | |
[000002b53a2464a9] construct `coroutine_try` default | |
[000002b53a2464a9] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a2464a8] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a2464d8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a2464d8] ~destruct `FinalSuspend` | |
[000002b53a2464a0] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|SRR | |
main test start T|SRS | |
operator new(272) | |
[000002b53a246dd0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246dd1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246dd1] ~destruct `InitialSuspend` | |
[000002b53a246dd8] construct `coroutine_local` default | |
[000002b53a246dd9] construct `coroutine_try` default | |
[000002b53a246dd9] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246dd8] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246e08] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main destroy | |
[000002b53a246e08] ~destruct `FinalSuspend` | |
[000002b53a246dd0] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|SRS | |
main test start T|SRU | |
operator new(272) | |
[000002b53a246350] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246351] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246351] ~destruct `InitialSuspend` | |
[000002b53a246358] construct `coroutine_local` default | |
[000002b53a246359] construct `coroutine_try` default | |
[000002b53a246359] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246358] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246388] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a246388] ~destruct `FinalSuspend` | |
[000002b53a246350] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|SRU | |
main test start T|SSR | |
operator new(272) | |
[000002b53a246c80] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246c81] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246c81] ~destruct `InitialSuspend` | |
[000002b53a246c88] construct `coroutine_local` default | |
[000002b53a246c89] construct `coroutine_try` default | |
[000002b53a246c89] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246c88] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246cb8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246cb8] ~destruct `FinalSuspend` | |
[000002b53a246c80] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|SSR | |
main test start T|SSS | |
operator new(272) | |
[000002b53a246200] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246201] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246201] ~destruct `InitialSuspend` | |
[000002b53a246208] construct `coroutine_local` default | |
[000002b53a246209] construct `coroutine_try` default | |
[000002b53a246209] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246208] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246238] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main destroy | |
[000002b53a246238] ~destruct `FinalSuspend` | |
[000002b53a246200] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|SSS | |
main test start T|SSU | |
operator new(272) | |
[000002b53a246890] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246891] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246891] ~destruct `InitialSuspend` | |
[000002b53a246898] construct `coroutine_local` default | |
[000002b53a246899] construct `coroutine_try` default | |
[000002b53a246899] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246898] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a2468c8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a2468c8] ~destruct `FinalSuspend` | |
[000002b53a246890] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|SSU | |
main test start T|SUR | |
operator new(272) | |
[000002b53a246c80] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246c81] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246c81] ~destruct `InitialSuspend` | |
[000002b53a246c88] construct `coroutine_local` default | |
[000002b53a246c89] construct `coroutine_try` default | |
[000002b53a246c89] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246c88] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246cb8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246cb8] ~destruct `FinalSuspend` | |
[000002b53a246c80] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|SUR | |
main test start T|SUS | |
operator new(272) | |
[000002b53a246890] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246891] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246891] ~destruct `InitialSuspend` | |
[000002b53a246898] construct `coroutine_local` default | |
[000002b53a246899] construct `coroutine_try` default | |
[000002b53a246899] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246898] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a2468c8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main destroy | |
[000002b53a2468c8] ~destruct `FinalSuspend` | |
[000002b53a246890] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|SUS | |
main test start T|SUU | |
operator new(272) | |
[000002b53a246350] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246351] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002b53a246351] ~destruct `InitialSuspend` | |
[000002b53a246358] construct `coroutine_local` default | |
[000002b53a246359] construct `coroutine_try` default | |
[000002b53a246359] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246358] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246388] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a246388] ~destruct `FinalSuspend` | |
[000002b53a246350] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|SUU | |
main test start T|URR | |
operator new(272) | |
[000002b53a246b30] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246b31] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246b31] ~destruct `InitialSuspend` | |
[000002b53a246b38] construct `coroutine_local` default | |
[000002b53a246b39] construct `coroutine_try` default | |
[000002b53a246b39] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246b38] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246b68] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246b68] ~destruct `FinalSuspend` | |
[000002b53a246b30] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|URR | |
main test start T|URS | |
operator new(272) | |
[000002b53a2464a0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2464a1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a2464a1] ~destruct `InitialSuspend` | |
[000002b53a2464a8] construct `coroutine_local` default | |
[000002b53a2464a9] construct `coroutine_try` default | |
[000002b53a2464a9] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a2464a8] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a2464d8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a2464d8] ~destruct `FinalSuspend` | |
[000002b53a2464a0] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|URS | |
main test start T|URU | |
operator new(272) | |
[000002b53a246890] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246891] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246891] ~destruct `InitialSuspend` | |
[000002b53a246898] construct `coroutine_local` default | |
[000002b53a246899] construct `coroutine_try` default | |
[000002b53a246899] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246898] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a2468c8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a2468c8] ~destruct `FinalSuspend` | |
[000002b53a246890] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|URU | |
main test start T|USR | |
operator new(272) | |
[000002b53a246350] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246351] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246351] ~destruct `InitialSuspend` | |
[000002b53a246358] construct `coroutine_local` default | |
[000002b53a246359] construct `coroutine_try` default | |
[000002b53a246359] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246358] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246388] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246388] ~destruct `FinalSuspend` | |
[000002b53a246350] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|USR | |
main test start T|USS | |
operator new(272) | |
[000002b53a2469e0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2469e1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a2469e1] ~destruct `InitialSuspend` | |
[000002b53a2469e8] construct `coroutine_local` default | |
[000002b53a2469e9] construct `coroutine_try` default | |
[000002b53a2469e9] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a2469e8] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246a18] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a246a18] ~destruct `FinalSuspend` | |
[000002b53a2469e0] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|USS | |
main test start T|USU | |
operator new(272) | |
[000002b53a246b30] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246b31] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246b31] ~destruct `InitialSuspend` | |
[000002b53a246b38] construct `coroutine_local` default | |
[000002b53a246b39] construct `coroutine_try` default | |
[000002b53a246b39] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246b38] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246b68] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a246b68] ~destruct `FinalSuspend` | |
[000002b53a246b30] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|USU | |
main test start T|UUR | |
operator new(272) | |
[000002b53a246c80] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246c81] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246c81] ~destruct `InitialSuspend` | |
[000002b53a246c88] construct `coroutine_local` default | |
[000002b53a246c89] construct `coroutine_try` default | |
[000002b53a246c89] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246c88] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246cb8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000002b53a246cb8] ~destruct `FinalSuspend` | |
[000002b53a246c80] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|UUR | |
main test start T|UUS | |
operator new(272) | |
[000002b53a246200] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a246201] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a246201] ~destruct `InitialSuspend` | |
[000002b53a246208] construct `coroutine_local` default | |
[000002b53a246209] construct `coroutine_try` default | |
[000002b53a246209] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a246208] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246238] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002b53a246238] ~destruct `FinalSuspend` | |
[000002b53a246200] ~destruct `promise_type` | |
operator delete | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|UUS | |
main test start T|UUU | |
operator new(272) | |
[000002b53a2465f0] construct `promise_type` default | |
get_return_object | |
[000000bf916fed20] construct `Task` default | |
initial_suspend | |
[000002b53a2465f1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002b53a2465f1] ~destruct `InitialSuspend` | |
[000002b53a2465f8] construct `coroutine_local` default | |
[000002b53a2465f9] construct `coroutine_try` default | |
[000002b53a2465f9] ~destruct `coroutine_try` | |
coroutine catch | |
[000002b53a2465f8] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: coroutine throw | |
final_suspend | |
[000002b53a246628] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
FinalSuspend::await_resume | |
[000002b53a246628] ~destruct `FinalSuspend` | |
[000002b53a2465f0] ~destruct `promise_type` | |
operator delete | |
main after makeTask | |
[000000bf916fed20] ~destruct `Task` | |
main test end T|UUU | |
main end | |
[000000bf916fec74] ~destruct `main` | |
[00007ff769fb7863] ~destruct `global` |
Nothing surprising here, the coroutine does what it's asked to do in each case and everything is cleaned up before the next pass.
You can use your counting search feature to see that the text main test start
appears 81 times, which makes sense for 34 test passes, and similarly both ~destruct `promise_type`
and operator delete
also appear 81 times each, so there's no leaks happening yet.
The reason there are so many test passes is to account for each combination of the three Operation
s and the three AwaitBehavior
s for each of the three points where an awaitable is used (initial suspend, middle suspend, and final suspend).
Actually, some of these test passes are redundant, and there are some things we could also test that we aren't yet, but I leave those matters as an exercise for the reader to figure out.
If you're only curious about the combinations that pertain to your use cases, feel free to edit the buildTestCasesImpl
function to suppress the test cases you don't care about, and the output will shrink considerably.
(You can also play with the checkboxes above the output if your browser supports the necessary CSS functionality.)
Anyway, let's start throwing exceptions!
Well, actually the entire bottom third of the output is from throwing an exception from the coroutine body while not suspended, but that's ordinary.
Let's start throwing exceptions from strange locations too.
For starters, trying to throw from
doesn't yield any interesting results, it just gets caught in main
as expected in all test cases.
But things get interesting with
- it's implicitly
by default even though we didn't specify, so first we have to explicitly mark it as
to let the exception escape without calling std::terminate
early:
#include <array> | |
#include <cassert> | |
#include <coroutine> | |
#include <cstdint> | |
#include <exception> | |
#include <initializer_list> | |
#include <new> | |
#include <print> | |
#include <stdexcept> | |
#include <utility> | |
{ | |
std::uintptr_t addr() const | |
{ | |
| |
} | |
char const* name() const | |
{ | |
| |
} | |
LifetimeDebugger() | |
{ | |
std::println(stderr, | |
} | |
LifetimeDebugger(LifetimeDebugger const& l) | |
{ | |
std::println(stderr, | |
} | |
LifetimeDebugger& operator=(LifetimeDebugger const& l) | |
{ | |
std::println(stderr, | |
| |
} | |
LifetimeDebugger(LifetimeDebugger&& l) | |
{ | |
std::println(stderr, | |
} | |
LifetimeDebugger& operator=(LifetimeDebugger&& l) | |
{ | |
std::println(stderr, | |
| |
} | |
~LifetimeDebugger() | |
{ | |
std::println(stderr, | |
} | |
}; | |
#if defined(_MSC_VER) && !defined(__clang__) | |
#define DEBUG_LIFETIME(name) LifetimeDebugger<std::array{#name}> debugLifetime##name | |
#else | |
#define DEBUG_LIFETIME(name) | |
#endif | |
DEBUG_LIFETIME(global); | |
{ | |
~ThrowOnDestruct() | |
{ | |
std::println(stderr, | |
if(std::uncaught_exceptions() <= 0) | |
{ | |
| |
} | |
} | |
}; | |
: char | |
{ | |
Return = 'R', | |
Await = 'A', | |
Throw = 'T', | |
}; | |
: char | |
{ | |
AwaitReadyTrue = 'R', | |
AwaitSuspendTrue = 'S', | |
AwaitSuspendFalse = 'U', | |
}; | |
AwaitBehavior initialSuspendBehavior; | |
AwaitBehavior middleSuspendBehavior; | |
AwaitBehavior finalSuspendBehavior; | |
{ | |
Operation o; | |
AwaitBehavior i, m, f; | |
}; | |
{ | |
| |
| |
std::size_t index{}; | |
| |
{ | |
| |
{ | |
| |
{ | |
| |
{ | |
((cases[index] = {o, i, m, f}), ...); | |
++index; | |
} | |
} | |
} | |
} | |
| |
} | |
{ | |
std::array<TestCase, NUM_TEST_CASES> cases; | |
buildTestCasesImpl(cases); | |
| |
} | |
{ | |
| |
{ | |
DEBUG_LIFETIME(promise_type); | |
void* | |
{ | |
std::println(stderr, | |
| |
} | |
void | |
{ | |
std::println(stderr, | |
| |
{ | |
| |
} | |
| |
} | |
Task get_return_object() | |
{ | |
std::println(stderr, | |
| |
} | |
| |
| |
{ | |
DEBUG_LIFETIME(InitialSuspend); | |
bool await_ready() | |
{ | |
std::println(stderr, | |
| |
} | |
bool await_suspend(std::coroutine_handle<promise_type>) | |
{ | |
std::println(stderr, | |
| |
} | |
void await_resume() | |
{ | |
std::println(stderr, | |
} | |
}; | |
| |
{ | |
DEBUG_LIFETIME(MiddleSuspend); | |
bool await_ready() | |
{ | |
std::println(stderr, | |
| |
} | |
bool await_suspend(std::coroutine_handle<promise_type>) | |
{ | |
std::println(stderr, | |
| |
} | |
void await_resume() | |
{ | |
std::println(stderr, | |
} | |
}; | |
| |
{ | |
DEBUG_LIFETIME(FinalSuspend); | |
bool await_ready() | |
{ | |
std::println(stderr, | |
| |
} | |
bool await_suspend(std::coroutine_handle<promise_type>) | |
{ | |
std::println(stderr, | |
| |
} | |
void await_resume() | |
{ | |
std::println(stderr, | |
} | |
}; | |
InitialSuspend initial_suspend() | |
{ | |
std::println(stderr, | |
| |
} | |
FinalSuspend final_suspend() | |
{ | |
std::println(stderr, | |
| |
} | |
void return_void() | |
{ | |
std::println(stderr, | |
} | |
void unhandled_exception() | |
{ | |
std::println(stderr, | |
try | |
{ | |
std::rethrow_exception(std::current_exception()); | |
} | |
catch(std::exception const& e) | |
{ | |
std::println(stderr, | |
} | |
catch(...) | |
{ | |
std::println(stderr, | |
} | |
} | |
MiddleSuspend await_transform(std::suspend_always) | |
{ | |
std::println(stderr, | |
| |
} | |
}; | |
std::coroutine_handle<promise_type> h; | |
DEBUG_LIFETIME(Task); | |
}; | |
Task makeTask(Operation | |
{ | |
DEBUG_LIFETIME(coroutine_local); | |
| |
{ | |
DEBUG_LIFETIME(coroutine_try); | |
| |
{ | |
| |
| |
| |
} | |
std::println(stderr, | |
} | |
| |
{ | |
std::println(stderr, | |
| |
} | |
std::println(stderr, | |
} | |
int main() | |
{ | |
DEBUG_LIFETIME(main); | |
std::println(stderr, | |
| |
| |
| |
{ | |
std::println(stderr, | |
| |
| |
| |
| |
{ | |
Task t(makeTask(o)); | |
std::println(stderr, | |
| |
{ | |
std::println(stderr, | |
t.h.resume(); | |
} | |
| |
{ | |
std::println(stderr, | |
t.h.destroy(); | |
} | |
} | |
| |
{ | |
std::println(stderr, | |
} | |
| |
{ | |
std::println(stderr, | |
} | |
std::println(stderr, | |
} | |
std::println(stderr, | |
} | |
Whatever you think should happen here, you're wrong, because compilers don't even agree (and the standard is too terse and spread out for me to puzzle out).
GCC 14.1 propagates the exception out of the coroutine stuff and back to whoever called makeTask()
, .resume()
, or even .destroy()
- yes, even though .destroy()
is marked
, GCC propagates the exception out of it!
Clang 17.0.3 propagates the exception out of makeTask()
or .resume()
if the coroutine doesn't suspend at its final_suspend
, but otherwise calling .destroy()
results in process termination.
MSVC v143 14.40.33807 does the unthinkable and calls promise_type::unhandled_exception()
and peforms a final_suspend
.
If that doesn't suspend the coroutine, it tries the destruction process over again.
In a production app, this will likely result in double frees and other terrible things, eventually (hopefully quickly) culminating in a crash.
However, since our test coroutine promise_type
has no state, we just get stuck in a loop on the first test case, and the stack doesn't grow either, so it just loops infinitely.
[00007ff669267863] construct `global` default | |
[000000b3cbefef64] construct `main` default | |
main start | |
main test start R|RRR | |
operator new(272) | |
[000001e59e202300] construct `promise_type` default | |
get_return_object | |
[000000b3cbeff010] construct `Task` default | |
initial_suspend | |
[000001e59e202301] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000001e59e202301] ~destruct `InitialSuspend` | |
[000001e59e202308] construct `coroutine_local` default | |
[000001e59e202309] construct `coroutine_try` default | |
return_void | |
[000001e59e202309] ~destruct `coroutine_try` | |
[000001e59e202308] ~destruct `coroutine_local` | |
final_suspend | |
[000001e59e202338] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000001e59e202338] ~destruct `FinalSuspend` | |
[000001e59e202300] ~destruct `promise_type` | |
operator delete | |
unhandled_exception | |
exception: operator delete | |
final_suspend | |
[000001e59e202338] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000001e59e202338] ~destruct `FinalSuspend` | |
[000001e59e202300] ~destruct `promise_type` | |
operator delete | |
unhandled_exception | |
exception: operator delete | |
final_suspend | |
[000001e59e202338] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_resume | |
[000001e59e202338] ~destruct `FinalSuspend` | |
[000001e59e202300] ~destruct `promise_type` | |
operator delete | |
...ad infinitum... |
Ok, that's hilariously terrifying, but also extremely unrealistic.
Most people don't even write explicit overloads of
and
in the first place, let alone going through the effort to make
explicitly
and doing something that could throw an exception from it.
It's an unrealistic scenario.
Let's look at a more realistic scenario instead: user-provided types.
Imagine our Task
type is a template which takes the expected return type, and once the result has been calculated we store it in our promise_type
, maybe wrapped in another type to handle cases like void
or references.
Maybe you even did some optimization where instead of using a standard library wrapper, you used a
so you could compact or make atomic the state flags, as some coroutine guides teach.
Pop quiz: what is the default
specification for destructors?
I can already hear you thinking, it's
even if not explicitly specified.
Unfortunately, that intuition is wrong - the default specification is inhereted from the weakest class data member, meaning if any class data member has a
destructor, the enclosing class' destructor automatically becomes
too unless it was explicitly marked otherwise!
So uh, about that hypothetical scenario we were discussing... you see how storing a user-provided type can be problematic, right?
Let's simulate it.
Start fresh with our original template and add this data member to our promise_type
:
{ | ||
| ||
{ | ||
DEBUG_LIFETIME(promise_type); | ||
ThrowOnDestruct tod; | ||
void* | ||
{ |
Yep, just like with our previous deranged code modifcation, MSVC loops infinitely and Clang sometimes propagates and sometimes terminates.
Interestingly, GCC fails with an internal compiler error, but we can get around that by deleting or commenting out the DEBUG_LIFETIME(promise_type);
line (and optionally doing it manually by adding a constructor and destructor to promise_type
), after which point it dutifully also does the same thing as in the
case: propagating the exception out of .destroy()
.
You might think that MSVC won't loop because ThrowOnDestruct
only throws when there's no uncaught exceptions, but returning from promise_type::uncaught_exception()
exits the catch block of the compiler-generated state machine, meaning there's no longer any active exceptions, so it is free to offend again.
The lesson here is you should always explicitly add the
specifier to your destructors, and you should manually destruct any user-provided types at an opportune time so you can transmit any exception from it.
You might wonder how an exception could be transmitted anywhere useful if we're in the promise_type
destructor, and indeed if you don't control who is allowed to destroy the coroutine and all your shared state is in the coroutine promise_type
there's not much you can do.
But if you can make the Task
in charge of the coroutine destruction, even if only sometimes, then you just need to set a pointer in the promise_type
to where it can store the exception, destroy the coroutine, and then look in your goodie bag for a treat to pass out to someone else.
So, that's one problem solved!
We can now properly store user-provided types with throwing destructors in our promise_type
, hooray!
And with this achievement, we've opened Pandora's box.
What are some other places that types with throwing destructors can end up at?
Hm, how about... a local variable of the coroutine function body?
Let's revert to our original template code and make this change:
Task makeTask(Operation | ||
{ | ||
DEBUG_LIFETIME(coroutine_local); | ||
ThrowOnDestruct tod; | ||
| ||
{ | ||
DEBUG_LIFETIME(coroutine_try); | ||
| ||
{ |
Well, the code runs and doesn't crash, but what does it actually do?
If we use our counting search feature on the new output, we see that both ~destruct `promise_type`
and operator delete
appear 78 times.
Wait, 78 is less than 81!
We have a leak in three test cases!
Looking at the output, most of the time things go as normal: when we return from the coroutine the destructor exception is treated as an ordinary exception, and when we throw our own exception it suppresses the destructor exception thanks to our guard.
But something strange happens in the specific instances where we're suspended in a
and the coroutine is destroyed; I've isolated the output of the leaking cases, see if you can figure it out:
main test start A|RSS | |
operator new(272) | |
[000002bb39cc6c80] construct `promise_type` default | |
get_return_object | |
[000000f90d7dece0] construct `Task` default | |
initial_suspend | |
[000002bb39cc6c81] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_resume | |
[000002bb39cc6c81] ~destruct `InitialSuspend` | |
[000002bb39cc6c88] construct `coroutine_local` default | |
[000002bb39cc6c8a] construct `coroutine_try` default | |
await_transform | |
[000002bb39cc6c99] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002bb39cc6c99] ~destruct `MiddleSuspend` | |
[000002bb39cc6c8a] ~destruct `coroutine_try` | |
~ThrowOnDestruct, uncaught_exceptions = 0 | |
[000002bb39cc6c88] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: ThrowOnDestruct | |
final_suspend | |
[000002bb39cc6cb8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
[000000f90d7dece0] ~destruct `Task` | |
main test end A|RSS | |
main test start A|SSS | |
operator new(272) | |
[000002bb39cc6dd0] construct `promise_type` default | |
get_return_object | |
[000000f90d7dece0] construct `Task` default | |
initial_suspend | |
[000002bb39cc6dd1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
main after makeTask | |
main resume | |
InitialSuspend::await_resume | |
[000002bb39cc6dd1] ~destruct `InitialSuspend` | |
[000002bb39cc6dd8] construct `coroutine_local` default | |
[000002bb39cc6dda] construct `coroutine_try` default | |
await_transform | |
[000002bb39cc6de9] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
main destroy | |
[000002bb39cc6de9] ~destruct `MiddleSuspend` | |
[000002bb39cc6dda] ~destruct `coroutine_try` | |
~ThrowOnDestruct, uncaught_exceptions = 0 | |
[000002bb39cc6dd8] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: ThrowOnDestruct | |
final_suspend | |
[000002bb39cc6e08] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
[000000f90d7dece0] ~destruct `Task` | |
main test end A|SSS | |
main test start A|USS | |
operator new(272) | |
[000002bb39cc60b0] construct `promise_type` default | |
get_return_object | |
[000000f90d7dece0] construct `Task` default | |
initial_suspend | |
[000002bb39cc60b1] construct `InitialSuspend` default | |
InitialSuspend::await_ready | |
InitialSuspend::await_suspend | |
InitialSuspend::await_resume | |
[000002bb39cc60b1] ~destruct `InitialSuspend` | |
[000002bb39cc60b8] construct `coroutine_local` default | |
[000002bb39cc60ba] construct `coroutine_try` default | |
await_transform | |
[000002bb39cc60c9] construct `MiddleSuspend` default | |
MiddleSuspend::await_ready | |
MiddleSuspend::await_suspend | |
main after makeTask | |
main destroy | |
[000002bb39cc60c9] ~destruct `MiddleSuspend` | |
[000002bb39cc60ba] ~destruct `coroutine_try` | |
~ThrowOnDestruct, uncaught_exceptions = 0 | |
[000002bb39cc60b8] ~destruct `coroutine_local` | |
unhandled_exception | |
exception: ThrowOnDestruct | |
final_suspend | |
[000002bb39cc60e8] construct `FinalSuspend` default | |
FinalSuspend::await_ready | |
FinalSuspend::await_suspend | |
[000000f90d7dece0] ~destruct `Task` | |
main test end A|USS |
The initial suspend doesn't seem to matter, but all three cases use the
middle awaiter to suspend and also suspend during the final_suspend
.
From the output we can see that during the call to .destroy()
, the destructor of the local variable throws the exception and triggers the normal unhandled exception handling: promise_type::unhandled_exception()
is called, followed by final_suspend
, which doesn't resume the coroutine, and the compiler looks at a job well done for putting the coroutine at its final suspend point, and then returns from .destroy()
with the caller none the wiser.
All three of MSVC, Clang, and GCC agree on this behavior for once!
Whether it's a compiler bug or a dark corner of the C++ standard, we can actually work around this problem too, but with a twist: in addition to the escape hatch for transmitting an exception during destruction, we also need to transform all awaiters with await_transform
so we can set a flag in the promise state to know whether the coroutine is currently suspended.
Then, in promise_type::unhandled_exception()
, we can see that the coroutine is suspended while the exception occurred, and we can store the exception and/or set another flag in the promise state to note that that exception needs to be transferred too, since now there's two different places we could receive an exception from during destruction.
Most importantly, our final suspend awaiter needs to be updated to detect this circumstance and convince the compiler to finish destroying the coroutine, usually by returning
from await_suspend
, or by destroying the coroutine handle if your return type is a coroutine handle since it's not allowed to return the same handle that was passed in for final suspend.
(Yes, this does mean .destroy()
is called twice, and yes, it is also called recursively in this case, and yes, it really does work this way.)
Also be careful to remember that the awaiter you're transforming could throw an exception from await_suspend
as a valid way to resume the coroutine without going through await_resume
, so you need to temporarily catch the exception, mark the coroutine as resumed, and then rethrow it.
As for actually figuring out the awaiter type given the possibilities of overloading
, just remember you can use
clauses in
statements within await_transform
to dramatically simplify things.
That's certainly a lot of effort to handle a seldom-used feature of the C++ language, but hey, we did it! We solved the interactions between throwing destructors and coroutines! Why is the boss music still playing...? Wait... oh no... What does this do...?
Task makeTask(Operation | ||
{ | ||
DEBUG_LIFETIME(coroutine_local); | ||
ThrowOnDestruct tod; | ||
| ||
{ | ||
DEBUG_LIFETIME(coroutine_try); | ||
ThrowOnDestruct tod; | ||
| ||
{ |
You... you see it too, right?
Those coroutine catch
lines weren't there in the output before, right?
Do you have any idea what this means!?
...
Hahaha...
...
I present to you... the coroutine that couldn't be killed:
#include <coroutine> | |
#include <print> | |
bool destructed{ | |
{ | |
| |
{ | |
~promise_type(){ destructed = | |
Task get_return_object(){ | |
std::suspend_never initial_suspend(){ | |
std::suspend_never final_suspend() noexcept { | |
void return_void(){} | |
void unhandled_exception(){ | |
}; | |
std::coroutine_handle<promise_type> h; | |
}; | |
Task makeTask() | |
{ | |
| |
{ | |
| |
{ | |
ThrowOnDestruct tod; | |
| |
} | |
| |
{ | |
} | |
std::println(stderr, "coroutine lives"); | |
} | |
} | |
int main() | |
{ | |
std::println(stderr, "main start\n"); | |
| |
{ | |
Task t(makeTask()); | |
| |
{ | |
std::println(stderr, "main destroy"); | |
t.h.destroy(); | |
} | |
} | |
| |
{ | |
std::println(stderr, "main exception"); | |
} | |
std::println(stderr, "main end"); | |
} | |
All three compilers output this...
main start | |
main destroy | |
coroutine lives | |
main destroy | |
coroutine lives | |
main destroy | |
coroutine lives | |
main destroy | |
coroutine lives | |
main destroy | |
coroutine lives | |
main destroy | |
coroutine lives | |
main destroy | |
coroutine lives | |
...ad infinitum... | |
...ad infinitum... |
There is no hope. All is lost. You can't even detect this by counting the number of active uncaught exceptions, because who knows what exception shenangians other code got up to while the coroutine was suspended. This is undetectable and unkillable.
...
Well, I suppose if the promise_type
knew it was supposed to be getting destructed, it could subvert the coroutine's wishes during its await_transform
... but that's even assuming the coroutine ever suspends again.
Besides, who would repeatedly call .destroy()
in a loop until the ~promise_type()
reported that it ran?
The coroutine not only gets to escape, it gets notified that an attempt was made on its life, and it can do whatever it wants with that information.
If I were you, I'd stay a few address spaces away from it.
I have no idea if this is standards-compliant.
I've tried reading the C++ standard before and learned that my eyes glaze over at subtle details like the difference between resuming a coroutine and resume()
ing a coroutine.
All I know is, this coroutine is out on the prowl, and at least three compilers are enabling its devious behavior.
Please, be careful out there.
Comments
Post a Comment
Remember the universal code of conduct