include/boost/corosio/native/native_tcp_socket.hpp

95.5% Lines (85/89) 100.0% List of functions (66/66) 64.7% Branches (44/68)
native_tcp_socket.hpp
f(x) Functions (66)
Function Calls Lines Branches Blocks
boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::~native_tcp_socket() :68 92x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::~native_tcp_socket() :68 82x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::get_impl() :74 31x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::get_impl() :74 30x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::native_read_awaitable(boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_read_awaitable<boost::capy::mutable_buffer>&&) :80 14x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::~native_read_awaitable() :80 28x 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{}>::native_read_awaitable<boost::capy::mutable_buffer>&&) :80 14x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::~native_read_awaitable() :80 28x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::native_read_awaitable(boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>&, boost::capy::mutable_buffer) :88 14x 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 14x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_ready() const :95 7x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_ready() const :95 7x 100.0% 50.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_resume() const :102 7x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_resume() const :102 7x 100.0% 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_suspend(std::__1::coroutine_handle<void>, boost::capy::io_env const*) :109 7x 100.0% 50.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_read_awaitable<boost::capy::mutable_buffer>::await_suspend(std::__1::coroutine_handle<void>, boost::capy::io_env const*) :109 7x 80.0% 50.0% 50.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_write_awaitable<boost::capy::const_buffer>::native_write_awaitable(boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_write_awaitable<boost::capy::const_buffer>&&) :119 16x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_write_awaitable<boost::capy::const_buffer>::~native_write_awaitable() :119 32x 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{}>::native_write_awaitable<boost::capy::const_buffer>&&) :119 16x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_write_awaitable<boost::capy::const_buffer>::~native_write_awaitable() :119 32x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_write_awaitable<boost::capy::const_buffer>::native_write_awaitable(boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>&, boost::capy::const_buffer) :127 16x 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 16x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_ready() const :134 8x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_ready() const :134 8x 100.0% 50.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_resume() const :141 8x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_resume() const :141 8x 100.0% 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_suspend(std::__1::coroutine_handle<void>, boost::capy::io_env const*) :148 8x 100.0% 50.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_write_awaitable<boost::capy::const_buffer>::await_suspend(std::__1::coroutine_handle<void>, boost::capy::io_env const*) :148 8x 80.0% 50.0% 50.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_wait_awaitable&&) :157 6x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_wait_awaitable::~native_wait_awaitable() :157 12x 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{}>::native_wait_awaitable&&) :157 6x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_wait_awaitable::~native_wait_awaitable() :157 12x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>&, boost::corosio::wait_type) :164 6x 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 6x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_wait_awaitable::await_ready() const :170 3x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_wait_awaitable::await_ready() const :170 3x 100.0% 50.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_wait_awaitable::await_resume() const :177 3x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_wait_awaitable::await_resume() const :177 3x 100.0% 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_wait_awaitable::await_suspend(std::__1::coroutine_handle<void>, boost::capy::io_env const*) :184 3x 100.0% 50.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_wait_awaitable::await_suspend(std::__1::coroutine_handle<void>, boost::capy::io_env const*) :184 3x 75.0% 50.0% 50.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_connect_awaitable::native_connect_awaitable(boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_connect_awaitable&&) :192 52x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_connect_awaitable::~native_connect_awaitable() :192 78x 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{}>::native_connect_awaitable&&) :192 48x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_connect_awaitable::~native_connect_awaitable() :192 72x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_connect_awaitable::native_connect_awaitable(boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>&, boost::corosio::endpoint) :199 26x 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 24x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_connect_awaitable::await_ready() const :205 13x 100.0% 50.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_connect_awaitable::await_ready() const :205 12x 100.0% 50.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_connect_awaitable::await_resume() const :212 13x 80.0% 50.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_connect_awaitable::await_resume() const :212 12x 100.0% 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_connect_awaitable::await_suspend(std::__1::coroutine_handle<void>, boost::capy::io_env const*) :219 13x 80.0% 50.0% 50.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_connect_awaitable::await_suspend(std::__1::coroutine_handle<void>, boost::capy::io_env const*) :219 12x 80.0% 50.0% 50.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_tcp_socket(boost::capy::execution_context&) :233 29x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::native_tcp_socket(boost::capy::execution_context&) :233 26x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::native_tcp_socket(boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>&&) :259 17x 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 15x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::operator=(boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>&&) :272 3x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::operator=(boost::corosio::native_tcp_socket<boost::corosio::select_t{}>&&) :272 2x 100.0% 100.0% auto boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::read_some<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&) :291 7x 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 7x 100.0% 100.0% auto boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::write_some<boost::capy::const_buffer>(boost::capy::const_buffer const&) :310 8x 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 8x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::connect(boost::corosio::endpoint) :330 13x 83.3% 25.0% 83.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::connect(boost::corosio::endpoint) :330 12x 100.0% 75.0% 83.0% boost::corosio::native_tcp_socket<boost::corosio::kqueue_t{}>::wait(boost::corosio::wait_type) :347 3x 100.0% 100.0% boost::corosio::native_tcp_socket<boost::corosio::select_t{}>::wait(boost::corosio::wait_type) :347 3x 100.0% 100.0%
Line Branch 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 61x impl_type& get_impl() noexcept
75 {
76 61x 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 14x mutable std::size_t bytes_transferred_ = 0;
87
88 42x native_read_awaitable(
89 native_tcp_socket& self, MutableBufferSequence buffers) noexcept
90 14x : self_(self)
91 14x , buffers_(std::move(buffers))
92 14x {
93 28x }
94
95 14x bool await_ready() const noexcept
96 {
97 // A pre-set ec_ means the initiator failed before
98 // dispatch (e.g. a closed object).
99
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
14x return static_cast<bool>(ec_) || token_.stop_requested();
100 }
101
102 14x [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept
103 {
104
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 5 times.
14x if (token_.stop_requested())
105 4x return {make_error_code(std::errc::operation_canceled), 0};
106 10x return {ec_, bytes_transferred_};
107 14x }
108
109 14x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
110 -> std::coroutine_handle<>
111 {
112 14x token_ = env->stop_token;
113
4/8
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
28x return self_.get_impl().read_some(
114 14x 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 16x mutable std::size_t bytes_transferred_ = 0;
126
127 48x native_write_awaitable(
128 native_tcp_socket& self, ConstBufferSequence buffers) noexcept
129 16x : self_(self)
130 16x , buffers_(std::move(buffers))
131 16x {
132 32x }
133
134 16x bool await_ready() const noexcept
135 {
136 // A pre-set ec_ means the initiator failed before
137 // dispatch (e.g. a closed object).
138
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
16x return static_cast<bool>(ec_) || token_.stop_requested();
139 }
140
141 16x [[nodiscard]] capy::io_result<std::size_t> await_resume() const noexcept
142 {
143
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 7 times.
16x if (token_.stop_requested())
144 2x return {make_error_code(std::errc::operation_canceled), 0};
145 14x return {ec_, bytes_transferred_};
146 16x }
147
148 16x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
149 -> std::coroutine_handle<>
150 {
151 16x token_ = env->stop_token;
152
4/8
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
32x return self_.get_impl().write_some(
153 16x 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 18x native_wait_awaitable(native_tcp_socket& self, wait_type w) noexcept
165 6x : self_(self)
166 6x , w_(w)
167 6x {
168 12x }
169
170 6x bool await_ready() const noexcept
171 {
172 // A pre-set ec_ means the initiator failed before
173 // dispatch (e.g. a closed object).
174
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
6x return static_cast<bool>(ec_) || token_.stop_requested();
175 }
176
177 6x [[nodiscard]] capy::io_result<> await_resume() const noexcept
178 {
179
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 2 times.
6x if (token_.stop_requested())
180 2x return {make_error_code(std::errc::operation_canceled)};
181 4x return {ec_};
182 6x }
183
184 6x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
185 -> std::coroutine_handle<>
186 {
187 6x token_ = env->stop_token;
188
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6x 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 75x native_connect_awaitable(native_tcp_socket& self, endpoint ep) noexcept
200 25x : self_(self)
201 25x , endpoint_(ep)
202 25x {
203 50x }
204
205 25x bool await_ready() const noexcept
206 {
207 // A pre-set ec_ means the initiator failed before
208 // dispatch (e.g. a closed object).
209
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
25x return static_cast<bool>(ec_) || token_.stop_requested();
210 }
211
212 25x [[nodiscard]] capy::io_result<> await_resume() const noexcept
213 {
214
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 11 times.
25x if (token_.stop_requested())
215 2x return {make_error_code(std::errc::operation_canceled)};
216 23x return {ec_};
217 25x }
218
219 25x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
220 -> std::coroutine_handle<>
221 {
222 25x token_ = env->stop_token;
223
4/8
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
50x return self_.get_impl().connect(
224 25x 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 110x explicit native_tcp_socket(capy::execution_context& ctx)
234 55x : io_object(create_handle<service_type>(ctx))
235 110x {
236 55x }
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 32x 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 5x 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 14x [[nodiscard]] auto read_some(MB const& buffers)
292 {
293 14x 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 16x [[nodiscard]] auto write_some(CB const& buffers)
311 {
312 16x 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 25x [[nodiscard]] auto connect(endpoint ep)
331 {
332 25x native_connect_awaitable aw(*this, ep);
333
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1 time.
25x if (!is_open())
334
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
2x aw.ec_ = open(ep.is_v6() ? tcp::v6() : tcp::v4());
335 25x return aw;
336 25x }
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 6x [[nodiscard]] auto wait(wait_type w)
348 {
349 6x return native_wait_awaitable(*this, w);
350 }
351 };
352
353 } // namespace boost::corosio
354
355 #endif
356