include/boost/corosio/native/native_local_stream_acceptor.hpp

100.0% Lines (51 / 51) 100.0% Functions (26 / 26)
native_local_stream_acceptor.hpp
f(x) Functions (26)
Function Calls Lines Blocks
boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::get_impl() :75 5x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::get_impl() :75 5x 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 4x 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 4x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_accept_awaitable::await_resume() const :114 4x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_accept_awaitable::await_resume() const :114 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 :122 2x 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 :122 2x 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{}>&) :135 3x 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{}>&) :135 3x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_move_accept_awaitable::await_resume() const :142 3x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_move_accept_awaitable::await_resume() const :142 3x 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 :155 1x 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 :155 1x 100.0% 80.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::native_local_stream_acceptor(boost::capy::execution_context&) :167 9x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::native_local_stream_acceptor(boost::capy::execution_context&) :167 9x 100.0% 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{}>&&) :187 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{}>&&) :187 1x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::accept(boost::corosio::local_stream_socket&) :214 4x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::accept(boost::corosio::local_stream_socket&) :214 4x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::epoll_t{}>::accept() :238 4x 100.0% 100.0% boost::corosio::native_local_stream_acceptor<boost::corosio::select_t{}>::accept() :238 4x 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 10x impl_type& get_impl() noexcept
76 {
77 10x 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 8x native_accept_awaitable(
107 native_local_stream_acceptor& acc,
108 local_stream_socket& peer) noexcept
109 8x : acc_(acc)
110 8x , peer_(peer)
111 {
112 8x }
113
114 8x [[nodiscard]] capy::results<> await_resume() const noexcept
115 {
116 8x if (!this->ec_)
117 4x acc_.reset_peer_impl(peer_, peer_impl_);
118 8x return {this->ec_};
119 }
120
121 std::coroutine_handle<>
122 4x dispatch(capy::continuation& cont, capy::executor_ref ex) const
123 {
124 12x return acc_.get_impl().accept(
125 12x cont, ex, this->token_, &this->ec_, &peer_impl_);
126 }
127 };
128
129 struct native_move_accept_awaitable
130 : detail::void_op_base<native_move_accept_awaitable>
131 {
132 native_local_stream_acceptor& acc_;
133 mutable io_object::implementation* peer_impl_ = nullptr;
134
135 6x explicit native_move_accept_awaitable(
136 native_local_stream_acceptor& acc) noexcept
137 6x : acc_(acc)
138 {
139 6x }
140
141 [[nodiscard]] capy::results<native_local_stream_socket<Backend>>
142 6x await_resume() const noexcept
143 {
144 6x if (this->ec_ || !peer_impl_)
145 return {
146 4x this->ec_,
147 4x native_local_stream_socket<Backend>(acc_.context())};
148
149 2x native_local_stream_socket<Backend> peer(acc_.context());
150 2x acc_.reset_peer_impl(peer, peer_impl_);
151 2x return {this->ec_, std::move(peer)};
152 2x }
153
154 std::coroutine_handle<>
155 2x dispatch(capy::continuation& cont, capy::executor_ref ex) const
156 {
157 6x return acc_.get_impl().accept(
158 6x cont, ex, this->token_, &this->ec_, &peer_impl_);
159 }
160 };
161
162 public:
163 /** Construct a native acceptor from an execution context.
164
165 @param ctx The execution context that owns this acceptor.
166 */
167 18x explicit native_local_stream_acceptor(capy::execution_context& ctx)
168 18x : local_stream_acceptor(handle(ctx, ctx.use_service<service_type>()), ctx)
169 {
170 18x }
171
172 /** Construct a native acceptor from an executor.
173
174 @param ex The executor whose context owns the acceptor.
175 */
176 template<class Ex>
177 requires(!std::same_as<
178 std::remove_cvref_t<Ex>,
179 native_local_stream_acceptor>) &&
180 capy::Executor<Ex>
181 explicit native_local_stream_acceptor(Ex const& ex)
182 : native_local_stream_acceptor(ex.context())
183 {
184 }
185
186 /// Move construct.
187 2x native_local_stream_acceptor(native_local_stream_acceptor&&) noexcept =
188 default;
189
190 /// Move assign.
191 native_local_stream_acceptor&
192 operator=(native_local_stream_acceptor&&) noexcept = default;
193
194 /// Copy construction is disabled; the handle is uniquely owned.
195 native_local_stream_acceptor(native_local_stream_acceptor const&) = delete;
196 /// Copy assignment is disabled; the handle is uniquely owned.
197 native_local_stream_acceptor&
198 operator=(native_local_stream_acceptor const&) = delete;
199
200 /** Asynchronously accept an incoming connection.
201
202 Calls the backend implementation directly, bypassing virtual
203 dispatch. Otherwise identical to @ref local_stream_acceptor::accept.
204
205 @param peer The socket to receive the accepted connection.
206
207 @return An awaitable yielding `results<>`.
208
209 A closed acceptor reports `errc::bad_file_descriptor`.
210
211 Both this acceptor and @p peer must outlive the returned
212 awaitable.
213 */
214 8x [[nodiscard]] auto accept(local_stream_socket& peer)
215 {
216 8x native_accept_awaitable aw(*this, peer);
217 8x if (!is_open())
218 2x aw.ec_ = make_error_code(std::errc::bad_file_descriptor);
219 8x return aw;
220 }
221
222 /** Asynchronously accept an incoming connection, returning the peer.
223
224 Calls the backend implementation directly, bypassing virtual
225 dispatch. The accepted peer is returned as a
226 @ref native_local_stream_socket so that subsequent I/O on it
227 is also devirtualized.
228
229 @return An awaitable yielding
230 `results<native_local_stream_socket<Backend>>`.
231
232 A closed acceptor reports `errc::bad_file_descriptor`.
233
234 @throws std::logic_error If the acceptor is moved-from.
235
236 This acceptor must outlive the returned awaitable.
237 */
238 8x [[nodiscard]] auto accept()
239 {
240 // The awaitable builds the peer from context(), which a
241 // moved-from acceptor no longer has.
242 8x if (!h_)
243 2x detail::throw_logic_error("accept: acceptor moved-from");
244 6x native_move_accept_awaitable aw(*this);
245 6x if (!is_open())
246 2x aw.ec_ = make_error_code(std::errc::bad_file_descriptor);
247 6x return aw;
248 }
249
250 /** Asynchronously wait for the acceptor to be ready.
251
252 Calls the backend implementation directly, bypassing virtual
253 dispatch. Otherwise identical to @ref local_stream_acceptor::wait.
254
255 @param w The wait direction (typically `wait_type::read`).
256
257 @return An awaitable yielding `results<>`.
258 */
259 6x [[nodiscard]] auto wait(wait_type w)
260 {
261 6x return native_wait_awaitable(*this, w);
262 }
263 };
264
265 } // namespace boost::corosio
266
267 #endif // BOOST_COROSIO_NATIVE_NATIVE_LOCAL_STREAM_ACCEPTOR_HPP
268