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

100.0% Lines (30 / 30) 100.0% Functions (18 / 18)
uring_file_service_base.hpp
f(x) Functions (18)
Function Calls Lines Blocks
boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_descriptor_service, boost::corosio::detail::descriptor_service, boost::corosio::detail::uring_descriptor>::uring_file_service_base(boost::corosio::detail::uring_scheduler&) :64 53x 100.0% 100.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_random_access_file_service, boost::corosio::detail::random_access_file_service, boost::corosio::detail::uring_random_access_file>::uring_file_service_base(boost::corosio::detail::uring_scheduler&) :64 82x 100.0% 100.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_stream_file_service, boost::corosio::detail::file_service, boost::corosio::detail::uring_stream_file>::uring_file_service_base(boost::corosio::detail::uring_scheduler&) :64 75x 100.0% 100.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_descriptor_service, boost::corosio::detail::descriptor_service, boost::corosio::detail::uring_descriptor>::~uring_file_service_base() :70 53x 100.0% 100.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_random_access_file_service, boost::corosio::detail::random_access_file_service, boost::corosio::detail::uring_random_access_file>::~uring_file_service_base() :70 82x 100.0% 100.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_stream_file_service, boost::corosio::detail::file_service, boost::corosio::detail::uring_stream_file>::~uring_file_service_base() :70 75x 100.0% 100.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_descriptor_service, boost::corosio::detail::descriptor_service, boost::corosio::detail::uring_descriptor>::construct() :72 59x 100.0% 71.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_random_access_file_service, boost::corosio::detail::random_access_file_service, boost::corosio::detail::uring_random_access_file>::construct() :72 111x 100.0% 71.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_stream_file_service, boost::corosio::detail::file_service, boost::corosio::detail::uring_stream_file>::construct() :72 103x 100.0% 71.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_descriptor_service, boost::corosio::detail::descriptor_service, boost::corosio::detail::uring_descriptor>::destroy(boost::corosio::io_object::implementation*) :84 53x 100.0% 70.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_random_access_file_service, boost::corosio::detail::random_access_file_service, boost::corosio::detail::uring_random_access_file>::destroy(boost::corosio::io_object::implementation*) :84 106x 100.0% 70.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_stream_file_service, boost::corosio::detail::file_service, boost::corosio::detail::uring_stream_file>::destroy(boost::corosio::io_object::implementation*) :84 102x 100.0% 70.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_descriptor_service, boost::corosio::detail::descriptor_service, boost::corosio::detail::uring_descriptor>::close(boost::corosio::io_object::handle&) :94 97x 100.0% 100.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_random_access_file_service, boost::corosio::detail::random_access_file_service, boost::corosio::detail::uring_random_access_file>::close(boost::corosio::io_object::handle&) :94 199x 100.0% 100.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_stream_file_service, boost::corosio::detail::file_service, boost::corosio::detail::uring_stream_file>::close(boost::corosio::io_object::handle&) :94 188x 100.0% 100.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_descriptor_service, boost::corosio::detail::descriptor_service, boost::corosio::detail::uring_descriptor>::shutdown() :100 53x 100.0% 100.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_random_access_file_service, boost::corosio::detail::random_access_file_service, boost::corosio::detail::uring_random_access_file>::shutdown() :100 82x 100.0% 100.0% boost::corosio::detail::uring_file_service_base<boost::corosio::detail::uring_stream_file_service, boost::corosio::detail::file_service, boost::corosio::detail::uring_stream_file>::shutdown() :100 75x 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_FILE_SERVICE_BASE_HPP
11 #define BOOST_COROSIO_NATIVE_DETAIL_URING_URING_FILE_SERVICE_BASE_HPP
12
13 #include <boost/corosio/detail/platform.hpp>
14
15 #if BOOST_COROSIO_HAS_URING
16
17 #include <boost/corosio/detail/intrusive.hpp>
18 #include <boost/corosio/io/io_object.hpp>
19 #include <boost/corosio/native/detail/uring/uring_scheduler.hpp>
20
21 #include <memory>
22 #include <mutex>
23 #include <unordered_map>
24
25 /*
26 Shared lifecycle plumbing for io_uring file services.
27
28 uring_stream_file_service and uring_random_access_file_service were
29 byte-for-byte identical apart from the impl type and open_file's parameter
30 type: both make_shared the file impl from the scheduler, track it in an
31 intrusive list + raw->shared_ptr map, and close every file on shutdown.
32 This base factors that out; the concrete services add only open_file.
33
34 This is a separate base from uring_socket_service_base because file
35 services differ from socket services in three ways that match the reactor
36 socket service instead: they track via an intrusive list + map (sockets:
37 map only), they CLOSE files on shutdown (sockets: cancel only), and the
38 impl ctor takes just the scheduler (sockets: service + scheduler). See
39 tasks/proactor-dedup-decisions.md (#14).
40
41 Requirements on File: derive from enable_shared_from_this<File> and
42 intrusive_list<File>::node, a `File(uring_scheduler&)` constructor, and
43 a `void close_file() noexcept` method (cancel in-flight ops + close fd).
44 uring_descriptor_service reuses it too, as asio's file service reuses
45 its descriptor service.
46
47 @tparam Derived The concrete service (CRTP; unused today but kept for
48 symmetry / future hooks).
49 @tparam ServiceBase The abstract service vtable base (file_service,
50 random_access_file_service).
51 @tparam File The concrete io_uring file impl type.
52 */
53
54 namespace boost::corosio::detail {
55
56 template<class Derived, class ServiceBase, class File>
57 class uring_file_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 210x explicit uring_file_service_base(uring_scheduler& sched) noexcept
65 210x : sched_(&sched)
66 {
67 210x }
68
69 public:
70 210x ~uring_file_service_base() override = default;
71
72 273x io_object::implementation* construct() override
73 {
74 273x auto ptr = std::make_shared<File>(*sched_);
75 273x auto* impl = ptr.get();
76 {
77 273x std::lock_guard<std::mutex> lock(mutex_);
78 273x file_list_.push_back(impl);
79 273x file_ptrs_[impl] = std::move(ptr);
80 273x }
81 273x return impl;
82 273x }
83
84 261x void destroy(io_object::implementation* p) override
85 {
86 // close_file() already does cancel_and_flush(fd_) before ::close.
87 261x auto& impl = static_cast<File&>(*p);
88 261x impl.close_file();
89 261x std::lock_guard<std::mutex> lock(mutex_);
90 261x file_list_.remove(&impl);
91 261x file_ptrs_.erase(&impl);
92 261x }
93
94 484x void close(io_object::handle& h) override
95 {
96 484x if (h.get())
97 484x static_cast<File&>(*h.get()).close_file();
98 484x }
99
100 210x void shutdown() override
101 {
102 // file_ptrs_ is deliberately not cleared: the scheduler shuts
103 // down after this service and drains its completed ops, so
104 // every impl must outlive that drain. The map frees them when
105 // the service is destroyed.
106 210x std::lock_guard<std::mutex> lock(mutex_);
107 222x for (auto* impl = file_list_.pop_front(); impl != nullptr;
108 12x impl = file_list_.pop_front())
109 12x impl->close_file();
110 210x }
111
112 /// Return the scheduler used by files created by this service.
113 uring_scheduler& scheduler() noexcept
114 {
115 return *sched_;
116 }
117
118 protected:
119 uring_scheduler* sched_;
120 std::mutex mutex_;
121 intrusive_list<File> file_list_;
122 std::unordered_map<File*, std::shared_ptr<File>> file_ptrs_;
123
124 private:
125 uring_file_service_base(uring_file_service_base const&) = delete;
126 uring_file_service_base& operator=(uring_file_service_base const&) = delete;
127 };
128
129 } // namespace boost::corosio::detail
130
131 #endif // BOOST_COROSIO_HAS_URING
132
133 #endif // BOOST_COROSIO_NATIVE_DETAIL_URING_URING_FILE_SERVICE_BASE_HPP
134