LCOV - code coverage report
Current view: top level - opt/homebrew/include/boost/smart_ptr/detail - shared_count.hpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 68 76 89.5 %
Date: 2026-06-25 07:23:43 Functions: 185 243 76.1 %

          Line data    Source code
       1             : #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
       2             : #define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
       3             : 
       4             : // MS compatible compilers support #pragma once
       5             : 
       6             : #if defined(_MSC_VER) && (_MSC_VER >= 1020)
       7             : # pragma once
       8             : #endif
       9             : 
      10             : //
      11             : //  detail/shared_count.hpp
      12             : //
      13             : //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
      14             : //  Copyright 2004-2005 Peter Dimov
      15             : //
      16             : // Distributed under the Boost Software License, Version 1.0. (See
      17             : // accompanying file LICENSE_1_0.txt or copy at
      18             : // http://www.boost.org/LICENSE_1_0.txt)
      19             : //
      20             : 
      21             : #include <boost/smart_ptr/bad_weak_ptr.hpp>
      22             : #include <boost/smart_ptr/detail/sp_counted_base.hpp>
      23             : #include <boost/smart_ptr/detail/sp_counted_impl.hpp>
      24             : #include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
      25             : #include <boost/smart_ptr/detail/deprecated_macros.hpp>
      26             : #include <boost/core/checked_delete.hpp>
      27             : #include <boost/throw_exception.hpp>
      28             : #include <boost/core/addressof.hpp>
      29             : #include <boost/config.hpp>
      30             : #include <boost/config/workaround.hpp>
      31             : #include <cstdint>
      32             : #include <memory>            // std::auto_ptr
      33             : #include <functional>        // std::less
      34             : #include <cstddef>           // std::size_t
      35             : 
      36             : #ifdef BOOST_NO_EXCEPTIONS
      37             : # include <new>              // std::bad_alloc
      38             : #endif
      39             : 
      40             : #if defined( BOOST_SP_DISABLE_DEPRECATED )
      41             : #pragma GCC diagnostic push
      42             : #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
      43             : #endif
      44             : 
      45             : namespace boost
      46             : {
      47             : 
      48             : namespace movelib
      49             : {
      50             : 
      51             : template< class T, class D > class unique_ptr;
      52             : 
      53             : } // namespace movelib
      54             : 
      55             : namespace detail
      56             : {
      57             : 
      58             : struct sp_nothrow_tag {};
      59             : 
      60             : template< class D > struct sp_inplace_tag
      61             : {
      62             : };
      63             : 
      64             : template< class T > class sp_reference_wrapper
      65             : { 
      66             : public:
      67             : 
      68             :     explicit sp_reference_wrapper( T & t): t_( boost::addressof( t ) )
      69             :     {
      70             :     }
      71             : 
      72             :     template< class Y > void operator()( Y * p ) const
      73             :     {
      74             :         (*t_)( p );
      75             :     }
      76             : 
      77             : private:
      78             : 
      79             :     T * t_;
      80             : };
      81             : 
      82             : template< class D > struct sp_convert_reference
      83             : {
      84             :     typedef D type;
      85             : };
      86             : 
      87             : template< class D > struct sp_convert_reference< D& >
      88             : {
      89             :     typedef sp_reference_wrapper< D > type;
      90             : };
      91             : 
      92             : template<class T> std::size_t sp_hash_pointer( T* p ) noexcept
      93             : {
      94             :     std::uintptr_t v = reinterpret_cast<std::uintptr_t>( p );
      95             : 
      96             :     // match boost::hash<T*>
      97             :     return static_cast<std::size_t>( v + ( v >> 3 ) );
      98             : }
      99             : 
     100             : class weak_count;
     101             : 
     102             : class shared_count
     103             : {
     104             : private:
     105             : 
     106             :     sp_counted_base * pi_;
     107             : 
     108             :     friend class weak_count;
     109             : 
     110             : public:
     111             : 
     112    20905826 :     constexpr shared_count() noexcept: pi_(0)
     113    10452913 :     {
     114    20905826 :     }
     115             : 
     116             :     constexpr explicit shared_count( sp_counted_base * pi ) noexcept: pi_( pi )
     117             :     {
     118             :     }
     119             : 
     120      962526 :     template<class Y> explicit shared_count( Y * p ): pi_( 0 )
     121      481263 :     {
     122             : #ifndef BOOST_NO_EXCEPTIONS
     123             : 
     124             :         try
     125             :         {
     126      481263 :             pi_ = new sp_counted_impl_p<Y>( p );
     127      481263 :         }
     128             :         catch(...)
     129             :         {
     130           0 :             boost::checked_delete( p );
     131           0 :             throw;
     132           0 :         }
     133             : 
     134             : #else
     135             : 
     136             :         pi_ = new sp_counted_impl_p<Y>( p );
     137             : 
     138             :         if( pi_ == 0 )
     139             :         {
     140             :             boost::checked_delete( p );
     141             :             boost::throw_exception( std::bad_alloc() );
     142             :         }
     143             : 
     144             : #endif
     145      962526 :     }
     146             : 
     147             :     template<class P, class D> shared_count( P p, D d ): pi_(0)
     148             :     {
     149             : #ifndef BOOST_NO_EXCEPTIONS
     150             : 
     151             :         try
     152             :         {
     153             :             pi_ = new sp_counted_impl_pd<P, D>(p, d);
     154             :         }
     155             :         catch(...)
     156             :         {
     157             :             d(p); // delete p
     158             :             throw;
     159             :         }
     160             : 
     161             : #else
     162             : 
     163             :         pi_ = new sp_counted_impl_pd<P, D>(p, d);
     164             : 
     165             :         if(pi_ == 0)
     166             :         {
     167             :             d(p); // delete p
     168             :             boost::throw_exception(std::bad_alloc());
     169             :         }
     170             : 
     171             : #endif
     172             :     }
     173             : 
     174      239088 :     template< class P, class D > shared_count( P p, sp_inplace_tag<D> ): pi_( 0 )
     175      119544 :     {
     176             : #ifndef BOOST_NO_EXCEPTIONS
     177             : 
     178             :         try
     179             :         {
     180      119544 :             pi_ = new sp_counted_impl_pd< P, D >( p );
     181      119544 :         }
     182             :         catch( ... )
     183             :         {
     184           0 :             D::operator_fn( p ); // delete p
     185           0 :             throw;
     186           0 :         }
     187             : 
     188             : #else
     189             : 
     190             :         pi_ = new sp_counted_impl_pd< P, D >( p );
     191             : 
     192             :         if( pi_ == 0 )
     193             :         {
     194             :             D::operator_fn( p ); // delete p
     195             :             boost::throw_exception( std::bad_alloc() );
     196             :         }
     197             : 
     198             : #endif // #ifndef BOOST_NO_EXCEPTIONS
     199      239088 :     }
     200             : 
     201             :     template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 )
     202             :     {
     203             :         typedef sp_counted_impl_pda<P, D, A> impl_type;
     204             : 
     205             :         typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
     206             : 
     207             :         A2 a2( a );
     208             : 
     209             : #ifndef BOOST_NO_EXCEPTIONS
     210             : 
     211             :         try
     212             :         {
     213             :             pi_ = a2.allocate( 1 );
     214             :             ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
     215             :         }
     216             :         catch(...)
     217             :         {
     218             :             d( p );
     219             : 
     220             :             if( pi_ != 0 )
     221             :             {
     222             :                 a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
     223             :             }
     224             : 
     225             :             throw;
     226             :         }
     227             : 
     228             : #else
     229             : 
     230             :         pi_ = a2.allocate( 1 );
     231             : 
     232             :         if( pi_ != 0 )
     233             :         {
     234             :             ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
     235             :         }
     236             :         else
     237             :         {
     238             :             d( p );
     239             :             boost::throw_exception( std::bad_alloc() );
     240             :         }
     241             : 
     242             : #endif
     243             :     }
     244             : 
     245             :     template< class P, class D, class A > shared_count( P p, sp_inplace_tag< D >, A a ): pi_( 0 )
     246             :     {
     247             :         typedef sp_counted_impl_pda< P, D, A > impl_type;
     248             : 
     249             :         typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
     250             : 
     251             :         A2 a2( a );
     252             : 
     253             : #ifndef BOOST_NO_EXCEPTIONS
     254             : 
     255             :         try
     256             :         {
     257             :             pi_ = a2.allocate( 1 );
     258             :             ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
     259             :         }
     260             :         catch(...)
     261             :         {
     262             :             D::operator_fn( p );
     263             : 
     264             :             if( pi_ != 0 )
     265             :             {
     266             :                 a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
     267             :             }
     268             : 
     269             :             throw;
     270             :         }
     271             : 
     272             : #else
     273             : 
     274             :         pi_ = a2.allocate( 1 );
     275             : 
     276             :         if( pi_ != 0 )
     277             :         {
     278             :             ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
     279             :         }
     280             :         else
     281             :         {
     282             :             D::operator_fn( p );
     283             :             boost::throw_exception( std::bad_alloc() );
     284             :         }
     285             : 
     286             : #endif // #ifndef BOOST_NO_EXCEPTIONS
     287             :     }
     288             : 
     289             : #ifndef BOOST_NO_AUTO_PTR
     290             : 
     291             :     // auto_ptr<Y> is special cased to provide the strong guarantee
     292             : 
     293             :     template<class Y>
     294             :     explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) )
     295             :     {
     296             : #ifdef BOOST_NO_EXCEPTIONS
     297             : 
     298             :         if( pi_ == 0 )
     299             :         {
     300             :             boost::throw_exception(std::bad_alloc());
     301             :         }
     302             : 
     303             : #endif
     304             : 
     305             :         r.release();
     306             :     }
     307             : 
     308             : #endif 
     309             : 
     310             :     template<class Y, class D>
     311             :     explicit shared_count( std::unique_ptr<Y, D> & r ): pi_( 0 )
     312             :     {
     313             :         typedef typename sp_convert_reference<D>::type D2;
     314             : 
     315             :         D2 d2( static_cast<D&&>( r.get_deleter() ) );
     316             :         pi_ = new sp_counted_impl_pd< typename std::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
     317             : 
     318             : #ifdef BOOST_NO_EXCEPTIONS
     319             : 
     320             :         if( pi_ == 0 )
     321             :         {
     322             :             boost::throw_exception( std::bad_alloc() );
     323             :         }
     324             : 
     325             : #endif
     326             : 
     327             :         r.release();
     328             :     }
     329             : 
     330             :     template<class Y, class D>
     331             :     explicit shared_count( boost::movelib::unique_ptr<Y, D> & r ): pi_( 0 )
     332             :     {
     333             :         typedef typename sp_convert_reference<D>::type D2;
     334             : 
     335             :         D2 d2( r.get_deleter() );
     336             :         pi_ = new sp_counted_impl_pd< typename boost::movelib::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
     337             : 
     338             : #ifdef BOOST_NO_EXCEPTIONS
     339             : 
     340             :         if( pi_ == 0 )
     341             :         {
     342             :             boost::throw_exception( std::bad_alloc() );
     343             :         }
     344             : 
     345             : #endif
     346             : 
     347             :         r.release();
     348             :     }
     349             : 
     350    25943674 :     ~shared_count() /*noexcept*/
     351    12971837 :     {
     352    12971837 :         if( pi_ != 0 ) pi_->release();
     353    25943674 :     }
     354             : 
     355     3385170 :     shared_count(shared_count const & r) noexcept: pi_(r.pi_)
     356     1692585 :     {
     357     1692585 :         if( pi_ != 0 ) pi_->add_ref_copy();
     358     3385170 :     }
     359             : 
     360      764006 :     shared_count(shared_count && r) noexcept: pi_(r.pi_)
     361      382003 :     {
     362      382003 :         r.pi_ = 0;
     363      764006 :     }
     364             : 
     365             :     explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
     366             :     shared_count( weak_count const & r, sp_nothrow_tag ) noexcept; // constructs an empty *this when r.use_count() == 0
     367             : 
     368             :     shared_count & operator= (shared_count const & r) noexcept
     369             :     {
     370             :         sp_counted_base * tmp = r.pi_;
     371             : 
     372             :         if( tmp != pi_ )
     373             :         {
     374             :             if( tmp != 0 ) tmp->add_ref_copy();
     375             :             if( pi_ != 0 ) pi_->release();
     376             :             pi_ = tmp;
     377             :         }
     378             : 
     379             :         return *this;
     380             :     }
     381             : 
     382     1739127 :     void swap(shared_count & r) noexcept
     383             :     {
     384     1739127 :         sp_counted_base * tmp = r.pi_;
     385     1739127 :         r.pi_ = pi_;
     386     1739127 :         pi_ = tmp;
     387     1739127 :     }
     388             : 
     389     3224272 :     long use_count() const noexcept
     390             :     {
     391     3224272 :         return pi_ != 0? pi_->use_count(): 0;
     392             :     }
     393             : 
     394     3224272 :     bool unique() const noexcept
     395             :     {
     396     3224272 :         return use_count() == 1;
     397             :     }
     398             : 
     399      215391 :     bool empty() const noexcept
     400             :     {
     401      215391 :         return pi_ == 0;
     402             :     }
     403             : 
     404             :     bool operator==( shared_count const & r ) const noexcept
     405             :     {
     406             :         return pi_ == r.pi_;
     407             :     }
     408             : 
     409             :     bool operator==( weak_count const & r ) const noexcept;
     410             : 
     411             :     bool operator<( shared_count const & r ) const noexcept
     412             :     {
     413             :         return std::less<sp_counted_base *>()( pi_, r.pi_ );
     414             :     }
     415             : 
     416             :     bool operator<( weak_count const & r ) const noexcept;
     417             : 
     418             :     void * get_deleter( sp_typeinfo_ const & ti ) const noexcept
     419             :     {
     420             :         return pi_? pi_->get_deleter( ti ): 0;
     421             :     }
     422             : 
     423             :     void * get_local_deleter( sp_typeinfo_ const & ti ) const noexcept
     424             :     {
     425             :         return pi_? pi_->get_local_deleter( ti ): 0;
     426             :     }
     427             : 
     428      119544 :     void * get_untyped_deleter() const noexcept
     429             :     {
     430      119544 :         return pi_? pi_->get_untyped_deleter(): 0;
     431             :     }
     432             : 
     433             :     std::size_t hash_value() const noexcept
     434             :     {
     435             :         return sp_hash_pointer( pi_ );
     436             :     }
     437             : };
     438             : 
     439             : 
     440             : class weak_count
     441             : {
     442             : private:
     443             : 
     444             :     sp_counted_base * pi_;
     445             : 
     446             :     friend class shared_count;
     447             : 
     448             : public:
     449             : 
     450      119848 :     constexpr weak_count() noexcept: pi_(0)
     451       59924 :     {
     452      119848 :     }
     453             : 
     454       86066 :     weak_count(shared_count const & r) noexcept: pi_(r.pi_)
     455       43033 :     {
     456       43033 :         if(pi_ != 0) pi_->weak_add_ref();
     457       86066 :     }
     458             : 
     459       99322 :     weak_count(weak_count const & r) noexcept: pi_(r.pi_)
     460       49661 :     {
     461       49661 :         if(pi_ != 0) pi_->weak_add_ref();
     462       99322 :     }
     463             : 
     464             : // Move support
     465             : 
     466      160728 :     weak_count(weak_count && r) noexcept: pi_(r.pi_)
     467       80364 :     {
     468       80364 :         r.pi_ = 0;
     469      160728 :     }
     470             : 
     471      395334 :     ~weak_count() /*noexcept*/
     472      197667 :     {
     473      197667 :         if(pi_ != 0) pi_->weak_release();
     474      395334 :     }
     475             : 
     476             :     weak_count & operator= (shared_count const & r) noexcept
     477             :     {
     478             :         sp_counted_base * tmp = r.pi_;
     479             : 
     480             :         if( tmp != pi_ )
     481             :         {
     482             :             if(tmp != 0) tmp->weak_add_ref();
     483             :             if(pi_ != 0) pi_->weak_release();
     484             :             pi_ = tmp;
     485             :         }
     486             : 
     487             :         return *this;
     488             :     }
     489             : 
     490             :     weak_count & operator= (weak_count const & r) noexcept
     491             :     {
     492             :         sp_counted_base * tmp = r.pi_;
     493             : 
     494             :         if( tmp != pi_ )
     495             :         {
     496             :             if(tmp != 0) tmp->weak_add_ref();
     497             :             if(pi_ != 0) pi_->weak_release();
     498             :             pi_ = tmp;
     499             :         }
     500             : 
     501             :         return *this;
     502             :     }
     503             : 
     504       28168 :     void swap(weak_count & r) noexcept
     505             :     {
     506       28168 :         sp_counted_base * tmp = r.pi_;
     507       28168 :         r.pi_ = pi_;
     508       28168 :         pi_ = tmp;
     509       28168 :     }
     510             : 
     511      481295 :     long use_count() const noexcept
     512             :     {
     513      481295 :         return pi_ != 0? pi_->use_count(): 0;
     514             :     }
     515             : 
     516             :     bool empty() const noexcept
     517             :     {
     518             :         return pi_ == 0;
     519             :     }
     520             : 
     521             :     bool operator==( weak_count const & r ) const noexcept
     522             :     {
     523             :         return pi_ == r.pi_;
     524             :     }
     525             : 
     526             :     bool operator==( shared_count const & r ) const noexcept
     527             :     {
     528             :         return pi_ == r.pi_;
     529             :     }
     530             : 
     531             :     bool operator<( weak_count const & r ) const noexcept
     532             :     {
     533             :         return std::less<sp_counted_base *>()( pi_, r.pi_ );
     534             :     }
     535             : 
     536             :     bool operator<( shared_count const & r ) const noexcept
     537             :     {
     538             :         return std::less<sp_counted_base *>()( pi_, r.pi_ );
     539             :     }
     540             : 
     541             :     std::size_t hash_value() const noexcept
     542             :     {
     543             :         return sp_hash_pointer( pi_ );
     544             :     }
     545             : };
     546             : 
     547             : inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
     548             : {
     549             :     if( pi_ == 0 || !pi_->add_ref_lock() )
     550             :     {
     551             :         boost::throw_exception( boost::bad_weak_ptr() );
     552             :     }
     553             : }
     554             : 
     555      430784 : inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ) noexcept: pi_( r.pi_ )
     556      215392 : {
     557      215392 :     if( pi_ != 0 && !pi_->add_ref_lock() )
     558             :     {
     559           0 :         pi_ = 0;
     560           0 :     }
     561      430784 : }
     562             : 
     563             : inline bool shared_count::operator==( weak_count const & r ) const noexcept
     564             : {
     565             :     return pi_ == r.pi_;
     566             : }
     567             : 
     568             : inline bool shared_count::operator<( weak_count const & r ) const noexcept
     569             : {
     570             :     return std::less<sp_counted_base *>()( pi_, r.pi_ );
     571             : }
     572             : 
     573             : } // namespace detail
     574             : 
     575             : } // namespace boost
     576             : 
     577             : #if defined( BOOST_SP_DISABLE_DEPRECATED )
     578             : #pragma GCC diagnostic pop
     579             : #endif
     580             : 
     581             : #endif  // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED

Generated by: LCOV version 1.16