LCOV - code coverage report
Current view: top level - corosio/native/detail/reactor - reactor_service_finals.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 88.5 % 78 69 9
Test Date: 2026-04-09 23:21:11 Functions: 96.8 % 62 60 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_SERVICE_FINALS_HPP
      11                 : #define BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_SERVICE_FINALS_HPP
      12                 : 
      13                 : /* Parameterized final service types for reactor backends.
      14                 : 
      15                 :    One service template per protocol (TCP, local stream, UDP, local
      16                 :    datagram, TCP acceptor, local stream acceptor) because each abstract
      17                 :    service base declares different virtual methods.
      18                 : */
      19                 : 
      20                 : #include <boost/corosio/native/detail/reactor/reactor_socket_finals.hpp>
      21                 : #include <boost/corosio/native/detail/reactor/reactor_socket_service.hpp>
      22                 : #include <boost/corosio/native/detail/reactor/reactor_acceptor_service.hpp>
      23                 : #include <boost/corosio/detail/tcp_service.hpp>
      24                 : #include <boost/corosio/detail/udp_service.hpp>
      25                 : #include <boost/corosio/detail/local_stream_service.hpp>
      26                 : #include <boost/corosio/detail/local_datagram_service.hpp>
      27                 : 
      28                 : #include <boost/corosio/native/detail/make_err.hpp>
      29                 : 
      30                 : #include <system_error>
      31                 : #include <unistd.h>
      32                 : 
      33                 : namespace boost::corosio::detail {
      34                 : 
      35                 : // ============================================================
      36                 : // Shared socket creation helpers
      37                 : // ============================================================
      38                 : 
      39                 : template<class Traits, class SocketFinal>
      40                 : std::error_code
      41 HIT        8666 : do_open_socket(
      42                 :     SocketFinal* socket_impl,
      43                 :     int family, int type, int protocol,
      44                 :     bool is_ip) noexcept
      45                 : {
      46            8666 :     socket_impl->close_socket();
      47                 : 
      48            8666 :     int fd = Traits::create_socket(family, type, protocol);
      49            8666 :     if (fd < 0)
      50 MIS           0 :         return make_err(errno);
      51                 : 
      52                 :     std::error_code ec = is_ip
      53 HIT        8666 :         ? Traits::configure_ip_socket(fd, family)
      54              28 :         : Traits::configure_local_socket(fd);
      55                 : 
      56            8666 :     if (ec)
      57                 :     {
      58 MIS           0 :         ::close(fd);
      59               0 :         return ec;
      60                 :     }
      61                 : 
      62 HIT        8666 :     socket_impl->init_and_register(fd);
      63            8666 :     return {};
      64                 : }
      65                 : 
      66                 : template<class Traits, class SocketFinal>
      67                 : std::error_code
      68              28 : do_assign_fd(
      69                 :     SocketFinal* socket_impl,
      70                 :     int fd) noexcept
      71                 : {
      72              28 :     socket_impl->close_socket();
      73              28 :     socket_impl->init_and_register(fd);
      74              28 :     return {};
      75                 : }
      76                 : 
      77                 : template<class Traits, class AccFinal>
      78                 : std::error_code
      79             158 : do_open_acceptor(
      80                 :     AccFinal* acc_impl,
      81                 :     int family, int type, int protocol,
      82                 :     bool is_ip) noexcept
      83                 : {
      84             158 :     acc_impl->close_socket();
      85                 : 
      86             158 :     int fd = Traits::create_socket(family, type, protocol);
      87             158 :     if (fd < 0)
      88 MIS           0 :         return make_err(errno);
      89                 : 
      90                 :     std::error_code ec = is_ip
      91 HIT         158 :         ? Traits::configure_ip_acceptor(fd, family)
      92              12 :         : Traits::configure_local_socket(fd);
      93                 : 
      94             158 :     if (ec)
      95                 :     {
      96 MIS           0 :         ::close(fd);
      97               0 :         return ec;
      98                 :     }
      99                 : 
     100 HIT         158 :     acc_impl->init_acceptor_fd(fd);
     101             158 :     return {};
     102                 : }
     103                 : 
     104                 : // ============================================================
     105                 : // TCP service
     106                 : // ============================================================
     107                 : 
     108                 : template<class Traits, class SocketFinal>
     109                 : class reactor_tcp_service_final final
     110                 :     : public reactor_socket_service<
     111                 :           reactor_tcp_service_final<Traits, SocketFinal>,
     112                 :           tcp_service,
     113                 :           typename Traits::scheduler_type,
     114                 :           SocketFinal>
     115                 : {
     116                 :     using base_service = reactor_socket_service<
     117                 :         reactor_tcp_service_final, tcp_service,
     118                 :         typename Traits::scheduler_type, SocketFinal>;
     119                 :     friend base_service;
     120                 : 
     121                 : public:
     122             587 :     explicit reactor_tcp_service_final(capy::execution_context& ctx)
     123             587 :         : base_service(ctx) {}
     124                 : 
     125            8558 :     std::error_code open_socket(
     126                 :         tcp_socket::implementation& impl,
     127                 :         int family, int type, int protocol) override
     128                 :     {
     129            8558 :         return do_open_socket<Traits>(
     130                 :             static_cast<SocketFinal*>(&impl),
     131            8558 :             family, type, protocol, true);
     132                 :     }
     133                 : 
     134              12 :     std::error_code bind_socket(
     135                 :         tcp_socket::implementation& impl, endpoint ep) override
     136                 :     {
     137              12 :         return static_cast<SocketFinal*>(&impl)->do_bind(ep);
     138                 :     }
     139                 : 
     140 MIS           0 :     void pre_shutdown(SocketFinal* impl) noexcept
     141                 :     {
     142               0 :         impl->hook_.pre_shutdown(impl->native_handle());
     143               0 :     }
     144                 : 
     145 HIT       25643 :     void pre_destroy(SocketFinal* impl) noexcept
     146                 :     {
     147           25643 :         impl->hook_.pre_destroy(impl->native_handle());
     148           25643 :     }
     149                 : };
     150                 : 
     151                 : // ============================================================
     152                 : // Local stream service
     153                 : // ============================================================
     154                 : 
     155                 : template<class Traits, class SocketFinal>
     156                 : class reactor_local_stream_service_final final
     157                 :     : public reactor_socket_service<
     158                 :           reactor_local_stream_service_final<Traits, SocketFinal>,
     159                 :           local_stream_service,
     160                 :           typename Traits::scheduler_type,
     161                 :           SocketFinal>
     162                 : {
     163                 :     using base_service = reactor_socket_service<
     164                 :         reactor_local_stream_service_final, local_stream_service,
     165                 :         typename Traits::scheduler_type, SocketFinal>;
     166                 :     friend base_service;
     167                 : 
     168                 : public:
     169             587 :     explicit reactor_local_stream_service_final(capy::execution_context& ctx)
     170             587 :         : base_service(ctx) {}
     171                 : 
     172               8 :     std::error_code open_socket(
     173                 :         local_stream_socket::implementation& impl,
     174                 :         int family, int type, int protocol) override
     175                 :     {
     176               8 :         return do_open_socket<Traits>(
     177                 :             static_cast<SocketFinal*>(&impl),
     178               8 :             family, type, protocol, false);
     179                 :     }
     180                 : 
     181              16 :     std::error_code assign_socket(
     182                 :         local_stream_socket::implementation& impl, int fd) override
     183                 :     {
     184              16 :         return do_assign_fd<Traits>(
     185              16 :             static_cast<SocketFinal*>(&impl), fd);
     186                 :     }
     187                 : };
     188                 : 
     189                 : // ============================================================
     190                 : // UDP service
     191                 : // ============================================================
     192                 : 
     193                 : template<class Traits, class SocketFinal>
     194                 : class reactor_udp_service_final final
     195                 :     : public reactor_socket_service<
     196                 :           reactor_udp_service_final<Traits, SocketFinal>,
     197                 :           udp_service,
     198                 :           typename Traits::scheduler_type,
     199                 :           SocketFinal>
     200                 : {
     201                 :     using base_service = reactor_socket_service<
     202                 :         reactor_udp_service_final, udp_service,
     203                 :         typename Traits::scheduler_type, SocketFinal>;
     204                 :     friend base_service;
     205                 : 
     206                 : public:
     207             587 :     explicit reactor_udp_service_final(capy::execution_context& ctx)
     208             587 :         : base_service(ctx) {}
     209                 : 
     210              80 :     std::error_code open_datagram_socket(
     211                 :         udp_socket::implementation& impl,
     212                 :         int family, int type, int protocol) override
     213                 :     {
     214              80 :         return do_open_socket<Traits>(
     215                 :             static_cast<SocketFinal*>(&impl),
     216              80 :             family, type, protocol, true);
     217                 :     }
     218                 : 
     219              48 :     std::error_code bind_datagram(
     220                 :         udp_socket::implementation& impl, endpoint ep) override
     221                 :     {
     222              48 :         return static_cast<SocketFinal*>(&impl)->do_bind(ep);
     223                 :     }
     224                 : };
     225                 : 
     226                 : // ============================================================
     227                 : // Local datagram service
     228                 : // ============================================================
     229                 : 
     230                 : template<class Traits, class SocketFinal>
     231                 : class reactor_local_dgram_service_final final
     232                 :     : public reactor_socket_service<
     233                 :           reactor_local_dgram_service_final<Traits, SocketFinal>,
     234                 :           local_datagram_service,
     235                 :           typename Traits::scheduler_type,
     236                 :           SocketFinal>
     237                 : {
     238                 :     using base_service = reactor_socket_service<
     239                 :         reactor_local_dgram_service_final, local_datagram_service,
     240                 :         typename Traits::scheduler_type, SocketFinal>;
     241                 :     friend base_service;
     242                 : 
     243                 : public:
     244             587 :     explicit reactor_local_dgram_service_final(capy::execution_context& ctx)
     245             587 :         : base_service(ctx) {}
     246                 : 
     247              20 :     std::error_code open_socket(
     248                 :         local_datagram_socket::implementation& impl,
     249                 :         int family, int type, int protocol) override
     250                 :     {
     251              20 :         return do_open_socket<Traits>(
     252                 :             static_cast<SocketFinal*>(&impl),
     253              20 :             family, type, protocol, false);
     254                 :     }
     255                 : 
     256              12 :     std::error_code assign_socket(
     257                 :         local_datagram_socket::implementation& impl, int fd) override
     258                 :     {
     259              12 :         return do_assign_fd<Traits>(
     260              12 :             static_cast<SocketFinal*>(&impl), fd);
     261                 :     }
     262                 : 
     263              16 :     std::error_code bind_socket(
     264                 :         local_datagram_socket::implementation& impl,
     265                 :         corosio::local_endpoint ep) override
     266                 :     {
     267              16 :         return static_cast<SocketFinal*>(&impl)->do_bind(ep);
     268                 :     }
     269                 : };
     270                 : 
     271                 : // ============================================================
     272                 : // Acceptor service
     273                 : // ============================================================
     274                 : 
     275                 : template<class Traits, class ServiceBase, class AccFinal,
     276                 :          class StreamServiceFinal, class Endpoint>
     277                 : class reactor_acceptor_service_final final
     278                 :     : public reactor_acceptor_service<
     279                 :           reactor_acceptor_service_final<Traits, ServiceBase, AccFinal,
     280                 :                                          StreamServiceFinal, Endpoint>,
     281                 :           ServiceBase,
     282                 :           typename Traits::scheduler_type,
     283                 :           AccFinal,
     284                 :           StreamServiceFinal>
     285                 : {
     286                 :     using base_service = reactor_acceptor_service<
     287                 :         reactor_acceptor_service_final,
     288                 :         ServiceBase,
     289                 :         typename Traits::scheduler_type,
     290                 :         AccFinal,
     291                 :         StreamServiceFinal>;
     292                 :     friend base_service;
     293                 : 
     294                 : public:
     295            1174 :     explicit reactor_acceptor_service_final(capy::execution_context& ctx)
     296            1174 :         : base_service(ctx)
     297                 :     {
     298                 :         // Look up the concrete stream service directly by its type.
     299                 :         // Avoids dynamic_cast which can fail across template boundaries
     300                 :         // on some platforms (FreeBSD clang RTTI/visibility).
     301            1174 :         this->stream_svc_ =
     302            1174 :             this->ctx_.template find_service<StreamServiceFinal>();
     303            1174 :     }
     304                 : 
     305             158 :     std::error_code open_acceptor_socket(
     306                 :         typename AccFinal::impl_base_type& impl,
     307                 :         int family, int type, int protocol) override
     308                 :     {
     309             158 :         return do_open_acceptor<Traits>(
     310                 :             static_cast<AccFinal*>(&impl),
     311                 :             family, type, protocol,
     312             158 :             std::is_same_v<Endpoint, endpoint>);
     313                 :     }
     314                 : 
     315             156 :     std::error_code bind_acceptor(
     316                 :         typename AccFinal::impl_base_type& impl,
     317                 :         Endpoint ep) override
     318                 :     {
     319             156 :         return static_cast<AccFinal*>(&impl)->do_bind(ep);
     320                 :     }
     321                 : 
     322             140 :     std::error_code listen_acceptor(
     323                 :         typename AccFinal::impl_base_type& impl,
     324                 :         int backlog) override
     325                 :     {
     326             140 :         return static_cast<AccFinal*>(&impl)->do_listen(backlog);
     327                 :     }
     328                 : };
     329                 : 
     330                 : } // namespace boost::corosio::detail
     331                 : 
     332                 : #endif // BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_SERVICE_FINALS_HPP
        

Generated by: LCOV version 2.3