LCOV - code coverage report
Current view: top level - corosio/native/detail/epoll - epoll_op.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 12 12
Test Date: 2026-03-13 23:11:04 Functions: 100.0 % 2 2

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2026 Steve Gerbino
       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_EPOLL_EPOLL_OP_HPP
      11                 : #define BOOST_COROSIO_NATIVE_DETAIL_EPOLL_EPOLL_OP_HPP
      12                 : 
      13                 : #include <boost/corosio/detail/platform.hpp>
      14                 : 
      15                 : #if BOOST_COROSIO_HAS_EPOLL
      16                 : 
      17                 : #include <boost/corosio/native/detail/reactor/reactor_op.hpp>
      18                 : #include <boost/corosio/native/detail/reactor/reactor_descriptor_state.hpp>
      19                 : 
      20                 : /*
      21                 :     epoll Operation State
      22                 :     =====================
      23                 : 
      24                 :     Each async I/O operation has a corresponding epoll_op-derived struct that
      25                 :     holds the operation's state while it's in flight. The socket impl owns
      26                 :     fixed slots for each operation type (conn_, rd_, wr_), so only one
      27                 :     operation of each type can be pending per socket at a time.
      28                 : 
      29                 :     Persistent Registration
      30                 :     -----------------------
      31                 :     File descriptors are registered with epoll once (via descriptor_state) and
      32                 :     stay registered until closed. The descriptor_state tracks which operations
      33                 :     are pending (read_op, write_op, connect_op). When an event arrives, the
      34                 :     reactor dispatches to the appropriate pending operation.
      35                 : 
      36                 :     Impl Lifetime Management
      37                 :     ------------------------
      38                 :     When cancel() posts an op to the scheduler's ready queue, the socket impl
      39                 :     might be destroyed before the scheduler processes the op. The `impl_ptr`
      40                 :     member holds a shared_ptr to the impl, keeping it alive until the op
      41                 :     completes. This is set by cancel() and cleared in operator() after the
      42                 :     coroutine is resumed.
      43                 : 
      44                 :     EOF Detection
      45                 :     -------------
      46                 :     For reads, 0 bytes with no error means EOF. But an empty user buffer also
      47                 :     returns 0 bytes. The `empty_buffer_read` flag distinguishes these cases.
      48                 : 
      49                 :     SIGPIPE Prevention
      50                 :     ------------------
      51                 :     Writes use sendmsg() with MSG_NOSIGNAL instead of writev() to prevent
      52                 :     SIGPIPE when the peer has closed.
      53                 : */
      54                 : 
      55                 : namespace boost::corosio::detail {
      56                 : 
      57                 : // Forward declarations
      58                 : class epoll_socket;
      59                 : class epoll_acceptor;
      60                 : struct epoll_op;
      61                 : 
      62                 : // Forward declaration
      63                 : class epoll_scheduler;
      64                 : 
      65                 : /// Per-descriptor state for persistent epoll registration.
      66                 : struct descriptor_state final : reactor_descriptor_state
      67                 : {};
      68                 : 
      69                 : /// epoll base operation — thin wrapper over reactor_op.
      70                 : struct epoll_op : reactor_op<epoll_socket, epoll_acceptor>
      71                 : {
      72                 :     void operator()() override;
      73                 : };
      74                 : 
      75                 : /// epoll connect operation.
      76                 : struct epoll_connect_op final : reactor_connect_op<epoll_op>
      77                 : {
      78                 :     void operator()() override;
      79                 :     void cancel() noexcept override;
      80                 : };
      81                 : 
      82                 : /// epoll scatter-read operation.
      83                 : struct epoll_read_op final : reactor_read_op<epoll_op>
      84                 : {
      85                 :     void cancel() noexcept override;
      86                 : };
      87                 : 
      88                 : /** Provides sendmsg(MSG_NOSIGNAL) with EINTR retry for epoll writes. */
      89                 : struct epoll_write_policy
      90                 : {
      91 HIT      127248 :     static ssize_t write(int fd, iovec* iovecs, int count) noexcept
      92                 :     {
      93          127248 :         msghdr msg{};
      94          127248 :         msg.msg_iov    = iovecs;
      95          127248 :         msg.msg_iovlen = static_cast<std::size_t>(count);
      96                 : 
      97                 :         ssize_t n;
      98                 :         do
      99                 :         {
     100          127248 :             n = ::sendmsg(fd, &msg, MSG_NOSIGNAL);
     101                 :         }
     102          127248 :         while (n < 0 && errno == EINTR);
     103          127248 :         return n;
     104                 :     }
     105                 : };
     106                 : 
     107                 : /// epoll gather-write operation.
     108                 : struct epoll_write_op final : reactor_write_op<epoll_op, epoll_write_policy>
     109                 : {
     110                 :     void cancel() noexcept override;
     111                 : };
     112                 : 
     113                 : /** Provides accept4(SOCK_NONBLOCK|SOCK_CLOEXEC) with EINTR retry. */
     114                 : struct epoll_accept_policy
     115                 : {
     116            4395 :     static int do_accept(int fd, sockaddr_storage& peer) noexcept
     117                 :     {
     118            4395 :         socklen_t addrlen = sizeof(peer);
     119                 :         int new_fd;
     120                 :         do
     121                 :         {
     122            4395 :             new_fd = ::accept4(
     123                 :                 fd, reinterpret_cast<sockaddr*>(&peer), &addrlen,
     124                 :                 SOCK_NONBLOCK | SOCK_CLOEXEC);
     125                 :         }
     126            4395 :         while (new_fd < 0 && errno == EINTR);
     127            4395 :         return new_fd;
     128                 :     }
     129                 : };
     130                 : 
     131                 : /// epoll accept operation.
     132                 : struct epoll_accept_op final : reactor_accept_op<epoll_op, epoll_accept_policy>
     133                 : {
     134                 :     void operator()() override;
     135                 :     void cancel() noexcept override;
     136                 : };
     137                 : 
     138                 : } // namespace boost::corosio::detail
     139                 : 
     140                 : #endif // BOOST_COROSIO_HAS_EPOLL
     141                 : 
     142                 : #endif // BOOST_COROSIO_NATIVE_DETAIL_EPOLL_EPOLL_OP_HPP
        

Generated by: LCOV version 2.3