include/boost/capy/ex/run.hpp

100.0% Lines (271 / 271, 3 excl) 88.4% Functions (281 / 318, 1 excl)
run.hpp
f(x) Functions (319)
Function Calls Lines Blocks
boost::capy::detail::boundary_trampoline::promise_type::unwind() :88 10x 100.0% 100.0% boost::capy::detail::boundary_trampoline::promise_type::~promise_type() :96 87x 100.0% 100.0% boost::capy::detail::boundary_trampoline::promise_type::get_return_object() :107 87x 100.0% 100.0% boost::capy::detail::boundary_trampoline::promise_type::initial_suspend() :113 87x 100.0% 100.0% boost::capy::detail::boundary_trampoline::promise_type::final_suspend() :115 85x 100.0% 100.0% boost::capy::detail::boundary_trampoline::promise_type::final_suspend()::awaiter::await_ready() const :120 85x 100.0% 100.0% boost::capy::detail::boundary_trampoline::promise_type::final_suspend()::awaiter::await_suspend(std::__n4861::coroutine_handle<void>) :122 85x 100.0% 100.0% boost::capy::detail::boundary_trampoline::promise_type::final_suspend()::awaiter::await_resume() const :141 – – – boost::capy::detail::boundary_trampoline::promise_type::return_void() :146 85x 100.0% 100.0% boost::capy::detail::boundary_trampoline::boundary_trampoline() :152 88x 100.0% 100.0% boost::capy::detail::boundary_trampoline::~boundary_trampoline() :154 261x 100.0% 100.0% boost::capy::detail::boundary_trampoline::boundary_trampoline(boost::capy::detail::boundary_trampoline&&) :166 86x 100.0% 100.0% boost::capy::detail::boundary_trampoline::operator=(boost::capy::detail::boundary_trampoline&&) :169 88x 100.0% 100.0% boost::capy::detail::boundary_trampoline::boundary_trampoline(std::__n4861::coroutine_handle<boost::capy::detail::boundary_trampoline::promise_type>) :184 87x 100.0% 100.0% boost::capy::detail::make_boundary_trampoline() :188 87x 100.0% 44.0% boost::capy::detail::run_awaitable_ex<boost::capy::lax_task, boost::capy::test_executor, true, void>::~run_awaitable_ex() :225 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, false, void>::~run_awaitable_ex() :225 4x 80.0% 80.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, true, void>::~run_awaitable_ex() :225 4x 80.0% 79.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::~run_awaitable_ex() :225 2x 80.0% 80.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, boost::capy::test_allocator<std::byte> >::~run_awaitable_ex() :225 2x 80.0% 81.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, std::pmr::memory_resource*>::~run_awaitable_ex() :225 2x 80.0% 80.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, void>::~run_awaitable_ex() :225 2x 80.0% 80.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, boost::capy::test_allocator<std::byte> >::~run_awaitable_ex() :225 2x 80.0% 80.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, std::pmr::memory_resource*>::~run_awaitable_ex() :225 2x 80.0% 79.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::thread_pool::executor_type, true, void>::~run_awaitable_ex() :225 104x 80.0% 79.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::closing_executor, true, void>::~run_awaitable_ex() :225 2x 100.0% 71.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::run_test::throwing_post_executor, true, void>::~run_awaitable_ex() :225 1x 80.0% 64.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::executor_ref>, true, void>::~run_awaitable_ex() :225 2x 80.0% 80.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::~run_awaitable_ex() :225 2x 80.0% 80.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test::priority_executor<boost::capy::queuing_executor>, true, void>::~run_awaitable_ex() :225 4x 80.0% 79.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, false, void>::~run_awaitable_ex() :225 2x 80.0% 80.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, boost::capy::counting_allocator<std::byte> >::~run_awaitable_ex() :225 2x 100.0% 87.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, std::pmr::memory_resource*>::~run_awaitable_ex() :225 2x 100.0% 86.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, void>::~run_awaitable_ex() :225 18x 100.0% 86.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, false, void>::~run_awaitable_ex() :225 2x 80.0% 80.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, std::pmr::memory_resource*>::~run_awaitable_ex() :225 2x 80.0% 79.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, void>::~run_awaitable_ex() :225 6x 100.0% 86.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<int>, boost::capy::test_executor, true, void>::~run_awaitable_ex() :225 2x 80.0% 79.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<void>, boost::capy::test_executor, true, void>::~run_awaitable_ex() :225 2x 80.0% 79.0% boost::capy::detail::run_awaitable_ex<boost::capy::lax_task, boost::capy::test_executor, true, void>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, false, void>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, true, void>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, boost::capy::test_allocator<std::byte> >::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, std::pmr::memory_resource*>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, void>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, boost::capy::test_allocator<std::byte> >::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, std::pmr::memory_resource*>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::thread_pool::executor_type, true, void>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::closing_executor, true, void>::destroy_inner(void*) :238 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::run_test::throwing_post_executor, true, void>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::executor_ref>, true, void>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test::priority_executor<boost::capy::queuing_executor>, true, void>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, false, void>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, boost::capy::counting_allocator<std::byte> >::destroy_inner(void*) :238 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, std::pmr::memory_resource*>::destroy_inner(void*) :238 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, void>::destroy_inner(void*) :238 6x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, false, void>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, std::pmr::memory_resource*>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, void>::destroy_inner(void*) :238 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<int>, boost::capy::test_executor, true, void>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<void>, boost::capy::test_executor, true, void>::destroy_inner(void*) :238 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::lax_task, boost::capy::test_executor, true, void>::run_awaitable_ex(boost::capy::test_executor, boost::capy::lax_task) :247 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, true, void>::run_awaitable_ex(boost::capy::test_executor, boost::capy::task<bool>) :247 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::run_awaitable_ex(boost::capy::strand<boost::capy::thread_pool::executor_type>, boost::capy::task<int>) :247 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::thread_pool::executor_type, true, void>::run_awaitable_ex(boost::capy::thread_pool::executor_type, boost::capy::task<int>) :247 52x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::closing_executor, true, void>::run_awaitable_ex(boost::capy::closing_executor, boost::capy::task<void>) :247 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::run_test::throwing_post_executor, true, void>::run_awaitable_ex(boost::capy::run_test::throwing_post_executor, boost::capy::task<void>) :247 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::executor_ref>, true, void>::run_awaitable_ex(boost::capy::strand<boost::capy::executor_ref>, boost::capy::task<void>) :247 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::run_awaitable_ex(boost::capy::strand<boost::capy::thread_pool::executor_type>, boost::capy::task<void>) :247 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test::priority_executor<boost::capy::queuing_executor>, true, void>::run_awaitable_ex(boost::capy::test::priority_executor<boost::capy::queuing_executor>, boost::capy::task<void>) :247 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, void>::run_awaitable_ex(boost::capy::test_executor, boost::capy::task<void>) :247 9x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, void>::run_awaitable_ex(boost::capy::thread_pool::executor_type, boost::capy::task<void>) :247 3x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<int>, boost::capy::test_executor, true, void>::run_awaitable_ex(boost::capy::test_executor, boost::capy::test::custom_task<int>) :247 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<void>, boost::capy::test_executor, true, void>::run_awaitable_ex(boost::capy::test_executor, boost::capy::test::custom_task<void>) :247 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, false, void>::run_awaitable_ex(boost::capy::test_executor, boost::capy::task<bool>, std::stop_token) :255 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, void>::run_awaitable_ex(boost::capy::test_executor, boost::capy::task<int>, std::stop_token) :255 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, false, void>::run_awaitable_ex(boost::capy::test_executor, boost::capy::task<void>, std::stop_token) :255 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, false, void>::run_awaitable_ex(boost::capy::thread_pool::executor_type, boost::capy::task<void>, std::stop_token) :255 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, boost::capy::test_allocator<std::byte> >::run_awaitable_ex<boost::capy::test_allocator<std::byte> >(boost::capy::test_executor, boost::capy::test_allocator<std::byte>, boost::capy::task<int>) :266 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, std::pmr::memory_resource*>::run_awaitable_ex<std::pmr::memory_resource*>(boost::capy::test_executor, std::pmr::memory_resource*, boost::capy::task<int>) :266 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, boost::capy::counting_allocator<std::byte> >::run_awaitable_ex<boost::capy::counting_allocator<std::byte> >(boost::capy::test_executor, boost::capy::counting_allocator<std::byte>, boost::capy::task<void>) :266 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, std::pmr::memory_resource*>::run_awaitable_ex<std::pmr::memory_resource*>(boost::capy::test_executor, std::pmr::memory_resource*, boost::capy::task<void>) :266 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, std::pmr::memory_resource*>::run_awaitable_ex<std::pmr::memory_resource*>(boost::capy::thread_pool::executor_type, std::pmr::memory_resource*, boost::capy::task<void>) :266 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, boost::capy::test_allocator<std::byte> >::run_awaitable_ex<boost::capy::test_allocator<std::byte> >(boost::capy::test_executor, boost::capy::test_allocator<std::byte>, boost::capy::task<int>, std::stop_token) :276 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, std::pmr::memory_resource*>::run_awaitable_ex<std::pmr::memory_resource*>(boost::capy::test_executor, std::pmr::memory_resource*, boost::capy::task<int>, std::stop_token) :276 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::lax_task, boost::capy::test_executor, true, void>::await_ready() const :284 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, false, void>::await_ready() const :284 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, true, void>::await_ready() const :284 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, boost::capy::test_allocator<std::byte> >::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, std::pmr::memory_resource*>::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, void>::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, boost::capy::test_allocator<std::byte> >::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, std::pmr::memory_resource*>::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::thread_pool::executor_type, true, void>::await_ready() const :284 52x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::closing_executor, true, void>::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::executor_ref>, true, void>::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test::priority_executor<boost::capy::queuing_executor>, true, void>::await_ready() const :284 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, false, void>::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, boost::capy::counting_allocator<std::byte> >::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, std::pmr::memory_resource*>::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, void>::await_ready() const :284 9x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, false, void>::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, std::pmr::memory_resource*>::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, void>::await_ready() const :284 3x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<int>, boost::capy::test_executor, true, void>::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<void>, boost::capy::test_executor, true, void>::await_ready() const :284 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::lax_task, boost::capy::test_executor, true, void>::await_resume() :289 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, false, void>::await_resume() :289 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, true, void>::await_resume() :289 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::await_resume() :289 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, boost::capy::test_allocator<std::byte> >::await_resume() :289 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, std::pmr::memory_resource*>::await_resume() :289 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, void>::await_resume() :289 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, boost::capy::test_allocator<std::byte> >::await_resume() :289 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, std::pmr::memory_resource*>::await_resume() :289 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::thread_pool::executor_type, true, void>::await_resume() :289 52x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::closing_executor, true, void>::await_resume() :289 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::executor_ref>, true, void>::await_resume() :289 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::await_resume() :289 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test::priority_executor<boost::capy::queuing_executor>, true, void>::await_resume() :289 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, false, void>::await_resume() :289 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, boost::capy::counting_allocator<std::byte> >::await_resume() :289 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, std::pmr::memory_resource*>::await_resume() :289 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, void>::await_resume() :289 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, false, void>::await_resume() :289 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, std::pmr::memory_resource*>::await_resume() :289 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, void>::await_resume() :289 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<int>, boost::capy::test_executor, true, void>::await_resume() :289 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<void>, boost::capy::test_executor, true, void>::await_resume() :289 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::lax_task, boost::capy::test_executor, true, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, false, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 2x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, true, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 2x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, boost::capy::test_allocator<std::byte> >::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 62.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, std::pmr::memory_resource*>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 62.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, boost::capy::test_allocator<std::byte> >::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 62.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, std::pmr::memory_resource*>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 62.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::thread_pool::executor_type, true, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 52x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::closing_executor, true, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::run_test::throwing_post_executor, true, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 96.9% 86.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::executor_ref>, true, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test::priority_executor<boost::capy::queuing_executor>, true, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 2x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, false, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, boost::capy::counting_allocator<std::byte> >::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 62.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, std::pmr::memory_resource*>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 62.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 9x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, false, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, std::pmr::memory_resource*>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 62.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 3x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<int>, boost::capy::test_executor, true, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<void>, boost::capy::test_executor, true, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :296 1x 78.1% 61.0% boost::capy::detail::run_awaitable_ex<boost::capy::lax_task, boost::capy::test_executor, true, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::lax_task, boost::capy::test_executor, true, void>&&) :356 0 0.0% 0.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, false, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, false, void>&&) :356 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, true, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, true, void>&&) :356 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, boost::capy::test_allocator<std::byte> >::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, boost::capy::test_allocator<std::byte> >&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, std::pmr::memory_resource*>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, std::pmr::memory_resource*>&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, void>&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, boost::capy::test_allocator<std::byte> >::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, boost::capy::test_allocator<std::byte> >&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, std::pmr::memory_resource*>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, true, std::pmr::memory_resource*>&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::thread_pool::executor_type, true, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::thread_pool::executor_type, true, void>&&) :356 52x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::closing_executor, true, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::closing_executor, true, void>&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::executor_ref>, true, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::executor_ref>, true, void>&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test::priority_executor<boost::capy::queuing_executor>, true, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test::priority_executor<boost::capy::queuing_executor>, true, void>&&) :356 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, false, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, false, void>&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, boost::capy::counting_allocator<std::byte> >::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, boost::capy::counting_allocator<std::byte> >&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, std::pmr::memory_resource*>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, std::pmr::memory_resource*>&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, void>&&) :356 9x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, false, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, false, void>&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, std::pmr::memory_resource*>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, std::pmr::memory_resource*>&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::thread_pool::executor_type, true, void>&&) :356 3x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<int>, boost::capy::test_executor, true, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<int>, boost::capy::test_executor, true, void>&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<void>, boost::capy::test_executor, true, void>::run_awaitable_ex(boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<void>, boost::capy::test_executor, true, void>&&) :356 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::lax_task, false, void>::~run_awaitable() :381 0 0.0% 0.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, boost::capy::test_allocator<std::byte> >::~run_awaitable() :381 2x 80.0% 50.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, std::pmr::memory_resource*>::~run_awaitable() :381 2x 80.0% 47.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, void>::~run_awaitable() :381 2x 80.0% 47.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, boost::capy::test_allocator<std::byte> >::~run_awaitable() :381 2x 80.0% 47.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, std::pmr::memory_resource*>::~run_awaitable() :381 2x 80.0% 44.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, false, void>::~run_awaitable() :381 2x 80.0% 47.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, true, boost::capy::counting_allocator<std::byte> >::~run_awaitable() :381 2x 100.0% 88.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, true, std::pmr::memory_resource*>::~run_awaitable() :381 22x 100.0% 88.0% boost::capy::detail::run_awaitable<boost::capy::lax_task, false, void>::run_awaitable(boost::capy::lax_task, std::stop_token) :400 0 0.0% 0.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, void>::run_awaitable(boost::capy::task<int>, std::stop_token) :400 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, false, void>::run_awaitable(boost::capy::task<void>, std::stop_token) :400 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, boost::capy::test_allocator<std::byte> >::run_awaitable<boost::capy::test_allocator<std::byte> >(boost::capy::test_allocator<std::byte>, boost::capy::task<int>) :410 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, std::pmr::memory_resource*>::run_awaitable<std::pmr::memory_resource*>(std::pmr::memory_resource*, boost::capy::task<int>) :410 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, true, boost::capy::counting_allocator<std::byte> >::run_awaitable<boost::capy::counting_allocator<std::byte> >(boost::capy::counting_allocator<std::byte>, boost::capy::task<void>) :410 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, true, std::pmr::memory_resource*>::run_awaitable<std::pmr::memory_resource*>(std::pmr::memory_resource*, boost::capy::task<void>) :410 11x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, boost::capy::test_allocator<std::byte> >::run_awaitable<boost::capy::test_allocator<std::byte> >(boost::capy::test_allocator<std::byte>, boost::capy::task<int>, std::stop_token) :419 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, std::pmr::memory_resource*>::run_awaitable<std::pmr::memory_resource*>(std::pmr::memory_resource*, boost::capy::task<int>, std::stop_token) :419 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::lax_task, false, void>::await_ready() const :426 0 0.0% 0.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, boost::capy::test_allocator<std::byte> >::await_ready() const :426 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, std::pmr::memory_resource*>::await_ready() const :426 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, void>::await_ready() const :426 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, boost::capy::test_allocator<std::byte> >::await_ready() const :426 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, std::pmr::memory_resource*>::await_ready() const :426 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, false, void>::await_ready() const :426 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, true, boost::capy::counting_allocator<std::byte> >::await_ready() const :426 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, true, std::pmr::memory_resource*>::await_ready() const :426 11x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::lax_task, false, void>::await_resume() :431 0 0.0% 0.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, boost::capy::test_allocator<std::byte> >::await_resume() :431 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, std::pmr::memory_resource*>::await_resume() :431 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, void>::await_resume() :431 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, boost::capy::test_allocator<std::byte> >::await_resume() :431 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, std::pmr::memory_resource*>::await_resume() :431 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, false, void>::await_resume() :431 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, true, boost::capy::counting_allocator<std::byte> >::await_resume() :431 0 0.0% 0.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, true, std::pmr::memory_resource*>::await_resume() :431 2x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::lax_task, false, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :437 0 0.0% 0.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, boost::capy::test_allocator<std::byte> >::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :437 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, std::pmr::memory_resource*>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :437 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :437 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, boost::capy::test_allocator<std::byte> >::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :437 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, std::pmr::memory_resource*>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :437 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, false, void>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :437 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, true, boost::capy::counting_allocator<std::byte> >::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :437 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, true, std::pmr::memory_resource*>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::await_context const*) :437 11x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::lax_task, false, void>::run_awaitable(boost::capy::detail::run_awaitable<boost::capy::lax_task, false, void>&&) :465 0 0.0% 0.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, boost::capy::test_allocator<std::byte> >::run_awaitable(boost::capy::detail::run_awaitable<boost::capy::task<int>, false, boost::capy::test_allocator<std::byte> >&&) :465 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, std::pmr::memory_resource*>::run_awaitable(boost::capy::detail::run_awaitable<boost::capy::task<int>, false, std::pmr::memory_resource*>&&) :465 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, void>::run_awaitable(boost::capy::detail::run_awaitable<boost::capy::task<int>, false, void>&&) :465 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, boost::capy::test_allocator<std::byte> >::run_awaitable(boost::capy::detail::run_awaitable<boost::capy::task<int>, true, boost::capy::test_allocator<std::byte> >&&) :465 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, std::pmr::memory_resource*>::run_awaitable(boost::capy::detail::run_awaitable<boost::capy::task<int>, true, std::pmr::memory_resource*>&&) :465 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, false, void>::run_awaitable(boost::capy::detail::run_awaitable<boost::capy::task<void>, false, void>&&) :465 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, true, boost::capy::counting_allocator<std::byte> >::run_awaitable(boost::capy::detail::run_awaitable<boost::capy::task<void>, true, boost::capy::counting_allocator<std::byte> >&&) :465 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, true, std::pmr::memory_resource*>::run_awaitable(boost::capy::detail::run_awaitable<boost::capy::task<void>, true, std::pmr::memory_resource*>&&) :465 11x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, boost::capy::counting_allocator<std::byte> >::run_wrapper_ex(boost::capy::test_executor, boost::capy::counting_allocator<std::byte>) :488 1x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, boost::capy::test_allocator<std::byte> >::run_wrapper_ex(boost::capy::test_executor, boost::capy::test_allocator<std::byte>) :488 2x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, false, boost::capy::test_allocator<std::byte> >::run_wrapper_ex(boost::capy::test_executor, std::stop_token, boost::capy::test_allocator<std::byte>) :497 1x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, false, boost::capy::test_allocator<std::byte> >::~run_wrapper_ex() :510 1x 75.0% 80.0% boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, boost::capy::counting_allocator<std::byte> >::~run_wrapper_ex() :510 1x 75.0% 80.0% boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, boost::capy::test_allocator<std::byte> >::~run_wrapper_ex() :510 2x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, false, boost::capy::test_allocator<std::byte> >::operator()<boost::capy::task<int> >(boost::capy::task<int>) && :523 1x 100.0% 72.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, boost::capy::counting_allocator<std::byte> >::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :523 1x 100.0% 71.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, boost::capy::test_allocator<std::byte> >::operator()<boost::capy::task<int> >(boost::capy::task<int>) && :523 1x 100.0% 83.0% boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, std::pmr::memory_resource*>::run_wrapper_ex(boost::capy::test_executor, std::pmr::memory_resource*) :550 3x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::thread_pool::executor_type, true, std::pmr::memory_resource*>::run_wrapper_ex(boost::capy::thread_pool::executor_type, std::pmr::memory_resource*) :550 1x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, false, std::pmr::memory_resource*>::run_wrapper_ex(boost::capy::test_executor, std::stop_token, std::pmr::memory_resource*) :558 1x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, false, std::pmr::memory_resource*>::~run_wrapper_ex() :570 1x 75.0% 75.0% boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, std::pmr::memory_resource*>::~run_wrapper_ex() :570 3x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::thread_pool::executor_type, true, std::pmr::memory_resource*>::~run_wrapper_ex() :570 1x 75.0% 67.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, false, std::pmr::memory_resource*>::operator()<boost::capy::task<int> >(boost::capy::task<int>) && :583 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, std::pmr::memory_resource*>::operator()<boost::capy::task<int> >(boost::capy::task<int>) && :583 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, std::pmr::memory_resource*>::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :583 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::thread_pool::executor_type, true, std::pmr::memory_resource*>::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :583 1x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::closing_executor, true, void>::run_wrapper_ex(boost::capy::closing_executor) :605 1x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::run_test::throwing_post_executor, true, void>::run_wrapper_ex(boost::capy::run_test::throwing_post_executor) :605 1x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::strand<boost::capy::executor_ref>, true, void>::run_wrapper_ex(boost::capy::strand<boost::capy::executor_ref>) :605 1x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::run_wrapper_ex(boost::capy::strand<boost::capy::thread_pool::executor_type>) :605 2x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::test::priority_executor<boost::capy::queuing_executor>, true, void>::run_wrapper_ex(boost::capy::test::priority_executor<boost::capy::queuing_executor>) :605 2x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, void>::run_wrapper_ex(boost::capy::test_executor) :605 13x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::thread_pool::executor_type, true, void>::run_wrapper_ex(boost::capy::thread_pool::executor_type) :605 55x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, false, void>::run_wrapper_ex(boost::capy::test_executor, std::stop_token) :611 4x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::thread_pool::executor_type, false, void>::run_wrapper_ex(boost::capy::thread_pool::executor_type, std::stop_token) :611 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::closing_executor, true, void>::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :625 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::run_test::throwing_post_executor, true, void>::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :625 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::strand<boost::capy::executor_ref>, true, void>::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :625 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::operator()<boost::capy::task<int> >(boost::capy::task<int>) && :625 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::strand<boost::capy::thread_pool::executor_type>, true, void>::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :625 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test::priority_executor<boost::capy::queuing_executor>, true, void>::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :625 2x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, false, void>::operator()<boost::capy::task<bool> >(boost::capy::task<bool>) && :625 2x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, false, void>::operator()<boost::capy::task<int> >(boost::capy::task<int>) && :625 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, false, void>::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :625 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, void>::operator()<boost::capy::lax_task>(boost::capy::lax_task) && :625 0 0.0% 0.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, void>::operator()<boost::capy::task<bool> >(boost::capy::task<bool>) && :625 2x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, void>::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :625 9x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, void>::operator()<boost::capy::test::custom_task<int> >(boost::capy::test::custom_task<int>) && :625 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, void>::operator()<boost::capy::test::custom_task<void> >(boost::capy::test::custom_task<void>) && :625 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::thread_pool::executor_type, false, void>::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :625 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::thread_pool::executor_type, true, void>::operator()<boost::capy::task<int> >(boost::capy::task<int>) && :625 52x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::thread_pool::executor_type, true, void>::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :625 3x 100.0% 100.0% boost::capy::detail::run_wrapper<true, boost::capy::counting_allocator<std::byte> >::run_wrapper(boost::capy::counting_allocator<std::byte>) :653 1x 100.0% 100.0% boost::capy::detail::run_wrapper<true, boost::capy::test_allocator<std::byte> >::run_wrapper(boost::capy::test_allocator<std::byte>) :653 2x 100.0% 100.0% boost::capy::detail::run_wrapper<false, boost::capy::test_allocator<std::byte> >::run_wrapper(std::stop_token, boost::capy::test_allocator<std::byte>) :661 1x 100.0% 100.0% boost::capy::detail::run_wrapper<false, boost::capy::test_allocator<std::byte> >::~run_wrapper() :673 1x 75.0% 80.0% boost::capy::detail::run_wrapper<true, boost::capy::counting_allocator<std::byte> >::~run_wrapper() :673 1x 75.0% 80.0% boost::capy::detail::run_wrapper<true, boost::capy::test_allocator<std::byte> >::~run_wrapper() :673 2x 100.0% 100.0% auto boost::capy::detail::run_wrapper<false, boost::capy::test_allocator<std::byte> >::operator()<boost::capy::task<int> >(boost::capy::task<int>) && :686 1x 100.0% 71.0% auto boost::capy::detail::run_wrapper<true, boost::capy::counting_allocator<std::byte> >::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :686 1x 100.0% 69.0% auto boost::capy::detail::run_wrapper<true, boost::capy::test_allocator<std::byte> >::operator()<boost::capy::task<int> >(boost::capy::task<int>) && :686 1x 100.0% 82.0% boost::capy::detail::run_wrapper<true, std::pmr::memory_resource*>::run_wrapper(std::pmr::memory_resource*) :712 13x 100.0% 100.0% boost::capy::detail::run_wrapper<false, std::pmr::memory_resource*>::run_wrapper(std::stop_token, std::pmr::memory_resource*) :719 1x 100.0% 100.0% boost::capy::detail::run_wrapper<false, std::pmr::memory_resource*>::~run_wrapper() :730 1x 75.0% 75.0% boost::capy::detail::run_wrapper<true, std::pmr::memory_resource*>::~run_wrapper() :730 13x 100.0% 100.0% auto boost::capy::detail::run_wrapper<false, std::pmr::memory_resource*>::operator()<boost::capy::task<int> >(boost::capy::task<int>) && :743 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper<true, std::pmr::memory_resource*>::operator()<boost::capy::task<int> >(boost::capy::task<int>) && :743 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper<true, std::pmr::memory_resource*>::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :743 11x 100.0% 100.0% boost::capy::detail::run_wrapper<false, void>::run_wrapper(std::stop_token) :764 2x 100.0% 100.0% auto boost::capy::detail::run_wrapper<false, void>::operator()<boost::capy::lax_task>(boost::capy::lax_task) && :776 0 0.0% 0.0% auto boost::capy::detail::run_wrapper<false, void>::operator()<boost::capy::task<int> >(boost::capy::task<int>) && :776 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper<false, void>::operator()<boost::capy::task<void> >(boost::capy::task<void>) && :776 1x 100.0% 100.0% auto boost::capy::run<boost::capy::closing_executor>(boost::capy::closing_executor) :814 1x 100.0% 100.0% auto boost::capy::run<boost::capy::run_test::throwing_post_executor>(boost::capy::run_test::throwing_post_executor) :814 1x 100.0% 100.0% auto boost::capy::run<boost::capy::strand<boost::capy::executor_ref> >(boost::capy::strand<boost::capy::executor_ref>) :814 1x 100.0% 100.0% auto boost::capy::run<boost::capy::strand<boost::capy::thread_pool::executor_type> >(boost::capy::strand<boost::capy::thread_pool::executor_type>) :814 2x 100.0% 100.0% auto boost::capy::run<boost::capy::test_executor>(boost::capy::test_executor) :814 12x 100.0% 100.0% auto boost::capy::run<boost::capy::thread_pool::executor_type>(boost::capy::thread_pool::executor_type) :814 55x 100.0% 100.0% auto boost::capy::run<boost::capy::test_executor>(boost::capy::test_executor, std::stop_token) :830 4x 100.0% 100.0% auto boost::capy::run<boost::capy::thread_pool::executor_type>(boost::capy::thread_pool::executor_type, std::stop_token) :830 1x 100.0% 100.0% auto boost::capy::run<boost::capy::test_executor>(boost::capy::test_executor, std::pmr::memory_resource*) :847 3x 100.0% 100.0% auto boost::capy::run<boost::capy::thread_pool::executor_type>(boost::capy::thread_pool::executor_type, std::pmr::memory_resource*) :847 1x 100.0% 100.0% auto boost::capy::run<boost::capy::test_executor, boost::capy::counting_allocator<std::byte> >(boost::capy::test_executor, boost::capy::counting_allocator<std::byte>) :868 1x 100.0% 80.0% auto boost::capy::run<boost::capy::test_executor, boost::capy::test_allocator<std::byte> >(boost::capy::test_executor, boost::capy::test_allocator<std::byte>) :868 2x 100.0% 100.0% auto boost::capy::run<boost::capy::test_executor>(boost::capy::test_executor, std::stop_token, std::pmr::memory_resource*) :886 1x 100.0% 100.0% auto boost::capy::run<boost::capy::test_executor, boost::capy::test_allocator<std::byte> >(boost::capy::test_executor, std::stop_token, boost::capy::test_allocator<std::byte>) :908 1x 100.0% 82.0% boost::capy::run(std::stop_token) :928 2x 100.0% 100.0% boost::capy::run(std::pmr::memory_resource*) :943 13x 100.0% 100.0% auto boost::capy::run<boost::capy::counting_allocator<std::byte> >(boost::capy::counting_allocator<std::byte>) :971 1x 100.0% 78.0% auto boost::capy::run<boost::capy::test_allocator<std::byte> >(boost::capy::test_allocator<std::byte>) :971 2x 100.0% 100.0% boost::capy::run(std::stop_token, std::pmr::memory_resource*) :986 1x 100.0% 100.0% auto boost::capy::run<boost::capy::test_allocator<std::byte> >(std::stop_token, boost::capy::test_allocator<std::byte>) :1007 1x 100.0% 80.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/capy
8 //
9
10 #ifndef BOOST_CAPY_RUN_HPP
11 #define BOOST_CAPY_RUN_HPP
12
13 #include <boost/capy/detail/config.hpp>
14 #include <boost/capy/detail/await_suspend_helper.hpp>
15 #include <boost/capy/detail/run.hpp>
16 #include <boost/capy/concept/executor.hpp>
17 #include <boost/capy/concept/context_runnable.hpp>
18 #include <boost/capy/ex/abandon.hpp>
19 #include <boost/capy/ex/executor_ref.hpp>
20 #include <coroutine>
21 #include <boost/capy/ex/frame_alloc_mixin.hpp>
22 #include <boost/capy/ex/frame_allocator.hpp>
23 #include <boost/capy/ex/await_context.hpp>
24
25 #include <exception>
26 #include <memory_resource>
27 #include <stop_token>
28 #include <type_traits>
29 #include <utility>
30 #include <variant>
31
32 /*
33 Allocator Lifetime Strategy
34 ===========================
35
36 When using run() with a custom allocator:
37
38 co_await run(ex, alloc)(my_task());
39
40 The wrapper run(ex, alloc) returns is a temporary holding the
41 frame_memory_resource my_task()'s frame is allocated from, so it must
42 live until that frame is freed: the awaitable is awaited in the
43 full-expression that made the wrapper, and the temporary lives until
44 the co_await completes. Keeping the awaitable and awaiting it later
45 frees the task's frame through a dead resource.
46
47 The awaitable also holds a copy of the allocator. In await_suspend it
48 overwrites the promise's saved frame_allocator pointer with the
49 awaitable's resource, so tasks the inner task creates allocate from
50 it through TLS.
51 */
52
53 namespace boost::capy::detail {
54
55 /** Minimal coroutine that dispatches through the caller's executor.
56
57 Sits between the inner task and the parent when executors
58 diverge. The inner task's `final_suspend` resumes this
59 trampoline via symmetric transfer. The trampoline's own
60 `final_suspend` posts the parent through the caller's executor to
61 restore the correct execution context.
62
63 It also owns the inner task's segment. Abandoning that segment
64 resumes the trampoline on the inner executor, or has a closed
65 executor destroy it: either way it destroys the inner task, which
66 unwinds the segment, then abandons the caller's segment, which
67 unwinds the parent on its own executor. The caller's execution
68 context must outlive that.
69 */
70 struct boundary_trampoline
71 {
72 struct promise_type
73 : detail::process_frame_mixin
74 {
75 executor_ref caller_ex_;
76 continuation parent_;
77 chain_owner segment_;
78 // The awaitable's trampoline object until the inner task
79 // completes or is unwound; null afterward.
80 boundary_trampoline* owner_ = nullptr;
81 // Destroys the inner task the awaitable owns.
82 void (*destroy_inner_)(void*) noexcept = nullptr;
83 void* awaitable_ = nullptr;
84
85 // Unwind the inner segment, then hand the parent to its own
86 // segment's owner. The last touch of this frame: abandoning the
87 // parent can destroy the awaitable, and this frame with it.
88 10x void unwind() noexcept
89 {
90 10x destroy_inner_(awaitable_);
91 10x owner_ = nullptr;
92 10x auto parent = parent_;
93 10x capy::abandon(parent);
94 10x }
95
96 87x ~promise_type()
97 {
98 // Linked only when a closed executor destroyed this frame
99 // instead of resuming it to unwind.
100 87x if(owner_)
101 {
102 1x owner_->h_ = nullptr;
103 1x unwind();
104 }
105 87x }
106
107 87x boundary_trampoline get_return_object() noexcept
108 {
109 return boundary_trampoline{
110 87x std::coroutine_handle<promise_type>::from_promise(*this)};
111 }
112
113 87x std::suspend_always initial_suspend() noexcept { return {}; }
114
115 85x auto final_suspend() noexcept
116 {
117 struct awaiter
118 {
119 promise_type* p_;
120 85x bool await_ready() const noexcept { return false; }
121
122 85x auto await_suspend(
123 std::coroutine_handle<>) noexcept
124 {
125 // Nothing here touches p_ after the post or the
126 // unwind: either can destroy this frame.
127 85x if(p_->segment_.abandoned())
128 {
129 9x p_->unwind();
130 }
131 else
132 {
133 76x p_->owner_ = nullptr;
134 76x auto ex = p_->caller_ex_;
135 76x ex.post(p_->parent_);
136 }
137 85x return detail::symmetric_transfer(
138 170x std::noop_coroutine());
139 }
140
141 − void await_resume() const noexcept {} // LCOV_EXCL_LINE final_suspend awaiter, never resumed
142 };
143 85x return awaiter{this};
144 }
145
146 85x void return_void() noexcept {}
147 void unhandled_exception() noexcept {}
148 };
149
150 std::coroutine_handle<promise_type> h_{nullptr};
151
152 88x boundary_trampoline() noexcept = default;
153
154 261x ~boundary_trampoline()
155 {
156 261x if(h_)
157 {
158 85x h_.promise().owner_ = nullptr;
159 85x h_.destroy();
160 }
161 261x }
162
163 boundary_trampoline(boundary_trampoline const&) = delete;
164 boundary_trampoline& operator=(boundary_trampoline const&) = delete;
165
166 86x boundary_trampoline(boundary_trampoline&& o) noexcept
167 86x : h_(std::exchange(o.h_, nullptr)) {}
168
169 88x boundary_trampoline& operator=(boundary_trampoline&& o) noexcept
170 {
171 88x if(this != &o)
172 {
173 88x if(h_)
174 {
175 1x h_.promise().owner_ = nullptr;
176 1x h_.destroy();
177 }
178 88x h_ = std::exchange(o.h_, nullptr);
179 }
180 88x return *this;
181 }
182
183 private:
184 87x explicit boundary_trampoline(std::coroutine_handle<promise_type> h) noexcept
185 87x : h_(h) {}
186 };
187
188 87x inline boundary_trampoline make_boundary_trampoline()
189 {
190 co_return;
191 174x }
192
193 /** Awaitable that binds a ContextRunnable to a specific executor.
194
195 Stores the executor and inner task by value. When co_awaited, the
196 co_await expression's lifetime extension keeps both alive for the
197 duration of the operation.
198
199 A dispatch trampoline handles the executor switch on completion:
200 the inner task's `final_suspend` resumes the trampoline, which
201 dispatches back through the caller's executor.
202
203 The `await_context` is owned by this awaitable and is guaranteed to
204 outlive the inner task and all awaitables in its chain. Awaitables
205 may store `await_context const*` without concern for dangling references.
206
207 @tparam Task The ContextRunnable type
208 @tparam Ex The executor type
209 @tparam InheritStopToken If true, inherit caller's stop token
210 @tparam Alloc The allocator type (void for no allocator)
211 */
212 template<ContextRunnable Task, Executor Ex, bool InheritStopToken, class Alloc = void>
213 struct [[nodiscard]] run_awaitable_ex
214 {
215 Ex ex_;
216 frame_memory_resource<Alloc> resource_;
217 std::conditional_t<InheritStopToken, std::monostate, std::stop_token> st_;
218 await_context env_;
219 executor_ref caller_ex_;
220 boundary_trampoline tr_;
221 continuation task_cont_;
222 bool holds_work_ = false;
223 Task inner_; // Last: destroyed first, while env_ is still valid
224
225 173x ~run_awaitable_ex()
226 {
227 // Only a parent destroyed from above leaves the trampoline
228 // still linked: the inner task is still running.
229 173x if(tr_.h_ && tr_.h_.promise().owner_)
230 − std::terminate(); // LCOV_EXCL_LINE reached only in a death test's child process
231 // A parent unwound instead of resumed never reaches
232 // await_resume.
233 173x if(holds_work_)
234 11x caller_ex_.on_work_finished();
235 173x }
236
237 // Called by the trampoline to unwind the inner segment.
238 10x static void destroy_inner(void* p) noexcept
239 {
240 10x auto& self = *static_cast<run_awaitable_ex*>(p);
241 10x auto h = self.inner_.handle();
242 10x self.inner_.release();
243 10x h.destroy();
244 10x }
245
246 // void allocator, inherit stop token
247 75x run_awaitable_ex(Ex ex, Task inner)
248 requires (InheritStopToken && std::is_void_v<Alloc>)
249 75x : ex_(std::move(ex))
250 75x , inner_(std::move(inner))
251 {
252 75x }
253
254 // void allocator, explicit stop token
255 5x run_awaitable_ex(Ex ex, Task inner, std::stop_token st)
256 requires (!InheritStopToken && std::is_void_v<Alloc>)
257 5x : ex_(std::move(ex))
258 5x , st_(std::move(st))
259 5x , inner_(std::move(inner))
260 {
261 5x }
262
263 // with allocator, inherit stop token (use template to avoid void parameter)
264 template<class A>
265 requires (InheritStopToken && !std::is_void_v<Alloc> && std::same_as<A, Alloc>)
266 5x run_awaitable_ex(Ex ex, A alloc, Task inner)
267 5x : ex_(std::move(ex))
268 5x , resource_(std::move(alloc))
269 5x , inner_(std::move(inner))
270 {
271 5x }
272
273 // with allocator, explicit stop token (use template to avoid void parameter)
274 template<class A>
275 requires (!InheritStopToken && !std::is_void_v<Alloc> && std::same_as<A, Alloc>)
276 2x run_awaitable_ex(Ex ex, A alloc, Task inner, std::stop_token st)
277 2x : ex_(std::move(ex))
278 2x , resource_(std::move(alloc))
279 2x , st_(std::move(st))
280 2x , inner_(std::move(inner))
281 {
282 2x }
283
284 86x bool await_ready() const noexcept
285 {
286 86x return inner_.await_ready();
287 }
288
289 75x decltype(auto) await_resume()
290 {
291 75x if(std::exchange(holds_work_, false))
292 75x caller_ex_.on_work_finished();
293 75x return inner_.await_resume();
294 }
295
296 87x std::coroutine_handle<> await_suspend(std::coroutine_handle<> cont, await_context const* caller_env)
297 {
298 87x tr_ = make_boundary_trampoline();
299 87x auto& tp = tr_.h_.promise();
300 87x tp.owner_ = &tr_;
301 87x tp.caller_ex_ = caller_env->executor;
302 87x tp.parent_.h = cont;
303 87x tp.parent_.owner = caller_env->owner;
304 87x tp.destroy_inner_ = &run_awaitable_ex::destroy_inner;
305 87x tp.awaitable_ = this;
306 87x tp.segment_.bind(tr_.h_, ex_);
307 87x caller_ex_ = caller_env->executor;
308 // Released once the parent resumes or is unwound. Not on the
309 // post back: the parent's chain may own the executor object and
310 // can be gone by the time post returns.
311 87x caller_ex_.on_work_started();
312 87x holds_work_ = true;
313
314 87x auto h = inner_.handle();
315 87x auto& p = h.promise();
316 87x p.set_continuation(tr_.h_);
317
318 87x env_.owner = &tp.segment_;
319 87x env_.executor = ex_;
320 if constexpr (InheritStopToken)
321 80x env_.stop_token = caller_env->stop_token;
322 else
323 7x env_.stop_token = st_;
324
325 if constexpr (!std::is_void_v<Alloc>)
326 7x env_.frame_allocator = resource_.get();
327 else
328 80x env_.frame_allocator = caller_env->frame_allocator;
329
330 87x p.set_environment(&env_);
331 87x task_cont_.h = h;
332 87x task_cont_.owner = &tp.segment_;
333 try
334 {
335 87x ex_.post(task_cont_);
336 }
337 2x catch(...)
338 {
339 // The parent resumes with the exception: nothing may still
340 // treat the task as lent or hold work for the parent.
341 1x p.set_continuation(std::noop_coroutine());
342 1x task_cont_.h = nullptr;
343 1x tr_ = boundary_trampoline();
344 1x holds_work_ = false;
345 1x caller_ex_.on_work_finished();
346 1x throw;
347 }
348 86x return std::noop_coroutine();
349 }
350
351 // Non-copyable
352 run_awaitable_ex(run_awaitable_ex const&) = delete;
353 run_awaitable_ex& operator=(run_awaitable_ex const&) = delete;
354
355 // Movable (no noexcept - Task may throw)
356 86x run_awaitable_ex(run_awaitable_ex&&) = default;
357 run_awaitable_ex& operator=(run_awaitable_ex&&) = default;
358 };
359
360 /** Awaitable that runs a task with optional stop_token override.
361
362 Does NOT store an executor - the task inherits the caller's executor
363 directly. Executors always match, so no dispatch trampoline is needed.
364 The inner task's `final_suspend` resumes the parent directly via
365 unconditional symmetric transfer.
366
367 @tparam Task The ContextRunnable type
368 @tparam InheritStopToken If true, inherit caller's stop token
369 @tparam Alloc The allocator type (void for no allocator)
370 */
371 template<ContextRunnable Task, bool InheritStopToken, class Alloc = void>
372 struct [[nodiscard]] run_awaitable
373 {
374 frame_memory_resource<Alloc> resource_;
375 std::conditional_t<InheritStopToken, std::monostate, std::stop_token> st_;
376 await_context env_;
377 // Set while the parent is suspended awaiting the inner task.
378 bool lent_ = false;
379 Task inner_; // Last: destroyed first, while env_ is still valid
380
381 36x ~run_awaitable()
382 {
383 // Only the unwind of an abandoned chain destroys an inner task
384 // still awaited; checked here so it terminates whatever the
385 // task type does when destroyed while lent.
386 36x auto h = inner_.handle();
387 46x if(lent_ && h && !h.done() &&
388 10x !(env_.owner && env_.owner->abandoned()))
389 − std::terminate(); // LCOV_EXCL_LINE reached only in a death test's child process
390 36x }
391
392 // void allocator, inherit stop token
393 explicit run_awaitable(Task inner)
394 requires (InheritStopToken && std::is_void_v<Alloc>)
395 : inner_(std::move(inner))
396 {
397 }
398
399 // void allocator, explicit stop token
400 2x run_awaitable(Task inner, std::stop_token st)
401 requires (!InheritStopToken && std::is_void_v<Alloc>)
402 2x : st_(std::move(st))
403 2x , inner_(std::move(inner))
404 {
405 2x }
406
407 // with allocator, inherit stop token (use template to avoid void parameter)
408 template<class A>
409 requires (InheritStopToken && !std::is_void_v<Alloc> && std::same_as<A, Alloc>)
410 14x run_awaitable(A alloc, Task inner)
411 14x : resource_(std::move(alloc))
412 14x , inner_(std::move(inner))
413 {
414 14x }
415
416 // with allocator, explicit stop token (use template to avoid void parameter)
417 template<class A>
418 requires (!InheritStopToken && !std::is_void_v<Alloc> && std::same_as<A, Alloc>)
419 2x run_awaitable(A alloc, Task inner, std::stop_token st)
420 2x : resource_(std::move(alloc))
421 2x , st_(std::move(st))
422 2x , inner_(std::move(inner))
423 {
424 2x }
425
426 18x bool await_ready() const noexcept
427 {
428 18x return inner_.await_ready();
429 }
430
431 8x decltype(auto) await_resume()
432 {
433 8x lent_ = false;
434 8x return inner_.await_resume();
435 }
436
437 18x std::coroutine_handle<> await_suspend(std::coroutine_handle<> cont, await_context const* caller_env)
438 {
439 18x auto h = inner_.handle();
440 18x auto& p = h.promise();
441 18x p.set_continuation(cont);
442 18x lent_ = true;
443
444 18x env_.owner = caller_env->owner;
445 18x env_.executor = caller_env->executor;
446 if constexpr (InheritStopToken)
447 14x env_.stop_token = caller_env->stop_token;
448 else
449 4x env_.stop_token = st_;
450
451 if constexpr (!std::is_void_v<Alloc>)
452 16x env_.frame_allocator = resource_.get();
453 else
454 2x env_.frame_allocator = caller_env->frame_allocator;
455
456 18x p.set_environment(&env_);
457 18x return h;
458 }
459
460 // Non-copyable
461 run_awaitable(run_awaitable const&) = delete;
462 run_awaitable& operator=(run_awaitable const&) = delete;
463
464 // Movable (no noexcept - Task may throw)
465 18x run_awaitable(run_awaitable&&) = default;
466 run_awaitable& operator=(run_awaitable&&) = default;
467 };
468
469 /** Wrapper returned by run(ex, ...) that accepts a task for execution.
470
471 @tparam Ex The executor type.
472 @tparam InheritStopToken If true, inherit caller's stop token.
473 @tparam Alloc The allocator type (void for no allocator).
474 */
475 template<Executor Ex, bool InheritStopToken, class Alloc>
476 class [[nodiscard]] run_wrapper_ex
477 {
478 Ex ex_;
479 std::conditional_t<InheritStopToken, std::monostate, std::stop_token> st_;
480 frame_memory_resource<Alloc> resource_;
481 Alloc alloc_; // Copy to pass to awaitable
482
483 std::pmr::memory_resource* saved_tls_ =
484 get_current_frame_allocator();
485 bool restored_ = false;
486
487 public:
488 3x run_wrapper_ex(Ex ex, Alloc alloc)
489 requires InheritStopToken
490 3x : ex_(std::move(ex))
491 3x , resource_(alloc)
492 3x , alloc_(std::move(alloc))
493 {
494 3x set_current_frame_allocator(&resource_);
495 3x }
496
497 1x run_wrapper_ex(Ex ex, std::stop_token st, Alloc alloc)
498 requires (!InheritStopToken)
499 1x : ex_(std::move(ex))
500 1x , st_(std::move(st))
501 1x , resource_(alloc)
502 1x , alloc_(std::move(alloc))
503 {
504 1x set_current_frame_allocator(&resource_);
505 1x }
506
507 // Restores the caller's allocator when evaluating the task argument
508 // threw. Not afterwards: a wrapper destroyed with a torn-down parent
509 // frame must not touch the tearing thread's allocator.
510 4x ~run_wrapper_ex()
511 {
512 4x if(!restored_)
513 1x set_current_frame_allocator(saved_tls_);
514 4x }
515
516 // Non-copyable, non-movable (must be used immediately)
517 run_wrapper_ex(run_wrapper_ex const&) = delete;
518 run_wrapper_ex(run_wrapper_ex&&) = delete;
519 run_wrapper_ex& operator=(run_wrapper_ex const&) = delete;
520 run_wrapper_ex& operator=(run_wrapper_ex&&) = delete;
521
522 template<ContextRunnable Task>
523 3x [[nodiscard]] auto operator()(Task t) &&
524 {
525 // The task's frame is made; the caller's own frames are not.
526 3x set_current_frame_allocator(saved_tls_);
527 3x restored_ = true;
528 if constexpr (InheritStopToken)
529 return run_awaitable_ex<Task, Ex, true, Alloc>{
530 2x std::move(ex_), std::move(alloc_), std::move(t)};
531 else
532 return run_awaitable_ex<Task, Ex, false, Alloc>{
533 1x std::move(ex_), std::move(alloc_), std::move(t), std::move(st_)};
534 }
535 };
536
537 /// Specialization for memory_resource* - stores pointer directly.
538 template<Executor Ex, bool InheritStopToken>
539 class [[nodiscard]] run_wrapper_ex<Ex, InheritStopToken, std::pmr::memory_resource*>
540 {
541 Ex ex_;
542 std::conditional_t<InheritStopToken, std::monostate, std::stop_token> st_;
543 std::pmr::memory_resource* mr_;
544
545 std::pmr::memory_resource* saved_tls_ =
546 get_current_frame_allocator();
547 bool restored_ = false;
548
549 public:
550 4x run_wrapper_ex(Ex ex, std::pmr::memory_resource* mr)
551 requires InheritStopToken
552 4x : ex_(std::move(ex))
553 4x , mr_(mr)
554 {
555 4x set_current_frame_allocator(mr_);
556 4x }
557
558 1x run_wrapper_ex(Ex ex, std::stop_token st, std::pmr::memory_resource* mr)
559 requires (!InheritStopToken)
560 1x : ex_(std::move(ex))
561 1x , st_(std::move(st))
562 1x , mr_(mr)
563 {
564 1x set_current_frame_allocator(mr_);
565 1x }
566
567 // Restores the caller's allocator when evaluating the task argument
568 // threw. Not afterwards: a wrapper destroyed with a torn-down parent
569 // frame must not touch the tearing thread's allocator.
570 5x ~run_wrapper_ex()
571 {
572 5x if(!restored_)
573 1x set_current_frame_allocator(saved_tls_);
574 5x }
575
576 // Non-copyable, non-movable (must be used immediately)
577 run_wrapper_ex(run_wrapper_ex const&) = delete;
578 run_wrapper_ex(run_wrapper_ex&&) = delete;
579 run_wrapper_ex& operator=(run_wrapper_ex const&) = delete;
580 run_wrapper_ex& operator=(run_wrapper_ex&&) = delete;
581
582 template<ContextRunnable Task>
583 4x [[nodiscard]] auto operator()(Task t) &&
584 {
585 // The task's frame is made; the caller's own frames are not.
586 4x set_current_frame_allocator(saved_tls_);
587 4x restored_ = true;
588 if constexpr (InheritStopToken)
589 return run_awaitable_ex<Task, Ex, true, std::pmr::memory_resource*>{
590 3x std::move(ex_), mr_, std::move(t)};
591 else
592 return run_awaitable_ex<Task, Ex, false, std::pmr::memory_resource*>{
593 1x std::move(ex_), mr_, std::move(t), std::move(st_)};
594 }
595 };
596
597 /// Specialization for no allocator (void).
598 template<Executor Ex, bool InheritStopToken>
599 class [[nodiscard]] run_wrapper_ex<Ex, InheritStopToken, void>
600 {
601 Ex ex_;
602 std::conditional_t<InheritStopToken, std::monostate, std::stop_token> st_;
603
604 public:
605 75x explicit run_wrapper_ex(Ex ex)
606 requires InheritStopToken
607 75x : ex_(std::move(ex))
608 {
609 75x }
610
611 5x run_wrapper_ex(Ex ex, std::stop_token st)
612 requires (!InheritStopToken)
613 5x : ex_(std::move(ex))
614 5x , st_(std::move(st))
615 {
616 5x }
617
618 // Non-copyable, non-movable (must be used immediately)
619 run_wrapper_ex(run_wrapper_ex const&) = delete;
620 run_wrapper_ex(run_wrapper_ex&&) = delete;
621 run_wrapper_ex& operator=(run_wrapper_ex const&) = delete;
622 run_wrapper_ex& operator=(run_wrapper_ex&&) = delete;
623
624 template<ContextRunnable Task>
625 80x [[nodiscard]] auto operator()(Task t) &&
626 {
627 if constexpr (InheritStopToken)
628 return run_awaitable_ex<Task, Ex, true>{
629 75x std::move(ex_), std::move(t)};
630 else
631 return run_awaitable_ex<Task, Ex, false>{
632 5x std::move(ex_), std::move(t), std::move(st_)};
633 }
634 };
635
636 /** Wrapper returned by run(st) or run(alloc) that accepts a task.
637
638 @tparam InheritStopToken If true, inherit caller's stop token.
639 @tparam Alloc The allocator type (void for no allocator).
640 */
641 template<bool InheritStopToken, class Alloc>
642 class [[nodiscard]] run_wrapper
643 {
644 std::conditional_t<InheritStopToken, std::monostate, std::stop_token> st_;
645 frame_memory_resource<Alloc> resource_;
646 Alloc alloc_; // Copy to pass to awaitable
647
648 std::pmr::memory_resource* saved_tls_ =
649 get_current_frame_allocator();
650 bool restored_ = false;
651
652 public:
653 3x explicit run_wrapper(Alloc alloc)
654 requires InheritStopToken
655 3x : resource_(alloc)
656 3x , alloc_(std::move(alloc))
657 {
658 3x set_current_frame_allocator(&resource_);
659 3x }
660
661 1x run_wrapper(std::stop_token st, Alloc alloc)
662 requires (!InheritStopToken)
663 1x : st_(std::move(st))
664 1x , resource_(alloc)
665 1x , alloc_(std::move(alloc))
666 {
667 1x set_current_frame_allocator(&resource_);
668 1x }
669
670 // Restores the caller's allocator when evaluating the task argument
671 // threw. Not afterwards: a wrapper destroyed with a torn-down parent
672 // frame must not touch the tearing thread's allocator.
673 4x ~run_wrapper()
674 {
675 4x if(!restored_)
676 1x set_current_frame_allocator(saved_tls_);
677 4x }
678
679 // Non-copyable, non-movable (must be used immediately)
680 run_wrapper(run_wrapper const&) = delete;
681 run_wrapper(run_wrapper&&) = delete;
682 run_wrapper& operator=(run_wrapper const&) = delete;
683 run_wrapper& operator=(run_wrapper&&) = delete;
684
685 template<ContextRunnable Task>
686 3x [[nodiscard]] auto operator()(Task t) &&
687 {
688 // The task's frame is made; the caller's own frames are not.
689 3x set_current_frame_allocator(saved_tls_);
690 3x restored_ = true;
691 if constexpr (InheritStopToken)
692 return run_awaitable<Task, true, Alloc>{
693 2x std::move(alloc_), std::move(t)};
694 else
695 return run_awaitable<Task, false, Alloc>{
696 1x std::move(alloc_), std::move(t), std::move(st_)};
697 }
698 };
699
700 /// Specialization for memory_resource* - stores pointer directly.
701 template<bool InheritStopToken>
702 class [[nodiscard]] run_wrapper<InheritStopToken, std::pmr::memory_resource*>
703 {
704 std::conditional_t<InheritStopToken, std::monostate, std::stop_token> st_;
705 std::pmr::memory_resource* mr_;
706
707 std::pmr::memory_resource* saved_tls_ =
708 get_current_frame_allocator();
709 bool restored_ = false;
710
711 public:
712 13x explicit run_wrapper(std::pmr::memory_resource* mr)
713 requires InheritStopToken
714 13x : mr_(mr)
715 {
716 13x set_current_frame_allocator(mr_);
717 13x }
718
719 1x run_wrapper(std::stop_token st, std::pmr::memory_resource* mr)
720 requires (!InheritStopToken)
721 1x : st_(std::move(st))
722 1x , mr_(mr)
723 {
724 1x set_current_frame_allocator(mr_);
725 1x }
726
727 // Restores the caller's allocator when evaluating the task argument
728 // threw. Not afterwards: a wrapper destroyed with a torn-down parent
729 // frame must not touch the tearing thread's allocator.
730 14x ~run_wrapper()
731 {
732 14x if(!restored_)
733 1x set_current_frame_allocator(saved_tls_);
734 14x }
735
736 // Non-copyable, non-movable (must be used immediately)
737 run_wrapper(run_wrapper const&) = delete;
738 run_wrapper(run_wrapper&&) = delete;
739 run_wrapper& operator=(run_wrapper const&) = delete;
740 run_wrapper& operator=(run_wrapper&&) = delete;
741
742 template<ContextRunnable Task>
743 13x [[nodiscard]] auto operator()(Task t) &&
744 {
745 // The task's frame is made; the caller's own frames are not.
746 13x set_current_frame_allocator(saved_tls_);
747 13x restored_ = true;
748 if constexpr (InheritStopToken)
749 return run_awaitable<Task, true, std::pmr::memory_resource*>{
750 12x mr_, std::move(t)};
751 else
752 return run_awaitable<Task, false, std::pmr::memory_resource*>{
753 1x mr_, std::move(t), std::move(st_)};
754 }
755 };
756
757 /// Specialization for stop_token only (no allocator).
758 template<>
759 class [[nodiscard]] run_wrapper<false, void>
760 {
761 std::stop_token st_;
762
763 public:
764 2x explicit run_wrapper(std::stop_token st)
765 2x : st_(std::move(st))
766 {
767 2x }
768
769 // Non-copyable, non-movable (must be used immediately)
770 run_wrapper(run_wrapper const&) = delete;
771 run_wrapper(run_wrapper&&) = delete;
772 run_wrapper& operator=(run_wrapper const&) = delete;
773 run_wrapper& operator=(run_wrapper&&) = delete;
774
775 template<ContextRunnable Task>
776 2x [[nodiscard]] auto operator()(Task t) &&
777 {
778 2x return run_awaitable<Task, false, void>{std::move(t), std::move(st_)};
779 }
780 };
781
782 } // namespace boost::capy::detail
783
784 namespace boost::capy {
785
786 /** Bind a task to execute on a specific executor.
787
788 Returns a wrapper that accepts a task and produces an awaitable.
789 When co_awaited, the task runs on the specified executor.
790
791 If the inner task is abandoned before it completes, for example
792 because its execution context is torn down, the caller's chain is
793 abandoned too: it is unwound by its owner, on the owner's executor,
794 without the caller resuming. The awaitable holds work on the
795 caller's executor until the caller resumes or is unwound.
796
797 @par Preconditions
798 The caller's execution context outlives the inner task and the
799 unwind of the caller's chain. This is not detected.
800
801 @par Example
802 @par !example example_2
803
804
805 @param ex The executor on which the task should run.
806
807 @return A wrapper that accepts a task for execution.
808
809 @see task
810 @see Executor
811 */
812 template<Executor Ex>
813 [[nodiscard]] auto
814 75x run(Ex ex)
815 {
816 75x return detail::run_wrapper_ex<Ex, true, void>{std::move(ex)};
817 }
818
819 /** Bind a task to an executor with a stop token.
820
821 @param ex The executor on which the task should run.
822 @param st The stop token for cooperative cancellation.
823
824 @return A wrapper that accepts a task for execution.
825
826 @see run(Ex), which describes teardown and its precondition.
827 */
828 template<Executor Ex>
829 [[nodiscard]] auto
830 5x run(Ex ex, std::stop_token st)
831 {
832 return detail::run_wrapper_ex<Ex, false, void>{
833 5x std::move(ex), std::move(st)};
834 }
835
836 /** Bind a task to an executor with a memory resource.
837
838 @param ex The executor on which the task should run.
839 @param mr The memory resource for frame allocation.
840
841 @return A wrapper that accepts a task for execution.
842
843 @see run(Ex), which describes teardown and its precondition.
844 */
845 template<Executor Ex>
846 [[nodiscard]] auto
847 4x run(Ex ex, std::pmr::memory_resource* mr)
848 {
849 return detail::run_wrapper_ex<Ex, true, std::pmr::memory_resource*>{
850 4x std::move(ex), mr};
851 }
852
853 /** Bind a task to an executor with a standard allocator.
854
855 Await the awaitable in the expression that creates it, as in
856 `co_await run(ex, alloc)(task())`: the task's frame is allocated from
857 memory the wrapper holds until the end of that expression.
858
859 @param ex The executor on which the task should run.
860 @param alloc The allocator for frame allocation.
861
862 @return A wrapper that accepts a task for execution.
863
864 @see run(Ex), which describes teardown and its precondition.
865 */
866 template<Executor Ex, detail::Allocator Alloc>
867 [[nodiscard]] auto
868 3x run(Ex ex, Alloc alloc)
869 {
870 return detail::run_wrapper_ex<Ex, true, Alloc>{
871 3x std::move(ex), std::move(alloc)};
872 }
873
874 /** Bind a task to an executor with stop token and memory resource.
875
876 @param ex The executor on which the task should run.
877 @param st The stop token for cooperative cancellation.
878 @param mr The memory resource for frame allocation.
879
880 @return A wrapper that accepts a task for execution.
881
882 @see run(Ex), which describes teardown and its precondition.
883 */
884 template<Executor Ex>
885 [[nodiscard]] auto
886 1x run(Ex ex, std::stop_token st, std::pmr::memory_resource* mr)
887 {
888 return detail::run_wrapper_ex<Ex, false, std::pmr::memory_resource*>{
889 1x std::move(ex), std::move(st), mr};
890 }
891
892 /** Bind a task to an executor with stop token and standard allocator.
893
894 Await the awaitable in the expression that creates it, as in
895 `co_await run(ex, alloc)(task())`: the task's frame is allocated from
896 memory the wrapper holds until the end of that expression.
897
898 @param ex The executor on which the task should run.
899 @param st The stop token for cooperative cancellation.
900 @param alloc The allocator for frame allocation.
901
902 @return A wrapper that accepts a task for execution.
903
904 @see run(Ex), which describes teardown and its precondition.
905 */
906 template<Executor Ex, detail::Allocator Alloc>
907 [[nodiscard]] auto
908 1x run(Ex ex, std::stop_token st, Alloc alloc)
909 {
910 return detail::run_wrapper_ex<Ex, false, Alloc>{
911 1x std::move(ex), std::move(st), std::move(alloc)};
912 }
913
914 /** Run a task with a custom stop token.
915
916 The task inherits the caller's executor. Only the stop token
917 is overridden.
918
919 @par Example
920 @par !example example_1
921
922
923 @param st The stop token for cooperative cancellation.
924
925 @return A wrapper that accepts a task for execution.
926 */
927 [[nodiscard]] inline auto
928 2x run(std::stop_token st)
929 {
930 2x return detail::run_wrapper<false, void>{std::move(st)};
931 }
932
933 /** Run a task with a custom memory resource.
934
935 The task inherits the caller's executor. The memory resource
936 is used for nested frame allocations.
937
938 @param mr The memory resource for frame allocation.
939
940 @return A wrapper that accepts a task for execution.
941 */
942 [[nodiscard]] inline auto
943 13x run(std::pmr::memory_resource* mr)
944 {
945 13x return detail::run_wrapper<true, std::pmr::memory_resource*>{mr};
946 }
947
948 // MrDocs 0.8.0 reports `run: Documented parameter 'alloc' does not exist` and
949 // pins it to the run(Ex) overload near the top of this namespace:
950 // `detail::Allocator` is implementation-defined, so the constraint is erased
951 // and the two single-parameter `run` overloads collapse onto one page. The
952 // finding is grandfathered in doc/lint/baseline.json. Deleting the `@param
953 // alloc` below clears it and produces no replacement finding, because MrDocs
954 // has no model of this overload at all -- so it would silently drop real
955 // documentation. Keep the `@param`.
956 /** Run a task with a custom standard allocator.
957
958 Await the awaitable in the expression that creates it, as in
959 `co_await run(alloc)(task())`: the task's frame is allocated from
960 memory the wrapper holds until the end of that expression.
961
962 The task inherits the caller's executor. The allocator is used
963 for nested frame allocations.
964
965 @param alloc The allocator for frame allocation.
966
967 @return A wrapper that accepts a task for execution.
968 */
969 template<detail::Allocator Alloc>
970 [[nodiscard]] auto
971 3x run(Alloc alloc)
972 {
973 3x return detail::run_wrapper<true, Alloc>{std::move(alloc)};
974 }
975
976 /** Run a task with stop token and memory resource.
977
978 The task inherits the caller's executor.
979
980 @param st The stop token for cooperative cancellation.
981 @param mr The memory resource for frame allocation.
982
983 @return A wrapper that accepts a task for execution.
984 */
985 [[nodiscard]] inline auto
986 1x run(std::stop_token st, std::pmr::memory_resource* mr)
987 {
988 return detail::run_wrapper<false, std::pmr::memory_resource*>{
989 1x std::move(st), mr};
990 }
991
992 /** Run a task with stop token and standard allocator.
993
994 Await the awaitable in the expression that creates it, as in
995 `co_await run(alloc)(task())`: the task's frame is allocated from
996 memory the wrapper holds until the end of that expression.
997
998 The task inherits the caller's executor.
999
1000 @param st The stop token for cooperative cancellation.
1001 @param alloc The allocator for frame allocation.
1002
1003 @return A wrapper that accepts a task for execution.
1004 */
1005 template<detail::Allocator Alloc>
1006 [[nodiscard]] auto
1007 1x run(std::stop_token st, Alloc alloc)
1008 {
1009 return detail::run_wrapper<false, Alloc>{
1010 1x std::move(st), std::move(alloc)};
1011 }
1012
1013 } // namespace boost::capy
1014
1015 #endif
1016