include/boost/corosio/native/native_posix_descriptor.hpp

100.0% Lines (22 / 22) 100.0% Functions (14 / 14)
native_posix_descriptor.hpp
f(x) Functions (14)
Function Calls Lines Blocks
boost::corosio::native_posix_descriptor<boost::corosio::epoll_t{}>::get_impl() :74 3x 100.0% 100.0% boost::corosio::native_posix_descriptor<boost::corosio::select_t{}>::get_impl() :74 3x 100.0% 100.0% boost::corosio::native_posix_descriptor<boost::corosio::epoll_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::native_read_awaitable(boost::corosio::native_posix_descriptor<boost::corosio::epoll_t{}>&, boost::capy::mutable_buffer) :86 3x 100.0% 100.0% boost::corosio::native_posix_descriptor<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::native_read_awaitable(boost::corosio::native_posix_descriptor<boost::corosio::select_t{}>&, boost::capy::mutable_buffer) :86 3x 100.0% 100.0% boost::corosio::native_posix_descriptor<boost::corosio::epoll_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::dispatch(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref) const :95 2x 100.0% 75.0% boost::corosio::native_posix_descriptor<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::dispatch(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref) const :95 2x 100.0% 75.0% boost::corosio::native_posix_descriptor<boost::corosio::epoll_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_posix_descriptor<boost::corosio::epoll_t{}>&, boost::corosio::wait_type) :129 2x 100.0% 100.0% boost::corosio::native_posix_descriptor<boost::corosio::select_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_posix_descriptor<boost::corosio::select_t{}>&, boost::corosio::wait_type) :129 2x 100.0% 100.0% boost::corosio::native_posix_descriptor<boost::corosio::epoll_t{}>::native_wait_awaitable::dispatch(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref) const :137 1x 100.0% 80.0% boost::corosio::native_posix_descriptor<boost::corosio::select_t{}>::native_wait_awaitable::dispatch(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref) const :137 1x 100.0% 80.0% boost::corosio::native_posix_descriptor<boost::corosio::epoll_t{}>::native_posix_descriptor(boost::capy::execution_context&) :148 6x 100.0% 100.0% boost::corosio::native_posix_descriptor<boost::corosio::select_t{}>::native_posix_descriptor(boost::capy::execution_context&) :148 6x 100.0% 100.0% auto boost::corosio::native_posix_descriptor<boost::corosio::epoll_t{}>::read_some<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&) :190 3x 100.0% 100.0% auto boost::corosio::native_posix_descriptor<boost::corosio::select_t{}>::read_some<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&) :190 3x 100.0% 100.0%
Line TLA Hits Source 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
74 6x impl_type& get_impl() noexcept
75 {
76 6x 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
86 6x native_read_awaitable(
87 native_posix_descriptor& self,
88 MutableBufferSequence buffers) noexcept
89 6x : self_(self)
90 6x , buffers_(std::move(buffers))
91 {
92 6x }
93
94 std::coroutine_handle<>
95 4x dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
96 {
97 12x return self_.get_impl().read_some(
98 12x 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
129 4x native_wait_awaitable(
130 native_posix_descriptor& self, wait_type w) noexcept
131 4x : self_(self)
132 4x , w_(w)
133 {
134 4x }
135
136 std::coroutine_handle<>
137 2x dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
138 {
139 2x 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 */
148 12x explicit native_posix_descriptor(capy::execution_context& ctx)
149 12x : io_object(handle(ctx, ctx.use_service<service_type>()))
150 {
151 12x }
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>
190 6x [[nodiscard]] auto read_some(MB const& buffers)
191 {
192 6x 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 */
219 4x [[nodiscard]] auto wait(wait_type w)
220 {
221 4x 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
230