LCOV - code coverage report
Current view: top level - corosio/detail - scheduler_op.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 37.5 % 8 3 5
Test Date: 2026-02-17 20:54:14 Functions: 50.0 % 6 3 3

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
       3                 : // Copyright (c) 2026 Steve Gerbino
       4                 : //
       5                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       6                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       7                 : //
       8                 : // Official repository: https://github.com/cppalliance/corosio
       9                 : //
      10                 : 
      11                 : #ifndef BOOST_COROSIO_DETAIL_SCHEDULER_OP_HPP
      12                 : #define BOOST_COROSIO_DETAIL_SCHEDULER_OP_HPP
      13                 : 
      14                 : #include <boost/corosio/detail/config.hpp>
      15                 : #include <boost/corosio/detail/intrusive.hpp>
      16                 : 
      17                 : #include <cstddef>
      18                 : #include <cstdint>
      19                 : #include <utility>
      20                 : 
      21                 : namespace boost::corosio::detail {
      22                 : 
      23                 : /** Base class for completion handlers using function pointer dispatch.
      24                 : 
      25                 :     Handlers are continuations that execute after an asynchronous
      26                 :     operation completes. They can be queued for deferred invocation,
      27                 :     allowing callbacks and coroutine resumptions to be posted to an
      28                 :     executor.
      29                 : 
      30                 :     This class uses a function pointer instead of virtual dispatch
      31                 :     to minimize overhead in the completion path. Each derived class
      32                 :     provides a static completion function that handles both normal
      33                 :     invocation and destruction.
      34                 : 
      35                 :     @par Function Pointer Convention
      36                 : 
      37                 :     The func_type signature is:
      38                 :     @code
      39                 :     void(*)(void* owner, scheduler_op* op, std::uint32_t bytes, std::uint32_t error);
      40                 :     @endcode
      41                 : 
      42                 :     - When owner != nullptr: Normal completion. Process the operation.
      43                 :     - When owner == nullptr: Destroy mode. Clean up without invoking.
      44                 : 
      45                 :     @par Ownership Contract
      46                 : 
      47                 :     Callers must invoke exactly ONE of `complete()` or `destroy()`,
      48                 :     never both.
      49                 : 
      50                 :     @see scheduler_op_queue
      51                 : */
      52                 : class scheduler_op : public intrusive_queue<scheduler_op>::node
      53                 : {
      54                 : public:
      55                 :     /** Function pointer type for completion handling.
      56                 : 
      57                 :         @param owner Pointer to the scheduler (nullptr for destroy).
      58                 :         @param op The operation to complete or destroy.
      59                 :         @param bytes Bytes transferred (for I/O operations).
      60                 :         @param error Error code from the operation.
      61                 :     */
      62                 :     using func_type = void (*)(
      63                 :         void* owner,
      64                 :         scheduler_op* op,
      65                 :         std::uint32_t bytes,
      66                 :         std::uint32_t error);
      67                 : 
      68                 :     /** Complete the operation via function pointer (IOCP path).
      69                 : 
      70                 :         @param owner Pointer to the owning scheduler.
      71                 :         @param bytes Bytes transferred.
      72                 :         @param error Error code.
      73                 :     */
      74                 :     void complete(void* owner, std::uint32_t bytes, std::uint32_t error)
      75                 :     {
      76                 :         func_(owner, this, bytes, error);
      77                 :     }
      78                 : 
      79                 :     /** Invoke the handler (epoll/select path).
      80                 : 
      81                 :         Override in derived classes to handle operation completion.
      82                 :         Default implementation does nothing.
      83                 :     */
      84 MIS           0 :     virtual void operator()() {}
      85                 : 
      86                 :     /** Destroy without invoking the handler.
      87                 : 
      88                 :         Called during shutdown or when discarding queued operations.
      89                 :         Override in derived classes if cleanup is needed.
      90                 :         Default implementation calls through func_ if set.
      91                 :     */
      92               0 :     virtual void destroy()
      93                 :     {
      94               0 :         if (func_)
      95               0 :             func_(nullptr, this, 0, 0);
      96               0 :     }
      97                 : 
      98 HIT       94616 :     virtual ~scheduler_op() = default;
      99                 : 
     100                 : protected:
     101                 :     /** Default constructor for derived classes using virtual dispatch.
     102                 : 
     103                 :         Used by epoll/select backends that override operator() and destroy().
     104                 :     */
     105           94474 :     scheduler_op() noexcept : func_(nullptr) {}
     106                 : 
     107                 :     /** Construct with completion function for function pointer dispatch.
     108                 : 
     109                 :         Used by IOCP backend for non-virtual completion.
     110                 : 
     111                 :         @param func The static function to call for completion/destruction.
     112                 :     */
     113             142 :     explicit scheduler_op(func_type func) noexcept : func_(func) {}
     114                 : 
     115                 :     func_type func_;
     116                 : 
     117                 :     // Pad to 32 bytes so derived structs (descriptor_state, epoll_op)
     118                 :     // keep hot fields on optimal cache line boundaries
     119                 :     std::byte reserved_[sizeof(void*)] = {};
     120                 : };
     121                 : 
     122                 : using op_queue = intrusive_queue<scheduler_op>;
     123                 : 
     124                 : /** An intrusive FIFO queue of scheduler_ops.
     125                 : 
     126                 :     This queue stores scheduler_ops using an intrusive linked list,
     127                 :     avoiding additional allocations for queue nodes. Scheduler_ops
     128                 :     are popped in the order they were pushed (first-in, first-out).
     129                 : 
     130                 :     The destructor calls `destroy()` on any remaining scheduler_ops.
     131                 : 
     132                 :     @note This is not thread-safe. External synchronization is
     133                 :     required for concurrent access.
     134                 : 
     135                 :     @see scheduler_op
     136                 : */
     137                 : class scheduler_op_queue
     138                 : {
     139                 :     op_queue q_;
     140                 : 
     141                 : public:
     142                 :     scheduler_op_queue() = default;
     143                 : 
     144                 :     scheduler_op_queue(scheduler_op_queue&& other) noexcept
     145                 :         : q_(std::move(other.q_))
     146                 :     {
     147                 :     }
     148                 : 
     149                 :     scheduler_op_queue(scheduler_op_queue const&)            = delete;
     150                 :     scheduler_op_queue& operator=(scheduler_op_queue const&) = delete;
     151                 :     scheduler_op_queue& operator=(scheduler_op_queue&&)      = delete;
     152                 : 
     153                 :     ~scheduler_op_queue()
     154                 :     {
     155                 :         while (auto* h = q_.pop())
     156                 :             h->destroy();
     157                 :     }
     158                 : 
     159                 :     bool empty() const noexcept
     160                 :     {
     161                 :         return q_.empty();
     162                 :     }
     163                 :     void push(scheduler_op* h) noexcept
     164                 :     {
     165                 :         q_.push(h);
     166                 :     }
     167                 :     void push(scheduler_op_queue& other) noexcept
     168                 :     {
     169                 :         q_.splice(other.q_);
     170                 :     }
     171                 :     scheduler_op* pop() noexcept
     172                 :     {
     173                 :         return q_.pop();
     174                 :     }
     175                 : };
     176                 : 
     177                 : } // namespace boost::corosio::detail
     178                 : 
     179                 : #endif
        

Generated by: LCOV version 2.3