include/boost/corosio/native/native_tcp_socket.hpp

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