include/boost/corosio/native/native_local_stream_acceptor.hpp

98.4% Lines (63 / 64) 100.0% Functions (34 / 34)
native_local_stream_acceptor.hpp
f(x) Functions (34)
Function Calls Lines Blocks
boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::get_impl() :75 7x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::get_impl() :75 7x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>&, boost::corosio::wait_type) :85 3x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>&, boost::corosio::wait_type) :85 3x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_wait_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :93 2x 100.0% 80.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_wait_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :93 2x 100.0% 80.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_accept_awaitable::native_accept_awaitable(boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>&, boost::corosio::local_stream_socket&) :106 5x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_accept_awaitable::native_accept_awaitable(boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>&, boost::corosio::local_stream_socket&) :106 5x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_accept_awaitable::~native_accept_awaitable() :116 10x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_accept_awaitable::~native_accept_awaitable() :116 10x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_accept_awaitable::await_resume() const :122 4x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_accept_awaitable::await_resume() const :122 4x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_accept_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :130 3x 100.0% 80.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_accept_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :130 3x 100.0% 80.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_move_accept_awaitable::native_move_accept_awaitable(boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>&) :143 5x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_move_accept_awaitable::native_move_accept_awaitable(boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>&) :143 5x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_move_accept_awaitable::~native_move_accept_awaitable() :151 10x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_move_accept_awaitable::~native_move_accept_awaitable() :151 10x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_move_accept_awaitable::await_resume() const :158 4x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_move_accept_awaitable::await_resume() const :158 4x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_move_accept_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :169 2x 100.0% 80.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_move_accept_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :169 2x 100.0% 80.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_local_stream_acceptor(boost::capy::execution_context&) :181 11x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_local_stream_acceptor(boost::capy::execution_context&) :181 11x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_local_stream_acceptor(boost::capy::execution_context&, boost::corosio::local_endpoint, int) :212 2x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_local_stream_acceptor(boost::capy::execution_context&, boost::corosio::local_endpoint, int) :212 2x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_local_stream_acceptor<boost::corosio::io_context::executor_type>(boost::corosio::io_context::executor_type const&, boost::corosio::local_endpoint, int) :236 1x 66.7% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_local_stream_acceptor<boost::corosio::io_context::executor_type>(boost::corosio::io_context::executor_type const&, boost::corosio::local_endpoint, int) :236 1x 66.7% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_local_stream_acceptor(boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>&&) :243 1x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_local_stream_acceptor(boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>&&) :243 1x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::accept(boost::corosio::local_stream_socket&) :271 5x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::accept(boost::corosio::local_stream_socket&) :271 5x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::accept() :297 5x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::accept() :297 5x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Steve Gerbino
3 // Copyright (c) 2026 Michael Vandeberg
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/cppalliance/corosio
9 //
10
11 #ifndef BOOST_COROSIO_NATIVE_NATIVE_LOCAL_STREAM_ACCEPTOR_HPP
12 #define BOOST_COROSIO_NATIVE_NATIVE_LOCAL_STREAM_ACCEPTOR_HPP
13
14 #include <boost/corosio/local_stream_acceptor.hpp>
15 #include <boost/corosio/native/native_local_stream_socket.hpp>
16 #include <boost/corosio/backend.hpp>
17 #include <boost/corosio/detail/op_base.hpp>
18
19 #ifndef BOOST_COROSIO_MRDOCS
20 #if BOOST_COROSIO_HAS_EPOLL
21 #include <boost/corosio/native/detail/epoll/epoll_types.hpp>
22 #endif
23
24 #if BOOST_COROSIO_HAS_SELECT
25 #include <boost/corosio/native/detail/select/select_types.hpp>
26 #endif
27
28 #if BOOST_COROSIO_HAS_KQUEUE
29 #include <boost/corosio/native/detail/kqueue/kqueue_types.hpp>
30 #endif
31
32 #if BOOST_COROSIO_HAS_URING
33 #include <boost/corosio/native/detail/uring/uring_types.hpp>
34 #endif
35
36 #if BOOST_COROSIO_HAS_IOCP
37 #include <boost/corosio/native/detail/iocp/win_local_stream_acceptor_service.hpp>
38 #endif
39 #endif // !BOOST_COROSIO_MRDOCS
40
41 namespace boost::corosio {
42
43 /** Accepts Unix domain stream connections, calling the backend directly.
44
45 This class template inherits from @ref local_stream_acceptor. It
46 shadows both `accept` overloads (the peer-reference form and the
47 move-return form) with versions that call the backend implementation
48 directly. The compiler can then inline through the entire call
49 chain. The move-return form yields a
50 @ref native_local_stream_socket so subsequent I/O on the peer
51 is also devirtualized.
52
53 Non-async operations (`listen`, `close`, `cancel`) remain
54 unchanged and dispatch through the compiled library.
55
56 A `native_local_stream_acceptor` IS-A `local_stream_acceptor`
57 and can be passed to any function expecting
58 `local_stream_acceptor&`.
59
60 @tparam Backend A backend tag value (e.g., `epoll`).
61
62 @par Thread Safety
63 Same as @ref local_stream_acceptor.
64
65 @see @ref local_stream_acceptor, @ref epoll_t, @ref iocp_t
66 */
67 template<auto Backend>
68 class native_local_stream_acceptor : public local_stream_acceptor
69 {
70 using backend_type = decltype(Backend);
71 using impl_type = typename backend_type::local_stream_acceptor_type;
72 using service_type =
73 typename backend_type::local_stream_acceptor_service_type;
74
75 14x impl_type& get_impl() noexcept
76 {
77 14x return *static_cast<impl_type*>(h_.get());
78 }
79
80 struct native_wait_awaitable : detail::void_op_base<native_wait_awaitable>
81 {
82 native_local_stream_acceptor& acc_;
83 wait_type w_;
84
85 6x native_wait_awaitable(
86 native_local_stream_acceptor& acc, wait_type w) noexcept
87 6x : acc_(acc)
88 6x , w_(w)
89 {
90 6x }
91
92 std::coroutine_handle<>
93 4x dispatch(capy::continuation& cont, capy::executor_ref ex) const
94 {
95 4x return acc_.get_impl().wait(cont, ex, w_, this->token_, &this->ec_);
96 }
97 };
98
99 struct native_accept_awaitable
100 : detail::void_op_base<native_accept_awaitable>
101 {
102 native_local_stream_acceptor& acc_;
103 local_stream_socket& peer_;
104 mutable io_object::implementation* peer_impl_ = nullptr;
105
106 10x native_accept_awaitable(
107 native_local_stream_acceptor& acc,
108 local_stream_socket& peer) noexcept
109 10x : acc_(acc)
110 10x , peer_(peer)
111 {
112 10x }
113
114 // A peer accepted for an awaiter that never resumed is closed
115 // here, or nothing would own it.
116 20x ~native_accept_awaitable()
117 {
118 20x if (peer_impl_)
119 2x discard_peer(acc_, peer_impl_);
120 20x }
121
122 8x [[nodiscard]] capy::results<> await_resume() const noexcept
123 {
124 8x if (!this->ec_)
125 4x acc_.reset_peer_impl(peer_, std::exchange(peer_impl_, nullptr));
126 8x return {this->ec_};
127 }
128
129 std::coroutine_handle<>
130 6x dispatch(capy::continuation& cont, capy::executor_ref ex) const
131 {
132 18x return acc_.get_impl().accept(
133 18x cont, ex, this->token_, &this->ec_, &peer_impl_);
134 }
135 };
136
137 struct native_move_accept_awaitable
138 : detail::void_op_base<native_move_accept_awaitable>
139 {
140 native_local_stream_acceptor& acc_;
141 mutable io_object::implementation* peer_impl_ = nullptr;
142
143 10x explicit native_move_accept_awaitable(
144 native_local_stream_acceptor& acc) noexcept
145 10x : acc_(acc)
146 {
147 10x }
148
149 // A peer accepted for an awaiter that never resumed is closed
150 // here, or nothing would own it.
151 20x ~native_move_accept_awaitable()
152 {
153 20x if (peer_impl_)
154 2x discard_peer(acc_, peer_impl_);
155 20x }
156
157 [[nodiscard]] capy::results<native_local_stream_socket<Backend>>
158 8x await_resume() const noexcept
159 {
160 8x if (this->ec_ || !peer_impl_)
161 6x return {this->ec_, native_local_stream_socket<Backend>()};
162
163 2x native_local_stream_socket<Backend> peer(acc_.context());
164 2x acc_.reset_peer_impl(peer, std::exchange(peer_impl_, nullptr));
165 2x return {this->ec_, std::move(peer)};
166 2x }
167
168 std::coroutine_handle<>
169 4x dispatch(capy::continuation& cont, capy::executor_ref ex) const
170 {
171 12x return acc_.get_impl().accept(
172 12x cont, ex, this->token_, &this->ec_, &peer_impl_);
173 }
174 };
175
176 public:
177 /** Construct a native acceptor from an execution context.
178
179 @param ctx The execution context that owns this acceptor.
180 */
181 22x explicit native_local_stream_acceptor(capy::execution_context& ctx)
182 22x : local_stream_acceptor(handle(ctx, ctx.use_service<service_type>()), ctx)
183 {
184 22x }
185
186 /** Construct a native acceptor from an executor.
187
188 @param ex The executor whose context owns the acceptor.
189 */
190 template<class Ex>
191 requires(!std::same_as<
192 std::remove_cvref_t<Ex>,
193 native_local_stream_acceptor>) &&
194 capy::Executor<Ex>
195 explicit native_local_stream_acceptor(Ex const& ex)
196 : native_local_stream_acceptor(ex.context())
197 {
198 }
199
200 /** Construct a native acceptor that is open, bound, and listening.
201
202 Creates a fully bound listening acceptor in a single
203 expression, throwing the codes the piecewise `open()` +
204 `bind()` + `listen()` path returns.
205
206 @param ctx The execution context that owns this acceptor.
207 @param ep The local endpoint to bind to.
208 @param backlog The maximum pending connection queue length.
209
210 @throws std::system_error on open, bind, or listen failure.
211 */
212 4x native_local_stream_acceptor(
213 capy::execution_context& ctx,
214 corosio::local_endpoint ep,
215 int backlog = 128)
216 : local_stream_acceptor(
217 8x handle(ctx, ctx.use_service<service_type>()),
218 ctx,
219 4x std::move(ep),
220 8x backlog)
221 {
222 2x }
223
224 /** Construct a native acceptor that is open, bound, and listening.
225
226 @param ex The executor whose context owns the acceptor.
227 @param ep The local endpoint to bind to.
228 @param backlog The maximum pending connection queue length.
229
230 @tparam Ex A type satisfying @ref capy::Executor.
231
232 @throws std::system_error on open, bind, or listen failure.
233 */
234 template<class Ex>
235 requires capy::Executor<Ex>
236 2x native_local_stream_acceptor(
237 Ex const& ex, corosio::local_endpoint ep, int backlog = 128)
238 2x : native_local_stream_acceptor(ex.context(), std::move(ep), backlog)
239 {
240 ✗ }
241
242 /// Move construct.
243 2x native_local_stream_acceptor(native_local_stream_acceptor&&) noexcept =
244 default;
245
246 /// Move assign.
247 native_local_stream_acceptor&
248 operator=(native_local_stream_acceptor&&) noexcept = default;
249
250 /// Copy construction is disabled; the handle is uniquely owned.
251 native_local_stream_acceptor(native_local_stream_acceptor const&) = delete;
252 /// Copy assignment is disabled; the handle is uniquely owned.
253 native_local_stream_acceptor&
254 operator=(native_local_stream_acceptor const&) = delete;
255
256 /** Asynchronously accept an incoming connection.
257
258 Calls the backend implementation directly, bypassing virtual
259 dispatch. Otherwise identical to @ref local_stream_acceptor::accept.
260
261 @param peer The socket to receive the accepted connection.
262
263 @return An awaitable yielding `results<>`.
264
265 A closed or moved-from acceptor reports
266 `errc::bad_file_descriptor`.
267
268 Both this acceptor and @p peer must outlive the returned
269 awaitable.
270 */
271 10x [[nodiscard]] auto accept(local_stream_socket& peer)
272 {
273 10x native_accept_awaitable aw(*this, peer);
274 10x if (!is_open())
275 2x aw.ec_ = make_error_code(std::errc::bad_file_descriptor);
276 10x return aw;
277 }
278
279 /** Asynchronously accept an incoming connection, returning the peer.
280
281 Calls the backend implementation directly, bypassing virtual
282 dispatch. The accepted peer is returned as a
283 @ref native_local_stream_socket so that subsequent I/O on it
284 is also devirtualized.
285
286 @return An awaitable yielding
287 `results<native_local_stream_socket<Backend>>`.
288
289 A closed or moved-from acceptor reports
290 `errc::bad_file_descriptor`.
291 On failure the returned socket is default-constructed and not
292 open. It has no context, so it may only be destroyed, assigned,
293 or checked with `is_open()`.
294
295 This acceptor must outlive the returned awaitable.
296 */
297 10x [[nodiscard]] auto accept()
298 {
299 10x native_move_accept_awaitable aw(*this);
300 10x if (!is_open())
301 4x aw.ec_ = make_error_code(std::errc::bad_file_descriptor);
302 10x return aw;
303 }
304
305 /** Asynchronously wait for the acceptor to be ready.
306
307 Calls the backend implementation directly, bypassing virtual
308 dispatch. Otherwise identical to @ref local_stream_acceptor::wait.
309
310 @param w The wait direction (typically `wait_type::read`).
311
312 @return An awaitable yielding `results<>`.
313 */
314 6x [[nodiscard]] auto wait(wait_type w)
315 {
316 6x return native_wait_awaitable(*this, w);
317 }
318 };
319
320 } // namespace boost::corosio
321
322 #endif // BOOST_COROSIO_NATIVE_NATIVE_LOCAL_STREAM_ACCEPTOR_HPP
323