include/boost/corosio/native/detail/reactor/reactor_op_complete.hpp

91.7% Lines (99/108) 100.0% List of functions (16/16) 55.2% Branches (128/232)
reactor_op_complete.hpp
f(x) Functions (16)
Function Calls Lines Branches Blocks
void boost::corosio::detail::complete_io_op<boost::corosio::detail::kqueue_datagram_op>(boost::corosio::detail::kqueue_datagram_op&) :39 10x 100.0% 66.0% void boost::corosio::detail::complete_io_op<boost::corosio::detail::kqueue_op>(boost::corosio::detail::kqueue_op&) :39 213791x 100.0% 79.2% 86.0% void boost::corosio::detail::complete_io_op<boost::corosio::detail::kqueue_recv_op>(boost::corosio::detail::kqueue_recv_op&) :39 2x 93.8% 36.1% 73.0% void boost::corosio::detail::complete_io_op<boost::corosio::detail::select_datagram_op>(boost::corosio::detail::select_datagram_op&) :39 10x 100.0% 66.0% void boost::corosio::detail::complete_io_op<boost::corosio::detail::select_op>(boost::corosio::detail::select_op&) :39 203956x 0.0% 0.0% 80.0% void boost::corosio::detail::complete_io_op<boost::corosio::detail::select_recv_op>(boost::corosio::detail::select_recv_op&) :39 2x 100.0% 73.0% void boost::corosio::detail::complete_connect_op<boost::corosio::detail::kqueue_connect_op>(boost::corosio::detail::kqueue_connect_op&) :72 5309x 96.0% 66.7% 83.0% void boost::corosio::detail::complete_connect_op<boost::corosio::detail::kqueue_udp_connect_op>(boost::corosio::detail::kqueue_udp_connect_op&) :72 5x 92.0% 25.0% 77.0% void boost::corosio::detail::complete_connect_op<boost::corosio::detail::select_connect_op>(boost::corosio::detail::select_connect_op&) :72 1739x 0.0% 0.0% 83.0% void boost::corosio::detail::complete_connect_op<boost::corosio::detail::select_udp_connect_op>(boost::corosio::detail::select_udp_connect_op&) :72 5x 100.0% 77.0% bool boost::corosio::detail::setup_accepted_socket<boost::corosio::detail::kqueue_tcp_socket, boost::corosio::detail::kqueue_tcp_acceptor>(boost::corosio::detail::kqueue_tcp_acceptor*, int&, sockaddr_storage const&, boost::corosio::io_object::implementation**, std::__1::error_code*) :122 5307x 90.5% 50.0% 83.0% bool boost::corosio::detail::setup_accepted_socket<boost::corosio::detail::select_tcp_socket, boost::corosio::detail::select_tcp_acceptor>(boost::corosio::detail::select_tcp_acceptor*, int&, sockaddr_storage const&, boost::corosio::io_object::implementation**, std::__1::error_code*) :122 1737x 100.0% 83.0% void boost::corosio::detail::complete_accept_op<boost::corosio::detail::kqueue_tcp_socket, boost::corosio::detail::kqueue_accept_op>(boost::corosio::detail::kqueue_accept_op&) :168 5316x 82.8% 61.5% 80.0% void boost::corosio::detail::complete_accept_op<boost::corosio::detail::select_tcp_socket, boost::corosio::detail::select_accept_op>(boost::corosio::detail::select_accept_op&) :168 1740x 100.0% 80.0% void boost::corosio::detail::complete_datagram_op<boost::corosio::detail::kqueue_recv_from_op>(boost::corosio::detail::kqueue_recv_from_op&, boost::corosio::endpoint*) :221 11x 94.1% 71.4% 80.0% void boost::corosio::detail::complete_datagram_op<boost::corosio::detail::select_recv_from_op>(boost::corosio::detail::select_recv_from_op&, boost::corosio::endpoint*) :221 14x 100.0% 80.0%
Line Branch 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_DETAIL_REACTOR_REACTOR_OP_COMPLETE_HPP
11 #define BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_OP_COMPLETE_HPP
12
13 #include <boost/corosio/detail/dispatch_coro.hpp>
14 #include <boost/corosio/native/detail/endpoint_convert.hpp>
15 #include <boost/corosio/native/detail/make_err.hpp>
16 #include <boost/corosio/io/io_object.hpp>
17
18 #include <coroutine>
19 #include <mutex>
20 #include <utility>
21
22 #include <netinet/in.h>
23 #include <sys/socket.h>
24 #include <unistd.h>
25
26 namespace boost::corosio::detail {
27
28 /** Complete a base read/write operation.
29
30 Translates the recorded errno and cancellation state into
31 an error_code, stores the byte count, then resumes the
32 caller via symmetric transfer.
33
34 @tparam Op The concrete operation type.
35 @param op The operation to complete.
36 */
37 template<typename Op>
38 void
39 417771x complete_io_op(Op& op)
40 {
41 417771x op.stop_cb.reset();
42 417771x op.socket_impl_->desc_state_.scheduler_->reset_inline_budget();
43
44
9/12
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 203894 times.
✓ Branch 2 taken 726 times.
✓ Branch 3 taken 213075 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 10 times.
✓ Branch 10 taken 1 time.
✓ Branch 11 taken 1 time.
417771x if (op.cancelled.load(std::memory_order_acquire))
45 790x *op.ec_out = capy::error::canceled;
46
8/12
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 203893 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 213068 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 8 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 time.
416981x else if (op.errn != 0)
47 10x *op.ec_out = make_err(op.errn);
48
12/24
✓ Branch 0 taken 123740 times.
✓ Branch 1 taken 80153 times.
✓ Branch 2 taken 123740 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 125430 times.
✓ Branch 5 taken 87638 times.
✓ Branch 6 taken 125425 times.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 1 time.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 time.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 8 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 time.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 time.
✗ Branch 23 not taken.
416971x else if (op.is_read_operation() && op.bytes_transferred == 0)
49 5x *op.ec_out = capy::error::eof;
50 else
51 416966x *op.ec_out = {};
52
53 417771x *op.bytes_out = op.bytes_transferred;
54
55 417771x op.cont_op.cont.h = op.h;
56 417771x capy::executor_ref saved_ex(op.ex);
57 417771x auto prevent = std::move(op.impl_ptr);
58
10/24
✓ Branch 0 taken 203956 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 203956 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 213801 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 213801 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 10 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 10 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 2 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 2 times.
✗ Branch 23 not taken.
417771x dispatch_coro(saved_ex, op.cont_op.cont).resume();
59 417771x }
60
61 /** Complete a connect operation with endpoint caching.
62
63 On success, queries the local endpoint via getsockname and
64 caches both endpoints in the socket impl. Then resumes the
65 caller via symmetric transfer.
66
67 @tparam Op The concrete connect operation type.
68 @param op The operation to complete.
69 */
70 template<typename Op>
71 void
72 7058x complete_connect_op(Op& op)
73 {
74 7058x op.stop_cb.reset();
75 7058x op.socket_impl_->desc_state_.scheduler_->reset_inline_budget();
76
77 7058x bool success =
78
5/8
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1737 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 5312 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
7058x (op.errn == 0 && !op.cancelled.load(std::memory_order_acquire));
79
80
8/16
✓ Branch 0 taken 1737 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1737 times.
✓ Branch 4 taken 5312 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5312 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 5 times.
7058x if (success && op.socket_impl_)
81 {
82 7054x endpoint local_ep;
83 7054x sockaddr_storage local_storage{};
84 7054x socklen_t local_len = sizeof(local_storage);
85
6/16
✗ Branch 0 not taken.
✓ Branch 1 taken 1737 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1737 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5312 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5312 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 5 times.
14108x if (::getsockname(
86 7054x op.fd, reinterpret_cast<sockaddr*>(&local_storage),
87 7054x &local_len) == 0)
88 7054x local_ep = from_sockaddr(local_storage);
89 7054x op.socket_impl_->set_endpoints(local_ep, op.target_endpoint);
90 7054x }
91
92
3/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1739 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5314 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
7058x if (op.cancelled.load(std::memory_order_acquire))
93 *op.ec_out = capy::error::canceled;
94
5/8
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1737 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 5312 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
7058x else if (op.errn != 0)
95 4x *op.ec_out = make_err(op.errn);
96 else
97 7054x *op.ec_out = {};
98
99 7058x op.cont_op.cont.h = op.h;
100 7058x capy::executor_ref saved_ex(op.ex);
101 7058x auto prevent = std::move(op.impl_ptr);
102
6/16
✓ Branch 0 taken 1739 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1739 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5314 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5314 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 5 times.
✗ Branch 15 not taken.
7058x dispatch_coro(saved_ex, op.cont_op.cont).resume();
103 7058x }
104
105 /** Construct and register a peer socket from an accepted fd.
106
107 Creates a new socket impl via the acceptor's associated
108 socket service, registers it with the scheduler, and caches
109 the local and remote endpoints.
110
111 @tparam SocketImpl The concrete socket implementation type.
112 @tparam AcceptorImpl The concrete acceptor implementation type.
113 @param acceptor_impl The acceptor that accepted the connection.
114 @param accepted_fd The accepted file descriptor (set to -1 on success).
115 @param peer_storage The peer address from accept().
116 @param impl_out Output pointer for the new socket impl.
117 @param ec_out Output pointer for any error.
118 @return True on success, false on failure.
119 */
120 template<typename SocketImpl, typename AcceptorImpl>
121 bool
122 7044x setup_accepted_socket(
123 AcceptorImpl* acceptor_impl,
124 int& accepted_fd,
125 sockaddr_storage const& peer_storage,
126 io_object::implementation** impl_out,
127 std::error_code* ec_out)
128 {
129 7044x auto* socket_svc = acceptor_impl->service().tcp_service();
130
2/4
✓ Branch 0 taken 1737 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5307 times.
✗ Branch 3 not taken.
7044x if (!socket_svc)
131 {
132 *ec_out = make_err(ENOENT);
133 return false;
134 }
135
136 7044x auto& impl = static_cast<SocketImpl&>(*socket_svc->construct());
137 7044x impl.set_socket(accepted_fd);
138
139 7044x impl.desc_state_.fd = accepted_fd;
140 {
141 7044x std::lock_guard lock(impl.desc_state_.mutex);
142 7044x impl.desc_state_.read_op = nullptr;
143 7044x impl.desc_state_.write_op = nullptr;
144 7044x impl.desc_state_.connect_op = nullptr;
145 7044x }
146 7044x socket_svc->scheduler().register_descriptor(accepted_fd, &impl.desc_state_);
147
148 14088x impl.set_endpoints(
149 7044x acceptor_impl->local_endpoint(), from_sockaddr(peer_storage));
150
151
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1737 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5307 times.
7044x if (impl_out)
152 7044x *impl_out = &impl;
153 7044x accepted_fd = -1;
154 7044x return true;
155 7044x }
156
157 /** Complete an accept operation.
158
159 Sets up the peer socket on success, or closes the accepted
160 fd on failure. Then resumes the caller via symmetric transfer.
161
162 @tparam SocketImpl The concrete socket implementation type.
163 @tparam Op The concrete accept operation type.
164 @param op The operation to complete.
165 */
166 template<typename SocketImpl, typename Op>
167 void
168 7056x complete_accept_op(Op& op)
169 {
170 7056x op.stop_cb.reset();
171 7056x op.acceptor_impl_->desc_state_.scheduler_->reset_inline_budget();
172
173 7056x bool success =
174
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1740 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5316 times.
7056x (op.errn == 0 && !op.cancelled.load(std::memory_order_acquire));
175
176
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1737 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 5307 times.
7056x if (op.cancelled.load(std::memory_order_acquire))
177 12x *op.ec_out = capy::error::canceled;
178
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1737 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5307 times.
7044x else if (op.errn != 0)
179 *op.ec_out = make_err(op.errn);
180 else
181 7044x *op.ec_out = {};
182
183
8/12
✓ Branch 0 taken 1737 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1737 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1737 times.
✓ Branch 6 taken 5307 times.
✓ Branch 7 taken 9 times.
✓ Branch 8 taken 5307 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 5307 times.
7056x if (success && op.accepted_fd >= 0 && op.acceptor_impl_)
184 {
185
2/4
✓ Branch 0 taken 1737 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5307 times.
✗ Branch 3 not taken.
7044x if (!setup_accepted_socket<SocketImpl>(
186 7044x op.acceptor_impl_, op.accepted_fd, op.peer_storage, op.impl_out,
187 7044x op.ec_out))
188 success = false;
189 7044x }
190
191
6/8
✓ Branch 0 taken 1737 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1737 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5307 times.
✓ Branch 5 taken 9 times.
✓ Branch 6 taken 5307 times.
✗ Branch 7 not taken.
7056x if (!success || !op.acceptor_impl_)
192 {
193
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
12x if (op.accepted_fd >= 0)
194 {
195 ::close(op.accepted_fd);
196 op.accepted_fd = -1;
197 }
198
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
12x if (op.impl_out)
199 12x *op.impl_out = nullptr;
200 12x }
201
202 7056x op.cont_op.cont.h = op.h;
203 7056x capy::executor_ref saved_ex(op.ex);
204 7056x auto prevent = std::move(op.impl_ptr);
205
4/8
✓ Branch 0 taken 1740 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1740 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5316 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5316 times.
✗ Branch 7 not taken.
7056x dispatch_coro(saved_ex, op.cont_op.cont).resume();
206 7056x }
207
208 /** Complete a datagram operation (send_to or recv_from).
209
210 For recv_from operations, writes the source endpoint from the
211 recorded sockaddr_storage into the caller's endpoint pointer.
212 Then resumes the caller via symmetric transfer.
213
214 @tparam Op The concrete datagram operation type.
215 @param op The operation to complete.
216 @param source_out Optional pointer to store source endpoint
217 (non-null for recv_from, null for send_to).
218 */
219 template<typename Op>
220 void
221 25x complete_datagram_op(Op& op, endpoint* source_out)
222 {
223 25x op.stop_cb.reset();
224 25x op.socket_impl_->desc_state_.scheduler_->reset_inline_budget();
225
226
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 6 times.
25x if (op.cancelled.load(std::memory_order_acquire))
227 10x *op.ec_out = capy::error::canceled;
228
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
15x else if (op.errn != 0)
229 *op.ec_out = make_err(op.errn);
230 else
231 15x *op.ec_out = {};
232
233 25x *op.bytes_out = op.bytes_transferred;
234
235
10/12
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 1 time.
✓ Branch 8 taken 5 times.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 5 times.
25x if (source_out && !op.cancelled.load(std::memory_order_acquire) &&
236 13x op.errn == 0)
237 13x *source_out = from_sockaddr(op.source_storage);
238
239 25x op.cont_op.cont.h = op.h;
240 25x capy::executor_ref saved_ex(op.ex);
241 25x auto prevent = std::move(op.impl_ptr);
242
4/8
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
25x dispatch_coro(saved_ex, op.cont_op.cont).resume();
243 25x }
244
245 } // namespace boost::corosio::detail
246
247 #endif // BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_OP_COMPLETE_HPP
248