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