include/boost/corosio/native/detail/io_uring/io_uring_socket_service_base.hpp

92.1% Lines (35/38) 100.0% List of functions (26/26)
io_uring_socket_service_base.hpp
f(x) Functions (26)
Function Calls Lines Blocks
boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_local_datagram_service, boost::corosio::detail::local_datagram_service, boost::corosio::detail::io_uring_local_datagram_socket>::io_uring_socket_service_base(boost::capy::execution_context&) :64 551x 100.0% 86.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::io_uring_local_stream_socket>::io_uring_socket_service_base(boost::capy::execution_context&) :64 551x 100.0% 86.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::io_uring_tcp_socket>::io_uring_socket_service_base(boost::capy::execution_context&) :64 551x 100.0% 86.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_udp_service, boost::corosio::detail::udp_service, boost::corosio::detail::io_uring_udp_socket>::io_uring_socket_service_base(boost::capy::execution_context&) :64 551x 100.0% 86.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_local_datagram_service, boost::corosio::detail::local_datagram_service, boost::corosio::detail::io_uring_local_datagram_socket>::~io_uring_socket_service_base() :70 551x 100.0% 100.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::io_uring_local_stream_socket>::~io_uring_socket_service_base() :70 551x 100.0% 100.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::io_uring_tcp_socket>::~io_uring_socket_service_base() :70 551x 100.0% 100.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_udp_service, boost::corosio::detail::udp_service, boost::corosio::detail::io_uring_udp_socket>::~io_uring_socket_service_base() :70 551x 100.0% 100.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_local_datagram_service, boost::corosio::detail::local_datagram_service, boost::corosio::detail::io_uring_local_datagram_socket>::shutdown() :72 551x 80.0% 50.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::io_uring_local_stream_socket>::shutdown() :72 551x 80.0% 50.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::io_uring_tcp_socket>::shutdown() :72 551x 80.0% 50.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_udp_service, boost::corosio::detail::udp_service, boost::corosio::detail::io_uring_udp_socket>::shutdown() :72 551x 80.0% 50.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_local_datagram_service, boost::corosio::detail::local_datagram_service, boost::corosio::detail::io_uring_local_datagram_socket>::construct() :89 79x 100.0% 71.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::io_uring_local_stream_socket>::construct() :89 61x 100.0% 71.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::io_uring_tcp_socket>::construct() :89 6217x 100.0% 71.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_udp_service, boost::corosio::detail::udp_service, boost::corosio::detail::io_uring_udp_socket>::construct() :89 90x 100.0% 71.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_local_datagram_service, boost::corosio::detail::local_datagram_service, boost::corosio::detail::io_uring_local_datagram_socket>::destroy(boost::corosio::io_object::implementation*) :99 79x 83.3% 64.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::io_uring_local_stream_socket>::destroy(boost::corosio::io_object::implementation*) :99 70x 83.3% 64.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::io_uring_tcp_socket>::destroy(boost::corosio::io_object::implementation*) :99 9275x 83.3% 64.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_udp_service, boost::corosio::detail::udp_service, boost::corosio::detail::io_uring_udp_socket>::destroy(boost::corosio::io_object::implementation*) :99 90x 83.3% 64.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_local_datagram_service, boost::corosio::detail::local_datagram_service, boost::corosio::detail::io_uring_local_datagram_socket>::close(boost::corosio::io_object::handle&) :109 145x 100.0% 100.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::io_uring_local_stream_socket>::close(boost::corosio::io_object::handle&) :109 114x 100.0% 100.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::io_uring_tcp_socket>::close(boost::corosio::io_object::handle&) :109 15427x 100.0% 100.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_udp_service, boost::corosio::detail::udp_service, boost::corosio::detail::io_uring_udp_socket>::close(boost::corosio::io_object::handle&) :109 169x 100.0% 100.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_local_stream_service, boost::corosio::detail::local_stream_service, boost::corosio::detail::io_uring_local_stream_socket>::register_impl(std::shared_ptr<boost::corosio::detail::io_uring_local_stream_socket>) :121 9x 100.0% 80.0% boost::corosio::detail::io_uring_socket_service_base<boost::corosio::detail::io_uring_tcp_service, boost::corosio::detail::tcp_service, boost::corosio::detail::io_uring_tcp_socket>::register_impl(std::shared_ptr<boost::corosio::detail::io_uring_tcp_socket>) :121 3058x 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_IO_URING_IO_URING_SOCKET_SERVICE_BASE_HPP
11 #define BOOST_COROSIO_NATIVE_DETAIL_IO_URING_IO_URING_SOCKET_SERVICE_BASE_HPP
12
13 #include <boost/corosio/detail/platform.hpp>
14
15 #if BOOST_COROSIO_HAS_IO_URING
16
17 #include <boost/corosio/io/io_object.hpp>
18 #include <boost/corosio/native/detail/io_uring/io_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 io_uring_tcp_service, io_uring_udp_service, io_uring_local_stream_service,
31 and io_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, io_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 io_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 2204x explicit io_uring_socket_service_base(capy::execution_context& ctx)
65 2204x : sched_(&ctx.template use_service<io_uring_scheduler>())
66 {
67 2204x }
68
69 public:
70 2204x ~io_uring_socket_service_base() override = default;
71
72 2204x 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 2204x std::vector<std::shared_ptr<Socket>> live;
79 {
80 2204x std::lock_guard lk(mutex_);
81 2204x live.reserve(impls_.size());
82 2204x for (auto& [_, p] : impls_)
83 live.push_back(p);
84 2204x }
85 2204x for (auto& p : live)
86 p->cancel();
87 2204x }
88
89 6447x io_object::implementation* construct() override
90 {
91 6447x auto p = std::make_shared<Socket>(
92 6447x static_cast<Derived&>(*this), *sched_);
93 6447x auto* raw = p.get();
94 6447x std::lock_guard lk(mutex_);
95 6447x impls_.emplace(raw, std::move(p));
96 6447x return raw;
97 6447x }
98
99 9514x void destroy(io_object::implementation* p) override
100 {
101 9514x if (!p)
102 return;
103 9514x std::lock_guard lk(mutex_);
104 9514x impls_.erase(static_cast<Socket*>(p));
105 9514x }
106
107 // Close the fd eagerly when the public close() is called, before
108 // destroy() drops the shared_ptr and the destructor runs.
109 15855x void close(io_object::handle& h) override
110 {
111 15855x if (auto* sock = static_cast<Socket*>(h.get()))
112 15855x sock->close_socket();
113 15855x }
114
115 /// Return the scheduler used by sockets created by this service.
116 io_uring_scheduler& scheduler() noexcept { return *sched_; }
117
118 protected:
119 /// Register an externally-built impl (used by adopt_fd on stream
120 /// services after accept(2)). Returns the raw pointer.
121 3067x Socket* register_impl(std::shared_ptr<Socket> p)
122 {
123 3067x auto* raw = p.get();
124 3067x std::lock_guard lk(mutex_);
125 3067x impls_.emplace(raw, std::move(p));
126 3067x return raw;
127 3067x }
128
129 io_uring_scheduler* sched_;
130 std::mutex mutex_;
131 std::unordered_map<Socket*, std::shared_ptr<Socket>> impls_;
132
133 private:
134 io_uring_socket_service_base(io_uring_socket_service_base const&) = delete;
135 io_uring_socket_service_base&
136 operator=(io_uring_socket_service_base const&) = delete;
137 };
138
139 } // namespace boost::corosio::detail
140
141 #endif // BOOST_COROSIO_HAS_IO_URING
142
143 #endif // BOOST_COROSIO_NATIVE_DETAIL_IO_URING_IO_URING_SOCKET_SERVICE_BASE_HPP
144