include/boost/capy/asio/executor_adapter.hpp
90.9% Lines (30/33)
64.6% List of functions (42/65)
Functions (65)
Function
Calls
Lines
Blocks
boost::capy::detail::asio_adapter_context_service<boost::asio::execution_context>::asio_adapter_context_service(boost::capy::execution_context&)
:44
1x
100.0%
80.0%
boost::capy::detail::asio_adapter_context_service<boost::asio::execution_context>::shutdown()
:45
1x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 1>::asio_executor_adapter<0>(boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 0> const&)
:121
1x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 4>::asio_executor_adapter<0>(boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 0> const&)
:121
5x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 0>::asio_executor_adapter<1>(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 1> const&)
:121
0
0.0%
0.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 0>::asio_executor_adapter<4>(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 4> const&)
:121
0
0.0%
0.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 1>::asio_executor_adapter<0>(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 0> const&)
:121
2x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 1>::asio_executor_adapter<5>(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 5> const&)
:121
0
0.0%
0.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 4>::asio_executor_adapter<0>(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 0> const&)
:121
3x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 4>::asio_executor_adapter<5>(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 5> const&)
:121
0
0.0%
0.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 5>::asio_executor_adapter<1>(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 1> const&)
:121
0
0.0%
0.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 5>::asio_executor_adapter<4>(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 4> const&)
:121
0
0.0%
0.0%
boost::capy::asio_executor_adapter<boost::capy::thread_pool::executor_type, std::pmr::polymorphic_allocator<void>, 1>::asio_executor_adapter<0>(boost::capy::asio_executor_adapter<boost::capy::thread_pool::executor_type, std::pmr::polymorphic_allocator<void>, 0> const&)
:121
3x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 0>::asio_executor_adapter<0>(boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 0>&&)
:139
3x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 4>::asio_executor_adapter<4>(boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 4>&&)
:139
6x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 0>::asio_executor_adapter<0>(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 0>&&)
:139
8x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 1>::asio_executor_adapter<1>(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 1>&&)
:139
1x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 4>::asio_executor_adapter<4>(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 4>&&)
:139
6x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 5>::asio_executor_adapter<5>(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 5>&&)
:139
0
0.0%
0.0%
boost::capy::asio_executor_adapter<boost::capy::thread_pool::executor_type, std::pmr::polymorphic_allocator<void>, 1>::asio_executor_adapter<1>(boost::capy::asio_executor_adapter<boost::capy::thread_pool::executor_type, std::pmr::polymorphic_allocator<void>, 1>&&)
:139
3x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 1>::asio_executor_adapter<std::pmr::polymorphic_allocator<void> >(boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 1>, std::pmr::polymorphic_allocator<void> const&)
:170
1x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 4>::asio_executor_adapter<std::pmr::polymorphic_allocator<void> >(boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 4>, std::pmr::polymorphic_allocator<void> const&)
:170
3x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::allocator<void>, 0>::asio_executor_adapter<std::pmr::polymorphic_allocator<void> >(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 0>, std::allocator<void> const&)
:170
1x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::allocator<void>, 1>::asio_executor_adapter<std::pmr::polymorphic_allocator<void> >(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 1>, std::allocator<void> const&)
:170
2x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::thread_pool::executor_type, std::allocator<void>, 1>::asio_executor_adapter<std::pmr::polymorphic_allocator<void> >(boost::capy::asio_executor_adapter<boost::capy::thread_pool::executor_type, std::pmr::polymorphic_allocator<void>, 1>, std::allocator<void> const&)
:170
3x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 0>::asio_executor_adapter(boost::capy::executor_ref)
:188
6x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 0>::asio_executor_adapter(boost::capy::test_executor)
:188
3x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::thread_pool::executor_type, std::pmr::polymorphic_allocator<void>, 0>::asio_executor_adapter(boost::capy::thread_pool::executor_type)
:188
3x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 0>::~asio_executor_adapter()
:201
10x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 1>::~asio_executor_adapter()
:201
3x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 4>::~asio_executor_adapter()
:201
17x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::allocator<void>, 0>::~asio_executor_adapter()
:201
1x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::allocator<void>, 1>::~asio_executor_adapter()
:201
2x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 0>::~asio_executor_adapter()
:201
16x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 1>::~asio_executor_adapter()
:201
6x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 4>::~asio_executor_adapter()
:201
9x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 5>::~asio_executor_adapter()
:201
0
0.0%
0.0%
boost::capy::asio_executor_adapter<boost::capy::thread_pool::executor_type, std::allocator<void>, 1>::~asio_executor_adapter()
:201
3x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::thread_pool::executor_type, std::pmr::polymorphic_allocator<void>, 0>::~asio_executor_adapter()
:201
3x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::thread_pool::executor_type, std::pmr::polymorphic_allocator<void>, 1>::~asio_executor_adapter()
:201
12x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 0>::operator==(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 0> const&) const
:245
0
0.0%
0.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 1>::operator==(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 1> const&) const
:245
0
0.0%
0.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 4>::operator==(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 4> const&) const
:245
0
0.0%
0.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 5>::operator==(boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 5> const&) const
:245
0
0.0%
0.0%
void boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 1>::execute<boost::asio::detail::work_dispatcher<boost::asio::detail::empty_work_function, boost::capy::detail::asio_coroutine_completion_handler<boost::asio::cancellation_slot>, boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 0>, void> >(boost::asio::detail::work_dispatcher<boost::asio::detail::empty_work_function, boost::capy::detail::asio_coroutine_completion_handler<boost::asio::cancellation_slot>, boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 0>, void>&&) const
:277
1x
100.0%
100.0%
void boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 4>::execute<boost::asio::detail::binder0<boost::asio::detail::binder2<boost::capy::detail::asio_coroutine_completion_handler<boost::asio::cancellation_slot, boost::system::error_code, unsigned long>, boost::system::error_code, unsigned long> > >(boost::asio::detail::binder0<boost::asio::detail::binder2<boost::capy::detail::asio_coroutine_completion_handler<boost::asio::cancellation_slot, boost::system::error_code, unsigned long>, boost::system::error_code, unsigned long> >&&) const
:277
2x
100.0%
100.0%
void boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 4>::execute<boost::asio::detail::binder0<boost::capy::detail::asio_coroutine_completion_handler<boost::asio::cancellation_slot> > >(boost::asio::detail::binder0<boost::capy::detail::asio_coroutine_completion_handler<boost::asio::cancellation_slot> >&&) const
:277
1x
100.0%
100.0%
void boost::capy::asio_executor_adapter<boost::capy::executor_ref, std::pmr::polymorphic_allocator<void>, 4>::execute<boost::asio::detail::binder2<boost::capy::detail::asio_coroutine_completion_handler<boost::asio::cancellation_slot, boost::system::error_code, unsigned long>, boost::system::error_code, unsigned long> >(boost::asio::detail::binder2<boost::capy::detail::asio_coroutine_completion_handler<boost::asio::cancellation_slot, boost::system::error_code, unsigned long>, boost::system::error_code, unsigned long>&&) const
:277
0
0.0%
0.0%
void boost::capy::asio_executor_adapter<boost::capy::test_executor, std::allocator<void>, 0>::execute<boost::asio::detail::binder0<boost::capy::boost_asio_test::testExecutor()::{lambda()#2}> >(boost::asio::detail::binder0<boost::capy::boost_asio_test::testExecutor()::{lambda()#2}>&&) const
:277
1x
100.0%
100.0%
void boost::capy::asio_executor_adapter<boost::capy::test_executor, std::allocator<void>, 1>::execute<boost::asio::detail::binder0<boost::capy::boost_asio_test::testExecutor()::{lambda()#1}> >(boost::asio::detail::binder0<boost::capy::boost_asio_test::testExecutor()::{lambda()#1}>&&) const
:277
1x
100.0%
100.0%
void boost::capy::asio_executor_adapter<boost::capy::test_executor, std::allocator<void>, 1>::execute<boost::asio::detail::work_dispatcher<boost::asio::detail::empty_work_function, boost::asio::detail::append_handler<boost::asio::detail::promise_handler<void (std::__exception_ptr::exception_ptr), std::allocator<void> >, std::__exception_ptr::exception_ptr>, boost::asio::detail::promise_executor<void, boost::asio::execution::detail::blocking::possibly_t<0> >, void> >(boost::asio::detail::work_dispatcher<boost::asio::detail::empty_work_function, boost::asio::detail::append_handler<boost::asio::detail::promise_handler<void (std::__exception_ptr::exception_ptr), std::allocator<void> >, std::__exception_ptr::exception_ptr>, boost::asio::detail::promise_executor<void, boost::asio::execution::detail::blocking::possibly_t<0> >, void>&&) const
:277
1x
100.0%
100.0%
void boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 0>::execute<boost::asio::detail::executor_function>(boost::asio::detail::executor_function&&) const
:277
0
0.0%
0.0%
void boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 0>::execute<boost::asio::detail::executor_function_view&>(boost::asio::detail::executor_function_view&) const
:277
0
0.0%
0.0%
void boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 1>::execute<boost::asio::detail::executor_function>(boost::asio::detail::executor_function&&) const
:277
0
0.0%
0.0%
void boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 1>::execute<boost::asio::detail::executor_function_view&>(boost::asio::detail::executor_function_view&) const
:277
0
0.0%
0.0%
void boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 4>::execute<boost::asio::detail::executor_function>(boost::asio::detail::executor_function&&) const
:277
1x
100.0%
100.0%
void boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 4>::execute<boost::asio::detail::executor_function_view&>(boost::asio::detail::executor_function_view&) const
:277
0
0.0%
0.0%
void boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 5>::execute<boost::asio::detail::executor_function>(boost::asio::detail::executor_function&&) const
:277
0
0.0%
0.0%
void boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 5>::execute<boost::asio::detail::executor_function_view&>(boost::asio::detail::executor_function_view&) const
:277
0
0.0%
0.0%
void boost::capy::asio_executor_adapter<boost::capy::thread_pool::executor_type, std::allocator<void>, 1>::execute<boost::asio::detail::binder0<boost::asio::detail::append_handler<boost::asio::detail::read_op<boost::capy::async_read_stream<boost::capy::noexcept_stream<boost::capy::test::read_stream>, boost::capy::thread_pool::executor_type>, boost::asio::mutable_buffer, boost::asio::mutable_buffer const*, boost::asio::detail::transfer_all_t, boost::capy::boost_asio_test::testStreamToAsio()::{lambda(boost::system::error_code, unsigned long)#2}>, std::error_code, unsigned long> > >(boost::asio::detail::binder0<boost::asio::detail::append_handler<boost::asio::detail::read_op<boost::capy::async_read_stream<boost::capy::noexcept_stream<boost::capy::test::read_stream>, boost::capy::thread_pool::executor_type>, boost::asio::mutable_buffer, boost::asio::mutable_buffer const*, boost::asio::detail::transfer_all_t, boost::capy::boost_asio_test::testStreamToAsio()::{lambda(boost::system::error_code, unsigned long)#2}>, std::error_code, unsigned long> >&&) const
:277
2x
100.0%
100.0%
void boost::capy::asio_executor_adapter<boost::capy::thread_pool::executor_type, std::allocator<void>, 1>::execute<boost::asio::detail::binder0<boost::asio::detail::append_handler<boost::asio::detail::write_op<boost::capy::async_write_stream<boost::capy::noexcept_stream<boost::capy::test::write_stream>, boost::capy::thread_pool::executor_type>, boost::asio::const_buffer, boost::asio::const_buffer const*, boost::asio::detail::transfer_all_t, boost::capy::boost_asio_test::testStreamToAsio()::{lambda(boost::system::error_code, unsigned long)#1}>, std::error_code, unsigned long> > >(boost::asio::detail::binder0<boost::asio::detail::append_handler<boost::asio::detail::write_op<boost::capy::async_write_stream<boost::capy::noexcept_stream<boost::capy::test::write_stream>, boost::capy::thread_pool::executor_type>, boost::asio::const_buffer, boost::asio::const_buffer const*, boost::asio::detail::transfer_all_t, boost::capy::boost_asio_test::testStreamToAsio()::{lambda(boost::system::error_code, unsigned long)#1}>, std::error_code, unsigned long> >&&) const
:277
1x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 0>::context() const
:298
1x
100.0%
100.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 1>::context() const
:298
0
0.0%
0.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 4>::context() const
:298
0
0.0%
0.0%
boost::capy::asio_executor_adapter<boost::capy::test_executor, std::pmr::polymorphic_allocator<void>, 5>::context() const
:298
0
0.0%
0.0%
| Line | TLA | Hits | Source Code |
|---|---|---|---|
| 1 | // | ||
| 2 | // Copyright (c) 2026 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_ASIO_EXECUTOR_ADAPTER_HPP | ||
| 11 | #define BOOST_CAPY_ASIO_EXECUTOR_ADAPTER_HPP | ||
| 12 | |||
| 13 | #include <boost/capy/asio/detail/continuation.hpp> | ||
| 14 | #include <boost/capy/ex/any_executor.hpp> | ||
| 15 | #include <boost/capy/ex/execution_context.hpp> | ||
| 16 | #include <memory_resource> | ||
| 17 | |||
| 18 | |||
| 19 | namespace boost { | ||
| 20 | namespace capy { | ||
| 21 | |||
| 22 | /** @addtogroup asio | ||
| 23 | * @{ | ||
| 24 | */ | ||
| 25 | |||
| 26 | namespace detail | ||
| 27 | { | ||
| 28 | |||
| 29 | /** @brief Service that bridges capy's execution_context with Asio's. | ||
| 30 | * @internal | ||
| 31 | * | ||
| 32 | * This service inherits from both capy's service and the target Asio | ||
| 33 | * execution context, allowing capy executors wrapped in `asio_executor_adapter` | ||
| 34 | * to be queried for their Asio execution context. | ||
| 35 | * | ||
| 36 | * @tparam ExecutionContext The Asio execution_context type (boost::asio or standalone) | ||
| 37 | */ | ||
| 38 | template<typename ExecutionContext> | ||
| 39 | struct asio_adapter_context_service | ||
| 40 | : execution_context::service, | ||
| 41 | // shutdown is protected | ||
| 42 | ExecutionContext | ||
| 43 | { | ||
| 44 | 1x | asio_adapter_context_service(boost::capy::execution_context &) {} | |
| 45 | 1x | void shutdown() override {ExecutionContext::shutdown();} | |
| 46 | }; | ||
| 47 | |||
| 48 | } | ||
| 49 | |||
| 50 | |||
| 51 | /** @brief Adapts a capy executor to be usable with Asio. | ||
| 52 | * | ||
| 53 | * `asio_executor_adapter` wraps a capy executor and exposes it as an | ||
| 54 | * Asio-compatible executor. This allows capy coroutines and executors to | ||
| 55 | * interoperate seamlessly with Asio's async operations. | ||
| 56 | * | ||
| 57 | * The adapter tracks execution properties (blocking behavior and work tracking) | ||
| 58 | * as compile-time template parameters for zero-overhead property queries. | ||
| 59 | * | ||
| 60 | * @tparam Executor The underlying capy executor type (default: `capy::any_executor`) | ||
| 61 | * @tparam Allocator The allocator type for handler allocation | ||
| 62 | * (default: `std::pmr::polymorphic_allocator<void>`) | ||
| 63 | * @tparam Bits Compile-time bitfield encoding blocking and work-tracking properties | ||
| 64 | * | ||
| 65 | * @par Execution Properties | ||
| 66 | * The adapter supports the standard Asio execution properties: | ||
| 67 | * - `blocking`: `possibly` (default), `never`, or `always` | ||
| 68 | * - `outstanding_work`: `untracked` (default) or `tracked` | ||
| 69 | * - `allocator`: Custom allocator for handler allocation | ||
| 70 | * - `context`: Returns the associated capy execution_context | ||
| 71 | * | ||
| 72 | * @par Example | ||
| 73 | * @code | ||
| 74 | * // Wrap a capy executor for use with Asio | ||
| 75 | * capy::any_executor capy_exec = ...; | ||
| 76 | * asio_executor_adapter<> asio_exec(capy_exec); | ||
| 77 | * | ||
| 78 | * // Use with Asio operations | ||
| 79 | * asio::post(asio_exec, []{ std::cout << "Hello from capy!\n"; }); | ||
| 80 | * | ||
| 81 | * // Require non-blocking execution | ||
| 82 | * auto never_blocking = asio::require(asio_exec, | ||
| 83 | * asio::execution::blocking.never); | ||
| 84 | * @endcode | ||
| 85 | * | ||
| 86 | * @see wrap_asio_executor For the reverse direction (Asio to capy) | ||
| 87 | */ | ||
| 88 | template<typename Executor = capy::any_executor, | ||
| 89 | typename Allocator = std::pmr::polymorphic_allocator<void>, | ||
| 90 | int Bits = 0> | ||
| 91 | struct asio_executor_adapter | ||
| 92 | { | ||
| 93 | /// @name Blocking Property Constants | ||
| 94 | /// @{ | ||
| 95 | constexpr static int blocking_possibly = 0b000; ///< May block the caller | ||
| 96 | constexpr static int blocking_never = 0b001; ///< Never blocks the caller | ||
| 97 | constexpr static int blocking_always = 0b010; ///< Always blocks until complete | ||
| 98 | constexpr static int blocking_mask = 0b011; ///< Mask for blocking bits | ||
| 99 | /// @} | ||
| 100 | |||
| 101 | /// @name Work Tracking Property Constants | ||
| 102 | /// @{ | ||
| 103 | constexpr static int work_untracked = 0b000; ///< Work is not tracked | ||
| 104 | constexpr static int work_tracked = 0b100; ///< Outstanding work is tracked | ||
| 105 | constexpr static int work_mask = 0b100; ///< Mask for work tracking bit | ||
| 106 | /// @} | ||
| 107 | |||
| 108 | |||
| 109 | /// @name Constructors | ||
| 110 | /// @{ | ||
| 111 | |||
| 112 | /** @brief Copy constructor from adapter with different property bits. | ||
| 113 | * | ||
| 114 | * Creates a copy with potentially different execution properties. | ||
| 115 | * If this adapter tracks work, `on_work_started()` is called. | ||
| 116 | * | ||
| 117 | * @tparam Bits_ The source adapter's property bits | ||
| 118 | * @param rhs The source adapter to copy from | ||
| 119 | */ | ||
| 120 | template<int Bits_> | ||
| 121 | 14x | asio_executor_adapter( | |
| 122 | const asio_executor_adapter<Executor, Allocator, Bits_> & rhs) | ||
| 123 | noexcept(std::is_nothrow_copy_constructible_v<Executor>) | ||
| 124 | 14x | : executor_(rhs.executor_), allocator_(rhs.allocator_) | |
| 125 | { | ||
| 126 | if constexpr((Bits & work_mask) == work_tracked) | ||
| 127 | 8x | executor_.on_work_started(); | |
| 128 | 14x | } | |
| 129 | |||
| 130 | /** @brief Move constructor from adapter with different property bits. | ||
| 131 | * | ||
| 132 | * Moves from another adapter with potentially different properties. | ||
| 133 | * If this adapter tracks work, `on_work_started()` is called. | ||
| 134 | * | ||
| 135 | * @tparam Bits_ The source adapter's property bits | ||
| 136 | * @param rhs The source adapter to move from | ||
| 137 | */ | ||
| 138 | template<int Bits_> | ||
| 139 | 27x | asio_executor_adapter( | |
| 140 | asio_executor_adapter<Executor, Allocator, Bits_> && rhs) | ||
| 141 | noexcept(std::is_nothrow_move_constructible_v<Executor>) | ||
| 142 | 27x | : executor_(std::move(rhs.executor_)) | |
| 143 | 27x | , allocator_(std::move(rhs.allocator_)) | |
| 144 | { | ||
| 145 | if constexpr((Bits & work_mask) == work_tracked) | ||
| 146 | 12x | executor_.on_work_started(); | |
| 147 | 27x | } | |
| 148 | |||
| 149 | /** @brief Constructs from executor and allocator. | ||
| 150 | * | ||
| 151 | * @param executor The capy executor to wrap | ||
| 152 | * @param alloc The allocator for handler allocation | ||
| 153 | */ | ||
| 154 | asio_executor_adapter(Executor executor, const Allocator & alloc) | ||
| 155 | noexcept(std::is_nothrow_move_constructible_v<Executor> | ||
| 156 | && std::is_nothrow_copy_constructible_v<Allocator>) | ||
| 157 | : executor_(std::move(executor)), allocator_(alloc) | ||
| 158 | { | ||
| 159 | if constexpr((Bits & work_mask) == work_tracked) | ||
| 160 | executor_.on_work_started(); | ||
| 161 | } | ||
| 162 | |||
| 163 | /** @brief Constructs from adapter with different allocator. | ||
| 164 | * | ||
| 165 | * @tparam OtherAllocator The source adapter's allocator type | ||
| 166 | * @param executor The source adapter | ||
| 167 | * @param alloc The new allocator to use | ||
| 168 | */ | ||
| 169 | template<typename OtherAllocator> | ||
| 170 | 10x | explicit asio_executor_adapter( | |
| 171 | asio_executor_adapter<Executor, OtherAllocator, Bits> executor, | ||
| 172 | const Allocator & alloc) | ||
| 173 | noexcept(std::is_nothrow_move_constructible_v<Executor> && | ||
| 174 | std::is_nothrow_copy_constructible_v<Allocator>) | ||
| 175 | 10x | : executor_(std::move(executor.executor_)), allocator_(alloc) | |
| 176 | { | ||
| 177 | if constexpr((Bits & work_mask) == work_tracked) | ||
| 178 | 3x | executor_.on_work_started(); | |
| 179 | 10x | } | |
| 180 | |||
| 181 | |||
| 182 | /** @brief Constructs from a capy executor. | ||
| 183 | * | ||
| 184 | * The allocator is obtained from the executor's context frame allocator. | ||
| 185 | * | ||
| 186 | * @param executor The capy executor to wrap | ||
| 187 | */ | ||
| 188 | 12x | asio_executor_adapter(Executor executor) | |
| 189 | noexcept(std::is_nothrow_move_constructible_v<Executor>) | ||
| 190 | 12x | : executor_(std::move(executor)) | |
| 191 | 12x | , allocator_(executor_.context().get_frame_allocator()) | |
| 192 | { | ||
| 193 | if constexpr((Bits & work_mask) == work_tracked) | ||
| 194 | executor_.on_work_started(); | ||
| 195 | 12x | } | |
| 196 | |||
| 197 | /** @brief Destructor. | ||
| 198 | * | ||
| 199 | * If work tracking is enabled, calls `on_work_finished()`. | ||
| 200 | */ | ||
| 201 | 82x | ~asio_executor_adapter() | |
| 202 | { | ||
| 203 | if constexpr((Bits & work_mask) == work_tracked) | ||
| 204 | 26x | executor_.on_work_finished(); | |
| 205 | 82x | } | |
| 206 | |||
| 207 | /// @} | ||
| 208 | |||
| 209 | /// @name Assignment | ||
| 210 | /// @{ | ||
| 211 | |||
| 212 | /** @brief Copy assignment from adapter with different property bits. | ||
| 213 | * | ||
| 214 | * Properly handles work tracking when changing executors. | ||
| 215 | * | ||
| 216 | * @tparam Bits_ The source adapter's property bits | ||
| 217 | * @param rhs The source adapter | ||
| 218 | * @return Reference to this adapter | ||
| 219 | */ | ||
| 220 | template<int Bits_> | ||
| 221 | asio_executor_adapter & operator=( | ||
| 222 | const asio_executor_adapter<Executor, Allocator, Bits_> & rhs) | ||
| 223 | { | ||
| 224 | |||
| 225 | if constexpr((Bits & work_mask) == work_tracked) | ||
| 226 | if (rhs.executor_ != executor_) | ||
| 227 | { | ||
| 228 | rhs.executor_.on_work_started(); | ||
| 229 | executor_.on_work_finished(); | ||
| 230 | } | ||
| 231 | |||
| 232 | executor_ = rhs.executor_; | ||
| 233 | allocator_ = rhs.allocator_; | ||
| 234 | } | ||
| 235 | |||
| 236 | /// @} | ||
| 237 | |||
| 238 | /// @name Comparison | ||
| 239 | /// @{ | ||
| 240 | |||
| 241 | /** @brief Equality comparison. | ||
| 242 | * @param rhs The adapter to compare with | ||
| 243 | * @return `true` if both executor and allocator are equal | ||
| 244 | */ | ||
| 245 | ✗ | bool operator==(const asio_executor_adapter & rhs) const noexcept | |
| 246 | { | ||
| 247 | ✗ | return executor_ == rhs.executor_ | |
| 248 | ✗ | && allocator_ == rhs.allocator_; | |
| 249 | } | ||
| 250 | |||
| 251 | /** @brief Inequality comparison. | ||
| 252 | * @param rhs The adapter to compare with | ||
| 253 | * @return `true` if executor or allocator differs | ||
| 254 | */ | ||
| 255 | bool operator!=(const asio_executor_adapter & rhs) const noexcept | ||
| 256 | { | ||
| 257 | return executor_ != rhs.executor_ | ||
| 258 | && allocator_ != rhs.allocator_; | ||
| 259 | } | ||
| 260 | |||
| 261 | /// @} | ||
| 262 | |||
| 263 | /// @name Execution | ||
| 264 | /// @{ | ||
| 265 | |||
| 266 | /** @brief Executes a function according to the blocking property. | ||
| 267 | * | ||
| 268 | * The execution behavior depends on the `Bits` template parameter: | ||
| 269 | * - `blocking_never`: Posts the function for deferred execution | ||
| 270 | * - `blocking_possibly`: Dispatches (may run inline or post) | ||
| 271 | * - `blocking_always`: Executes the function inline immediately | ||
| 272 | * | ||
| 273 | * @tparam Function The callable type | ||
| 274 | * @param f The function to execute | ||
| 275 | */ | ||
| 276 | template <typename Function> | ||
| 277 | 11x | void execute(Function&& f) const | |
| 278 | { | ||
| 279 | if constexpr ((Bits & blocking_mask) == blocking_never) | ||
| 280 | 6x | executor_.post( | |
| 281 | 6x | detail::make_continuation(std::forward<Function>(f), allocator_)); | |
| 282 | else if constexpr((Bits & blocking_mask) == blocking_possibly) | ||
| 283 | 5x | executor_.dispatch( | |
| 284 | 5x | detail::make_continuation(std::forward<Function>(f), allocator_) | |
| 285 | 5x | ).resume(); | |
| 286 | else if constexpr((Bits & blocking_mask) == blocking_always) | ||
| 287 | std::forward<Function>(f)(); | ||
| 288 | 11x | } | |
| 289 | |||
| 290 | /// @} | ||
| 291 | |||
| 292 | /// @name Accessors | ||
| 293 | /// @{ | ||
| 294 | |||
| 295 | /** @brief Returns the associated execution context. | ||
| 296 | * @return Reference to the capy execution_context | ||
| 297 | */ | ||
| 298 | 1x | execution_context & context() const {return executor_.context(); } | |
| 299 | |||
| 300 | /** @brief Returns the associated allocator. | ||
| 301 | * @return Copy of the allocator | ||
| 302 | */ | ||
| 303 | Allocator get_allocator() const noexcept {return allocator_;} | ||
| 304 | |||
| 305 | /** @brief Returns the underlying capy executor. | ||
| 306 | * @return Copy of the wrapped executor | ||
| 307 | */ | ||
| 308 | const Executor get_capy_executor() const {return executor_;} | ||
| 309 | |||
| 310 | /// @} | ||
| 311 | private: | ||
| 312 | |||
| 313 | template<typename, typename, int> | ||
| 314 | friend struct asio_executor_adapter; | ||
| 315 | Executor executor_; | ||
| 316 | Allocator allocator_; | ||
| 317 | |||
| 318 | }; | ||
| 319 | |||
| 320 | /** @} */ // end of asio group | ||
| 321 | |||
| 322 | } | ||
| 323 | } | ||
| 324 | |||
| 325 | |||
| 326 | #endif //BOOST_CAPY_ASIO_EXECUTOR_ADAPTER_HPP | ||
| 327 | |||
| 328 |