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

97.4% Lines (37/0/38) 100.0% List of functions (26/0/26)
uring_socket_service_base.hpp
f(x) Functions (26)
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 799x 100.0% 86.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 799x 100.0% 86.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 799x 100.0% 86.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 799x 100.0% 86.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 799x 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 799x 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 799x 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 799x 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 799x 100.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 799x 100.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 799x 100.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 799x 80.0% 50.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() :89 126x 100.0% 71.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() :89 147x 100.0% 71.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() :89 6609x 100.0% 71.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() :89 132x 100.0% 71.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*) :99 125x 83.3% 64.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*) :99 158x 83.3% 64.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*) :99 9839x 83.3% 64.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*) :99 132x 83.3% 64.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&) :109 227x 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&) :109 258x 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&) :109 16355x 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&) :109 249x 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>::register_impl(std::shared_ptr<boost::corosio::detail::uring_local_stream_socket>) :124 12x 100.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>::register_impl(std::shared_ptr<boost::corosio::detail::uring_tcp_socket>) :124 3233x 100.0% 80.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/io/io_object.hpp>
18 #include <boost/corosio/native/detail/uring/uring_scheduler.hpp>
19 #include <boost/capy/ex/execution_context.hpp>
20
21 #include <memory>
22 #include <mutex>
23 #include <unordered_map>
24 #include <vector>
25
26 /*
27 Shared lifecycle plumbing for io_uring socket/datagram services.
28
29 construct / destroy / shutdown / close / scheduler() are identical across
30 uring_tcp_service, uring_udp_service, uring_local_stream_service,
31 and uring_local_datagram_service — they all make_shared the impl, track
32 it in a raw->shared_ptr map, cancel on shutdown, and close eagerly. This
33 base factors that out; the concrete services add only the protocol-
34 specific open/bind/adopt.
35
36 This is io_uring's own service base rather than a reuse of
37 reactor_socket_service: io_uring tracks impls in a map (the reactor uses
38 an intrusive list + map), cancels (not closes) on shutdown, and constructs
39 impls with a (service&, scheduler&) ctor. Reusing the reactor template
40 would force io_uring sockets to adopt the intrusive node, a close-on-
41 shutdown behavior change, and an Impl(Derived&) ctor — high churn and a
42 teardown behavior change for marginal extra sharing. See
43 tasks/proactor-dedup-decisions.md (#13).
44
45 Requirements on Socket: a `(Derived& service, uring_scheduler& sched)`
46 constructor and a `void close_socket() noexcept` method (cancel in-flight
47 ops + close fd + reset cached endpoints).
48
49 @tparam Derived The concrete service (CRTP, passed to the Socket ctor).
50 @tparam ServiceBase The abstract service vtable base (tcp_service, ...).
51 @tparam Socket The concrete io_uring socket impl type.
52 */
53
54 namespace boost::corosio::detail {
55
56 template<class Derived, class ServiceBase, class Socket>
57 class uring_socket_service_base : public ServiceBase
58 {
59 friend Derived;
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 3196x explicit uring_socket_service_base(capy::execution_context& ctx)
65 3196x : sched_(&ctx.template use_service<uring_scheduler>())
66 {
67 3196x }
68
69 public:
70 3196x ~uring_socket_service_base() override = default;
71
72 3196x void shutdown() override
73 {
74 // Snapshot live impls, then cancel without the lock held to avoid
75 // inversion if cancel() ever re-enters the service. Impls stay owned
76 // by impls_ until ~service (after the scheduler drains its queue),
77 // keeping every impl alive while its cancel CQEs are processed.
78 3196x std::vector<std::shared_ptr<Socket>> live;
79 {
80 3196x std::lock_guard lk(mutex_);
81 3196x live.reserve(impls_.size());
82 3201x for (auto& [_, p] : impls_)
83 5x live.push_back(p);
84 3196x }
85 3201x for (auto& p : live)
86 5x p->cancel();
87 3196x }
88
89 7014x io_object::implementation* construct() override
90 {
91 7014x auto p =
92 7014x std::make_shared<Socket>(static_cast<Derived&>(*this), *sched_);
93 7014x auto* raw = p.get();
94 7014x std::lock_guard lk(mutex_);
95 7014x impls_.emplace(raw, std::move(p));
96 7014x return raw;
97 7014x }
98
99 10254x void destroy(io_object::implementation* p) override
100 {
101 10254x if (!p)
102 return;
103 10254x std::lock_guard lk(mutex_);
104 10254x impls_.erase(static_cast<Socket*>(p));
105 10254x }
106
107 // Close the fd eagerly when the public close() is called, before
108 // destroy() drops the shared_ptr and the destructor runs.
109 17089x void close(io_object::handle& h) override
110 {
111 17089x if (auto* sock = static_cast<Socket*>(h.get()))
112 17089x sock->close_socket();
113 17089x }
114
115 /// Return the scheduler used by sockets created by this service.
116 uring_scheduler& scheduler() noexcept
117 {
118 return *sched_;
119 }
120
121 protected:
122 /// Register an externally-built impl (used by adopt_fd on stream
123 /// services after accept(2)). Returns the raw pointer.
124 3245x Socket* register_impl(std::shared_ptr<Socket> p)
125 {
126 3245x auto* raw = p.get();
127 3245x std::lock_guard lk(mutex_);
128 3245x impls_.emplace(raw, std::move(p));
129 3245x return raw;
130 3245x }
131
132 uring_scheduler* sched_;
133 std::mutex mutex_;
134 std::unordered_map<Socket*, std::shared_ptr<Socket>> impls_;
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