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: 97.9 % 48 47 1
Test Date: 2026-09-28 20:06:38 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 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 HIT          57 :     explicit reactor_descriptor_service(capy::execution_context& ctx)
      61              57 :         : state_(
      62                 :               std::make_unique<state_type>(
      63              57 :                   ctx.template use_service<scheduler_type>()))
      64                 :     {
      65              57 :     }
      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              57 :     ~reactor_descriptor_service() override = default;
      73                 : 
      74                 :     std::error_code assign_descriptor(
      75                 :         posix_descriptor::implementation& impl, native_handle_type fd) override;
      76                 : 
      77              57 :     void shutdown() override
      78                 :     {
      79              57 :         std::lock_guard lock(state_->mutex_);
      80                 : 
      81              57 :         while (auto* impl = state_->impl_list_.pop_front())
      82 MIS           0 :             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 HIT          57 :     }
      87                 : 
      88              59 :     io_object::implementation* construct() override
      89                 :     {
      90              59 :         auto impl = std::make_shared<DescFinal>(static_cast<Derived&>(*this));
      91              59 :         auto* raw = impl.get();
      92                 : 
      93                 :         {
      94              59 :             std::lock_guard lock(state_->mutex_);
      95              59 :             state_->impl_ptrs_.emplace(raw, std::move(impl));
      96              59 :             state_->impl_list_.push_back(raw);
      97              59 :         }
      98                 : 
      99              59 :         return raw;
     100              59 :     }
     101                 : 
     102              59 :     void destroy(io_object::implementation* impl) override
     103                 :     {
     104              59 :         auto* typed = static_cast<DescFinal*>(impl);
     105              59 :         typed->close_descriptor();
     106              59 :         std::lock_guard lock(state_->mutex_);
     107              59 :         state_->impl_list_.remove(typed);
     108              59 :         state_->impl_ptrs_.erase(typed);
     109              59 :     }
     110                 : 
     111             102 :     void close(io_object::handle& h) override
     112                 :     {
     113             102 :         static_cast<DescFinal*>(h.get())->close_descriptor();
     114             102 :     }
     115                 : 
     116             125 :     scheduler_type& scheduler() const noexcept
     117                 :     {
     118             125 :         return state_->sched_;
     119                 :     }
     120                 : 
     121              30 :     void post(scheduler_op* op)
     122                 :     {
     123              30 :         state_->sched_.post(op);
     124              30 :     }
     125                 : 
     126              16 :     void work_started() noexcept
     127                 :     {
     128              16 :         state_->sched_.work_started();
     129              16 :     }
     130                 : 
     131               5 :     void work_finished() noexcept
     132                 :     {
     133               5 :         state_->sched_.work_finished();
     134               5 :     }
     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              55 : reactor_descriptor_service<Derived, Traits, DescFinal>::assign_descriptor(
     148                 :     posix_descriptor::implementation& impl_base, native_handle_type fd)
     149                 : {
     150              55 :     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              55 :     if (fd >= 0 && fd == impl->native_handle())
     155               2 :         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              53 :     if (auto ec = validate_descriptor_fd(fd))
     160               6 :         return ec;
     161                 : 
     162              47 :     impl->close_descriptor();
     163                 : 
     164              47 :     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
        

Generated by: LCOV version 2.3