LCOV - code coverage report
Current view: top level - corosio/detail - object_ref.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 33 33
Test Date: 2026-10-08 18:13:32 Functions: 100.0 % 13 13

           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_OBJECT_REF_HPP
      12                 : #define BOOST_COROSIO_DETAIL_OBJECT_REF_HPP
      13                 : 
      14                 : #include <boost/corosio/detail/platform.hpp>
      15                 : #include <boost/corosio/io/io_object.hpp>
      16                 : #include <atomic>
      17                 : #include <utility>
      18                 : 
      19                 : namespace boost::corosio::detail {
      20                 : 
      21                 : /// Add one reference to `impl`. `impl` must be non-null.
      22                 : inline void
      23 HIT      105679 : acquire(io_object::implementation* impl) noexcept
      24                 : {
      25          105679 :     impl->refs_.fetch_add(1, std::memory_order_relaxed);
      26          105679 : }
      27                 : 
      28                 : /** Drop one reference; runs `retire()` at zero. `impl` must be
      29                 :     non-null.
      30                 : 
      31                 :     Uses release on the decrement and an acquire fence before the
      32                 :     zero-action so writes made while holding a reference are visible
      33                 :     to the recycler. TSan cannot model a standalone fence, so under
      34                 :     it the decrement itself is acq_rel instead -- strictly stronger,
      35                 :     and TSan's happens-before tracking models the exchange directly.
      36                 : */
      37                 : inline void
      38          126004 : release(io_object::implementation* impl) noexcept
      39                 : {
      40                 : #if BOOST_COROSIO_TSAN
      41                 :     if (impl->refs_.fetch_sub(1, std::memory_order_acq_rel) == 1)
      42                 :         impl->retire();
      43                 : #else
      44          252008 :     if (impl->refs_.fetch_sub(1, std::memory_order_release) == 1)
      45                 :     {
      46                 :         std::atomic_thread_fence(std::memory_order_acquire);
      47           20325 :         impl->retire();
      48                 :     }
      49                 : #endif
      50          126004 : }
      51                 : 
      52                 : /** Owning intrusive reference to an I/O implementation.
      53                 : 
      54                 :     Replaces `std::shared_ptr<void>` op keepalives: copy acquires,
      55                 :     move steals, destruction releases. Kept deliberately minimal —
      56                 :     two words smaller than a shared_ptr and no control block.
      57                 : */
      58                 : class object_ref
      59                 : {
      60                 :     io_object::implementation* p_ = nullptr;
      61                 : 
      62                 : public:
      63                 :     /// Destroy the object_ref, releasing the held reference, if any.
      64          950945 :     ~object_ref() { reset(); }
      65                 : 
      66                 :     /// Construct an object_ref holding no reference.
      67           30938 :     object_ref() noexcept = default;
      68                 : 
      69                 :     /// Construct an object_ref that acquires a new reference to `p`.
      70          105659 :     explicit object_ref(io_object::implementation* p) noexcept : p_(p)
      71                 :     {
      72          105659 :         if (p_)
      73          105659 :             acquire(p_);
      74          105659 :     }
      75                 : 
      76                 :     /// Construct a copy, acquiring another reference to `other`'s target.
      77               3 :     object_ref(object_ref const& other) noexcept : p_(other.p_)
      78                 :     {
      79               3 :         if (p_)
      80               3 :             acquire(p_);
      81               3 :     }
      82                 : 
      83                 :     /// Construct by transferring the reference out of `other`.
      84          511944 :     object_ref(object_ref&& other) noexcept
      85          511944 :         : p_(std::exchange(other.p_, nullptr))
      86                 :     {
      87          511944 :     }
      88                 : 
      89                 :     /// Release the held reference, if any, and acquire `other`'s target.
      90               2 :     object_ref& operator=(object_ref const& other) noexcept
      91                 :     {
      92               2 :         object_ref(other).swap(*this);
      93               2 :         return *this;
      94                 :     }
      95                 : 
      96                 :     /// Release the held reference, if any, and take ownership of `other`'s.
      97          408367 :     object_ref& operator=(object_ref&& other) noexcept
      98                 :     {
      99          408367 :         object_ref(std::move(other)).swap(*this);
     100          408367 :         return *this;
     101                 :     }
     102                 : 
     103                 :     /// Release the held reference, if any.
     104         1431925 :     void reset() noexcept
     105                 :     {
     106         1431925 :         if (p_)
     107          105662 :             release(std::exchange(p_, nullptr));
     108         1431925 :     }
     109                 : 
     110                 :     /// Return the held implementation pointer.
     111               3 :     io_object::implementation* get() const noexcept { return p_; }
     112                 : 
     113                 :     /// Return true if a reference is held.
     114           13452 :     explicit operator bool() const noexcept { return p_ != nullptr; }
     115                 : 
     116                 :     /// Exchange the implementation pointers held by `*this` and `other`.
     117          408369 :     void swap(object_ref& other) noexcept { std::swap(p_, other.p_); }
     118                 : };
     119                 : 
     120                 : } // namespace boost::corosio::detail
     121                 : 
     122                 : #endif
        

Generated by: LCOV version 2.3