LCOV - code coverage report
Current view: top level - include/boost/corosio - io_object.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 98.2 % 55 54
Test Date: 2026-02-15 04:10:46 Functions: 87.5 % 24 21

            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        24875 :         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         8995 :         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        67424 :         ~handle()
      91              :         {
      92        67424 :             if(impl_)
      93              :             {
      94        25432 :                 svc_->close(*this);
      95        25432 :                 svc_->destroy(impl_);
      96              :             }
      97        67424 :         }
      98              : 
      99              :         /// Construct an empty handle.
     100              :         handle() = default;
     101              : 
     102              :         /// Construct a handle bound to a context and service.
     103        25447 :         handle(
     104              :             capy::execution_context& ctx,
     105              :             io_service& svc)
     106        25447 :             : ctx_(&ctx)
     107        25447 :             , svc_(&svc)
     108        25447 :             , impl_(svc_->construct())
     109              :         {
     110        25447 :         }
     111              : 
     112              :         /// Move construct from another handle.
     113        41977 :         handle(handle&& other) noexcept
     114        41977 :             : ctx_(std::exchange(other.ctx_, nullptr))
     115        41977 :             , svc_(std::exchange(other.svc_, nullptr))
     116        41977 :             , impl_(std::exchange(other.impl_, nullptr))
     117              :         {
     118        41977 :         }
     119              : 
     120              :         /// Move assign from another handle.
     121           15 :         handle& operator=(handle&& other) noexcept
     122              :         {
     123           15 :             if (this != &other)
     124              :             {
     125           15 :                 if (impl_)
     126              :                 {
     127           15 :                     svc_->close(*this);
     128           15 :                     svc_->destroy(impl_);
     129              :                 }
     130           15 :                 ctx_ = std::exchange(other.ctx_, nullptr);
     131           15 :                 svc_ = std::exchange(other.svc_, nullptr);
     132           15 :                 impl_ = std::exchange(other.impl_, nullptr);
     133              :             }
     134           15 :             return *this;
     135              :         }
     136              : 
     137              :         handle(handle const&) = delete;
     138              :         handle& operator=(handle const&) = delete;
     139              : 
     140              :         /// Return true if the handle owns an implementation.
     141        58265 :         explicit operator bool() const noexcept
     142              :         {
     143        58265 :             return impl_ != nullptr;
     144              :         }
     145              : 
     146              :         /// Return the associated I/O service.
     147        24661 :         io_service& service() const noexcept
     148              :         {
     149        24661 :             return *svc_;
     150              :         }
     151              : 
     152              :         /// Return the platform implementation.
     153       588080 :         implementation* get() const noexcept
     154              :         {
     155       588080 :             return impl_;
     156              :         }
     157              : 
     158              :         /** Replace the implementation, destroying the old one.
     159              : 
     160              :             @param p The new implementation to own. May be nullptr.
     161              :         */
     162         8133 :         void reset(implementation* p) noexcept
     163              :         {
     164         8133 :             if (impl_)
     165              :             {
     166         8133 :                 svc_->close(*this);
     167         8133 :                 svc_->destroy(impl_);
     168              :             }
     169         8133 :             impl_ = p;
     170         8133 :         }
     171              : 
     172              :         /// Return the execution context.
     173           50 :         capy::execution_context& context() const noexcept
     174              :         {
     175           50 :             return *ctx_;
     176              :         }
     177              :     };
     178              : 
     179              :     /// Return the execution context.
     180              :     capy::execution_context&
     181           50 :     context() const noexcept
     182              :     {
     183           50 :         return h_.context();
     184              :     }
     185              : 
     186              : protected:
     187        25634 :     virtual ~io_object() = default;
     188              : 
     189              :     /** Create a handle bound to a service found in the context.
     190              : 
     191              :         @tparam Service The service type whose key_type is used for lookup.
     192              :         @param ctx The execution context to search for the service.
     193              : 
     194              :         @return A handle owning a freshly constructed implementation.
     195              : 
     196              :         @throws std::logic_error if the service is not installed.
     197              :     */
     198              :     template<class Service>
     199        25447 :     static handle create_handle(capy::execution_context& ctx)
     200              :     {
     201        25447 :         auto* svc = ctx.find_service<Service>();
     202        25447 :         if (!svc)
     203            0 :             detail::throw_logic_error(
     204              :                 "io_object::create_handle: service not installed");
     205        25447 :         return handle(ctx, *svc);
     206              :     }
     207              : 
     208              :     /// Construct an I/O object from a handle.
     209              :     explicit
     210        25447 :     io_object(handle h) noexcept
     211        25447 :         : h_(std::move(h))
     212              :     {
     213        25447 :     }
     214              : 
     215              :     /// Move construct from another I/O object.
     216          187 :     io_object(io_object&& other) noexcept
     217          187 :         : h_(std::move(other.h_))
     218              :     {
     219          187 :     }
     220              : 
     221              :     /// Move assign from another I/O object.
     222              :     io_object& operator=(io_object&& other) noexcept
     223              :     {
     224              :         if (this != &other)
     225              :             h_ = std::move(other.h_);
     226              :         return *this;
     227              :     }
     228              : 
     229              :     io_object(io_object const&) = delete;
     230              :     io_object& operator=(io_object const&) = delete;
     231              : 
     232              :     handle h_;
     233              : };
     234              : 
     235              : } // namespace boost::corosio
     236              : 
     237              : #endif
        

Generated by: LCOV version 2.3