include/boost/corosio/native/native_tcp_acceptor.hpp

100.0% Lines (48 / 48) 100.0% Functions (26 / 26)
native_tcp_acceptor.hpp
f(x) Functions (26)
Function Calls Lines Blocks
boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>::get_impl() :69 11x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>::get_impl() :69 10x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>&, boost::corosio::wait_type) :79 3x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>&, boost::corosio::wait_type) :79 3x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>::native_wait_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :86 2x 100.0% 80.0% boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>::native_wait_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :86 2x 100.0% 80.0% boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>::native_accept_awaitable::native_accept_awaitable(boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>&, boost::corosio::tcp_socket&) :99 10x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>::native_accept_awaitable::native_accept_awaitable(boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>&, boost::corosio::tcp_socket&) :99 9x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>::native_accept_awaitable::await_resume() const :106 10x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>::native_accept_awaitable::await_resume() const :106 9x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>::native_accept_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :114 8x 100.0% 80.0% boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>::native_accept_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :114 7x 100.0% 80.0% boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>::native_accept_value_awaitable::native_accept_value_awaitable(boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>&) :128 3x 100.0% 83.0% boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>::native_accept_value_awaitable::native_accept_value_awaitable(boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>&) :128 3x 100.0% 83.0% boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>::native_accept_value_awaitable::await_resume() :134 3x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>::native_accept_value_awaitable::await_resume() :134 3x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>::native_accept_value_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :142 1x 100.0% 80.0% boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>::native_accept_value_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :142 1x 100.0% 80.0% boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>::native_tcp_acceptor(boost::capy::execution_context&) :154 18x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>::native_tcp_acceptor(boost::capy::execution_context&) :154 17x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>::native_tcp_acceptor(boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>&&) :183 2x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>::native_tcp_acceptor(boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>&&) :183 2x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>::accept(boost::corosio::tcp_socket&) :215 6x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>::accept(boost::corosio::tcp_socket&) :215 5x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::epoll_t{}>::accept() :236 4x 100.0% 100.0% boost::corosio::native_tcp_acceptor<boost::corosio::select_t{}>::accept() :236 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_TCP_ACCEPTOR_HPP
12 #define BOOST_COROSIO_NATIVE_NATIVE_TCP_ACCEPTOR_HPP
13
14 #include <boost/corosio/tcp_acceptor.hpp>
15 #include <boost/corosio/backend.hpp>
16 #include <boost/corosio/detail/op_base.hpp>
17
18 #ifndef BOOST_COROSIO_MRDOCS
19 #if BOOST_COROSIO_HAS_EPOLL
20 #include <boost/corosio/native/detail/epoll/epoll_types.hpp>
21 #endif
22
23 #if BOOST_COROSIO_HAS_SELECT
24 #include <boost/corosio/native/detail/select/select_types.hpp>
25 #endif
26
27 #if BOOST_COROSIO_HAS_KQUEUE
28 #include <boost/corosio/native/detail/kqueue/kqueue_types.hpp>
29 #endif
30
31 #if BOOST_COROSIO_HAS_IOCP
32 #include <boost/corosio/native/detail/iocp/win_tcp_acceptor_service.hpp>
33 #endif
34
35 #if BOOST_COROSIO_HAS_URING
36 #include <boost/corosio/native/detail/uring/uring_types.hpp>
37 #endif
38 #endif // !BOOST_COROSIO_MRDOCS
39
40 namespace boost::corosio {
41
42 /** Accepts TCP connections, calling the backend directly.
43
44 This class template inherits from @ref tcp_acceptor. It shadows the
45 `accept` operation with a version that calls the backend
46 implementation directly. The compiler can then inline through the
47 entire call chain.
48
49 Non-async operations (`listen`, `close`, `cancel`) remain
50 unchanged and dispatch through the compiled library.
51
52 A `native_tcp_acceptor` IS-A `tcp_acceptor` and can be passed
53 to any function expecting `tcp_acceptor&`.
54
55 @tparam Backend A backend tag value (e.g., `epoll`).
56
57 @par Thread Safety
58 Same as @ref tcp_acceptor.
59
60 @see @ref tcp_acceptor, @ref epoll_t, @ref iocp_t
61 */
62 template<auto Backend>
63 class native_tcp_acceptor : public tcp_acceptor
64 {
65 using backend_type = decltype(Backend);
66 using impl_type = typename backend_type::tcp_acceptor_type;
67 using service_type = typename backend_type::tcp_acceptor_service_type;
68
69 21x impl_type& get_impl() noexcept
70 {
71 21x return *static_cast<impl_type*>(h_.get());
72 }
73
74 struct native_wait_awaitable : detail::void_op_base<native_wait_awaitable>
75 {
76 native_tcp_acceptor& acc_;
77 wait_type w_;
78
79 6x native_wait_awaitable(native_tcp_acceptor& acc, wait_type w) noexcept
80 6x : acc_(acc)
81 6x , w_(w)
82 {
83 6x }
84
85 std::coroutine_handle<>
86 4x dispatch(capy::continuation& cont, capy::executor_ref ex) const
87 {
88 4x return acc_.get_impl().wait(cont, ex, w_, this->token_, &this->ec_);
89 }
90 };
91
92 struct native_accept_awaitable
93 : detail::void_op_base<native_accept_awaitable>
94 {
95 native_tcp_acceptor& acc_;
96 tcp_socket& peer_;
97 mutable io_object::implementation* peer_impl_ = nullptr;
98
99 19x native_accept_awaitable(
100 native_tcp_acceptor& acc, tcp_socket& peer) noexcept
101 19x : acc_(acc)
102 19x , peer_(peer)
103 {
104 19x }
105
106 19x [[nodiscard]] capy::results<> await_resume() const noexcept
107 {
108 19x if (!this->ec_)
109 15x acc_.reset_peer_impl(peer_, peer_impl_);
110 19x return {this->ec_};
111 }
112
113 std::coroutine_handle<>
114 15x dispatch(capy::continuation& cont, capy::executor_ref ex) const
115 {
116 45x return acc_.get_impl().accept(
117 45x cont, ex, this->token_, &this->ec_, &peer_impl_);
118 }
119 };
120
121 struct native_accept_value_awaitable
122 : detail::void_op_base<native_accept_value_awaitable>
123 {
124 native_tcp_acceptor& acc_;
125 tcp_socket peer_;
126 mutable io_object::implementation* peer_impl_ = nullptr;
127
128 6x explicit native_accept_value_awaitable(native_tcp_acceptor& acc)
129 6x : acc_(acc)
130 6x , peer_(acc.context())
131 {
132 6x }
133
134 6x [[nodiscard]] capy::results<tcp_socket> await_resume() noexcept
135 {
136 6x if (!this->ec_ && peer_impl_)
137 2x acc_.reset_peer_impl(peer_, peer_impl_);
138 6x return {this->ec_, std::move(peer_)};
139 }
140
141 std::coroutine_handle<>
142 2x dispatch(capy::continuation& cont, capy::executor_ref ex) const
143 {
144 6x return acc_.get_impl().accept(
145 6x cont, ex, this->token_, &this->ec_, &peer_impl_);
146 }
147 };
148
149 public:
150 /** Construct a native acceptor from an execution context.
151
152 @param ctx The execution context that owns this acceptor.
153 */
154 35x explicit native_tcp_acceptor(capy::execution_context& ctx)
155 35x : tcp_acceptor(handle(ctx, ctx.use_service<service_type>()))
156 {
157 35x }
158
159 /** Construct a native acceptor from an executor.
160
161 @param ex The executor whose context owns the acceptor.
162
163 @tparam Ex A type satisfying @ref capy::Executor. Must not
164 be `native_tcp_acceptor` itself (disables implicit
165 conversion from move).
166 */
167 template<class Ex>
168 requires(!std::same_as<std::remove_cvref_t<Ex>, native_tcp_acceptor>) &&
169 capy::Executor<Ex>
170 explicit native_tcp_acceptor(Ex const& ex)
171 : native_tcp_acceptor(ex.context())
172 {
173 }
174
175 /** Move construct.
176
177 @param other The acceptor to move from.
178
179 @pre No awaitables returned by @p other's methods exist.
180 @pre The execution context associated with @p other must
181 outlive this acceptor.
182 */
183 4x native_tcp_acceptor(native_tcp_acceptor&&) noexcept = default;
184
185 /** Move assign.
186
187 @param other The acceptor to move from.
188
189 @pre No awaitables returned by either `*this` or @p other's
190 methods exist.
191 @pre The execution context associated with @p other must
192 outlive this acceptor.
193 */
194 native_tcp_acceptor& operator=(native_tcp_acceptor&&) noexcept = default;
195
196 /// Copy construction is disabled; the handle is uniquely owned.
197 native_tcp_acceptor(native_tcp_acceptor const&) = delete;
198 /// Copy assignment is disabled; the handle is uniquely owned.
199 native_tcp_acceptor& operator=(native_tcp_acceptor const&) = delete;
200
201 /** Asynchronously accept an incoming connection.
202
203 Calls the backend implementation directly, bypassing virtual
204 dispatch. Otherwise identical to @ref tcp_acceptor::accept.
205
206 @param peer The socket to receive the accepted connection.
207
208 @return An awaitable yielding `results<>`.
209
210 A closed acceptor reports `errc::bad_file_descriptor`.
211
212 Both this acceptor and @p peer must outlive the returned
213 awaitable.
214 */
215 19x [[nodiscard]] auto accept(tcp_socket& peer)
216 {
217 19x native_accept_awaitable aw(*this, peer);
218 19x if (!is_open())
219 2x aw.ec_ = make_error_code(std::errc::bad_file_descriptor);
220 19x return aw;
221 }
222
223 /** Asynchronously accept an incoming connection, returning the peer.
224
225 Calls the backend implementation directly, bypassing virtual
226 dispatch. Otherwise identical to @ref tcp_acceptor::accept().
227
228 @return An awaitable yielding `results<tcp_socket>`.
229
230 A closed acceptor reports `errc::bad_file_descriptor`.
231
232 @throws std::logic_error If the acceptor is moved-from.
233
234 This acceptor must outlive the returned awaitable.
235 */
236 8x [[nodiscard]] auto accept()
237 {
238 // The awaitable builds the peer from context(), which a
239 // moved-from acceptor no longer has.
240 8x if (!h_)
241 2x detail::throw_logic_error("accept: acceptor moved-from");
242 6x native_accept_value_awaitable aw(*this);
243 6x if (!is_open())
244 2x aw.ec_ = make_error_code(std::errc::bad_file_descriptor);
245 6x return aw;
246 }
247
248 /** Asynchronously wait for the acceptor to be ready.
249
250 Calls the backend implementation directly, bypassing virtual
251 dispatch. Otherwise identical to @ref tcp_acceptor::wait.
252
253 @param w The wait direction (typically `wait_type::read`).
254
255 @return An awaitable yielding `results<>`.
256 */
257 6x [[nodiscard]] auto wait(wait_type w)
258 {
259 6x return native_wait_awaitable(*this, w);
260 }
261 };
262
263 } // namespace boost::corosio
264
265 #endif
266