include/boost/corosio/native/native_local_stream_socket.hpp

100.0% Lines (73/0/73) 100.0% List of functions (44/0/44)
native_local_stream_socket.hpp
f(x) Functions (44)
Function Calls Lines Blocks
boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::get_impl() :75 17x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::get_impl() :75 17x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::native_read_awaitable(boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>&, boost::capy::mutable_buffer) :89 4x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::native_read_awaitable(boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>&, boost::capy::mutable_buffer) :89 4x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_ready() const :97 4x 100.0% 88.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_ready() const :97 4x 100.0% 88.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_resume() const :104 4x 100.0% 86.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_resume() const :104 4x 100.0% 86.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :111 4x 100.0% 77.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :111 4x 100.0% 77.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_write_awaitable<boost::capy::const_buffer>::native_write_awaitable(boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>&, boost::capy::const_buffer) :129 4x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_write_awaitable<boost::capy::const_buffer>::native_write_awaitable(boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>&, boost::capy::const_buffer) :129 4x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_ready() const :137 4x 100.0% 88.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_ready() const :137 4x 100.0% 88.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_resume() const :144 4x 100.0% 86.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_resume() const :144 4x 100.0% 86.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :151 4x 100.0% 77.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :151 4x 100.0% 77.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>&, boost::corosio::wait_type) :167 3x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>&, boost::corosio::wait_type) :167 3x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_wait_awaitable::await_ready() const :174 3x 100.0% 88.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_wait_awaitable::await_ready() const :174 3x 100.0% 88.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_wait_awaitable::await_resume() const :181 3x 100.0% 86.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_wait_awaitable::await_resume() const :181 3x 100.0% 86.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_wait_awaitable::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :188 3x 100.0% 82.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_wait_awaitable::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :188 3x 100.0% 82.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_connect_awaitable::native_connect_awaitable(boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>&, boost::corosio::local_endpoint) :204 6x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_connect_awaitable::native_connect_awaitable(boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>&, boost::corosio::local_endpoint) :204 6x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_connect_awaitable::await_ready() const :212 6x 100.0% 88.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_connect_awaitable::await_ready() const :212 6x 100.0% 88.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_connect_awaitable::await_resume() const :219 6x 100.0% 86.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_connect_awaitable::await_resume() const :219 6x 100.0% 86.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_connect_awaitable::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :226 6x 100.0% 82.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_connect_awaitable::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :226 6x 100.0% 82.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_local_stream_socket(boost::capy::execution_context&) :240 20x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_local_stream_socket(boost::capy::execution_context&) :240 20x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::native_local_stream_socket(boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>&&) :260 3x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::native_local_stream_socket(boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>&&) :260 3x 100.0% 100.0% auto boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::read_some<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&) :280 4x 100.0% 100.0% auto boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::read_some<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&) :280 4x 100.0% 100.0% auto boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::write_some<boost::capy::const_buffer>(boost::capy::const_buffer const&) :295 4x 100.0% 100.0% auto boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::write_some<boost::capy::const_buffer>(boost::capy::const_buffer const&) :295 4x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::epoll_t{}>::connect(boost::corosio::local_endpoint) :314 6x 100.0% 100.0% boost::corosio::native_local_stream_socket<boost::corosio::select_t{}>::connect(boost::corosio::local_endpoint) :314 6x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Steve Gerbino
3 // Copyright (c) 2026 Michael Vandeberg
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/cppalliance/corosio
9 //
10
11 #ifndef BOOST_COROSIO_NATIVE_NATIVE_LOCAL_STREAM_SOCKET_HPP
12 #define BOOST_COROSIO_NATIVE_NATIVE_LOCAL_STREAM_SOCKET_HPP
13
14 #include <boost/corosio/local_stream_socket.hpp>
15 #include <boost/corosio/backend.hpp>
16
17 #ifndef BOOST_COROSIO_MRDOCS
18 #if BOOST_COROSIO_HAS_EPOLL
19 #include <boost/corosio/native/detail/epoll/epoll_types.hpp>
20 #endif
21
22 #if BOOST_COROSIO_HAS_SELECT
23 #include <boost/corosio/native/detail/select/select_types.hpp>
24 #endif
25
26 #if BOOST_COROSIO_HAS_KQUEUE
27 #include <boost/corosio/native/detail/kqueue/kqueue_types.hpp>
28 #endif
29
30 #if BOOST_COROSIO_HAS_IO_URING
31 #include <boost/corosio/native/detail/io_uring/io_uring_types.hpp>
32 #endif
33
34 #if BOOST_COROSIO_HAS_IOCP
35 #include <boost/corosio/native/detail/iocp/win_local_stream_service.hpp>
36 #endif
37 #endif // !BOOST_COROSIO_MRDOCS
38
39 namespace boost::corosio {
40
41 /** An asynchronous Unix stream socket with devirtualized I/O operations.
42
43 This class template inherits from @ref local_stream_socket and
44 shadows the async operations (`read_some`, `write_some`,
45 `connect`) with versions that call the backend implementation
46 directly, allowing the compiler to inline through the entire
47 call chain.
48
49 Non-async operations (`open`, `close`, `cancel`, socket options)
50 remain unchanged and dispatch through the compiled library.
51
52 A `native_local_stream_socket` IS-A `local_stream_socket` and
53 can be passed to any function expecting `local_stream_socket&`
54 or `io_stream&`, in which case virtual dispatch is used
55 transparently.
56
57 @tparam Backend A backend tag value (e.g., `epoll`) whose type
58 provides the concrete implementation types.
59
60 @par Thread Safety
61 Same as @ref local_stream_socket.
62
63 @par Example
64 @par !example connect
65
66 @see local_stream_socket, epoll_t, iocp_t
67 */
68 template<auto Backend>
69 class native_local_stream_socket : public local_stream_socket
70 {
71 using backend_type = decltype(Backend);
72 using impl_type = typename backend_type::local_stream_socket_type;
73 using service_type = typename backend_type::local_stream_service_type;
74
75 34x impl_type& get_impl() noexcept
76 {
77 34x return *static_cast<impl_type*>(h_.get());
78 }
79
80 template<class MutableBufferSequence>
81 struct native_read_awaitable
82 {
83 native_local_stream_socket& self_;
84 MutableBufferSequence buffers_;
85 std::stop_token token_;
86 mutable std::error_code ec_;
87 mutable std::size_t bytes_transferred_ = 0;
88
89 8x native_read_awaitable(
90 native_local_stream_socket& self,
91 MutableBufferSequence buffers) noexcept
92 8x : self_(self)
93 8x , buffers_(std::move(buffers))
94 {
95 8x }
96
97 8x bool await_ready() const noexcept
98 {
99 // A pre-set ec_ means the initiator failed before
100 // dispatch (e.g. a closed object).
101 8x return static_cast<bool>(ec_) || token_.stop_requested();
102 }
103
104 8x [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept
105 {
106 8x if (token_.stop_requested())
107 2x return {make_error_code(std::errc::operation_canceled), 0};
108 6x return {ec_, bytes_transferred_};
109 }
110
111 8x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
112 -> std::coroutine_handle<>
113 {
114 8x token_ = env->stop_token;
115 24x return self_.get_impl().read_some(
116 24x h, env->executor, buffers_, token_, &ec_, &bytes_transferred_);
117 }
118 };
119
120 template<class ConstBufferSequence>
121 struct native_write_awaitable
122 {
123 native_local_stream_socket& self_;
124 ConstBufferSequence buffers_;
125 std::stop_token token_;
126 mutable std::error_code ec_;
127 mutable std::size_t bytes_transferred_ = 0;
128
129 8x native_write_awaitable(
130 native_local_stream_socket& self,
131 ConstBufferSequence buffers) noexcept
132 8x : self_(self)
133 8x , buffers_(std::move(buffers))
134 {
135 8x }
136
137 8x bool await_ready() const noexcept
138 {
139 // A pre-set ec_ means the initiator failed before
140 // dispatch (e.g. a closed object).
141 8x return static_cast<bool>(ec_) || token_.stop_requested();
142 }
143
144 8x [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept
145 {
146 8x if (token_.stop_requested())
147 2x return {make_error_code(std::errc::operation_canceled), 0};
148 6x return {ec_, bytes_transferred_};
149 }
150
151 8x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
152 -> std::coroutine_handle<>
153 {
154 8x token_ = env->stop_token;
155 24x return self_.get_impl().write_some(
156 24x h, env->executor, buffers_, token_, &ec_, &bytes_transferred_);
157 }
158 };
159
160 struct native_wait_awaitable
161 {
162 native_local_stream_socket& self_;
163 wait_type w_;
164 std::stop_token token_;
165 mutable std::error_code ec_;
166
167 6x native_wait_awaitable(
168 native_local_stream_socket& self, wait_type w) noexcept
169 6x : self_(self)
170 6x , w_(w)
171 {
172 6x }
173
174 6x bool await_ready() const noexcept
175 {
176 // A pre-set ec_ means the initiator failed before
177 // dispatch (e.g. auto-open).
178 6x return static_cast<bool>(ec_) || token_.stop_requested();
179 }
180
181 6x [[nodiscard]] capy::io_result<> await_resume() const noexcept
182 {
183 6x if (token_.stop_requested())
184 2x return {make_error_code(std::errc::operation_canceled)};
185 4x return {ec_};
186 }
187
188 6x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
189 -> std::coroutine_handle<>
190 {
191 6x token_ = env->stop_token;
192 18x return self_.get_impl().wait(
193 18x h, env->executor, w_, token_, &ec_);
194 }
195 };
196
197 struct native_connect_awaitable
198 {
199 native_local_stream_socket& self_;
200 corosio::local_endpoint endpoint_;
201 std::stop_token token_;
202 mutable std::error_code ec_;
203
204 12x native_connect_awaitable(
205 native_local_stream_socket& self,
206 corosio::local_endpoint ep) noexcept
207 12x : self_(self)
208 12x , endpoint_(ep)
209 {
210 12x }
211
212 12x bool await_ready() const noexcept
213 {
214 // A pre-set ec_ means the initiator failed before
215 // dispatch (e.g. a closed object).
216 12x return static_cast<bool>(ec_) || token_.stop_requested();
217 }
218
219 12x [[nodiscard]] capy::io_result<> await_resume() const noexcept
220 {
221 12x if (token_.stop_requested())
222 2x return {make_error_code(std::errc::operation_canceled)};
223 10x return {ec_};
224 }
225
226 12x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
227 -> std::coroutine_handle<>
228 {
229 12x token_ = env->stop_token;
230 36x return self_.get_impl().connect(
231 36x h, env->executor, endpoint_, token_, &ec_);
232 }
233 };
234
235 public:
236 /** Construct a native socket from an execution context.
237
238 @param ctx The execution context that will own this socket.
239 */
240 40x explicit native_local_stream_socket(capy::execution_context& ctx)
241 40x : io_object(create_handle<service_type>(ctx))
242 {
243 40x }
244
245 /** Construct a native socket from an executor.
246
247 @param ex The executor whose context will own the socket.
248 */
249 template<class Ex>
250 requires(!std::same_as<
251 std::remove_cvref_t<Ex>,
252 native_local_stream_socket>) &&
253 capy::Executor<Ex>
254 explicit native_local_stream_socket(Ex const& ex)
255 : native_local_stream_socket(ex.context())
256 {
257 }
258
259 /// Move construct.
260 6x native_local_stream_socket(native_local_stream_socket&&) noexcept = default;
261
262 /// Move assign.
263 native_local_stream_socket&
264 operator=(native_local_stream_socket&&) noexcept = default;
265
266 native_local_stream_socket(native_local_stream_socket const&) = delete;
267 native_local_stream_socket&
268 operator=(native_local_stream_socket const&) = delete;
269
270 /** Asynchronously read data from the socket.
271
272 Calls the backend implementation directly, bypassing virtual
273 dispatch. Otherwise identical to @ref io_stream::read_some.
274
275 @param buffers The buffer sequence to read into.
276
277 @return An awaitable yielding `(error_code, std::size_t)`.
278 */
279 template<capy::MutableBufferSequence MB>
280 8x [[nodiscard]] auto read_some(MB const& buffers)
281 {
282 8x return native_read_awaitable<MB>(*this, buffers);
283 }
284
285 /** Asynchronously write data to the socket.
286
287 Calls the backend implementation directly, bypassing virtual
288 dispatch. Otherwise identical to @ref io_stream::write_some.
289
290 @param buffers The buffer sequence to write from.
291
292 @return An awaitable yielding `(error_code, std::size_t)`.
293 */
294 template<capy::ConstBufferSequence CB>
295 8x [[nodiscard]] auto write_some(CB const& buffers)
296 {
297 8x return native_write_awaitable<CB>(*this, buffers);
298 }
299
300 /** Asynchronously connect to a remote endpoint.
301
302 Calls the backend implementation directly, bypassing virtual
303 dispatch. Otherwise identical to @ref local_stream_socket::connect.
304
305 If the socket is not already open, it is opened automatically.
306
307 @param ep The local endpoint (path) to connect to.
308
309 @return An awaitable yielding `io_result<>`.
310
311 If the socket needs to be opened and the open fails, the
312 awaitable completes immediately with that error.
313 */
314 12x [[nodiscard]] auto connect(corosio::local_endpoint ep)
315 {
316 12x native_connect_awaitable aw(*this, ep);
317 12x if (!is_open())
318 10x aw.ec_ = open();
319 12x return aw;
320 }
321
322 /** Asynchronously wait for the socket to be ready.
323
324 Calls the backend implementation directly, bypassing virtual
325 dispatch. Otherwise identical to @ref local_stream_socket::wait.
326
327 @param w The wait direction (read, write, or error).
328
329 @return An awaitable yielding `io_result<>`.
330 */
331 6x [[nodiscard]] auto wait(wait_type w)
332 {
333 6x return native_wait_awaitable(*this, w);
334 }
335 };
336
337 } // namespace boost::corosio
338
339 #endif // BOOST_COROSIO_NATIVE_NATIVE_LOCAL_STREAM_SOCKET_HPP
340