LCOV - code coverage report
Current view: top level - corosio/native/detail/reactor - reactor_backend.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 49.2 % 65 32 33
Test Date: 2026-04-09 23:21:11 Functions: 100.0 % 4 4

           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_BACKEND_HPP
      11                 : #define BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_BACKEND_HPP
      12                 : 
      13                 : /* Parameterized reactor backend.
      14                 : 
      15                 :    Assembles all socket, service, acceptor, and op types for a given
      16                 :    backend Traits type. Includes the accept() implementation (which
      17                 :    needs all types to be complete) and the reactor_types<Traits>
      18                 :    bundle used by backend.hpp.
      19                 : */
      20                 : 
      21                 : #include <boost/corosio/native/detail/reactor/reactor_service_finals.hpp>
      22                 : #include <boost/corosio/native/detail/reactor/reactor_op_complete.hpp>
      23                 : #include <boost/corosio/native/detail/endpoint_convert.hpp>
      24                 : #include <boost/corosio/detail/dispatch_coro.hpp>
      25                 : 
      26                 : #include <mutex>
      27                 : 
      28                 : namespace boost::corosio::detail {
      29                 : 
      30                 : // ============================================================
      31                 : // Acceptor accept() implementation
      32                 : // ============================================================
      33                 : 
      34                 : template<class Traits, class AccImplBase, class Endpoint>
      35                 : std::coroutine_handle<>
      36 HIT        8530 : reactor_acceptor_final<Traits, AccImplBase, Endpoint>::accept(
      37                 :     std::coroutine_handle<> h,
      38                 :     capy::executor_ref ex,
      39                 :     std::stop_token token,
      40                 :     std::error_code* ec,
      41                 :     io_object::implementation** impl_out)
      42                 : {
      43                 :     using socket_final = stream_socket_t<Traits, Endpoint>;
      44                 : 
      45            8530 :     auto& op = this->acc_;
      46            8530 :     op.reset();
      47            8530 :     op.h        = h;
      48            8530 :     op.ex       = ex;
      49            8530 :     op.ec_out   = ec;
      50            8530 :     op.impl_out = impl_out;
      51            8530 :     op.fd       = this->fd_;
      52            8530 :     op.start(token, this);
      53                 : 
      54            8530 :     sockaddr_storage peer_storage{};
      55                 : 
      56            8530 :     int accepted = Traits::accept_policy::do_accept(this->fd_, peer_storage);
      57                 : 
      58            8530 :     if (accepted >= 0)
      59                 :     {
      60                 :         {
      61               6 :             std::lock_guard lock(this->desc_state_.mutex);
      62               6 :             this->desc_state_.read_ready = false;
      63               6 :         }
      64                 : 
      65               6 :         if (this->svc_.scheduler().try_consume_inline_budget())
      66                 :         {
      67 MIS           0 :             auto* socket_svc = this->svc_.stream_service();
      68               0 :             if (socket_svc)
      69                 :             {
      70                 :                 auto& impl =
      71               0 :                     static_cast<socket_final&>(*socket_svc->construct());
      72               0 :                 impl.set_socket(accepted);
      73                 : 
      74               0 :                 impl.desc_state_.fd = accepted;
      75                 :                 {
      76               0 :                     std::lock_guard lock(impl.desc_state_.mutex);
      77               0 :                     impl.desc_state_.read_op    = nullptr;
      78               0 :                     impl.desc_state_.write_op   = nullptr;
      79               0 :                     impl.desc_state_.connect_op = nullptr;
      80               0 :                 }
      81               0 :                 socket_svc->scheduler().register_descriptor(
      82                 :                     accepted, &impl.desc_state_);
      83                 : 
      84               0 :                 impl.set_endpoints(
      85                 :                     this->local_endpoint_,
      86               0 :                     from_sockaddr_as(
      87                 :                         peer_storage,
      88                 :                         static_cast<socklen_t>(sizeof(peer_storage)),
      89                 :                         Endpoint{}));
      90                 : 
      91               0 :                 *ec = {};
      92               0 :                 if (impl_out)
      93               0 :                     *impl_out = &impl;
      94                 :             }
      95                 :             else
      96                 :             {
      97               0 :                 ::close(accepted);
      98               0 :                 *ec = make_err(ENOENT);
      99               0 :                 if (impl_out)
     100               0 :                     *impl_out = nullptr;
     101                 :             }
     102               0 :             op.cont_op.cont.h = h;
     103               0 :             return dispatch_coro(ex, op.cont_op.cont);
     104                 :         }
     105                 : 
     106 HIT           6 :         op.accepted_fd  = accepted;
     107               6 :         op.peer_storage = peer_storage;
     108               6 :         op.complete(0, 0);
     109               6 :         op.impl_ptr = this->shared_from_this();
     110               6 :         this->svc_.post(&op);
     111               6 :         return std::noop_coroutine();
     112                 :     }
     113                 : 
     114            8524 :     if (errno == EAGAIN || errno == EWOULDBLOCK)
     115                 :     {
     116            8524 :         op.impl_ptr = this->shared_from_this();
     117            8524 :         this->svc_.work_started();
     118                 : 
     119            8524 :         std::lock_guard lock(this->desc_state_.mutex);
     120            8524 :         bool io_done = false;
     121            8524 :         if (this->desc_state_.read_ready)
     122                 :         {
     123 MIS           0 :             this->desc_state_.read_ready = false;
     124               0 :             op.perform_io();
     125               0 :             io_done = (op.errn != EAGAIN && op.errn != EWOULDBLOCK);
     126               0 :             if (!io_done)
     127               0 :                 op.errn = 0;
     128                 :         }
     129                 : 
     130 HIT        8524 :         if (io_done || op.cancelled.load(std::memory_order_acquire))
     131                 :         {
     132 MIS           0 :             this->svc_.post(&op);
     133               0 :             this->svc_.work_finished();
     134                 :         }
     135                 :         else
     136                 :         {
     137 HIT        8524 :             this->desc_state_.read_op = &op;
     138                 :         }
     139            8524 :         return std::noop_coroutine();
     140            8524 :     }
     141                 : 
     142 MIS           0 :     op.complete(errno, 0);
     143               0 :     op.impl_ptr = this->shared_from_this();
     144               0 :     this->svc_.post(&op);
     145               0 :     return std::noop_coroutine();
     146                 : }
     147                 : 
     148                 : // ============================================================
     149                 : // Type bundle for backend.hpp
     150                 : // ============================================================
     151                 : 
     152                 : template<class Traits>
     153                 : struct reactor_types
     154                 : {
     155                 :     using tcp_socket_type = stream_socket_t<Traits, endpoint>;
     156                 :     using tcp_service_type = reactor_tcp_service_final<
     157                 :         Traits, tcp_socket_type>;
     158                 : 
     159                 :     using udp_socket_type = dgram_socket_t<Traits, endpoint>;
     160                 :     using udp_service_type = reactor_udp_service_final<
     161                 :         Traits, udp_socket_type>;
     162                 : 
     163                 :     using tcp_acceptor_type = stream_acceptor_t<Traits, endpoint>;
     164                 :     using tcp_acceptor_service_type = reactor_acceptor_service_final<
     165                 :         Traits, tcp_acceptor_service, tcp_acceptor_type,
     166                 :         tcp_service_type, endpoint>;
     167                 : 
     168                 :     using local_stream_socket_type = stream_socket_t<Traits, local_endpoint>;
     169                 :     using local_stream_service_type = reactor_local_stream_service_final<
     170                 :         Traits, local_stream_socket_type>;
     171                 : 
     172                 :     using local_datagram_socket_type = dgram_socket_t<Traits, local_endpoint>;
     173                 :     using local_datagram_service_type = reactor_local_dgram_service_final<
     174                 :         Traits, local_datagram_socket_type>;
     175                 : 
     176                 :     using local_stream_acceptor_type = stream_acceptor_t<Traits, local_endpoint>;
     177                 :     using local_stream_acceptor_service_type = reactor_acceptor_service_final<
     178                 :         Traits, local_stream_acceptor_service, local_stream_acceptor_type,
     179                 :         local_stream_service_type, local_endpoint>;
     180                 : };
     181                 : 
     182                 : } // namespace boost::corosio::detail
     183                 : 
     184                 : #endif // BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_BACKEND_HPP
        

Generated by: LCOV version 2.3