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

96.2% Lines (25 / 26) 100.0% Functions (32 / 32)
uring_socket_service_base.hpp
f(x) Functions (32)
Function Calls Lines Blocks
boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_datagram_service, boost::corosio::detail::local_datagram_service, boost::corosio::detail::uring_local_datagram_socket>::uring_socket_service_base(boost::capy::execution_context&) :64 73x 100.0% 83.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::uring_local_stream_socket>::uring_socket_service_base(boost::capy::execution_context&) :64 115x 100.0% 83.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::uring_tcp_socket>::uring_socket_service_base(boost::capy::execution_context&) :64 457x 100.0% 83.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_udp_service, boost::corosio::detail::udp_service, boost::corosio::detail::uring_udp_socket>::uring_socket_service_base(boost::capy::execution_context&) :64 100x 100.0% 83.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_datagram_service, boost::corosio::detail::local_datagram_service, boost::corosio::detail::uring_local_datagram_socket>::~uring_socket_service_base() :70 73x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::uring_local_stream_socket>::~uring_socket_service_base() :70 115x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::uring_tcp_socket>::~uring_socket_service_base() :70 457x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_udp_service, boost::corosio::detail::udp_service, boost::corosio::detail::uring_udp_socket>::~uring_socket_service_base() :70 100x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_datagram_service, boost::corosio::detail::local_datagram_service, boost::corosio::detail::uring_local_datagram_socket>::shutdown() :72 73x 75.0% 80.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::uring_local_stream_socket>::shutdown() :72 115x 75.0% 80.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::uring_tcp_socket>::shutdown() :72 457x 75.0% 80.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_udp_service, boost::corosio::detail::udp_service, boost::corosio::detail::uring_udp_socket>::shutdown() :72 100x 75.0% 80.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_datagram_service, boost::corosio::detail::local_datagram_service, boost::corosio::detail::uring_local_datagram_socket>::shutdown()::{lambda(boost::corosio::detail::uring_local_datagram_socket*)#1}::operator()(boost::corosio::detail::uring_local_datagram_socket*) const :84 5x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::uring_local_stream_socket>::shutdown()::{lambda(boost::corosio::detail::uring_local_stream_socket*)#1}::operator()(boost::corosio::detail::uring_local_stream_socket*) const :84 8x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::uring_tcp_socket>::shutdown()::{lambda(boost::corosio::detail::uring_tcp_socket*)#1}::operator()(boost::corosio::detail::uring_tcp_socket*) const :84 825x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_udp_service, boost::corosio::detail::udp_service, boost::corosio::detail::uring_udp_socket>::shutdown()::{lambda(boost::corosio::detail::uring_udp_socket*)#1}::operator()(boost::corosio::detail::uring_udp_socket*) const :84 4x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_datagram_service, boost::corosio::detail::local_datagram_service, boost::corosio::detail::uring_local_datagram_socket>::construct() :96 161x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::uring_local_stream_socket>::construct() :96 247x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::uring_tcp_socket>::construct() :96 7165x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_udp_service, boost::corosio::detail::udp_service, boost::corosio::detail::uring_udp_socket>::construct() :96 182x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_datagram_service, boost::corosio::detail::local_datagram_service, boost::corosio::detail::uring_local_datagram_socket>::destroy(boost::corosio::io_object::implementation*) :101 161x 75.0% 75.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::uring_local_stream_socket>::destroy(boost::corosio::io_object::implementation*) :101 264x 75.0% 75.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::uring_tcp_socket>::destroy(boost::corosio::io_object::implementation*) :101 10741x 75.0% 75.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_udp_service, boost::corosio::detail::udp_service, boost::corosio::detail::uring_udp_socket>::destroy(boost::corosio::io_object::implementation*) :101 182x 75.0% 75.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_datagram_service, boost::corosio::detail::local_datagram_service, boost::corosio::detail::uring_local_datagram_socket>::close(boost::corosio::io_object::handle&) :110 266x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::uring_local_stream_socket>::close(boost::corosio::io_object::handle&) :110 428x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::uring_tcp_socket>::close(boost::corosio::io_object::handle&) :110 17662x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_udp_service, boost::corosio::detail::udp_service, boost::corosio::detail::uring_udp_socket>::close(boost::corosio::io_object::handle&) :110 314x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_datagram_service, boost::corosio::detail::local_datagram_service, boost::corosio::detail::uring_local_datagram_socket>::acquire_impl() :128 159x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::uring_local_stream_socket>::acquire_impl() :128 261x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::uring_tcp_socket>::acquire_impl() :128 10731x 100.0% 100.0% boost::corosio::detail::uring_socket_service_base<boost::corosio::detail::uring_udp_service, boost::corosio::detail::udp_service, boost::corosio::detail::uring_udp_socket>::acquire_impl() :128 180x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Michael Vandeberg
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_SOCKET_SERVICE_BASE_HPP
11 #define BOOST_COROSIO_NATIVE_DETAIL_URING_URING_SOCKET_SERVICE_BASE_HPP
12
13 #include <boost/corosio/detail/platform.hpp>
14
15 #if BOOST_COROSIO_HAS_URING
16
17 #include <boost/corosio/detail/object_pool.hpp>
18 #include <boost/corosio/detail/object_ref.hpp>
19 #include <boost/corosio/io/io_object.hpp>
20 #include <boost/corosio/native/detail/uring/uring_scheduler.hpp>
21 #include <boost/capy/ex/execution_context.hpp>
22
23 #include <vector>
24
25 /*
26 Shared lifecycle plumbing for io_uring socket/datagram services.
27
28 construct / destroy / shutdown / close / scheduler() are identical across
29 uring_tcp_service, uring_udp_service, uring_local_stream_service,
30 and uring_local_datagram_service — they all pop-or-new the impl from a
31 per-service recycling pool, cancel on shutdown, and close eagerly. This
32 base factors that out; the concrete services add only the protocol-
33 specific open/bind/adopt.
34
35 This is io_uring's own service base rather than a reuse of
36 reactor_socket_service: io_uring cancels (not closes) on shutdown and
37 constructs impls with a (service&, scheduler&) ctor, vs. the reactor's
38 close-on-shutdown and Impl(Derived&) ctor. Reusing the reactor template
39 would force a teardown behavior change for marginal extra sharing. See
40 tasks/proactor-dedup-decisions.md (#13).
41
42 Requirements on Socket: a `(Derived& service, uring_scheduler& sched)`
43 constructor, a `void close_socket() noexcept` method (cancel in-flight
44 ops + close fd + reset cached endpoints), a `void reuse() noexcept`
45 method, and derivation from `intrusive_list<Socket>::node` (the pool's
46 live/free linkage).
47
48 @tparam Derived The concrete service (CRTP, passed to the Socket ctor).
49 @tparam ServiceBase The abstract service vtable base (tcp_service, ...).
50 @tparam Socket The concrete io_uring socket impl type.
51 */
52
53 namespace boost::corosio::detail {
54
55 template<class Derived, class ServiceBase, class Socket>
56 class uring_socket_service_base : public ServiceBase
57 {
58 friend Derived;
59 friend Socket;
60
61 // Private CRTP ctor: only `Derived` (the concrete service, a friend)
62 // constructs the base — prevents inheriting with the wrong Derived
63 // (bugprone-crtp-constructor-accessibility).
64 745x explicit uring_socket_service_base(capy::execution_context& ctx)
65 745x : sched_(&ctx.template use_service<uring_scheduler>())
66 {
67 745x }
68
69 public:
70 745x ~uring_socket_service_base() override = default;
71
72 745x void shutdown() override
73 {
74 // Snapshot live impls under an acquired reference, then cancel
75 // without the pool lock held to avoid inversion if cancel() ever
76 // re-enters the service. shutdown() sets shutting-down and
77 // takes the snapshot under one critical section, so each
78 // cancel's own release (if it drops the last ref) deletes
79 // rather than recycles. In-flight ops hold their own
80 // references, so every impl stays alive while its cancel CQEs
81 // are processed.
82 745x std::vector<Socket*> live;
83 745x pool_.shutdown(
84 745x [&](Socket* s)
85 {
86 842x acquire(s);
87 842x live.push_back(s);
88 });
89 1587x for (auto* s : live)
90 {
91 842x s->cancel();
92 842x release(s);
93 }
94 745x }
95
96 7755x io_object::implementation* construct() override
97 {
98 7755x return acquire_impl();
99 }
100
101 11348x void destroy(io_object::implementation* p) override
102 {
103 11348x if (!p)
104 ✗ return;
105 11348x release(static_cast<Socket*>(p));
106 }
107
108 // Close the fd eagerly when the public close() is called, before
109 // destroy() drops the service's reference and recycling runs.
110 18670x void close(io_object::handle& h) override
111 {
112 18670x if (auto* sock = static_cast<Socket*>(h.get()))
113 18670x sock->close_socket();
114 18670x }
115
116 /// Return the scheduler used by sockets created by this service.
117 uring_scheduler& scheduler() noexcept
118 {
119 return *sched_;
120 }
121
122 protected:
123 /** Pop a recycled impl or news one, with the service reference held.
124
125 Used by both `construct()` and the `adopt_fd` accepted-connection
126 path (which additionally calls `assign_fd()` on the result).
127 */
128 11348x Socket* acquire_impl()
129 {
130 11348x return pool_.acquire(static_cast<Derived&>(*this), *sched_);
131 }
132
133 uring_scheduler* sched_;
134 object_pool<Socket> pool_;
135
136 private:
137 uring_socket_service_base(uring_socket_service_base const&) = delete;
138 uring_socket_service_base&
139 operator=(uring_socket_service_base const&) = delete;
140 };
141
142 } // namespace boost::corosio::detail
143
144 #endif // BOOST_COROSIO_HAS_URING
145
146 #endif // BOOST_COROSIO_NATIVE_DETAIL_URING_URING_SOCKET_SERVICE_BASE_HPP
147