LCOV - code coverage report
Current view: top level - corosio/native/detail/reactor - reactor_descriptor_service.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 100.0 % 34 34
Test Date: 2026-10-17 04:01:32 Functions: 91.7 % 24 22 2

           TLA  Line data    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 HIT         117 :     explicit reactor_descriptor_service(capy::execution_context& ctx)
      65             117 :         : state_(
      66                 :               std::make_unique<state_type>(
      67             117 :                   ctx.template use_service<scheduler_type>()))
      68                 :     {
      69             117 :     }
      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             117 :     ~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             117 :     void shutdown() override
      83                 :     {
      84             117 :         state_->pool_.shutdown(
      85             135 :             [](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             117 :     }
      91                 : 
      92             205 :     io_object::implementation* construct() override
      93                 :     {
      94             205 :         return state_->pool_.acquire(static_cast<Derived&>(*this));
      95                 :     }
      96                 : 
      97             205 :     void destroy(io_object::implementation* impl) override
      98                 :     {
      99             205 :         auto* typed = static_cast<DescFinal*>(impl);
     100             205 :         typed->close_descriptor();
     101             205 :         release(typed);
     102             205 :     }
     103                 : 
     104             373 :     void close(io_object::handle& h) override
     105                 :     {
     106             373 :         static_cast<DescFinal*>(h.get())->close_descriptor();
     107             373 :     }
     108                 : 
     109             765 :     scheduler_type& scheduler() const noexcept
     110                 :     {
     111             765 :         return state_->sched_;
     112                 :     }
     113                 : 
     114              75 :     void post(scheduler_op* op)
     115                 :     {
     116              75 :         state_->sched_.post(op);
     117              75 :     }
     118                 : 
     119              93 :     void work_started() noexcept
     120                 :     {
     121              93 :         state_->sched_.work_started();
     122              93 :     }
     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             193 : reactor_descriptor_service<Derived, Traits, DescFinal>::assign_descriptor(
     136                 :     posix_stream_descriptor::implementation& impl_base, native_handle_type fd)
     137                 : {
     138             193 :     auto* impl = static_cast<DescFinal*>(&impl_base);
     139                 : 
     140                 :     // The public assign() guarantees the object is closed.
     141             193 :     if (auto ec = validate_descriptor_fd(fd))
     142               4 :         return ec;
     143                 : 
     144                 :     if constexpr (requires { Traits::max_descriptor; })
     145                 :     {
     146              94 :         if (fd >= Traits::max_descriptor)
     147               1 :             return make_err(EMFILE);
     148                 :     }
     149                 : 
     150             188 :     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
        

Generated by: LCOV version 2.3