include/boost/corosio/native/detail/reactor/reactor_descriptor_service.hpp

97.9% Lines (47 / 48) 100.0% Functions (20 / 20)
reactor_descriptor_service.hpp
f(x) Functions (20)
Function Calls Lines Blocks
boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::epoll_descriptor_service, boost::corosio::detail::epoll_traits, boost::corosio::detail::epoll_descriptor>::reactor_descriptor_service(boost::capy::execution_context&) :60 29x 100.0% 83.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::select_descriptor_service, boost::corosio::detail::select_traits, boost::corosio::detail::select_descriptor>::reactor_descriptor_service(boost::capy::execution_context&) :60 28x 100.0% 83.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::epoll_descriptor_service, boost::corosio::detail::epoll_traits, boost::corosio::detail::epoll_descriptor>::~reactor_descriptor_service() :72 29x 100.0% 100.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::select_descriptor_service, boost::corosio::detail::select_traits, boost::corosio::detail::select_descriptor>::~reactor_descriptor_service() :72 28x 100.0% 100.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::epoll_descriptor_service, boost::corosio::detail::epoll_traits, boost::corosio::detail::epoll_descriptor>::shutdown() :77 29x 80.0% 82.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::select_descriptor_service, boost::corosio::detail::select_traits, boost::corosio::detail::select_descriptor>::shutdown() :77 28x 80.0% 82.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::epoll_descriptor_service, boost::corosio::detail::epoll_traits, boost::corosio::detail::epoll_descriptor>::construct() :88 30x 100.0% 74.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::select_descriptor_service, boost::corosio::detail::select_traits, boost::corosio::detail::select_descriptor>::construct() :88 29x 100.0% 74.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::epoll_descriptor_service, boost::corosio::detail::epoll_traits, boost::corosio::detail::epoll_descriptor>::destroy(boost::corosio::io_object::implementation*) :102 30x 100.0% 83.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::select_descriptor_service, boost::corosio::detail::select_traits, boost::corosio::detail::select_descriptor>::destroy(boost::corosio::io_object::implementation*) :102 29x 100.0% 83.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::epoll_descriptor_service, boost::corosio::detail::epoll_traits, boost::corosio::detail::epoll_descriptor>::close(boost::corosio::io_object::handle&) :111 52x 100.0% 100.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::select_descriptor_service, boost::corosio::detail::select_traits, boost::corosio::detail::select_descriptor>::close(boost::corosio::io_object::handle&) :111 50x 100.0% 100.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::epoll_descriptor_service, boost::corosio::detail::epoll_traits, boost::corosio::detail::epoll_descriptor>::scheduler() const :116 63x 100.0% 100.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::select_descriptor_service, boost::corosio::detail::select_traits, boost::corosio::detail::select_descriptor>::scheduler() const :116 62x 100.0% 100.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::epoll_descriptor_service, boost::corosio::detail::epoll_traits, boost::corosio::detail::epoll_descriptor>::post(boost::corosio::detail::scheduler_op*) :121 15x 100.0% 100.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::select_descriptor_service, boost::corosio::detail::select_traits, boost::corosio::detail::select_descriptor>::post(boost::corosio::detail::scheduler_op*) :121 15x 100.0% 100.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::epoll_descriptor_service, boost::corosio::detail::epoll_traits, boost::corosio::detail::epoll_descriptor>::work_started() :126 8x 100.0% 100.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::select_descriptor_service, boost::corosio::detail::select_traits, boost::corosio::detail::select_descriptor>::work_started() :126 8x 100.0% 100.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::epoll_descriptor_service, boost::corosio::detail::epoll_traits, boost::corosio::detail::epoll_descriptor>::work_finished() :131 2x 100.0% 100.0% boost::corosio::detail::reactor_descriptor_service<boost::corosio::detail::select_descriptor_service, boost::corosio::detail::select_traits, boost::corosio::detail::select_descriptor>::work_finished() :131 3x 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_REACTOR_REACTOR_DESCRIPTOR_SERVICE_HPP
11 #define BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_DESCRIPTOR_SERVICE_HPP
12
13 #include <boost/corosio/detail/platform.hpp>
14
15 #if BOOST_COROSIO_POSIX
16
17 #include <boost/corosio/detail/descriptor_service.hpp>
18 #include <boost/corosio/detail/scheduler_op.hpp>
19 #include <boost/corosio/native/detail/validate_fd.hpp>
20 #include <boost/corosio/native/detail/reactor/reactor_descriptor.hpp>
21 #include <boost/corosio/native/detail/reactor/reactor_service_state.hpp>
22 #include <boost/capy/ex/execution_context.hpp>
23
24 #include <memory>
25 #include <mutex>
26 #include <system_error>
27
28 /* Reactor-backed descriptor_service.
29
30 assign_descriptor is the validate-before-mutate core the public
31 assign() contract rests on, modelled on do_assign_fd in
32 reactor_service_finals.hpp.
33
34 PARALLEL COPY: construct, destroy, close and shutdown here mirror the
35 same four members of reactor_socket_service.hpp, which this cannot
36 reuse because it calls close_socket() by name. A fix to the service
37 lifecycle -- the construct/destroy bookkeeping under state_->mutex_,
38 or shutdown's deliberate retention of impl_ptrs_ so impls outlive the
39 scheduler's drain -- belongs in both files.
40 */
41
42 namespace boost::corosio::detail {
43
44 /** CRTP base for reactor-backed descriptor services.
45
46 @tparam Derived The named final service type (CRTP self).
47 @tparam Traits Backend traits (epoll_traits, kqueue_traits, ...).
48 @tparam DescFinal The named final descriptor impl type.
49 */
50 template<class Derived, class Traits, class DescFinal>
51 class reactor_descriptor_service : public descriptor_service
52 {
53 using scheduler_type = typename Traits::scheduler_type;
54 using state_type = reactor_service_state<scheduler_type, DescFinal>;
55
56 friend Derived;
57
58 protected:
59 // NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility)
60 57x explicit reactor_descriptor_service(capy::execution_context& ctx)
61 57x : state_(
62 std::make_unique<state_type>(
63 57x ctx.template use_service<scheduler_type>()))
64 {
65 57x }
66
67 public:
68 /// True when a parked write-direction op must wake the reactor.
69 static constexpr bool needs_write_notification =
70 Traits::needs_write_notification;
71
72 57x ~reactor_descriptor_service() override = default;
73
74 std::error_code assign_descriptor(
75 posix_descriptor::implementation& impl, native_handle_type fd) override;
76
77 57x void shutdown() override
78 {
79 57x std::lock_guard lock(state_->mutex_);
80
81 57x while (auto* impl = state_->impl_list_.pop_front())
82 ✗ impl->close_descriptor();
83
84 // Don't clear impl_ptrs_ here: the scheduler shuts down after us
85 // and drains completed_ops_, so every impl must outlive that.
86 57x }
87
88 59x io_object::implementation* construct() override
89 {
90 59x auto impl = std::make_shared<DescFinal>(static_cast<Derived&>(*this));
91 59x auto* raw = impl.get();
92
93 {
94 59x std::lock_guard lock(state_->mutex_);
95 59x state_->impl_ptrs_.emplace(raw, std::move(impl));
96 59x state_->impl_list_.push_back(raw);
97 59x }
98
99 59x return raw;
100 59x }
101
102 59x void destroy(io_object::implementation* impl) override
103 {
104 59x auto* typed = static_cast<DescFinal*>(impl);
105 59x typed->close_descriptor();
106 59x std::lock_guard lock(state_->mutex_);
107 59x state_->impl_list_.remove(typed);
108 59x state_->impl_ptrs_.erase(typed);
109 59x }
110
111 102x void close(io_object::handle& h) override
112 {
113 102x static_cast<DescFinal*>(h.get())->close_descriptor();
114 102x }
115
116 125x scheduler_type& scheduler() const noexcept
117 {
118 125x return state_->sched_;
119 }
120
121 30x void post(scheduler_op* op)
122 {
123 30x state_->sched_.post(op);
124 30x }
125
126 16x void work_started() noexcept
127 {
128 16x state_->sched_.work_started();
129 16x }
130
131 5x void work_finished() noexcept
132 {
133 5x state_->sched_.work_finished();
134 5x }
135
136 protected:
137 std::unique_ptr<state_type> state_;
138
139 private:
140 reactor_descriptor_service(reactor_descriptor_service const&) = delete;
141 reactor_descriptor_service&
142 operator=(reactor_descriptor_service const&) = delete;
143 };
144
145 template<class Derived, class Traits, class DescFinal>
146 std::error_code
147 55x reactor_descriptor_service<Derived, Traits, DescFinal>::assign_descriptor(
148 posix_descriptor::implementation& impl_base, native_handle_type fd)
149 {
150 55x auto* impl = static_cast<DescFinal*>(&impl_base);
151
152 // fd >= 0 guard: an unset impl reports native_handle() == -1, and a
153 // caller-supplied -1 must fail as a bad fd, not a self-assign.
154 55x if (fd >= 0 && fd == impl->native_handle())
155 2x return std::make_error_code(std::errc::invalid_argument);
156
157 // Validate before touching the held descriptor: a failed assign
158 // must leave the object unchanged and the caller owning the fd.
159 53x if (auto ec = validate_descriptor_fd(fd))
160 6x return ec;
161
162 47x impl->close_descriptor();
163
164 47x return impl->init_and_register(fd);
165 }
166
167 } // namespace boost::corosio::detail
168
169 #endif // BOOST_COROSIO_POSIX
170
171 #endif // BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_DESCRIPTOR_SERVICE_HPP
172