LCOV - code coverage report
Current view: top level - include/boost/corosio - io_object.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 98.0 % 51 50 1
Test Date: 2026-02-16 16:21:08 Functions: 87.0 % 23 20 3

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
       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_IO_OBJECT_HPP
      11                 : #define BOOST_COROSIO_IO_OBJECT_HPP
      12                 : 
      13                 : #include <boost/corosio/detail/config.hpp>
      14                 : #include <boost/corosio/detail/except.hpp>
      15                 : #include <boost/capy/ex/execution_context.hpp>
      16                 : 
      17                 : #include <utility>
      18                 : 
      19                 : namespace boost::corosio {
      20                 : 
      21                 : /** Base class for platform I/O objects.
      22                 : 
      23                 :     Provides common infrastructure for I/O objects that wrap kernel
      24                 :     resources (sockets, timers, signal handlers, acceptors). Derived
      25                 :     classes dispatch operations through a platform-specific vtable
      26                 :     (IOCP, epoll, kqueue, io_uring).
      27                 : 
      28                 :     @par Semantics
      29                 :     Only concrete platform I/O types should inherit from `io_object`.
      30                 :     Test mocks, decorators, and stream adapters must not inherit from
      31                 :     this class. Use concepts or templates for generic I/O algorithms.
      32                 : 
      33                 :     @par Thread Safety
      34                 :     Distinct objects: Safe.
      35                 :     Shared objects: Unsafe. All operations on a single I/O object
      36                 :     must be serialized.
      37                 : 
      38                 :     @note Intended as a protected base class. The handle member
      39                 :         `h_` is accessible to derived classes.
      40                 : 
      41                 :     @see io_stream, tcp_socket, tcp_acceptor
      42                 : */
      43                 : class BOOST_COROSIO_DECL io_object
      44                 : {
      45                 : public:
      46                 :     class handle;
      47                 : 
      48                 :     /** Base interface for platform I/O implementations.
      49                 : 
      50                 :         Derived classes provide platform-specific operation dispatch.
      51                 :     */
      52                 :     struct implementation
      53                 :     {
      54 HIT       25600 :         virtual ~implementation() = default;
      55                 :     };
      56                 : 
      57                 :     /** Service interface for I/O object lifecycle management.
      58                 : 
      59                 :         Platform backends implement this interface to manage the
      60                 :         creation, closing, and destruction of I/O object
      61                 :         implementations.
      62                 :     */
      63                 :     struct io_service
      64                 :     {
      65            1680 :         virtual ~io_service() = default;
      66                 : 
      67                 :         /// Construct a new implementation instance.
      68                 :         virtual implementation* construct() = 0;
      69                 : 
      70                 :         /// Destroy the implementation, closing kernel resources and freeing memory.
      71                 :         virtual void destroy(implementation*) = 0;
      72                 : 
      73                 :         /// Close the I/O object, releasing kernel resources without deallocating.
      74            9239 :         virtual void close(handle&) {}
      75                 :     };
      76                 : 
      77                 :     /** RAII wrapper for I/O object implementation lifetime.
      78                 : 
      79                 :         Manages ownership of the platform-specific implementation,
      80                 :         automatically destroying it when the handle goes out of scope.
      81                 :     */
      82                 :     class handle
      83                 :     {
      84                 :         capy::execution_context* ctx_ = nullptr;
      85                 :         io_service* svc_ = nullptr;
      86                 :         implementation* impl_ = nullptr;
      87                 : 
      88                 :     public:
      89                 :         /// Destroy the handle and its implementation.
      90           69361 :         ~handle()
      91                 :         {
      92           69361 :             if (impl_)
      93                 :             {
      94           26154 :                 svc_->close(*this);
      95           26154 :                 svc_->destroy(impl_);
      96                 :             }
      97           69361 :         }
      98                 : 
      99                 :         /// Construct an empty handle.
     100                 :         handle() = default;
     101                 : 
     102                 :         /// Construct a handle bound to a context and service.
     103           26174 :         handle(capy::execution_context& ctx, io_service& svc)
     104           26174 :             : ctx_(&ctx)
     105           26174 :             , svc_(&svc)
     106           26174 :             , impl_(svc_->construct())
     107                 :         {
     108           26174 :         }
     109                 : 
     110                 :         /// Move construct from another handle.
     111           43187 :         handle(handle&& other) noexcept
     112           43187 :             : ctx_(std::exchange(other.ctx_, nullptr))
     113           43187 :             , svc_(std::exchange(other.svc_, nullptr))
     114           43187 :             , impl_(std::exchange(other.impl_, nullptr))
     115                 :         {
     116           43187 :         }
     117                 : 
     118                 :         /// Move assign from another handle.
     119              20 :         handle& operator=(handle&& other) noexcept
     120                 :         {
     121              20 :             if (this != &other)
     122                 :             {
     123              20 :                 if (impl_)
     124                 :                 {
     125              20 :                     svc_->close(*this);
     126              20 :                     svc_->destroy(impl_);
     127                 :                 }
     128              20 :                 ctx_ = std::exchange(other.ctx_, nullptr);
     129              20 :                 svc_ = std::exchange(other.svc_, nullptr);
     130              20 :                 impl_ = std::exchange(other.impl_, nullptr);
     131                 :             }
     132              20 :             return *this;
     133                 :         }
     134                 : 
     135                 :         handle(handle const&) = delete;
     136                 :         handle& operator=(handle const&) = delete;
     137                 : 
     138                 :         /// Return true if the handle owns an implementation.
     139           59955 :         explicit operator bool() const noexcept
     140                 :         {
     141           59955 :             return impl_ != nullptr;
     142                 :         }
     143                 : 
     144                 :         /// Return the associated I/O service.
     145           25385 :         io_service& service() const noexcept
     146                 :         {
     147           25385 :             return *svc_;
     148                 :         }
     149                 : 
     150                 :         /// Return the platform implementation.
     151          801817 :         implementation* get() const noexcept
     152                 :         {
     153          801817 :             return impl_;
     154                 :         }
     155                 : 
     156                 :         /** Replace the implementation, destroying the old one.
     157                 : 
     158                 :             @param p The new implementation to own. May be nullptr.
     159                 :         */
     160            8375 :         void reset(implementation* p) noexcept
     161                 :         {
     162            8375 :             if (impl_)
     163                 :             {
     164            8375 :                 svc_->close(*this);
     165            8375 :                 svc_->destroy(impl_);
     166                 :             }
     167            8375 :             impl_ = p;
     168            8375 :         }
     169                 : 
     170                 :         /// Return the execution context.
     171              10 :         capy::execution_context& context() const noexcept
     172                 :         {
     173              10 :             return *ctx_;
     174                 :         }
     175                 :     };
     176                 : 
     177                 :     /// Return the execution context.
     178              10 :     capy::execution_context& context() const noexcept
     179                 :     {
     180              10 :         return h_.context();
     181                 :     }
     182                 : 
     183                 : protected:
     184           26361 :     virtual ~io_object() = default;
     185                 : 
     186                 :     /** Create a handle bound to a service found in the context.
     187                 : 
     188                 :         @tparam Service The service type whose key_type is used for lookup.
     189                 :         @param ctx The execution context to search for the service.
     190                 : 
     191                 :         @return A handle owning a freshly constructed implementation.
     192                 : 
     193                 :         @throws std::logic_error if the service is not installed.
     194                 :     */
     195                 :     template<class Service>
     196           17052 :     static handle create_handle(capy::execution_context& ctx)
     197                 :     {
     198           17052 :         auto* svc = ctx.find_service<Service>();
     199           17052 :         if (!svc)
     200 MIS           0 :             detail::throw_logic_error(
     201                 :                 "io_object::create_handle: service not installed");
     202 HIT       17052 :         return handle(ctx, *svc);
     203                 :     }
     204                 : 
     205                 :     /// Construct an I/O object from a handle.
     206           26174 :     explicit io_object(handle h) noexcept : h_(std::move(h)) {}
     207                 : 
     208                 :     /// Move construct from another I/O object.
     209             187 :     io_object(io_object&& other) noexcept : h_(std::move(other.h_)) {}
     210                 : 
     211                 :     /// Move assign from another I/O object.
     212                 :     io_object& operator=(io_object&& other) noexcept
     213                 :     {
     214                 :         if (this != &other)
     215                 :             h_ = std::move(other.h_);
     216                 :         return *this;
     217                 :     }
     218                 : 
     219                 :     io_object(io_object const&) = delete;
     220                 :     io_object& operator=(io_object const&) = delete;
     221                 : 
     222                 :     handle h_;
     223                 : };
     224                 : 
     225                 : } // namespace boost::corosio
     226                 : 
     227                 : #endif
        

Generated by: LCOV version 2.3