100.00% Lines (22/22) 100.00% Functions (8/8)
TLA Baseline Branch
Line Hits Code Line Hits Code
  1 + //
  2 + // Copyright (c) 2026 Michael Vandeberg
  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/corosio
  8 + //
  9 +
  10 + #ifndef BOOST_COROSIO_NATIVE_NATIVE_POSIX_DESCRIPTOR_HPP
  11 + #define BOOST_COROSIO_NATIVE_NATIVE_POSIX_DESCRIPTOR_HPP
  12 +
  13 + #include <boost/corosio/detail/op_base.hpp>
  14 + #include <boost/corosio/posix_descriptor.hpp>
  15 + #include <boost/corosio/backend.hpp>
  16 +
  17 + #if BOOST_COROSIO_POSIX || defined(BOOST_COROSIO_MRDOCS)
  18 +
  19 + #ifndef BOOST_COROSIO_MRDOCS
  20 + #if BOOST_COROSIO_HAS_EPOLL
  21 + #include <boost/corosio/native/detail/epoll/epoll_types.hpp>
  22 + #endif
  23 +
  24 + #if BOOST_COROSIO_HAS_SELECT
  25 + #include <boost/corosio/native/detail/select/select_types.hpp>
  26 + #endif
  27 +
  28 + #if BOOST_COROSIO_HAS_KQUEUE
  29 + #include <boost/corosio/native/detail/kqueue/kqueue_types.hpp>
  30 + #endif
  31 +
  32 + #if BOOST_COROSIO_HAS_URING
  33 + // uring_types.hpp does not declare the descriptor: it was added
  34 + // after that header, in its own pair of files.
  35 + #include <boost/corosio/native/detail/uring/uring_descriptor_service.hpp>
  36 + #endif
  37 + #endif // !BOOST_COROSIO_MRDOCS
  38 +
  39 + namespace boost::corosio {
  40 +
  41 + /** Drives an already-open POSIX descriptor, calling the backend directly.
  42 +
  43 + This class template inherits from @ref posix_descriptor and
  44 + shadows the async operations (`read_some`, `write_some`, `wait`)
  45 + with versions that call the backend implementation directly.
  46 + This lets the compiler inline through the entire call chain.
  47 +
  48 + Non-async operations (`assign`, `release`, `close`, `cancel`)
  49 + remain unchanged and dispatch through the compiled library.
  50 +
  51 + A `native_posix_descriptor` IS-A `posix_descriptor` and can be
  52 + passed to any function expecting `posix_descriptor&` or
  53 + `io_stream&`, in which case virtual dispatch is used
  54 + transparently.
  55 +
  56 + @tparam Backend A backend tag value (e.g., `epoll`) whose type
  57 + provides the concrete implementation types.
  58 +
  59 + @par Thread Safety
  60 + Same as @ref posix_descriptor.
  61 +
  62 + @par Example
  63 + @par !example assign_and_wait
  64 +
  65 + @see posix_descriptor, epoll_t, kqueue_t
  66 + */
  67 + template<auto Backend>
  68 + class native_posix_descriptor : public posix_descriptor
  69 + {
  70 + using backend_type = decltype(Backend);
  71 + using impl_type = typename backend_type::descriptor_type;
  72 + using service_type = typename backend_type::descriptor_service_type;
  73 +
HITGNC   74 + 6 impl_type& get_impl() noexcept
  75 + {
HITGNC   76 + 6 return *static_cast<impl_type*>(h_.get());
  77 + }
  78 +
  79 + template<class MutableBufferSequence>
  80 + struct native_read_awaitable
  81 + : detail::bytes_op_base<native_read_awaitable<MutableBufferSequence>>
  82 + {
  83 + native_posix_descriptor& self_;
  84 + MutableBufferSequence buffers_;
  85 +
HITGNC   86 + 6 native_read_awaitable(
  87 + native_posix_descriptor& self,
  88 + MutableBufferSequence buffers) noexcept
HITGNC   89 + 6 : self_(self)
HITGNC   90 + 6 , buffers_(std::move(buffers))
  91 + {
HITGNC   92 + 6 }
  93 +
  94 + std::coroutine_handle<>
HITGNC   95 + 4 dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
  96 + {
HITGNC   97 + 12 return self_.get_impl().read_some(
HITGNC   98 + 12 h, ex, buffers_, this->token_, &this->ec_, &this->bytes_);
  99 + }
  100 + };
  101 +
  102 + template<class ConstBufferSequence>
  103 + struct native_write_awaitable
  104 + : detail::bytes_op_base<native_write_awaitable<ConstBufferSequence>>
  105 + {
  106 + native_posix_descriptor& self_;
  107 + ConstBufferSequence buffers_;
  108 +
  109 + native_write_awaitable(
  110 + native_posix_descriptor& self, ConstBufferSequence buffers) noexcept
  111 + : self_(self)
  112 + , buffers_(std::move(buffers))
  113 + {
  114 + }
  115 +
  116 + std::coroutine_handle<>
  117 + dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
  118 + {
  119 + return self_.get_impl().write_some(
  120 + h, ex, buffers_, this->token_, &this->ec_, &this->bytes_);
  121 + }
  122 + };
  123 +
  124 + struct native_wait_awaitable : detail::void_op_base<native_wait_awaitable>
  125 + {
  126 + native_posix_descriptor& self_;
  127 + wait_type w_;
  128 +
HITGNC   129 + 4 native_wait_awaitable(
  130 + native_posix_descriptor& self, wait_type w) noexcept
HITGNC   131 + 4 : self_(self)
HITGNC   132 + 4 , w_(w)
  133 + {
HITGNC   134 + 4 }
  135 +
  136 + std::coroutine_handle<>
HITGNC   137 + 2 dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
  138 + {
HITGNC   139 + 2 return self_.get_impl().wait(h, ex, w_, this->token_, &this->ec_);
  140 + }
  141 + };
  142 +
  143 + public:
  144 + /** Construct a native descriptor from an execution context.
  145 +
  146 + @param ctx The execution context that owns this object.
  147 + */
HITGNC   148 + 12 explicit native_posix_descriptor(capy::execution_context& ctx)
HITGNC   149 + 12 : io_object(handle(ctx, ctx.use_service<service_type>()))
  150 + {
HITGNC   151 + 12 }
  152 +
  153 + /** Construct a native descriptor from an executor.
  154 +
  155 + @param ex The executor whose context owns this object.
  156 + */
  157 + template<class Ex>
  158 + requires(!std::same_as<
  159 + std::remove_cvref_t<Ex>,
  160 + native_posix_descriptor>) &&
  161 + capy::Executor<Ex>
  162 + explicit native_posix_descriptor(Ex const& ex)
  163 + : native_posix_descriptor(ex.context())
  164 + {
  165 + }
  166 +
  167 + /// Move construct.
  168 + native_posix_descriptor(native_posix_descriptor&&) noexcept = default;
  169 +
  170 + /// Move assign.
  171 + native_posix_descriptor&
  172 + operator=(native_posix_descriptor&&) noexcept = default;
  173 +
  174 + /// Copy construction is disabled; the handle is uniquely owned.
  175 + native_posix_descriptor(native_posix_descriptor const&) = delete;
  176 + /// Copy assignment is disabled; the handle is uniquely owned.
  177 + native_posix_descriptor&
  178 + operator=(native_posix_descriptor const&) = delete;
  179 +
  180 + /** Asynchronously read data from the descriptor.
  181 +
  182 + Calls the backend implementation directly, bypassing virtual
  183 + dispatch. Otherwise identical to @ref io_stream::read_some.
  184 +
  185 + @param buffers The buffer sequence to read into.
  186 +
  187 + @return An awaitable yielding `(error_code, std::size_t)`.
  188 + */
  189 + template<capy::MutableBufferSequence MB>
HITGNC   190 + 6 [[nodiscard]] auto read_some(MB const& buffers)
  191 + {
HITGNC   192 + 6 return native_read_awaitable<MB>(*this, buffers);
  193 + }
  194 +
  195 + /** Asynchronously write data to the descriptor.
  196 +
  197 + Calls the backend implementation directly, bypassing virtual
  198 + dispatch. Otherwise identical to @ref io_stream::write_some.
  199 +
  200 + @param buffers The buffer sequence to write from.
  201 +
  202 + @return An awaitable yielding `(error_code, std::size_t)`.
  203 + */
  204 + template<capy::ConstBufferSequence CB>
  205 + [[nodiscard]] auto write_some(CB const& buffers)
  206 + {
  207 + return native_write_awaitable<CB>(*this, buffers);
  208 + }
  209 +
  210 + /** Wait for readiness without transferring bytes.
  211 +
  212 + Calls the backend implementation directly, bypassing virtual
  213 + dispatch. Otherwise identical to @ref posix_descriptor::wait.
  214 +
  215 + @param w The direction to wait on.
  216 +
  217 + @return An awaitable yielding `io_result<>`.
  218 + */
HITGNC   219 + 4 [[nodiscard]] auto wait(wait_type w)
  220 + {
HITGNC   221 + 4 return native_wait_awaitable(*this, w);
  222 + }
  223 + };
  224 +
  225 + } // namespace boost::corosio
  226 +
  227 + #endif // BOOST_COROSIO_POSIX || BOOST_COROSIO_MRDOCS
  228 +
  229 + #endif // BOOST_COROSIO_NATIVE_NATIVE_POSIX_DESCRIPTOR_HPP