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

100.0% Lines (34 / 34) 100.0% Functions (18 / 18)
reactor_descriptor_service.hpp
f(x) Functions (18)
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&) :64 59x 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&) :64 58x 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() :76 59x 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() :76 58x 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() :82 59x 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>::shutdown() :82 58x 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>::construct() :92 103x 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>::construct() :92 102x 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>::destroy(boost::corosio::io_object::implementation*) :97 103x 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>::destroy(boost::corosio::io_object::implementation*) :97 102x 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>::close(boost::corosio::io_object::handle&) :104 188x 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&) :104 185x 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 :109 357x 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 :109 408x 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*) :114 38x 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*) :114 37x 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() :119 47x 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() :119 46x 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 pool's acquire/recycle, or shutdown's reliance on
38 queued ops holding their own reference through the scheduler's
39 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 // The CRTP base reaches into state_->pool_ from retire().
59 template<class, class, class, class>
60 friend class reactor_descriptor;
61
62 protected:
63 // NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility)
64 117x explicit reactor_descriptor_service(capy::execution_context& ctx)
65 117x : state_(
66 std::make_unique<state_type>(
67 117x ctx.template use_service<scheduler_type>()))
68 {
69 117x }
70
71 public:
72 /// True when any parked op must wake the reactor.
73 static constexpr bool needs_park_notification =
74 Traits::needs_park_notification;
75
76 117x ~reactor_descriptor_service() override = default;
77
78 std::error_code assign_descriptor(
79 posix_stream_descriptor::implementation& impl,
80 native_handle_type fd) override;
81
82 117x void shutdown() override
83 {
84 117x state_->pool_.shutdown(
85 117x [](DescFinal* impl) { impl->close_descriptor(); });
86
87 // See reactor_socket_service::shutdown(): queued ops hold their
88 // own reference; the scheduler's drain releases them after us,
89 // and shutting-down mode deletes rather than recycles at zero.
90 117x }
91
92 205x io_object::implementation* construct() override
93 {
94 205x return state_->pool_.acquire(static_cast<Derived&>(*this));
95 }
96
97 205x void destroy(io_object::implementation* impl) override
98 {
99 205x auto* typed = static_cast<DescFinal*>(impl);
100 205x typed->close_descriptor();
101 205x release(typed);
102 205x }
103
104 373x void close(io_object::handle& h) override
105 {
106 373x static_cast<DescFinal*>(h.get())->close_descriptor();
107 373x }
108
109 765x scheduler_type& scheduler() const noexcept
110 {
111 765x return state_->sched_;
112 }
113
114 75x void post(scheduler_op* op)
115 {
116 75x state_->sched_.post(op);
117 75x }
118
119 93x void work_started() noexcept
120 {
121 93x state_->sched_.work_started();
122 93x }
123
124 protected:
125 std::unique_ptr<state_type> state_;
126
127 private:
128 reactor_descriptor_service(reactor_descriptor_service const&) = delete;
129 reactor_descriptor_service&
130 operator=(reactor_descriptor_service const&) = delete;
131 };
132
133 template<class Derived, class Traits, class DescFinal>
134 std::error_code
135 193x reactor_descriptor_service<Derived, Traits, DescFinal>::assign_descriptor(
136 posix_stream_descriptor::implementation& impl_base, native_handle_type fd)
137 {
138 193x auto* impl = static_cast<DescFinal*>(&impl_base);
139
140 // The public assign() guarantees the object is closed.
141 193x if (auto ec = validate_descriptor_fd(fd))
142 4x return ec;
143
144 if constexpr (requires { Traits::max_descriptor; })
145 {
146 94x if (fd >= Traits::max_descriptor)
147 1x return make_err(EMFILE);
148 }
149
150 188x return impl->init_and_register(fd);
151 }
152
153 } // namespace boost::corosio::detail
154
155 #endif // BOOST_COROSIO_POSIX
156
157 #endif // BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_DESCRIPTOR_SERVICE_HPP
158