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