include/boost/corosio/native/detail/uring/uring_multishot_acceptor.hpp

88.6% Lines (405 / 457) 96.3% Functions (78 / 81)
uring_multishot_acceptor.hpp
f(x) Functions (81)
Function Calls Lines Blocks
boost::corosio::detail::fd_is_listening(int) :56 8x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::accept_node::accept_node() :119 26x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::accept_node::accept_node() :119 702x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::accept_node::on_cancel() :126 2x 75.0% 80.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::accept_node::on_cancel() :126 219x 75.0% 80.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::accept_node::recycle_thunk(boost::corosio::detail::uring_accept_op*) :133 26x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::accept_node::recycle_thunk(boost::corosio::detail::uring_accept_op*) :133 4040x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::uring_multishot_acceptor_base(boost::corosio::detail::uring_local_stream_acceptor_service&, boost::corosio::detail::uring_scheduler&, boost::corosio::detail::uring_local_stream_service&) :183 60x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::uring_multishot_acceptor_base(boost::corosio::detail::uring_tcp_acceptor_service&, boost::corosio::detail::uring_scheduler&, boost::corosio::detail::uring_tcp_service&) :183 813x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::acquire_node() :201 26x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::acquire_node() :201 4040x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::release_node(boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::accept_node*) :235 26x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::release_node(boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::accept_node*) :235 4040x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::acquire_ready_locked() :246 2x 50.0% 86.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::acquire_ready_locked() :246 744x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::drain_ready_fds() :268 156x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::drain_ready_fds() :268 2092x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::discard_ready(boost::corosio::detail::intrusive_list<boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::ready_fd_node>&) :281 192x 37.5% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::discard_ready(boost::corosio::detail::intrusive_list<boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::ready_fd_node>&) :281 3312x 37.5% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::discard_ready(boost::corosio::detail::intrusive_list<boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::ready_fd_node>&)::{lambda(boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::ready_fd_node*)#1}::operator()(boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::ready_fd_node*) const :285 1x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::discard_ready(boost::corosio::detail::intrusive_list<boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::ready_fd_node>&)::{lambda(boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::ready_fd_node*)#1}::operator()(boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::ready_fd_node*) const :285 410x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::retire() :295 96x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::retire() :295 1279x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::~uring_multishot_acceptor_base() :301 60x 82.4% 89.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::~uring_multishot_acceptor_base() :301 813x 82.4% 89.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::local_endpoint() const :339 6x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::local_endpoint() const :339 777x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::is_open() const :344 327x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::is_open() const :344 11136x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::native_handle() const :349 8x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::native_handle() const :349 16x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::family() const :354 4x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::family() const :354 597x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::release_socket() :359 4x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::release_socket() :359 5x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::abort_all() :372 32x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::abort_all() :372 569x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::flush_listener() :387 52x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::flush_listener() :387 1248x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::flush_listener()::{lambda()#1}::operator()() const :391 51x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::flush_listener()::{lambda()#1}::operator()() const :391 1244x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::cancel() :402 3x 90.5% 91.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::cancel() :402 5x 76.2% 75.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::reuse() :450 36x 100.0% 65.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::reuse() :450 466x 100.0% 65.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::drain_waiters_only() :472 84x 88.2% 90.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::drain_waiters_only() :472 1817x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::park_read_wait(boost::capy::continuation&, boost::capy::executor_ref, std::stop_token const&, std::error_code*) :511 2x 70.3% 65.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::park_read_wait(boost::capy::continuation&, boost::capy::executor_ref, std::stop_token const&, std::error_code*) :511 9x 91.9% 89.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::set_option(int, int, void const*, unsigned long) :582 2x 85.7% 89.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::set_option(int, int, void const*, unsigned long) :582 593x 85.7% 89.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::get_option(int, int, void*, unsigned long*) const :598 2x 88.9% 90.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::get_option(int, int, void*, unsigned long*) const :598 4x 88.9% 90.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::adopt_listening_fd(int) :622 2x 90.9% 73.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::adopt_listening_fd(int) :622 6x 90.9% 73.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::prepare_listen_arm() :644 34x 81.8% 76.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::prepare_listen_arm() :644 1216x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::start_multishot() :665 36x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::start_multishot() :665 1220x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::start_multishot()::{lambda()#1}::operator()() const :682 35x 85.7% 80.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::start_multishot()::{lambda()#1}::operator()() const :682 1216x 85.7% 80.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::fail_arm(int) :702 0 0.0% 0.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::fail_arm(int) :702 2x 47.8% 47.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::dispatch_or_queue(boost::capy::continuation&, boost::capy::executor_ref, std::stop_token const&, std::error_code*, boost::corosio::io_object::implementation**) :747 22x 72.6% 71.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::dispatch_or_queue(boost::capy::continuation&, boost::capy::executor_ref, std::stop_token const&, std::error_code*, boost::corosio::io_object::implementation**) :747 4029x 79.0% 86.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::cancel_waiter(boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::accept_node*) :867 2x 68.8% 70.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::cancel_waiter(boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::accept_node*) :867 219x 87.5% 90.0% void boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::submit_arming<boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::on_arming_end(void*, boost::corosio::detail::uring_multi_accept_op*, bool)::{lambda()#1}>(boost::corosio::detail::uring_multi_accept_op*, boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::on_arming_end(void*, boost::corosio::detail::uring_multi_accept_op*, bool)::{lambda()#1}) :907 0 0.0% 0.0% void boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::submit_arming<boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::start_multishot()::{lambda()#1}>(boost::corosio::detail::uring_multi_accept_op*, boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::start_multishot()::{lambda()#1}) :907 36x 50.0% 36.0% void boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::submit_arming<boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::on_arming_end(void*, boost::corosio::detail::uring_multi_accept_op*, bool)::{lambda()#1}>(boost::corosio::detail::uring_multi_accept_op*, boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::on_arming_end(void*, boost::corosio::detail::uring_multi_accept_op*, bool)::{lambda()#1}) :907 3x 50.0% 36.0% void boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::submit_arming<boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::start_multishot()::{lambda()#1}>(boost::corosio::detail::uring_multi_accept_op*, boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::start_multishot()::{lambda()#1}) :907 1220x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::recycle_arming(boost::corosio::detail::uring_multi_accept_op*) :940 36x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::recycle_arming(boost::corosio::detail::uring_multi_accept_op*) :940 1220x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::on_accept_cqe(void*, boost::corosio::detail::uring_multi_accept_op*, int, int, bool) :947 56x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::on_accept_cqe(void*, boost::corosio::detail::uring_multi_accept_op*, int, int, bool) :947 5510x 100.0% 100.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::on_arming_end(void*, boost::corosio::detail::uring_multi_accept_op*, bool) :959 36x 78.6% 69.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::on_arming_end(void*, boost::corosio::detail::uring_multi_accept_op*, bool) :959 1221x 78.6% 94.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::on_arming_end(void*, boost::corosio::detail::uring_multi_accept_op*, bool)::{lambda()#1}::operator()() const :973 0 50.0% 0.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::on_arming_end(void*, boost::corosio::detail::uring_multi_accept_op*, bool)::{lambda()#1}::operator()() const :973 3x 87.5% 83.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_local_stream_acceptor, boost::corosio::local_stream_acceptor::implementation, boost::corosio::local_endpoint, boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::uring_local_stream_acceptor_service>::on_accept_cqe_impl(boost::corosio::detail::uring_multi_accept_op*, int, int, bool) :988 56x 79.3% 79.0% boost::corosio::detail::uring_multishot_acceptor_base<boost::corosio::detail::uring_tcp_acceptor, boost::corosio::tcp_acceptor::implementation, boost::corosio::endpoint, boost::corosio::detail::uring_tcp_service, boost::corosio::detail::uring_tcp_acceptor_service>::on_accept_cqe_impl(boost::corosio::detail::uring_multi_accept_op*, int, int, bool) :988 5510x 81.0% 82.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_DETAIL_URING_URING_MULTISHOT_ACCEPTOR_HPP
11 #define BOOST_COROSIO_NATIVE_DETAIL_URING_URING_MULTISHOT_ACCEPTOR_HPP
12
13 #include <boost/corosio/native/detail/endpoint_convert.hpp>
14 #include <boost/corosio/detail/config.hpp>
15 #include <boost/corosio/detail/platform.hpp>
16
17 #if BOOST_COROSIO_HAS_URING
18
19 #include <liburing.h>
20
21 #include <boost/corosio/detail/intrusive.hpp>
22 #include <boost/corosio/native/detail/uring/uring_acceptor_ops.hpp>
23 #include <boost/corosio/native/detail/uring/uring_buffer.hpp>
24 #include <boost/corosio/native/detail/uring/uring_op.hpp>
25 #include <boost/corosio/native/detail/uring/uring_scheduler.hpp>
26 #include <boost/corosio/native/detail/uring/uring_socket_ops.hpp>
27 #include <boost/corosio/native/detail/make_err.hpp>
28 #include <boost/corosio/detail/native_handle.hpp>
29 #include <boost/corosio/io/io_object.hpp>
30
31 #include <atomic>
32 #include <cstdint>
33 #include <coroutine>
34 #include <mutex>
35 #include <stop_token>
36 #include <system_error>
37 #include <utility>
38
39 #include <netinet/in.h>
40 #include <sys/socket.h>
41 #include <unistd.h>
42
43 namespace boost::corosio::detail {
44
45 /** Check whether a descriptor is in the listening state.
46
47 Multishot accept fails immediately on a non-listening socket and
48 the re-arm path would spin on that failure, so an adopted fd is
49 only armed when the kernel reports a listener. A query the
50 platform refuses is treated as listening so adoption still works.
51
52 @param fd The descriptor to probe.
53 @return True unless the kernel positively reports a non-listener.
54 */
55 inline bool
56 8x fd_is_listening(int fd) noexcept
57 {
58 8x int accepting = 0;
59 8x socklen_t alen = sizeof(accepting);
60 8x if (::getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &alen) != 0)
61 1x return true;
62 7x return accepting != 0;
63 }
64
65 template<
66 class Derived,
67 class ImplBase,
68 class Endpoint,
69 class PeerService,
70 class AcceptorService>
71 class uring_multishot_acceptor_base
72 : public ImplBase
73 , public intrusive_list<Derived>::node
74 {
75 protected:
76 struct ready_fd_node : intrusive_list<ready_fd_node>::node
77 {
78 int fd = -1;
79 sockaddr_storage peer{};
80 socklen_t peer_len = 0;
81 };
82
83 /** Pooled accept node: parked waiter and posted completion in one.
84
85 A parked accept used to be a `waiter_node` whose fields were
86 copied into a freshly allocated `uring_accept_op` at every
87 completion boundary. The two had strictly sequential lifetimes
88 (a waiter *becomes* a completion), so this node is both at
89 once — the intrusive hook parks it in `waiters_`/`free_nodes_`
90 and the inherited op posts it to the scheduler. Nodes recycle
91 through the owning acceptor's `free_nodes_` via `dispose`, so
92 steady-state accepts allocate nothing.
93
94 The inherited `cancelled` flag is the claim token: delivery,
95 arming-failure, and cancellation each claim the node with one
96 `exchange`, and the loser leaves completion to the winner.
97 Because the flag also decides how `do_handler` reports the
98 completion, every claiming path stores the final status after
99 `stop_cb.reset()` (which synchronizes with any in-flight
100 canceller) and before posting.
101
102 While in flight — parked or posted — the node holds an
103 `object_ref` on its acceptor (the inherited `object_ref_`
104 slot), so the impl cannot retire out from under `dispose`.
105 */
106 struct accept_node
107 : uring_accept_op
108 , intrusive_list<accept_node>::node
109 {
110 Derived* owner = nullptr;
111 /// True once linked into `waiters_` (guarded by `mutex_`).
112 /// The stop callback is armed before the node is queued, so
113 /// cancel_waiter must not unlink a node it never queued.
114 bool queued = false;
115 /// A readiness wait rather than an accept: completion
116 /// observes a pending connection without consuming it.
117 bool peek = false;
118
119 728x accept_node() noexcept
120 728x {
121 728x this->dispose = &recycle_thunk;
122 728x }
123
124 /// Claim the node for cancellation (the stop token fired);
125 /// losing the exchange means a delivery already owns it.
126 221x void on_cancel() noexcept override
127 {
128 221x if (this->cancelled.exchange(true, std::memory_order_acq_rel))
129 ✗ return;
130 221x owner->cancel_waiter(this);
131 }
132
133 4066x static void recycle_thunk(uring_accept_op* op) noexcept
134 {
135 4066x auto* n = static_cast<accept_node*>(op);
136 4066x n->owner->release_node(n);
137 4066x }
138 };
139
140 int fd_ = -1;
141 uring_scheduler* sched_;
142 PeerService* peer_service_;
143 /// Owning acceptor service; exposes the recycling pool to
144 /// retire(). Not used for anything else — the service already
145 /// drives shutdown/destroy from its own side.
146 AcceptorService* acceptor_svc_;
147 Endpoint local_endpoint_{};
148 mutable std::mutex mutex_;
149 intrusive_list<ready_fd_node> ready_fds_;
150 intrusive_list<accept_node> waiters_;
151 /// Recycled accept nodes and ready-fd nodes (guarded by `mutex_`).
152 /// Both survive impl recycling — the storage belongs to this impl
153 /// and only the destructor frees it — so steady-state accepts
154 /// allocate nothing.
155 intrusive_list<accept_node> free_nodes_;
156 intrusive_list<ready_fd_node> free_ready_;
157 /// Single parked readiness wait (guarded by `mutex_`). Multishot
158 /// accepting drains the kernel queue instantly, so a listener's
159 /// readiness lives in `ready_fds_`, not in `poll()`; the wait is
160 /// completed by the next delivery instead of a kernel poll.
161 accept_node* read_wait_ = nullptr;
162 /// Ended armings, kept for the next one (guarded by `mutex_`).
163 /// Survives impl recycling like `free_nodes_`; entries hold no
164 /// reference.
165 intrusive_list<uring_multi_accept_op> free_ops_;
166 /// The arming whose deliveries belong to this acceptor (guarded by
167 /// `mutex_`). Identity only: the kernel owns the op and its
168 /// reference. Never set while `closing_` is.
169 uring_multi_accept_op* armed_ = nullptr;
170 bool closing_ = false;
171 /// Non-zero once an arming failed to reach the kernel (guarded by
172 /// `mutex_`). Nothing will ever deliver a connection through an
173 /// SQE the ring never took, so an accept reports this instead of
174 /// parking on a delivery that cannot come. Cleared by the next
175 /// arming that does reach the kernel.
176 int arm_err_ = 0;
177
178 private:
179 // CRTP ctor private + Derived friended so the base cannot be
180 // constructed except as a CRTP base of Derived
181 // (clang-tidy bugprone-crtp-constructor-accessibility).
182 friend Derived;
183 873x uring_multishot_acceptor_base(
184 AcceptorService& acceptor_svc,
185 uring_scheduler& sched,
186 PeerService& peer_svc) noexcept
187 873x : sched_(&sched)
188 873x , peer_service_(&peer_svc)
189 873x , acceptor_svc_(&acceptor_svc)
190 {
191 873x }
192
193 protected:
194 /** Pop a recycled accept node, or allocate on the cold path.
195
196 Resets every per-use field and arms the `object_ref` keepalive
197 on this acceptor; the caller fills the request fields and
198 either parks or posts the node. OOM on the cold path
199 terminates, matching every other noexcept initiation path.
200 */
201 4066x accept_node* acquire_node() noexcept
202 {
203 accept_node* n;
204 {
205 4066x std::lock_guard lk(mutex_);
206 4066x n = free_nodes_.pop_front();
207 4066x }
208 4066x if (!n)
209 {
210 // NOLINTNEXTLINE(bugprone-unhandled-exception-at-new) — noexcept initiation path: OOM => std::terminate is the intended behavior
211 728x n = new accept_node();
212 }
213 4066x n->owner = static_cast<Derived*>(this);
214 4066x n->queued = false;
215 4066x n->peek = false;
216 4066x n->err = 0;
217 4066x n->accepted_fd = -1;
218 4066x n->peer_len = 0;
219 4066x n->ec_out = nullptr;
220 4066x n->impl_out = nullptr;
221 4066x n->peer_endpoint_out = nullptr;
222 4066x n->peer_service = nullptr;
223 4066x n->adopt_fn = nullptr;
224 4066x n->cancelled.store(false, std::memory_order_relaxed);
225 4066x n->object_ref_ = detail::object_ref(this);
226 4066x return n;
227 }
228
229 /** Return a consumed node to the free list; `dispose` target.
230
231 The keepalive is moved out first and dropped after the lock,
232 so a final release (which may reenter this impl's retire())
233 never runs under `mutex_`.
234 */
235 4066x void release_node(accept_node* n) noexcept
236 {
237 4066x auto keep = std::move(n->object_ref_);
238 {
239 4066x std::lock_guard lk(mutex_);
240 4066x free_nodes_.push_front(n);
241 4066x }
242 4066x }
243
244 /// Pop a recycled ready-fd node, or allocate on the cold path.
245 /// @pre `mutex_` is held.
246 746x ready_fd_node* acquire_ready_locked() noexcept
247 {
248 746x if (auto* r = free_ready_.pop_front())
249 {
250 205x r->fd = -1;
251 205x r->peer_len = 0;
252 205x return r;
253 }
254 // NOLINTNEXTLINE(bugprone-unhandled-exception-at-new) — CQE handler: noexcept, OOM => std::terminate is the intended behavior
255 541x return new ready_fd_node{};
256 }
257
258 public:
259 /** Close and free every fd parked in `ready_fds_`.
260
261 A multishot CQE can deliver a connection before any `accept()`
262 is outstanding to claim it; that connection's fd (and tracking
263 node) sits in `ready_fds_` until a later `accept()` consumes it
264 or the acceptor goes away. Idempotent: safe to call from both
265 `retire()` (recycling) and the destructor (pool-force-sweep
266 backstop) — the second call always sees an empty list.
267 */
268 2248x void drain_ready_fds() noexcept
269 {
270 2248x intrusive_list<ready_fd_node> drained;
271 {
272 2248x std::lock_guard lk(mutex_);
273 2658x while (auto* r = ready_fds_.pop_front())
274 410x drained.push_back(r);
275 2248x }
276 2248x discard_ready(drained);
277 2248x }
278
279 /// Close each parked connection in @p stale and return its node
280 /// to `free_ready_`. @pre `mutex_` is not held.
281 3504x void discard_ready(intrusive_list<ready_fd_node>& stale) noexcept
282 {
283 3504x if (stale.empty())
284 3454x return;
285 461x stale.for_each([](ready_fd_node* r) { ::close(r->fd); });
286 50x std::lock_guard lk(mutex_);
287 461x while (auto* r = stale.pop_front())
288 411x free_ready_.push_front(r);
289 50x }
290
291 /** Recycle into the owning service's pool at zero references.
292
293 No arming can be live here: an armed op holds a reference.
294 */
295 1375x void retire() noexcept override
296 {
297 1375x drain_ready_fds();
298 1375x acceptor_svc_->pool_.recycle(static_cast<Derived*>(this));
299 1375x }
300
301 873x ~uring_multishot_acceptor_base() override
302 {
303 uring_multi_accept_op* arming;
304 {
305 873x std::lock_guard lk(mutex_);
306 873x closing_ = true;
307 873x arming = std::exchange(armed_, nullptr);
308 873x }
309 873x if (fd_ >= 0)
310 {
311 ✗ sched_->flush_after_cancel(fd_, [&]() noexcept {
312 if (arming)
313 sched_->cancel_op_locked(arming);
314 });
315 ✗ ::close(fd_);
316 ✗ fd_ = -1;
317 }
318
319 // Backstop: retire() already drains this on the normal
320 // recycle path. This call only does real work when this impl
321 // is reached by the pool's unconditional force-sweep at
322 // shutdown without ever going through retire() first.
323 873x drain_ready_fds();
324
325 // The recycled-node storage belongs to this impl and is only
326 // freed here; in-flight nodes hold an object_ref on this impl,
327 // so none can still be parked or posted once the count reached
328 // zero (or the pool's force-sweep ran after scheduler drain).
329 // An arming the kernel never returned is not in `free_ops_`
330 // and is deliberately leaked: the ring may still write to it.
331 1601x while (auto* n = free_nodes_.pop_front())
332 728x delete n;
333 1414x while (auto* r = free_ready_.pop_front())
334 541x delete r;
335 1682x while (auto* op = free_ops_.pop_front())
336 809x delete op;
337 1746x }
338
339 783x Endpoint local_endpoint() const noexcept override
340 {
341 783x return local_endpoint_;
342 }
343
344 11463x bool is_open() const noexcept override
345 {
346 11463x return fd_ >= 0;
347 }
348
349 24x native_handle_type native_handle() const noexcept override
350 {
351 24x return fd_;
352 }
353
354 601x corosio::family family() const noexcept override
355 {
356 601x return to_family(socket_family(fd_));
357 }
358
359 9x native_handle_type release_socket() noexcept override
360 {
361 // Mirror the service close() path, except that the caller now
362 // owns the fd.
363 9x if (fd_ >= 0)
364 9x flush_listener();
365 9x int fd = fd_;
366 9x fd_ = -1;
367 9x local_endpoint_ = Endpoint{};
368 9x return fd;
369 }
370
371 /// Abort every operation and stop accepting, for service teardown.
372 601x void abort_all() noexcept
373 {
374 601x auto* arming = drain_waiters_only();
375 601x static_cast<Derived*>(this)->cancel_wait_op();
376 601x if (arming)
377 406x sched_->cancel_ops({arming});
378 601x }
379
380 /** Stop accepting and flush every SQE naming the listener.
381
382 Disowns the arming and cancels it with the readiness wait, so
383 the caller may then close or hand off the descriptor.
384
385 @pre The descriptor is open.
386 */
387 1300x void flush_listener() noexcept
388 {
389 1300x auto* arming = drain_waiters_only();
390 1300x static_cast<Derived*>(this)->cancel_wait_op();
391 1300x sched_->flush_after_cancel(fd_, [&]() noexcept {
392 1295x if (arming)
393 843x sched_->cancel_op_locked(arming);
394 });
395 1300x }
396
397 /** Cancel the pending accepts and waits.
398
399 The arming is left alone: the acceptor keeps listening, and a
400 connection that arrives meanwhile waits for the next accept.
401 */
402 8x void cancel() noexcept override
403 {
404 8x intrusive_list<accept_node> claimed;
405 {
406 8x std::lock_guard lk(mutex_);
407 // A waiter the stop callback already claimed belongs to it;
408 // see fail_arm().
409 8x intrusive_list<accept_node> keep;
410 11x while (auto* w = waiters_.pop_front())
411 {
412 3x if (!w->cancelled.exchange(true, std::memory_order_acq_rel))
413 3x claimed.push_back(w);
414 else
415 ✗ keep.push_back(w);
416 }
417 8x while (auto* w = keep.pop_front())
418 ✗ waiters_.push_back(w);
419 9x if (read_wait_ &&
420 1x !read_wait_->cancelled.exchange(
421 true, std::memory_order_acq_rel))
422 {
423 1x claimed.push_back(read_wait_);
424 1x read_wait_ = nullptr;
425 }
426 8x }
427 12x while (auto* w = claimed.pop_front())
428 {
429 // The claim is also the completion status.
430 4x w->stop_cb.reset();
431 4x sched_->post(w);
432 4x sched_->work_finished();
433 }
434 8x static_cast<Derived*>(this)->cancel_wait_op();
435 8x }
436
437 /** Reset state for recycling.
438
439 `close()`/`release_socket()` already drove fd_, local_endpoint_,
440 and the waiter/ready-fd queues to empty before the refcount
441 reached zero, so those are asserted rather than re-cleared.
442 `closing_` and `arm_err_` are the two fields that are NOT reset
443 by that close path (closing_ is only ever cleared by a re-listen
444 on a still-live acceptor, not by close) and must be explicitly
445 reset here or the next session would see this impl as still
446 shutting down.
447
448 @pre refs_ == 0, fd closed, no op or waiter in flight.
449 */
450 502x void reuse() noexcept
451 {
452 502x BOOST_COROSIO_ASSERT(fd_ == -1);
453 502x BOOST_COROSIO_ASSERT(local_endpoint_ == Endpoint{});
454 502x BOOST_COROSIO_ASSERT(ready_fds_.empty());
455 502x BOOST_COROSIO_ASSERT(waiters_.empty());
456 502x BOOST_COROSIO_ASSERT(read_wait_ == nullptr);
457 502x BOOST_COROSIO_ASSERT(armed_ == nullptr);
458 502x closing_ = false;
459 502x arm_err_ = 0;
460 502x }
461
462 /** Disown the arming and drain queued waiters with
463 operation_aborted, without submitting a kernel cancel.
464
465 Runs before the caller cancels the arming it returns: an arming
466 admitted after this sees `closing_` and is refused, and the one
467 admitted before it is already in the submission queue ahead of
468 the cancel.
469
470 @return The disowned arming, or null if none was live.
471 */
472 1901x uring_multi_accept_op* drain_waiters_only() noexcept
473 {
474 1901x intrusive_list<accept_node> drained;
475 uring_multi_accept_op* arming;
476 {
477 1901x std::lock_guard lk(mutex_);
478 1901x closing_ = true;
479 1901x arming = std::exchange(armed_, nullptr);
480 // Drain under the lock — the kernel cancel may not produce
481 // a !more CQE before the fd is closed, so we can't rely on
482 // on_accept_cqe_impl to surface operation_aborted.
483 2138x while (auto* w = waiters_.pop_front())
484 237x drained.push_back(w);
485 1901x if (read_wait_)
486 {
487 1x drained.push_back(read_wait_);
488 1x read_wait_ = nullptr;
489 }
490 1901x }
491
492 2139x while (auto* w = drained.pop_front())
493 {
494 // reset() synchronizes with an in-flight canceller; after
495 // it the stored status is ours to set.
496 238x w->stop_cb.reset();
497 238x w->cancelled.store(true, std::memory_order_release);
498 238x sched_->post(w);
499 238x sched_->work_finished();
500 }
501 1901x return arming;
502 }
503
504 /** Park a readiness wait, or complete it if a connection is
505 already queued.
506
507 Multishot accepting consumes the kernel queue as connections
508 arrive, so a poll on the listener never reports it readable;
509 readiness is the impl's ready queue plus future deliveries.
510 */
511 11x void park_read_wait(
512 capy::continuation& cont,
513 capy::executor_ref ex,
514 std::stop_token const& token,
515 std::error_code* ec) noexcept
516 {
517 11x auto* w = acquire_node();
518 11x w->cont = &cont;
519 11x w->ex = ex;
520 11x w->ec_out = ec;
521 11x w->peek = true;
522
523 11x bool ready = false;
524 11x bool aborted = false;
525 {
526 11x std::lock_guard lk(mutex_);
527 11x if (closing_)
528 {
529 ✗ aborted = true;
530 }
531 11x else if (!ready_fds_.empty())
532 {
533 4x ready = true;
534 }
535 11x }
536 11x if (ready || aborted)
537 {
538 4x if (aborted)
539 ✗ w->cancelled.store(true, std::memory_order_release);
540 4x sched_->post(w);
541 4x return;
542 }
543
544 // Same protocol as accept parking: arm the callback before
545 // the node is visible and outside `mutex_` (a pre-stopped
546 // token invokes the canceller synchronously, and the
547 // canceller takes `mutex_`).
548 7x w->start(token);
549
550 7x bool was_cancelled = false;
551 7x int arm_err = 0;
552 {
553 7x std::lock_guard lk(mutex_);
554 7x if (w->cancelled.load(std::memory_order_acquire) || closing_)
555 {
556 ✗ was_cancelled = true;
557 }
558 7x else if (ready_fds_.empty())
559 {
560 // Readiness here means a future delivery, which a failed
561 // arming has already ruled out: report it rather than
562 // wait on one.
563 7x arm_err = arm_err_;
564 7x if (arm_err == 0)
565 {
566 6x w->queued = true;
567 6x sched_->work_started();
568 6x read_wait_ = w;
569 6x return;
570 }
571 }
572 // else: a connection arrived while the callback was armed;
573 // complete as ready below.
574 7x }
575
576 1x w->stop_cb.reset();
577 1x w->err = arm_err;
578 1x w->cancelled.store(was_cancelled, std::memory_order_release);
579 1x sched_->post(w);
580 }
581
582 595x std::error_code set_option(
583 int level,
584 int optname,
585 void const* data,
586 std::size_t size) noexcept override
587 {
588 595x if (fd_ < 0)
589 ✗ return make_err(EBADF);
590 595x if (::setsockopt(
591 fd_, level, optname, reinterpret_cast<char const*>(data),
592 595x static_cast<socklen_t>(size)) < 0)
593 6x return make_err(errno);
594 589x return {};
595 }
596
597 std::error_code
598 6x get_option(int level, int optname, void* data, std::size_t* size)
599 const noexcept override
600 {
601 6x if (fd_ < 0)
602 ✗ return make_err(EBADF);
603 6x socklen_t len = static_cast<socklen_t>(*size);
604 12x if (::getsockopt(
605 6x fd_, level, optname, reinterpret_cast<char*>(data), &len) < 0)
606 2x return make_err(errno);
607 4x *size = static_cast<std::size_t>(len);
608 4x return {};
609 }
610
611 /** Take over an already-listening descriptor.
612
613 Clears the shutdown latch a previous release left behind and
614 discards connections parked from the replaced descriptor:
615 those belong to the socket the caller is handing away.
616
617 @pre No arming is live (`drain_waiters_only` has run if the
618 acceptor had a descriptor).
619
620 @param fd The adopted descriptor.
621 */
622 8x void adopt_listening_fd(int fd) noexcept
623 {
624 8x intrusive_list<ready_fd_node> stale;
625 {
626 8x std::lock_guard lk(mutex_);
627 8x BOOST_COROSIO_ASSERT(armed_ == nullptr);
628 8x fd_ = fd;
629 8x closing_ = false;
630 8x while (auto* r = ready_fds_.pop_front())
631 ✗ stale.push_back(r);
632 8x }
633 8x discard_ready(stale);
634 8x }
635
636 /** Ready the acceptor for a listen-time arming.
637
638 Returns `false` when a live arming already covers the
639 descriptor: a re-listen only changes the backlog. Otherwise
640 clears the shutdown latch a released descriptor left behind and
641 discards the connections it delivered, which belong to the
642 socket the caller took away.
643 */
644 1250x bool prepare_listen_arm() noexcept
645 {
646 1250x intrusive_list<ready_fd_node> stale;
647 {
648 1250x std::lock_guard lk(mutex_);
649 1250x if (armed_)
650 2x return false;
651 1248x closing_ = false;
652 1249x while (auto* r = ready_fds_.pop_front())
653 1x stale.push_back(r);
654 1250x }
655 1248x discard_ready(stale);
656 1248x return true;
657 }
658
659 /** Arm a multishot accept on the current descriptor.
660
661 The op is handed to the kernel with a reference on this
662 acceptor; the caller must hold one. Refused when closing or
663 when an arming is already live.
664 */
665 1256x void start_multishot() noexcept
666 {
667 uring_multi_accept_op* op;
668 {
669 1256x std::lock_guard lk(mutex_);
670 1256x op = free_ops_.pop_front();
671 1256x }
672 1256x if (!op)
673 {
674 // NOLINTNEXTLINE(bugprone-unhandled-exception-at-new) — noexcept initiation path: OOM => std::terminate is the intended behavior
675 809x op = new uring_multi_accept_op();
676 809x op->sched_ = sched_;
677 809x op->acceptor_impl = this;
678 809x op->on_cqe = &uring_multishot_acceptor_base::on_accept_cqe;
679 809x op->on_end = &uring_multishot_acceptor_base::on_arming_end;
680 }
681 1256x op->object_ref_ = detail::object_ref(this);
682 1256x submit_arming(op, [this, op]() noexcept {
683 1251x if (closing_ || armed_)
684 ✗ return false;
685 1251x armed_ = op;
686 1251x op->listen_fd = fd_;
687 1251x return true;
688 });
689 1256x }
690
691 /** Report an arming that never reached the kernel.
692
693 No CQE can arrive for an SQE the ring never took, so an accept
694 parked on this acceptor would park for good. The error is
695 remembered for the accepts still to come and delivered now to
696 whoever is already parked, which is the same EAGAIN every other
697 op reports when the SQ stays full.
698
699 @param err The code to report to the accepts this arming can no
700 longer serve.
701 */
702 2x void fail_arm(int err) noexcept
703 {
704 2x intrusive_list<accept_node> claimed;
705 {
706 2x std::lock_guard lk(mutex_);
707 2x arm_err_ = err;
708 // Claim each waiter the way a delivery does. One the
709 // canceller already claimed belongs to it: cancel_waiter
710 // is waiting on this mutex to unlink the node itself, so
711 // it has to still be in the list when it gets in.
712 2x intrusive_list<accept_node> keep;
713 2x while (auto* w = waiters_.pop_front())
714 {
715 ✗ if (!w->cancelled.exchange(true, std::memory_order_acq_rel))
716 ✗ claimed.push_back(w);
717 else
718 ✗ keep.push_back(w);
719 }
720 2x while (auto* w = keep.pop_front())
721 ✗ waiters_.push_back(w);
722 2x if (read_wait_ &&
723 ✗ !read_wait_->cancelled.exchange(
724 true, std::memory_order_acq_rel))
725 {
726 ✗ claimed.push_back(read_wait_);
727 ✗ read_wait_ = nullptr;
728 }
729 2x }
730
731 2x while (auto* w = claimed.pop_front())
732 {
733 // The exchange above was a claim, not the completion
734 // status: after reset() quiesces the canceller, restore
735 // the flag so the handler reports `err`, not canceled.
736 ✗ w->stop_cb.reset();
737 ✗ w->err = err;
738 ✗ w->cancelled.store(false, std::memory_order_release);
739 ✗ sched_->post(w);
740 ✗ sched_->work_finished(); // balance the waiter's work_started
741 }
742 2x }
743
744 /// Pull a parked fd or queue a waiter — used by Derived::accept().
745 /// Either case ends with the calling coroutine suspending; the
746 /// caller returns `std::noop_coroutine()` unconditionally.
747 4051x void dispatch_or_queue(
748 capy::continuation& cont,
749 capy::executor_ref ex,
750 std::stop_token const& token,
751 std::error_code* ec,
752 io_object::implementation** impl_out)
753 {
754 4051x auto* w = acquire_node();
755 4051x w->cont = &cont;
756 4051x w->ex = ex;
757 4051x w->ec_out = ec;
758 4051x w->impl_out = impl_out;
759
760 // A live arming takes each connection as it lands, so a direct
761 // accept would only find the backlog empty.
762 4051x bool armed = false;
763 {
764 4051x std::lock_guard lk(mutex_);
765 4051x armed = armed_ != nullptr;
766 4051x }
767 4051x if (!armed)
768 {
769 3x sockaddr_storage peer_storage{};
770 3x socklen_t peer_len = sizeof(peer_storage);
771 3x int accepted_fd = ::accept4(
772 fd_, reinterpret_cast<sockaddr*>(&peer_storage), &peer_len,
773 SOCK_NONBLOCK | SOCK_CLOEXEC);
774 3x if (accepted_fd >= 0)
775 {
776 ✗ w->peer_service = peer_service_;
777 ✗ w->adopt_fn = &Derived::adopt_thunk;
778 ✗ w->accepted_fd = accepted_fd;
779 ✗ w->peer_storage = peer_storage;
780 ✗ w->peer_len = peer_len;
781 ✗ sched_->post(w);
782 2x return;
783 }
784 // accept4 returned <0 — only EAGAIN/EWOULDBLOCK should fall
785 // through to the parked/waiter path. Other errors (EBADF,
786 // etc.) surface through the existing scheduler-completion
787 // path so the user sees them via the node's ec_out: `err`
788 // set means do_handler delivers make_err(err).
789 3x if (errno != EAGAIN && errno != EWOULDBLOCK)
790 {
791 2x w->err = errno;
792 2x sched_->post(w);
793 2x return;
794 }
795 }
796
797 4049x bool have_ready = false;
798 {
799 4049x std::lock_guard lk(mutex_);
800 4049x if (auto* r = ready_fds_.pop_front())
801 {
802 335x w->peer_service = peer_service_;
803 335x w->adopt_fn = &Derived::adopt_thunk;
804 335x w->accepted_fd = r->fd;
805 335x w->peer_storage = r->peer;
806 335x w->peer_len = r->peer_len;
807 335x free_ready_.push_front(r);
808 335x have_ready = true;
809 }
810 4049x }
811 4049x if (have_ready)
812 {
813 // Post outside the lock — acceptor mutex_ must never be
814 // held while dispatch_mutex_ is acquired by sched_->post().
815 335x sched_->post(w);
816 335x return;
817 }
818
819 // Arm the stop callback before the node is visible in
820 // `waiters_` and outside `mutex_`: an already-stopped token
821 // invokes the canceller synchronously from emplace, and
822 // cancel_waiter takes `mutex_` (self-deadlock if held).
823 // Arming pre-queue also keeps the CQE handler from claiming
824 // a node whose callback is not yet constructed.
825 3714x w->start(token);
826
827 3714x bool was_cancelled = false;
828 {
829 3714x std::lock_guard lk(mutex_);
830 3714x if (w->cancelled.load(std::memory_order_acquire))
831 {
832 // Canceller already fired (pre-stopped token); it saw
833 // queued == false and left completion to us.
834 ✗ was_cancelled = true;
835 }
836 3714x else if (auto* r = ready_fds_.pop_front())
837 {
838 // A connection arrived while the callback was armed;
839 // prefer it over parking the waiter behind it.
840 ✗ w->peer_service = peer_service_;
841 ✗ w->adopt_fn = &Derived::adopt_thunk;
842 ✗ w->accepted_fd = r->fd;
843 ✗ w->peer_storage = r->peer;
844 ✗ w->peer_len = r->peer_len;
845 ✗ free_ready_.push_front(r);
846 }
847 3714x else if (arm_err_ != 0)
848 {
849 // No arming reached the kernel, so no CQE will deliver
850 // a connection: parking here would park for good.
851 1x w->err = arm_err_;
852 }
853 else
854 {
855 3713x w->queued = true;
856 3713x sched_->work_started();
857 3713x waiters_.push_back(w);
858 3713x return;
859 }
860 3714x }
861
862 1x w->stop_cb.reset();
863 1x w->cancelled.store(was_cancelled, std::memory_order_release);
864 1x sched_->post(w);
865 }
866
867 221x void cancel_waiter(accept_node* w) noexcept
868 {
869 {
870 221x std::lock_guard lk(mutex_);
871 221x if (closing_)
872 7x return; // drain_waiters_only will complete with closing_ set
873 214x if (!w->queued)
874 ✗ return; // not queued yet; the parking path observes
875 // `cancelled` and completes the node
876 214x if (w->peek)
877 {
878 1x if (read_wait_ != w)
879 ✗ return; // already claimed by a delivery
880 1x read_wait_ = nullptr;
881 }
882 else
883 {
884 213x waiters_.remove(w);
885 }
886 214x sched_->cancel_posting_begin();
887 221x }
888 // `cancelled` is already true (the claim that routed here);
889 // that is also the completion status, so post as-is. The node's
890 // stop_cb is still engaged — do_handler resets it, and running
891 // that reset from the handler thread while this callback
892 // returns is the stop_callback destructor's documented
893 // wait-or-self case.
894 214x sched_->post(w);
895 214x sched_->work_finished(); // balance the work_started() from accept()
896 214x sched_->cancel_posting_end();
897 }
898
899 private:
900 /** Submit @p op as the live arming, or recycle it.
901
902 @param admit Runs under `mutex_`, itself under the ring mutex;
903 claims `armed_` for @p op and returns true, or returns
904 false to refuse.
905 */
906 template<class Admit>
907 1259x void submit_arming(uring_multi_accept_op* op, Admit admit) noexcept
908 {
909 1259x op->peer_storage = sockaddr_storage{};
910 1259x op->peer_len = sizeof(sockaddr_storage);
911 1259x op->res = 0;
912 // Deliberately no work_started(): the arming is an internal
913 // mechanism; user-visible work is tracked per accept.
914 // Once submitted, a re-arm's only reference to this acceptor
915 // is the op's, which the kernel may already have ended, so
916 // the error is cleared while admission still holds the lock.
917 1259x auto r = uring_try_submit_op_if(*sched_, op, [&]() noexcept {
918 std::lock_guard lk(mutex_);
919 if (!admit())
920 return false;
921 arm_err_ = 0;
922 return true;
923 });
924 1259x if (r == uring_guarded_submit::submitted)
925 1257x return;
926 2x if (r == uring_guarded_submit::sq_full)
927 {
928 {
929 2x std::lock_guard lk(mutex_);
930 2x if (armed_ == op)
931 2x armed_ = nullptr;
932 2x }
933 2x fail_arm(EAGAIN);
934 }
935 2x recycle_arming(op);
936 }
937
938 /// Return an ended arming to `free_ops_`, then drop its reference,
939 /// which may retire this impl, after the lock.
940 1256x void recycle_arming(uring_multi_accept_op* op) noexcept
941 {
942 1256x auto keep = std::move(op->object_ref_);
943 1256x std::lock_guard lk(mutex_);
944 1256x free_ops_.push_front(op);
945 1256x }
946
947 5566x static void on_accept_cqe(
948 void* self_ptr,
949 uring_multi_accept_op* op,
950 int new_fd,
951 int err,
952 bool more) noexcept
953 {
954 5566x static_cast<Derived*>(self_ptr)->on_accept_cqe_impl(
955 op, new_fd, err, more);
956 5566x }
957
958 static void
959 1257x on_arming_end(void* self_ptr, uring_multi_accept_op* op, bool live) noexcept
960 {
961 1257x auto* self = static_cast<Derived*>(self_ptr);
962 1257x if (live)
963 {
964 bool rearm;
965 {
966 655x std::lock_guard lk(self->mutex_);
967 655x rearm = self->armed_ == op && !self->closing_;
968 655x }
969 655x if (rearm)
970 {
971 // The kernel ended a live arming on its own; keep
972 // accepting with the same op and reference.
973 3x self->submit_arming(op, [self, op]() noexcept {
974 3x return self->armed_ == op && !self->closing_;
975 });
976 3x return;
977 }
978 }
979 {
980 1254x std::lock_guard lk(self->mutex_);
981 1254x if (self->armed_ == op)
982 ✗ self->armed_ = nullptr;
983 1254x }
984 1254x self->recycle_arming(op);
985 }
986
987 protected:
988 5566x void on_accept_cqe_impl(
989 uring_multi_accept_op* op, int new_fd, int err, bool more) noexcept
990 {
991 5566x accept_node* matched = nullptr;
992 5566x accept_node* claimed_peek = nullptr;
993 5566x intrusive_list<accept_node> closing_waiters;
994 {
995 5566x std::lock_guard lk(mutex_);
996 // A disowned arming's deliveries belong to a descriptor
997 // this acceptor no longer has.
998 5566x bool const stale = (op != armed_);
999 5569x if (!stale && new_fd >= 0 && read_wait_ &&
1000 3x !read_wait_->cancelled.exchange(
1001 true, std::memory_order_acq_rel))
1002 {
1003 // A parked readiness wait observes the delivery
1004 // without consuming it; the connection still flows
1005 // to a waiter or the ready queue below.
1006 3x claimed_peek = read_wait_;
1007 3x read_wait_ = nullptr;
1008 }
1009 5566x if (stale)
1010 {
1011 1557x if (new_fd >= 0)
1012 303x ::close(new_fd);
1013 1557x if (!more && closing_)
1014 {
1015 // Collect waiters to drain after the lock is released.
1016 1248x while (auto* w = waiters_.pop_front())
1017 ✗ closing_waiters.push_back(w);
1018 }
1019 }
1020 4009x else if (!waiters_.empty())
1021 {
1022 // Claim the head waiter atomically. If the canceller
1023 // already won the race (cancelled was already true),
1024 // leave the waiter in the list for cancel_waiter to
1025 // remove and dispatch with operation_aborted; park the
1026 // new_fd so the next waiter consumes it.
1027 3260x auto* head_w = waiters_.front();
1028 3260x if (!head_w->cancelled.exchange(
1029 true, std::memory_order_acq_rel))
1030 {
1031 3260x waiters_.pop_front();
1032 3260x matched = head_w;
1033 }
1034 ✗ else if (new_fd >= 0)
1035 {
1036 ✗ auto* node = acquire_ready_locked();
1037 ✗ node->fd = new_fd;
1038 ✗ node->peer = op->peer_storage;
1039 ✗ node->peer_len = op->peer_len;
1040 ✗ ready_fds_.push_back(node);
1041 }
1042 }
1043 749x else if (new_fd >= 0)
1044 {
1045 746x auto* node = acquire_ready_locked();
1046 746x node->fd = new_fd;
1047 746x node->peer = op->peer_storage;
1048 746x node->peer_len = op->peer_len;
1049 746x ready_fds_.push_back(node);
1050 }
1051 5566x }
1052
1053 // Each claim's exchange set `cancelled`; after reset() has
1054 // quiesced any in-flight canceller, restore the flag to the
1055 // real completion status before posting.
1056 5566x if (claimed_peek)
1057 {
1058 3x claimed_peek->stop_cb.reset();
1059 3x claimed_peek->cancelled.store(false, std::memory_order_release);
1060 3x sched_->post(claimed_peek);
1061 3x sched_->work_finished(); // balance the parking work_started
1062 }
1063
1064 5566x if (matched)
1065 {
1066 3260x matched->stop_cb.reset();
1067 3260x matched->peer_service = peer_service_;
1068 3260x matched->adopt_fn = &Derived::adopt_thunk;
1069 3260x if (err)
1070 {
1071 1x matched->err = err;
1072 }
1073 3259x else if (new_fd >= 0)
1074 {
1075 3259x matched->accepted_fd = new_fd;
1076 3259x matched->peer_storage = op->peer_storage;
1077 3259x matched->peer_len = op->peer_len;
1078 }
1079 3260x matched->cancelled.store(false, std::memory_order_release);
1080 3260x sched_->post(matched);
1081 3260x sched_->work_finished(); // balance waiter's work_started
1082 }
1083
1084 5566x while (auto* w = closing_waiters.pop_front())
1085 {
1086 ✗ w->stop_cb.reset();
1087 ✗ w->cancelled.store(true, std::memory_order_release);
1088 ✗ sched_->post(w);
1089 ✗ sched_->work_finished(); // balance waiter's work_started
1090 }
1091 5566x }
1092 };
1093
1094 } // namespace boost::corosio::detail
1095
1096 #endif // BOOST_COROSIO_HAS_URING
1097
1098 #endif // BOOST_COROSIO_NATIVE_DETAIL_URING_URING_MULTISHOT_ACCEPTOR_HPP
1099