include/boost/capy/ex/run.hpp

99.5% Lines (189/190) 99.4% List of functions (167/168)
run.hpp
f(x) Functions (168)
Function Calls Lines Blocks
boost::capy::detail::boundary_trampoline::promise_type::get_return_object() :81 18x 100.0% 100.0% boost::capy::detail::boundary_trampoline::promise_type::initial_suspend() :87 18x 100.0% 100.0% boost::capy::detail::boundary_trampoline::promise_type::final_suspend() :89 18x 100.0% 100.0% boost::capy::detail::boundary_trampoline::promise_type::final_suspend()::awaiter::await_ready() const :94 18x 100.0% 100.0% boost::capy::detail::boundary_trampoline::promise_type::final_suspend()::awaiter::await_suspend(std::__n4861::coroutine_handle<void>) :96 18x 100.0% 100.0% boost::capy::detail::boundary_trampoline::promise_type::final_suspend()::awaiter::await_resume() const :104 0 50.0% 0.0% boost::capy::detail::boundary_trampoline::promise_type::return_void() :109 18x 100.0% 100.0% boost::capy::detail::boundary_trampoline::boundary_trampoline() :115 18x 100.0% 100.0% boost::capy::detail::boundary_trampoline::~boundary_trampoline() :117 54x 100.0% 100.0% boost::capy::detail::boundary_trampoline::boundary_trampoline(boost::capy::detail::boundary_trampoline&&) :125 18x 100.0% 100.0% boost::capy::detail::boundary_trampoline::operator=(boost::capy::detail::boundary_trampoline&&) :128 18x 100.0% 88.0% boost::capy::detail::boundary_trampoline::boundary_trampoline(std::__n4861::coroutine_handle<boost::capy::detail::boundary_trampoline::promise_type>) :139 18x 100.0% 100.0% boost::capy::detail::make_boundary_trampoline() :143 18x 100.0% 44.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>) :179 2x 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>) :179 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>) :179 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>) :179 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>) :179 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::thread_pool::executor_type, boost::capy::task<void>) :179 1x 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>) :179 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>) :179 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) :187 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) :187 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) :187 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>) :198 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>) :198 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) :208 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) :208 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, false, void>::await_ready() const :216 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, true, void>::await_ready() const :216 2x 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 :216 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 :216 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, void>::await_ready() const :216 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 :216 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 :216 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 :216 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 :216 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 :216 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, false, void>::await_ready() const :216 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, void>::await_ready() const :216 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 :216 1x 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 :216 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 :216 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, false, void>::await_resume() :221 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<bool>, boost::capy::test_executor, true, void>::await_resume() :221 2x 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() :221 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() :221 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<int>, boost::capy::test_executor, false, void>::await_resume() :221 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() :221 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() :221 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_resume() :221 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() :221 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() :221 2x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, false, void>::await_resume() :221 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::task<void>, boost::capy::test_executor, true, void>::await_resume() :221 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() :221 1x 100.0% 100.0% boost::capy::detail::run_awaitable_ex<boost::capy::test::custom_task<int>, boost::capy::test_executor, true, void>::await_resume() :221 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() :221 1x 100.0% 100.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::io_env const*) :226 2x 100.0% 95.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::io_env const*) :226 2x 100.0% 95.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::io_env const*) :226 1x 100.0% 95.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::io_env const*) :226 1x 100.0% 95.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::io_env const*) :226 1x 100.0% 95.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::io_env const*) :226 1x 100.0% 95.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::io_env const*) :226 1x 100.0% 95.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::io_env const*) :226 1x 100.0% 95.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::io_env const*) :226 1x 100.0% 95.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::io_env const*) :226 2x 100.0% 95.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::io_env const*) :226 1x 100.0% 95.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::io_env const*) :226 1x 100.0% 95.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::io_env const*) :226 1x 100.0% 95.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::io_env const*) :226 1x 100.0% 95.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::io_env const*) :226 1x 100.0% 95.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>&&) :258 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>&&) :258 2x 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> >&&) :258 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*>&&) :258 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>&&) :258 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> >&&) :258 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*>&&) :258 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>&&) :258 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>&&) :258 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>&&) :258 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>&&) :258 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>&&) :258 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>&&) :258 1x 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>&&) :258 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>&&) :258 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, void>::run_awaitable(boost::capy::task<int>, std::stop_token) :289 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>) :299 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>) :299 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>) :299 1x 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) :308 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) :308 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, boost::capy::test_allocator<std::byte> >::await_ready() const :315 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, std::pmr::memory_resource*>::await_ready() const :315 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, void>::await_ready() const :315 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, boost::capy::test_allocator<std::byte> >::await_ready() const :315 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, std::pmr::memory_resource*>::await_ready() const :315 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, true, std::pmr::memory_resource*>::await_ready() const :315 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, boost::capy::test_allocator<std::byte> >::await_resume() :320 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, std::pmr::memory_resource*>::await_resume() :320 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, false, void>::await_resume() :320 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, boost::capy::test_allocator<std::byte> >::await_resume() :320 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<int>, true, std::pmr::memory_resource*>::await_resume() :320 1x 100.0% 100.0% boost::capy::detail::run_awaitable<boost::capy::task<void>, true, std::pmr::memory_resource*>::await_resume() :320 1x 100.0% 100.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::io_env const*) :325 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::io_env const*) :325 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::io_env const*) :325 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::io_env const*) :325 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::io_env const*) :325 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::io_env const*) :325 1x 100.0% 100.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> >&&) :351 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*>&&) :351 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>&&) :351 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> >&&) :351 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*>&&) :351 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*>&&) :351 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>) :370 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(boost::capy::test_executor, std::stop_token, boost::capy::test_allocator<std::byte>) :379 1x 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>) && :396 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>) && :396 1x 100.0% 82.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*) :416 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*) :424 1x 100.0% 100.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>) && :440 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>) && :440 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>) :459 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>) :459 1x 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>) :459 2x 100.0% 100.0% boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, void>::run_wrapper_ex(boost::capy::test_executor) :459 5x 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) :459 1x 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) :465 4x 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>) && :479 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>) && :479 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>) && :479 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>) && :479 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>) && :479 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>) && :479 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper_ex<boost::capy::test_executor, true, void>::operator()<boost::capy::task<bool> >(boost::capy::task<bool>) && :479 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>) && :479 1x 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>) && :479 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>) && :479 1x 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>) && :479 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>) :503 1x 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>) :511 1x 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>) && :527 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>) && :527 1x 100.0% 80.0% boost::capy::detail::run_wrapper<true, std::pmr::memory_resource*>::run_wrapper(std::pmr::memory_resource*) :546 2x 100.0% 100.0% boost::capy::detail::run_wrapper<false, std::pmr::memory_resource*>::run_wrapper(std::stop_token, std::pmr::memory_resource*) :553 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper<false, std::pmr::memory_resource*>::operator()<boost::capy::task<int> >(boost::capy::task<int>) && :568 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>) && :568 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>) && :568 1x 100.0% 100.0% boost::capy::detail::run_wrapper<false, void>::run_wrapper(std::stop_token) :586 1x 100.0% 100.0% auto boost::capy::detail::run_wrapper<false, void>::operator()<boost::capy::task<int> >(boost::capy::task<int>) && :598 1x 100.0% 100.0% auto boost::capy::run<boost::capy::strand<boost::capy::executor_ref> >(boost::capy::strand<boost::capy::executor_ref>) :627 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>) :627 1x 100.0% 100.0% auto boost::capy::run<boost::capy::test_executor>(boost::capy::test_executor) :627 4x 100.0% 100.0% auto boost::capy::run<boost::capy::thread_pool::executor_type>(boost::capy::thread_pool::executor_type) :627 1x 100.0% 100.0% auto boost::capy::run<boost::capy::test_executor>(boost::capy::test_executor, std::stop_token) :641 4x 100.0% 100.0% auto boost::capy::run<boost::capy::test_executor>(boost::capy::test_executor, std::pmr::memory_resource*) :656 1x 100.0% 100.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>) :671 1x 100.0% 100.0% auto boost::capy::run<boost::capy::test_executor>(boost::capy::test_executor, std::stop_token, std::pmr::memory_resource*) :687 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>) :703 1x 100.0% 82.0% boost::capy::run(std::stop_token) :725 1x 100.0% 100.0% boost::capy::run(std::pmr::memory_resource*) :740 2x 100.0% 100.0% auto boost::capy::run<boost::capy::test_allocator<std::byte> >(boost::capy::test_allocator<std::byte>) :756 1x 100.0% 100.0% boost::capy::run(std::stop_token, std::pmr::memory_resource*) :771 1x 100.0% 100.0% auto boost::capy::run<boost::capy::test_allocator<std::byte> >(std::stop_token, boost::capy::test_allocator<std::byte>) :788 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/io_runnable.hpp>
18 #include <boost/capy/ex/executor_ref.hpp>
19 #include <coroutine>
20 #include <boost/capy/ex/frame_alloc_mixin.hpp>
21 #include <boost/capy/ex/frame_allocator.hpp>
22 #include <boost/capy/ex/io_env.hpp>
23
24 #include <memory_resource>
25 #include <stop_token>
26 #include <type_traits>
27 #include <utility>
28 #include <variant>
29
30 /*
31 Allocator Lifetime Strategy
32 ===========================
33
34 When using run() with a custom allocator:
35
36 co_await run(ex, alloc)(my_task());
37
38 The evaluation order is:
39 1. run(ex, alloc) creates a temporary wrapper
40 2. my_task() allocates its coroutine frame using TLS
41 3. operator() returns an awaitable
42 4. Wrapper temporary is DESTROYED
43 5. co_await suspends caller, resumes task
44 6. Task body executes (wrapper is already dead!)
45
46 Problem: The wrapper's frame_memory_resource dies before the task
47 body runs. When initial_suspend::await_resume() restores TLS from
48 the saved pointer, it would point to dead memory.
49
50 Solution: Store a COPY of the allocator in the awaitable (not just
51 the wrapper). The co_await mechanism extends the awaitable's lifetime
52 until the await completes. In await_suspend, we overwrite the promise's
53 saved frame_allocator pointer to point to the awaitable's resource.
54
55 This works because standard allocator copies are equivalent - memory
56 allocated with one copy can be deallocated with another copy. The
57 task's own frame uses the footer-stored pointer (safe), while nested
58 task creation uses TLS pointing to the awaitable's resource (also safe).
59 */
60
61 namespace boost::capy::detail {
62
63 /** Minimal coroutine that dispatches through the caller's executor.
64
65 Sits between the inner task and the parent when executors
66 diverge. The inner task's `final_suspend` resumes this
67 trampoline via symmetric transfer. The trampoline's own
68 `final_suspend` dispatches the parent through the caller's
69 executor to restore the correct execution context.
70
71 The trampoline never touches the task's result.
72 */
73 struct BOOST_CAPY_CORO_DESTROY_WHEN_COMPLETE boundary_trampoline
74 {
75 struct promise_type
76 : frame_alloc_mixin
77 {
78 executor_ref caller_ex_;
79 continuation parent_;
80
81 18x boundary_trampoline get_return_object() noexcept
82 {
83 return boundary_trampoline{
84 18x std::coroutine_handle<promise_type>::from_promise(*this)};
85 }
86
87 18x std::suspend_always initial_suspend() noexcept { return {}; }
88
89 18x auto final_suspend() noexcept
90 {
91 struct awaiter
92 {
93 promise_type* p_;
94 18x bool await_ready() const noexcept { return false; }
95
96 18x auto await_suspend(
97 std::coroutine_handle<>) noexcept
98 {
99 18x p_->caller_ex_.post(p_->parent_);
100 18x return detail::symmetric_transfer(
101 36x std::noop_coroutine());
102 }
103
104 void await_resume() const noexcept {}
105 };
106 18x return awaiter{this};
107 }
108
109 18x void return_void() noexcept {}
110 void unhandled_exception() noexcept {}
111 };
112
113 std::coroutine_handle<promise_type> h_{nullptr};
114
115 18x boundary_trampoline() noexcept = default;
116
117 54x ~boundary_trampoline()
118 {
119 54x if(h_) h_.destroy();
120 54x }
121
122 boundary_trampoline(boundary_trampoline const&) = delete;
123 boundary_trampoline& operator=(boundary_trampoline const&) = delete;
124
125 18x boundary_trampoline(boundary_trampoline&& o) noexcept
126 18x : h_(std::exchange(o.h_, nullptr)) {}
127
128 18x boundary_trampoline& operator=(boundary_trampoline&& o) noexcept
129 {
130 18x if(this != &o)
131 {
132 18x if(h_) h_.destroy();
133 18x h_ = std::exchange(o.h_, nullptr);
134 }
135 18x return *this;
136 }
137
138 private:
139 18x explicit boundary_trampoline(std::coroutine_handle<promise_type> h) noexcept
140 18x : h_(h) {}
141 };
142
143 18x inline boundary_trampoline make_boundary_trampoline()
144 {
145 co_return;
146 36x }
147
148 /** Awaitable that binds an IoRunnable to a specific executor.
149
150 Stores the executor and inner task by value. When co_awaited, the
151 co_await expression's lifetime extension keeps both alive for the
152 duration of the operation.
153
154 A dispatch trampoline handles the executor switch on completion:
155 the inner task's `final_suspend` resumes the trampoline, which
156 dispatches back through the caller's executor.
157
158 The `io_env` is owned by this awaitable and is guaranteed to
159 outlive the inner task and all awaitables in its chain. Awaitables
160 may store `io_env const*` without concern for dangling references.
161
162 @tparam Task The IoRunnable type
163 @tparam Ex The executor type
164 @tparam InheritStopToken If true, inherit caller's stop token
165 @tparam Alloc The allocator type (void for no allocator)
166 */
167 template<IoRunnable Task, Executor Ex, bool InheritStopToken, class Alloc = void>
168 struct [[nodiscard]] run_awaitable_ex
169 {
170 Ex ex_;
171 frame_memory_resource<Alloc> resource_;
172 std::conditional_t<InheritStopToken, std::monostate, std::stop_token> st_;
173 io_env env_;
174 boundary_trampoline tr_;
175 continuation task_cont_;
176 Task inner_; // Last: destroyed first, while env_ is still valid
177
178 // void allocator, inherit stop token
179 10x run_awaitable_ex(Ex ex, Task inner)
180 requires (InheritStopToken && std::is_void_v<Alloc>)
181 10x : ex_(std::move(ex))
182 10x , inner_(std::move(inner))
183 {
184 10x }
185
186 // void allocator, explicit stop token
187 4x run_awaitable_ex(Ex ex, Task inner, std::stop_token st)
188 requires (!InheritStopToken && std::is_void_v<Alloc>)
189 4x : ex_(std::move(ex))
190 4x , st_(std::move(st))
191 4x , inner_(std::move(inner))
192 {
193 4x }
194
195 // with allocator, inherit stop token (use template to avoid void parameter)
196 template<class A>
197 requires (InheritStopToken && !std::is_void_v<Alloc> && std::same_as<A, Alloc>)
198 2x run_awaitable_ex(Ex ex, A alloc, Task inner)
199 2x : ex_(std::move(ex))
200 2x , resource_(std::move(alloc))
201 2x , inner_(std::move(inner))
202 {
203 2x }
204
205 // with allocator, explicit stop token (use template to avoid void parameter)
206 template<class A>
207 requires (!InheritStopToken && !std::is_void_v<Alloc> && std::same_as<A, Alloc>)
208 2x run_awaitable_ex(Ex ex, A alloc, Task inner, std::stop_token st)
209 2x : ex_(std::move(ex))
210 2x , resource_(std::move(alloc))
211 2x , st_(std::move(st))
212 2x , inner_(std::move(inner))
213 {
214 2x }
215
216 18x bool await_ready() const noexcept
217 {
218 18x return inner_.await_ready();
219 }
220
221 18x decltype(auto) await_resume()
222 {
223 18x return inner_.await_resume();
224 }
225
226 18x std::coroutine_handle<> await_suspend(std::coroutine_handle<> cont, io_env const* caller_env)
227 {
228 18x tr_ = make_boundary_trampoline();
229 18x tr_.h_.promise().caller_ex_ = caller_env->executor;
230 18x tr_.h_.promise().parent_.h = cont;
231
232 18x auto h = inner_.handle();
233 18x auto& p = h.promise();
234 18x p.set_continuation(tr_.h_);
235
236 18x env_.executor = ex_;
237 if constexpr (InheritStopToken)
238 12x env_.stop_token = caller_env->stop_token;
239 else
240 6x env_.stop_token = st_;
241
242 if constexpr (!std::is_void_v<Alloc>)
243 4x env_.frame_allocator = resource_.get();
244 else
245 14x env_.frame_allocator = caller_env->frame_allocator;
246
247 18x p.set_environment(&env_);
248 18x task_cont_.h = h;
249 18x ex_.post(task_cont_);
250 18x return std::noop_coroutine();
251 }
252
253 // Non-copyable
254 run_awaitable_ex(run_awaitable_ex const&) = delete;
255 run_awaitable_ex& operator=(run_awaitable_ex const&) = delete;
256
257 // Movable (no noexcept - Task may throw)
258 18x run_awaitable_ex(run_awaitable_ex&&) = default;
259 run_awaitable_ex& operator=(run_awaitable_ex&&) = default;
260 };
261
262 /** Awaitable that runs a task with optional stop_token override.
263
264 Does NOT store an executor - the task inherits the caller's executor
265 directly. Executors always match, so no dispatch trampoline is needed.
266 The inner task's `final_suspend` resumes the parent directly via
267 unconditional symmetric transfer.
268
269 @tparam Task The IoRunnable type
270 @tparam InheritStopToken If true, inherit caller's stop token
271 @tparam Alloc The allocator type (void for no allocator)
272 */
273 template<IoRunnable Task, bool InheritStopToken, class Alloc = void>
274 struct [[nodiscard]] run_awaitable
275 {
276 frame_memory_resource<Alloc> resource_;
277 std::conditional_t<InheritStopToken, std::monostate, std::stop_token> st_;
278 io_env env_;
279 Task inner_; // Last: destroyed first, while env_ is still valid
280
281 // void allocator, inherit stop token
282 explicit run_awaitable(Task inner)
283 requires (InheritStopToken && std::is_void_v<Alloc>)
284 : inner_(std::move(inner))
285 {
286 }
287
288 // void allocator, explicit stop token
289 1x run_awaitable(Task inner, std::stop_token st)
290 requires (!InheritStopToken && std::is_void_v<Alloc>)
291 1x : st_(std::move(st))
292 1x , inner_(std::move(inner))
293 {
294 1x }
295
296 // with allocator, inherit stop token (use template to avoid void parameter)
297 template<class A>
298 requires (InheritStopToken && !std::is_void_v<Alloc> && std::same_as<A, Alloc>)
299 3x run_awaitable(A alloc, Task inner)
300 3x : resource_(std::move(alloc))
301 3x , inner_(std::move(inner))
302 {
303 3x }
304
305 // with allocator, explicit stop token (use template to avoid void parameter)
306 template<class A>
307 requires (!InheritStopToken && !std::is_void_v<Alloc> && std::same_as<A, Alloc>)
308 2x run_awaitable(A alloc, Task inner, std::stop_token st)
309 2x : resource_(std::move(alloc))
310 2x , st_(std::move(st))
311 2x , inner_(std::move(inner))
312 {
313 2x }
314
315 6x bool await_ready() const noexcept
316 {
317 6x return inner_.await_ready();
318 }
319
320 6x decltype(auto) await_resume()
321 {
322 6x return inner_.await_resume();
323 }
324
325 6x std::coroutine_handle<> await_suspend(std::coroutine_handle<> cont, io_env const* caller_env)
326 {
327 6x auto h = inner_.handle();
328 6x auto& p = h.promise();
329 6x p.set_continuation(cont);
330
331 6x env_.executor = caller_env->executor;
332 if constexpr (InheritStopToken)
333 3x env_.stop_token = caller_env->stop_token;
334 else
335 3x env_.stop_token = st_;
336
337 if constexpr (!std::is_void_v<Alloc>)
338 5x env_.frame_allocator = resource_.get();
339 else
340 1x env_.frame_allocator = caller_env->frame_allocator;
341
342 6x p.set_environment(&env_);
343 6x return h;
344 }
345
346 // Non-copyable
347 run_awaitable(run_awaitable const&) = delete;
348 run_awaitable& operator=(run_awaitable const&) = delete;
349
350 // Movable (no noexcept - Task may throw)
351 6x run_awaitable(run_awaitable&&) = default;
352 run_awaitable& operator=(run_awaitable&&) = default;
353 };
354
355 /** Wrapper returned by run(ex, ...) that accepts a task for execution.
356
357 @tparam Ex The executor type.
358 @tparam InheritStopToken If true, inherit caller's stop token.
359 @tparam Alloc The allocator type (void for no allocator).
360 */
361 template<Executor Ex, bool InheritStopToken, class Alloc>
362 class [[nodiscard]] run_wrapper_ex
363 {
364 Ex ex_;
365 std::conditional_t<InheritStopToken, std::monostate, std::stop_token> st_;
366 frame_memory_resource<Alloc> resource_;
367 Alloc alloc_; // Copy to pass to awaitable
368
369 public:
370 1x run_wrapper_ex(Ex ex, Alloc alloc)
371 requires InheritStopToken
372 1x : ex_(std::move(ex))
373 1x , resource_(alloc)
374 1x , alloc_(std::move(alloc))
375 {
376 1x set_current_frame_allocator(&resource_);
377 1x }
378
379 1x run_wrapper_ex(Ex ex, std::stop_token st, Alloc alloc)
380 requires (!InheritStopToken)
381 1x : ex_(std::move(ex))
382 1x , st_(std::move(st))
383 1x , resource_(alloc)
384 1x , alloc_(std::move(alloc))
385 {
386 1x set_current_frame_allocator(&resource_);
387 1x }
388
389 // Non-copyable, non-movable (must be used immediately)
390 run_wrapper_ex(run_wrapper_ex const&) = delete;
391 run_wrapper_ex(run_wrapper_ex&&) = delete;
392 run_wrapper_ex& operator=(run_wrapper_ex const&) = delete;
393 run_wrapper_ex& operator=(run_wrapper_ex&&) = delete;
394
395 template<IoRunnable Task>
396 2x [[nodiscard]] auto operator()(Task t) &&
397 {
398 if constexpr (InheritStopToken)
399 return run_awaitable_ex<Task, Ex, true, Alloc>{
400 1x std::move(ex_), std::move(alloc_), std::move(t)};
401 else
402 return run_awaitable_ex<Task, Ex, false, Alloc>{
403 1x std::move(ex_), std::move(alloc_), std::move(t), std::move(st_)};
404 }
405 };
406
407 /// Specialization for memory_resource* - stores pointer directly.
408 template<Executor Ex, bool InheritStopToken>
409 class [[nodiscard]] run_wrapper_ex<Ex, InheritStopToken, std::pmr::memory_resource*>
410 {
411 Ex ex_;
412 std::conditional_t<InheritStopToken, std::monostate, std::stop_token> st_;
413 std::pmr::memory_resource* mr_;
414
415 public:
416 1x run_wrapper_ex(Ex ex, std::pmr::memory_resource* mr)
417 requires InheritStopToken
418 1x : ex_(std::move(ex))
419 1x , mr_(mr)
420 {
421 1x set_current_frame_allocator(mr_);
422 1x }
423
424 1x run_wrapper_ex(Ex ex, std::stop_token st, std::pmr::memory_resource* mr)
425 requires (!InheritStopToken)
426 1x : ex_(std::move(ex))
427 1x , st_(std::move(st))
428 1x , mr_(mr)
429 {
430 1x set_current_frame_allocator(mr_);
431 1x }
432
433 // Non-copyable, non-movable (must be used immediately)
434 run_wrapper_ex(run_wrapper_ex const&) = delete;
435 run_wrapper_ex(run_wrapper_ex&&) = delete;
436 run_wrapper_ex& operator=(run_wrapper_ex const&) = delete;
437 run_wrapper_ex& operator=(run_wrapper_ex&&) = delete;
438
439 template<IoRunnable Task>
440 2x [[nodiscard]] auto operator()(Task t) &&
441 {
442 if constexpr (InheritStopToken)
443 return run_awaitable_ex<Task, Ex, true, std::pmr::memory_resource*>{
444 1x std::move(ex_), mr_, std::move(t)};
445 else
446 return run_awaitable_ex<Task, Ex, false, std::pmr::memory_resource*>{
447 1x std::move(ex_), mr_, std::move(t), std::move(st_)};
448 }
449 };
450
451 /// Specialization for no allocator (void).
452 template<Executor Ex, bool InheritStopToken>
453 class [[nodiscard]] run_wrapper_ex<Ex, InheritStopToken, void>
454 {
455 Ex ex_;
456 std::conditional_t<InheritStopToken, std::monostate, std::stop_token> st_;
457
458 public:
459 10x explicit run_wrapper_ex(Ex ex)
460 requires InheritStopToken
461 10x : ex_(std::move(ex))
462 {
463 10x }
464
465 4x run_wrapper_ex(Ex ex, std::stop_token st)
466 requires (!InheritStopToken)
467 4x : ex_(std::move(ex))
468 4x , st_(std::move(st))
469 {
470 4x }
471
472 // Non-copyable, non-movable (must be used immediately)
473 run_wrapper_ex(run_wrapper_ex const&) = delete;
474 run_wrapper_ex(run_wrapper_ex&&) = delete;
475 run_wrapper_ex& operator=(run_wrapper_ex const&) = delete;
476 run_wrapper_ex& operator=(run_wrapper_ex&&) = delete;
477
478 template<IoRunnable Task>
479 14x [[nodiscard]] auto operator()(Task t) &&
480 {
481 if constexpr (InheritStopToken)
482 return run_awaitable_ex<Task, Ex, true>{
483 10x std::move(ex_), std::move(t)};
484 else
485 return run_awaitable_ex<Task, Ex, false>{
486 4x std::move(ex_), std::move(t), std::move(st_)};
487 }
488 };
489
490 /** Wrapper returned by run(st) or run(alloc) that accepts a task.
491
492 @tparam InheritStopToken If true, inherit caller's stop token.
493 @tparam Alloc The allocator type (void for no allocator).
494 */
495 template<bool InheritStopToken, class Alloc>
496 class [[nodiscard]] run_wrapper
497 {
498 std::conditional_t<InheritStopToken, std::monostate, std::stop_token> st_;
499 frame_memory_resource<Alloc> resource_;
500 Alloc alloc_; // Copy to pass to awaitable
501
502 public:
503 1x explicit run_wrapper(Alloc alloc)
504 requires InheritStopToken
505 1x : resource_(alloc)
506 1x , alloc_(std::move(alloc))
507 {
508 1x set_current_frame_allocator(&resource_);
509 1x }
510
511 1x run_wrapper(std::stop_token st, Alloc alloc)
512 requires (!InheritStopToken)
513 1x : st_(std::move(st))
514 1x , resource_(alloc)
515 1x , alloc_(std::move(alloc))
516 {
517 1x set_current_frame_allocator(&resource_);
518 1x }
519
520 // Non-copyable, non-movable (must be used immediately)
521 run_wrapper(run_wrapper const&) = delete;
522 run_wrapper(run_wrapper&&) = delete;
523 run_wrapper& operator=(run_wrapper const&) = delete;
524 run_wrapper& operator=(run_wrapper&&) = delete;
525
526 template<IoRunnable Task>
527 2x [[nodiscard]] auto operator()(Task t) &&
528 {
529 if constexpr (InheritStopToken)
530 return run_awaitable<Task, true, Alloc>{
531 1x std::move(alloc_), std::move(t)};
532 else
533 return run_awaitable<Task, false, Alloc>{
534 1x std::move(alloc_), std::move(t), std::move(st_)};
535 }
536 };
537
538 /// Specialization for memory_resource* - stores pointer directly.
539 template<bool InheritStopToken>
540 class [[nodiscard]] run_wrapper<InheritStopToken, std::pmr::memory_resource*>
541 {
542 std::conditional_t<InheritStopToken, std::monostate, std::stop_token> st_;
543 std::pmr::memory_resource* mr_;
544
545 public:
546 2x explicit run_wrapper(std::pmr::memory_resource* mr)
547 requires InheritStopToken
548 2x : mr_(mr)
549 {
550 2x set_current_frame_allocator(mr_);
551 2x }
552
553 1x run_wrapper(std::stop_token st, std::pmr::memory_resource* mr)
554 requires (!InheritStopToken)
555 1x : st_(std::move(st))
556 1x , mr_(mr)
557 {
558 1x set_current_frame_allocator(mr_);
559 1x }
560
561 // Non-copyable, non-movable (must be used immediately)
562 run_wrapper(run_wrapper const&) = delete;
563 run_wrapper(run_wrapper&&) = delete;
564 run_wrapper& operator=(run_wrapper const&) = delete;
565 run_wrapper& operator=(run_wrapper&&) = delete;
566
567 template<IoRunnable Task>
568 3x [[nodiscard]] auto operator()(Task t) &&
569 {
570 if constexpr (InheritStopToken)
571 return run_awaitable<Task, true, std::pmr::memory_resource*>{
572 2x mr_, std::move(t)};
573 else
574 return run_awaitable<Task, false, std::pmr::memory_resource*>{
575 1x mr_, std::move(t), std::move(st_)};
576 }
577 };
578
579 /// Specialization for stop_token only (no allocator).
580 template<>
581 class [[nodiscard]] run_wrapper<false, void>
582 {
583 std::stop_token st_;
584
585 public:
586 1x explicit run_wrapper(std::stop_token st)
587 1x : st_(std::move(st))
588 {
589 1x }
590
591 // Non-copyable, non-movable (must be used immediately)
592 run_wrapper(run_wrapper const&) = delete;
593 run_wrapper(run_wrapper&&) = delete;
594 run_wrapper& operator=(run_wrapper const&) = delete;
595 run_wrapper& operator=(run_wrapper&&) = delete;
596
597 template<IoRunnable Task>
598 1x [[nodiscard]] auto operator()(Task t) &&
599 {
600 1x return run_awaitable<Task, false, void>{std::move(t), std::move(st_)};
601 }
602 };
603
604 } // namespace boost::capy::detail
605
606 namespace boost::capy {
607
608 /** Bind a task to execute on a specific executor.
609
610 Returns a wrapper that accepts a task and produces an awaitable.
611 When co_awaited, the task runs on the specified executor.
612
613 @par Example
614 @code
615 co_await run(other_executor)(my_task());
616 @endcode
617
618 @param ex The executor on which the task should run.
619
620 @return A wrapper that accepts a task for execution.
621
622 @see task
623 @see executor
624 */
625 template<Executor Ex>
626 [[nodiscard]] auto
627 10x run(Ex ex)
628 {
629 10x return detail::run_wrapper_ex<Ex, true, void>{std::move(ex)};
630 }
631
632 /** Bind a task to an executor with a stop token.
633
634 @param ex The executor on which the task should run.
635 @param st The stop token for cooperative cancellation.
636
637 @return A wrapper that accepts a task for execution.
638 */
639 template<Executor Ex>
640 [[nodiscard]] auto
641 4x run(Ex ex, std::stop_token st)
642 {
643 return detail::run_wrapper_ex<Ex, false, void>{
644 4x std::move(ex), std::move(st)};
645 }
646
647 /** Bind a task to an executor with a memory resource.
648
649 @param ex The executor on which the task should run.
650 @param mr The memory resource for frame allocation.
651
652 @return A wrapper that accepts a task for execution.
653 */
654 template<Executor Ex>
655 [[nodiscard]] auto
656 1x run(Ex ex, std::pmr::memory_resource* mr)
657 {
658 return detail::run_wrapper_ex<Ex, true, std::pmr::memory_resource*>{
659 1x std::move(ex), mr};
660 }
661
662 /** Bind a task to an executor with a standard allocator.
663
664 @param ex The executor on which the task should run.
665 @param alloc The allocator for frame allocation.
666
667 @return A wrapper that accepts a task for execution.
668 */
669 template<Executor Ex, detail::Allocator Alloc>
670 [[nodiscard]] auto
671 1x run(Ex ex, Alloc alloc)
672 {
673 return detail::run_wrapper_ex<Ex, true, Alloc>{
674 1x std::move(ex), std::move(alloc)};
675 }
676
677 /** Bind a task to an executor with stop token and memory resource.
678
679 @param ex The executor on which the task should run.
680 @param st The stop token for cooperative cancellation.
681 @param mr The memory resource for frame allocation.
682
683 @return A wrapper that accepts a task for execution.
684 */
685 template<Executor Ex>
686 [[nodiscard]] auto
687 1x run(Ex ex, std::stop_token st, std::pmr::memory_resource* mr)
688 {
689 return detail::run_wrapper_ex<Ex, false, std::pmr::memory_resource*>{
690 1x std::move(ex), std::move(st), mr};
691 }
692
693 /** Bind a task to an executor with stop token and standard allocator.
694
695 @param ex The executor on which the task should run.
696 @param st The stop token for cooperative cancellation.
697 @param alloc The allocator for frame allocation.
698
699 @return A wrapper that accepts a task for execution.
700 */
701 template<Executor Ex, detail::Allocator Alloc>
702 [[nodiscard]] auto
703 1x run(Ex ex, std::stop_token st, Alloc alloc)
704 {
705 return detail::run_wrapper_ex<Ex, false, Alloc>{
706 1x std::move(ex), std::move(st), std::move(alloc)};
707 }
708
709 /** Run a task with a custom stop token.
710
711 The task inherits the caller's executor. Only the stop token
712 is overridden.
713
714 @par Example
715 @code
716 std::stop_source source;
717 co_await run(source.get_token())(cancellable_task());
718 @endcode
719
720 @param st The stop token for cooperative cancellation.
721
722 @return A wrapper that accepts a task for execution.
723 */
724 [[nodiscard]] inline auto
725 1x run(std::stop_token st)
726 {
727 1x return detail::run_wrapper<false, void>{std::move(st)};
728 }
729
730 /** Run a task with a custom memory resource.
731
732 The task inherits the caller's executor. The memory resource
733 is used for nested frame allocations.
734
735 @param mr The memory resource for frame allocation.
736
737 @return A wrapper that accepts a task for execution.
738 */
739 [[nodiscard]] inline auto
740 2x run(std::pmr::memory_resource* mr)
741 {
742 2x return detail::run_wrapper<true, std::pmr::memory_resource*>{mr};
743 }
744
745 /** Run a task with a custom standard allocator.
746
747 The task inherits the caller's executor. The allocator is used
748 for nested frame allocations.
749
750 @param alloc The allocator for frame allocation.
751
752 @return A wrapper that accepts a task for execution.
753 */
754 template<detail::Allocator Alloc>
755 [[nodiscard]] auto
756 1x run(Alloc alloc)
757 {
758 1x return detail::run_wrapper<true, Alloc>{std::move(alloc)};
759 }
760
761 /** Run a task with stop token and memory resource.
762
763 The task inherits the caller's executor.
764
765 @param st The stop token for cooperative cancellation.
766 @param mr The memory resource for frame allocation.
767
768 @return A wrapper that accepts a task for execution.
769 */
770 [[nodiscard]] inline auto
771 1x run(std::stop_token st, std::pmr::memory_resource* mr)
772 {
773 return detail::run_wrapper<false, std::pmr::memory_resource*>{
774 1x std::move(st), mr};
775 }
776
777 /** Run a task with stop token and standard allocator.
778
779 The task inherits the caller's executor.
780
781 @param st The stop token for cooperative cancellation.
782 @param alloc The allocator for frame allocation.
783
784 @return A wrapper that accepts a task for execution.
785 */
786 template<detail::Allocator Alloc>
787 [[nodiscard]] auto
788 1x run(std::stop_token st, Alloc alloc)
789 {
790 return detail::run_wrapper<false, Alloc>{
791 1x std::move(st), std::move(alloc)};
792 }
793
794 } // namespace boost::capy
795
796 #endif
797