include/boost/corosio/native/native_local_datagram_socket.hpp

95.3% Lines (123/129) 100.0% List of functions (70/70)
native_local_datagram_socket.hpp
f(x) Functions (70)
Function Calls Lines Blocks
boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::get_impl() :82 9x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::get_impl() :82 9x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_send_to_awaitable<boost::capy::const_buffer>::native_send_to_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>&, boost::capy::const_buffer, boost::corosio::local_endpoint, int) :98 2x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_send_to_awaitable<boost::capy::const_buffer>::native_send_to_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>&, boost::capy::const_buffer, boost::corosio::local_endpoint, int) :98 2x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_send_to_awaitable<boost::capy::const_buffer>::await_ready() const :110 2x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_send_to_awaitable<boost::capy::const_buffer>::await_ready() const :110 2x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_send_to_awaitable<boost::capy::const_buffer>::await_resume() const :115 2x 75.0% 67.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_send_to_awaitable<boost::capy::const_buffer>::await_resume() const :115 2x 75.0% 67.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_send_to_awaitable<boost::capy::const_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :122 2x 100.0% 77.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_send_to_awaitable<boost::capy::const_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :122 2x 100.0% 77.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_recv_from_awaitable<boost::capy::mutable_buffer>::native_recv_from_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>&, boost::capy::mutable_buffer, boost::corosio::local_endpoint&, int) :143 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_recv_from_awaitable<boost::capy::mutable_buffer>::native_recv_from_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>&, boost::capy::mutable_buffer, boost::corosio::local_endpoint&, int) :143 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_recv_from_awaitable<boost::capy::mutable_buffer>::await_ready() const :155 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_recv_from_awaitable<boost::capy::mutable_buffer>::await_ready() const :155 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_recv_from_awaitable<boost::capy::mutable_buffer>::await_resume() const :160 1x 75.0% 67.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_recv_from_awaitable<boost::capy::mutable_buffer>::await_resume() const :160 1x 75.0% 67.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_recv_from_awaitable<boost::capy::mutable_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :167 1x 100.0% 77.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_recv_from_awaitable<boost::capy::mutable_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :167 1x 100.0% 77.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>&, boost::corosio::wait_type) :184 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>&, boost::corosio::wait_type) :184 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_wait_awaitable::await_ready() const :191 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_wait_awaitable::await_ready() const :191 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_wait_awaitable::await_resume() const :196 1x 75.0% 67.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_wait_awaitable::await_resume() const :196 1x 75.0% 67.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_wait_awaitable::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :203 1x 100.0% 82.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_wait_awaitable::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :203 1x 100.0% 82.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_connect_awaitable::native_connect_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>&, boost::corosio::local_endpoint) :219 3x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_connect_awaitable::native_connect_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>&, boost::corosio::local_endpoint) :219 3x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_connect_awaitable::await_ready() const :227 3x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_connect_awaitable::await_ready() const :227 3x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_connect_awaitable::await_resume() const :232 3x 75.0% 67.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_connect_awaitable::await_resume() const :232 3x 75.0% 67.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_connect_awaitable::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :239 3x 100.0% 82.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_connect_awaitable::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :239 3x 100.0% 82.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_send_awaitable<boost::capy::const_buffer>::native_send_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>&, boost::capy::const_buffer, int) :258 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_send_awaitable<boost::capy::const_buffer>::native_send_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>&, boost::capy::const_buffer, int) :258 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_send_awaitable<boost::capy::const_buffer>::await_ready() const :268 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_send_awaitable<boost::capy::const_buffer>::await_ready() const :268 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_send_awaitable<boost::capy::const_buffer>::await_resume() const :273 1x 75.0% 67.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_send_awaitable<boost::capy::const_buffer>::await_resume() const :273 1x 75.0% 67.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_send_awaitable<boost::capy::const_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :280 1x 100.0% 77.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_send_awaitable<boost::capy::const_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :280 1x 100.0% 77.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_recv_awaitable<boost::capy::mutable_buffer>::native_recv_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>&, boost::capy::mutable_buffer, int) :300 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_recv_awaitable<boost::capy::mutable_buffer>::native_recv_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>&, boost::capy::mutable_buffer, int) :300 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_recv_awaitable<boost::capy::mutable_buffer>::await_ready() const :310 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_recv_awaitable<boost::capy::mutable_buffer>::await_ready() const :310 1x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_recv_awaitable<boost::capy::mutable_buffer>::await_resume() const :315 1x 75.0% 67.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_recv_awaitable<boost::capy::mutable_buffer>::await_resume() const :315 1x 75.0% 67.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_recv_awaitable<boost::capy::mutable_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :322 1x 100.0% 77.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_recv_awaitable<boost::capy::mutable_buffer>::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :322 1x 100.0% 77.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_local_datagram_socket(boost::capy::execution_context&) :337 13x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_local_datagram_socket(boost::capy::execution_context&) :337 13x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::send_to<boost::capy::const_buffer>(boost::capy::const_buffer const&, boost::corosio::local_endpoint, boost::corosio::message_flags) :374 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::send_to<boost::capy::const_buffer>(boost::capy::const_buffer const&, boost::corosio::local_endpoint, boost::corosio::message_flags) :374 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::send_to<boost::capy::const_buffer>(boost::capy::const_buffer const&, boost::corosio::local_endpoint) :387 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::send_to<boost::capy::const_buffer>(boost::capy::const_buffer const&, boost::corosio::local_endpoint) :387 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::recv_from<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&, boost::corosio::local_endpoint&, boost::corosio::message_flags) :398 2x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::recv_from<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&, boost::corosio::local_endpoint&, boost::corosio::message_flags) :398 2x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::recv_from<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&, boost::corosio::local_endpoint&) :411 2x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::recv_from<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&, boost::corosio::local_endpoint&) :411 2x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::connect(boost::corosio::local_endpoint) :423 3x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::connect(boost::corosio::local_endpoint) :423 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::send<boost::capy::const_buffer>(boost::capy::const_buffer const&, boost::corosio::message_flags) :436 2x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::send<boost::capy::const_buffer>(boost::capy::const_buffer const&, boost::corosio::message_flags) :436 2x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::send<boost::capy::const_buffer>(boost::capy::const_buffer const&) :446 2x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::send<boost::capy::const_buffer>(boost::capy::const_buffer const&) :446 2x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::recv<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&, boost::corosio::message_flags) :457 2x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::recv<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&, boost::corosio::message_flags) :457 2x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::recv<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&) :467 2x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::recv<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&) :467 2x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Steve Gerbino
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_LOCAL_DATAGRAM_SOCKET_HPP
11 #define BOOST_COROSIO_NATIVE_NATIVE_LOCAL_DATAGRAM_SOCKET_HPP
12
13 #include <boost/corosio/detail/platform.hpp>
14
15 #if BOOST_COROSIO_POSIX
16
17 #include <boost/corosio/local_datagram_socket.hpp>
18 #include <boost/corosio/backend.hpp>
19
20 #ifndef BOOST_COROSIO_MRDOCS
21 #if BOOST_COROSIO_HAS_EPOLL
22 #include <boost/corosio/native/detail/epoll/epoll_types.hpp>
23 #endif
24
25 #if BOOST_COROSIO_HAS_SELECT
26 #include <boost/corosio/native/detail/select/select_types.hpp>
27 #endif
28
29 #if BOOST_COROSIO_HAS_KQUEUE
30 #include <boost/corosio/native/detail/kqueue/kqueue_types.hpp>
31 #endif
32 #endif // !BOOST_COROSIO_MRDOCS
33
34 namespace boost::corosio {
35
36 /** An asynchronous Unix datagram socket with devirtualized I/O.
37
38 This class template inherits from @ref local_datagram_socket
39 and shadows the async operations (`send_to`, `recv_from`,
40 `connect`, `send`, `recv`) with versions that call the backend
41 implementation directly, allowing the compiler to inline
42 through the entire call chain.
43
44 Non-async operations (`open`, `close`, `cancel`, `bind`,
45 socket options) remain unchanged and dispatch through the
46 compiled library.
47
48 A `native_local_datagram_socket` IS-A `local_datagram_socket`
49 and can be passed to any function expecting
50 `local_datagram_socket&`, in which case virtual dispatch is
51 used transparently.
52
53 @tparam Backend A backend tag value (e.g., `epoll`) whose type
54 provides the concrete implementation types.
55
56 @par Thread Safety
57 Same as @ref local_datagram_socket.
58
59 @par Example
60 @code
61 #include <boost/corosio/native/native_local_datagram_socket.hpp>
62
63 native_io_context<epoll> ctx;
64 native_local_datagram_socket<epoll> s(ctx);
65 s.open();
66 s.bind(local_endpoint("/tmp/recv.sock"));
67 char buf[1024];
68 local_endpoint sender;
69 auto [ec, n] = co_await s.recv_from(
70 capy::mutable_buffer(buf, sizeof(buf)), sender);
71 @endcode
72
73 @see local_datagram_socket, epoll_t, iocp_t
74 */
75 template<auto Backend>
76 class native_local_datagram_socket : public local_datagram_socket
77 {
78 using backend_type = decltype(Backend);
79 using impl_type = typename backend_type::local_datagram_socket_type;
80 using service_type = typename backend_type::local_datagram_service_type;
81
82 18x impl_type& get_impl() noexcept
83 {
84 18x return *static_cast<impl_type*>(h_.get());
85 }
86
87 template<class ConstBufferSequence>
88 struct native_send_to_awaitable
89 {
90 native_local_datagram_socket& self_;
91 ConstBufferSequence buffers_;
92 corosio::local_endpoint dest_;
93 int flags_;
94 std::stop_token token_;
95 mutable std::error_code ec_;
96 mutable std::size_t bytes_transferred_ = 0;
97
98 4x native_send_to_awaitable(
99 native_local_datagram_socket& self,
100 ConstBufferSequence buffers,
101 corosio::local_endpoint dest,
102 int flags) noexcept
103 4x : self_(self)
104 4x , buffers_(std::move(buffers))
105 4x , dest_(dest)
106 4x , flags_(flags)
107 {
108 4x }
109
110 4x bool await_ready() const noexcept
111 {
112 4x return token_.stop_requested();
113 }
114
115 4x capy::io_result<std::size_t> await_resume() const noexcept
116 {
117 4x if (token_.stop_requested())
118 return {make_error_code(std::errc::operation_canceled), 0};
119 4x return {ec_, bytes_transferred_};
120 }
121
122 4x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
123 -> std::coroutine_handle<>
124 {
125 4x token_ = env->stop_token;
126 12x return self_.get_impl().send_to(
127 4x h, env->executor, buffers_, dest_, flags_,
128 12x token_, &ec_, &bytes_transferred_);
129 }
130 };
131
132 template<class MutableBufferSequence>
133 struct native_recv_from_awaitable
134 {
135 native_local_datagram_socket& self_;
136 MutableBufferSequence buffers_;
137 corosio::local_endpoint& source_;
138 int flags_;
139 std::stop_token token_;
140 mutable std::error_code ec_;
141 mutable std::size_t bytes_transferred_ = 0;
142
143 2x native_recv_from_awaitable(
144 native_local_datagram_socket& self,
145 MutableBufferSequence buffers,
146 corosio::local_endpoint& source,
147 int flags) noexcept
148 2x : self_(self)
149 2x , buffers_(std::move(buffers))
150 2x , source_(source)
151 2x , flags_(flags)
152 {
153 2x }
154
155 2x bool await_ready() const noexcept
156 {
157 2x return token_.stop_requested();
158 }
159
160 2x capy::io_result<std::size_t> await_resume() const noexcept
161 {
162 2x if (token_.stop_requested())
163 return {make_error_code(std::errc::operation_canceled), 0};
164 2x return {ec_, bytes_transferred_};
165 }
166
167 2x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
168 -> std::coroutine_handle<>
169 {
170 2x token_ = env->stop_token;
171 6x return self_.get_impl().recv_from(
172 2x h, env->executor, buffers_, &source_, flags_,
173 6x token_, &ec_, &bytes_transferred_);
174 }
175 };
176
177 struct native_wait_awaitable
178 {
179 native_local_datagram_socket& self_;
180 wait_type w_;
181 std::stop_token token_;
182 mutable std::error_code ec_;
183
184 2x native_wait_awaitable(
185 native_local_datagram_socket& self, wait_type w) noexcept
186 2x : self_(self)
187 2x , w_(w)
188 {
189 2x }
190
191 2x bool await_ready() const noexcept
192 {
193 2x return token_.stop_requested();
194 }
195
196 2x capy::io_result<> await_resume() const noexcept
197 {
198 2x if (token_.stop_requested())
199 return {make_error_code(std::errc::operation_canceled)};
200 2x return {ec_};
201 }
202
203 2x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
204 -> std::coroutine_handle<>
205 {
206 2x token_ = env->stop_token;
207 6x return self_.get_impl().wait(
208 6x h, env->executor, w_, token_, &ec_);
209 }
210 };
211
212 struct native_connect_awaitable
213 {
214 native_local_datagram_socket& self_;
215 corosio::local_endpoint endpoint_;
216 std::stop_token token_;
217 mutable std::error_code ec_;
218
219 6x native_connect_awaitable(
220 native_local_datagram_socket& self,
221 corosio::local_endpoint ep) noexcept
222 6x : self_(self)
223 6x , endpoint_(ep)
224 {
225 6x }
226
227 6x bool await_ready() const noexcept
228 {
229 6x return token_.stop_requested();
230 }
231
232 6x capy::io_result<> await_resume() const noexcept
233 {
234 6x if (token_.stop_requested())
235 return {make_error_code(std::errc::operation_canceled)};
236 6x return {ec_};
237 }
238
239 6x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
240 -> std::coroutine_handle<>
241 {
242 6x token_ = env->stop_token;
243 18x return self_.get_impl().connect(
244 18x h, env->executor, endpoint_, token_, &ec_);
245 }
246 };
247
248 template<class ConstBufferSequence>
249 struct native_send_awaitable
250 {
251 native_local_datagram_socket& self_;
252 ConstBufferSequence buffers_;
253 int flags_;
254 std::stop_token token_;
255 mutable std::error_code ec_;
256 mutable std::size_t bytes_transferred_ = 0;
257
258 2x native_send_awaitable(
259 native_local_datagram_socket& self,
260 ConstBufferSequence buffers,
261 int flags) noexcept
262 2x : self_(self)
263 2x , buffers_(std::move(buffers))
264 2x , flags_(flags)
265 {
266 2x }
267
268 2x bool await_ready() const noexcept
269 {
270 2x return token_.stop_requested();
271 }
272
273 2x capy::io_result<std::size_t> await_resume() const noexcept
274 {
275 2x if (token_.stop_requested())
276 return {make_error_code(std::errc::operation_canceled), 0};
277 2x return {ec_, bytes_transferred_};
278 }
279
280 2x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
281 -> std::coroutine_handle<>
282 {
283 2x token_ = env->stop_token;
284 6x return self_.get_impl().send(
285 2x h, env->executor, buffers_, flags_,
286 6x token_, &ec_, &bytes_transferred_);
287 }
288 };
289
290 template<class MutableBufferSequence>
291 struct native_recv_awaitable
292 {
293 native_local_datagram_socket& self_;
294 MutableBufferSequence buffers_;
295 int flags_;
296 std::stop_token token_;
297 mutable std::error_code ec_;
298 mutable std::size_t bytes_transferred_ = 0;
299
300 2x native_recv_awaitable(
301 native_local_datagram_socket& self,
302 MutableBufferSequence buffers,
303 int flags) noexcept
304 2x : self_(self)
305 2x , buffers_(std::move(buffers))
306 2x , flags_(flags)
307 {
308 2x }
309
310 2x bool await_ready() const noexcept
311 {
312 2x return token_.stop_requested();
313 }
314
315 2x capy::io_result<std::size_t> await_resume() const noexcept
316 {
317 2x if (token_.stop_requested())
318 return {make_error_code(std::errc::operation_canceled), 0};
319 2x return {ec_, bytes_transferred_};
320 }
321
322 2x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
323 -> std::coroutine_handle<>
324 {
325 2x token_ = env->stop_token;
326 6x return self_.get_impl().recv(
327 2x h, env->executor, buffers_, flags_,
328 6x token_, &ec_, &bytes_transferred_);
329 }
330 };
331
332 public:
333 /** Construct a native socket from an execution context.
334
335 @param ctx The execution context that will own this socket.
336 */
337 26x explicit native_local_datagram_socket(capy::execution_context& ctx)
338 26x : local_datagram_socket(create_handle<service_type>(ctx))
339 {
340 26x }
341
342 /** Construct a native socket from an executor.
343
344 @param ex The executor whose context will own the socket.
345 */
346 template<class Ex>
347 requires(!std::same_as<
348 std::remove_cvref_t<Ex>,
349 native_local_datagram_socket>) &&
350 capy::Executor<Ex>
351 explicit native_local_datagram_socket(Ex const& ex)
352 : native_local_datagram_socket(ex.context())
353 {
354 }
355
356 /// Move construct.
357 native_local_datagram_socket(native_local_datagram_socket&&) noexcept =
358 default;
359
360 /// Move assign.
361 native_local_datagram_socket&
362 operator=(native_local_datagram_socket&&) noexcept = default;
363
364 native_local_datagram_socket(native_local_datagram_socket const&) = delete;
365 native_local_datagram_socket&
366 operator=(native_local_datagram_socket const&) = delete;
367
368 /** Send a datagram to the specified destination.
369
370 Calls the backend implementation directly, bypassing virtual
371 dispatch. Otherwise identical to @ref local_datagram_socket::send_to.
372 */
373 template<capy::ConstBufferSequence CB>
374 6x auto send_to(
375 CB const& buffers,
376 corosio::local_endpoint dest,
377 corosio::message_flags flags)
378 {
379 6x if (!is_open())
380 2x detail::throw_logic_error("send_to: socket not open");
381 return native_send_to_awaitable<CB>(
382 4x *this, buffers, dest, static_cast<int>(flags));
383 }
384
385 /// @overload
386 template<capy::ConstBufferSequence CB>
387 6x auto send_to(CB const& buffers, corosio::local_endpoint dest)
388 {
389 6x return send_to(buffers, dest, corosio::message_flags::none);
390 }
391
392 /** Receive a datagram and capture the sender's endpoint.
393
394 Calls the backend implementation directly, bypassing virtual
395 dispatch. Otherwise identical to @ref local_datagram_socket::recv_from.
396 */
397 template<capy::MutableBufferSequence MB>
398 4x auto recv_from(
399 MB const& buffers,
400 corosio::local_endpoint& source,
401 corosio::message_flags flags)
402 {
403 4x if (!is_open())
404 2x detail::throw_logic_error("recv_from: socket not open");
405 return native_recv_from_awaitable<MB>(
406 2x *this, buffers, source, static_cast<int>(flags));
407 }
408
409 /// @overload
410 template<capy::MutableBufferSequence MB>
411 4x auto recv_from(MB const& buffers, corosio::local_endpoint& source)
412 {
413 4x return recv_from(buffers, source, corosio::message_flags::none);
414 }
415
416 /** Asynchronously connect to set the default peer.
417
418 Calls the backend implementation directly, bypassing virtual
419 dispatch. Otherwise identical to @ref local_datagram_socket::connect.
420
421 If the socket is not already open, it is opened automatically.
422 */
423 6x auto connect(corosio::local_endpoint ep)
424 {
425 6x if (!is_open())
426 2x open();
427 6x return native_connect_awaitable(*this, ep);
428 }
429
430 /** Send a datagram to the connected peer.
431
432 Calls the backend implementation directly, bypassing virtual
433 dispatch. Otherwise identical to @ref local_datagram_socket::send.
434 */
435 template<capy::ConstBufferSequence CB>
436 4x auto send(CB const& buffers, corosio::message_flags flags)
437 {
438 4x if (!is_open())
439 2x detail::throw_logic_error("send: socket not open");
440 return native_send_awaitable<CB>(
441 2x *this, buffers, static_cast<int>(flags));
442 }
443
444 /// @overload
445 template<capy::ConstBufferSequence CB>
446 4x auto send(CB const& buffers)
447 {
448 4x return send(buffers, corosio::message_flags::none);
449 }
450
451 /** Receive a datagram from the connected peer.
452
453 Calls the backend implementation directly, bypassing virtual
454 dispatch. Otherwise identical to @ref local_datagram_socket::recv.
455 */
456 template<capy::MutableBufferSequence MB>
457 4x auto recv(MB const& buffers, corosio::message_flags flags)
458 {
459 4x if (!is_open())
460 2x detail::throw_logic_error("recv: socket not open");
461 return native_recv_awaitable<MB>(
462 2x *this, buffers, static_cast<int>(flags));
463 }
464
465 /// @overload
466 template<capy::MutableBufferSequence MB>
467 4x auto recv(MB const& buffers)
468 {
469 4x return recv(buffers, corosio::message_flags::none);
470 }
471
472 /** Asynchronously wait for the socket to be ready.
473
474 Calls the backend implementation directly, bypassing virtual
475 dispatch. Otherwise identical to @ref local_datagram_socket::wait.
476
477 @param w The wait direction (read, write, or error).
478
479 @return An awaitable yielding `io_result<>`.
480 */
481 2x [[nodiscard]] auto wait(wait_type w)
482 {
483 2x return native_wait_awaitable(*this, w);
484 }
485 };
486
487 } // namespace boost::corosio
488
489 #endif // BOOST_COROSIO_POSIX
490
491 #endif // BOOST_COROSIO_NATIVE_NATIVE_LOCAL_DATAGRAM_SOCKET_HPP
492