Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:51:42

0001 #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED
0002 #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED
0003 
0004 // MS compatible compilers support #pragma once
0005 
0006 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
0007 # pragma once
0008 #endif
0009 
0010 //  detail/sp_counted_base_std_atomic.hpp - C++11 std::atomic
0011 //
0012 //  Copyright (c) 2007, 2013 Peter Dimov
0013 //
0014 //  Distributed under the Boost Software License, Version 1.0.
0015 //  See accompanying file LICENSE_1_0.txt or copy at
0016 //  http://www.boost.org/LICENSE_1_0.txt
0017 
0018 #include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
0019 #include <boost/smart_ptr/detail/sp_noexcept.hpp>
0020 #include <boost/config.hpp>
0021 #include <atomic>
0022 #include <cstdint>
0023 
0024 #if defined(BOOST_SP_REPORT_IMPLEMENTATION)
0025 
0026 #include <boost/config/pragma_message.hpp>
0027 BOOST_PRAGMA_MESSAGE("Using std::atomic sp_counted_base")
0028 
0029 #endif
0030 
0031 namespace boost
0032 {
0033 
0034 namespace detail
0035 {
0036 
0037 inline void atomic_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
0038 {
0039     pw->fetch_add( 1, std::memory_order_relaxed );
0040 }
0041 
0042 inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
0043 {
0044     return pw->fetch_sub( 1, std::memory_order_acq_rel );
0045 }
0046 
0047 inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
0048 {
0049     // long r = *pw;
0050     // if( r != 0 ) ++*pw;
0051     // return r;
0052 
0053     std::int_least32_t r = pw->load( std::memory_order_relaxed );
0054 
0055     for( ;; )
0056     {
0057         if( r == 0 )
0058         {
0059             return r;
0060         }
0061 
0062         if( pw->compare_exchange_weak( r, r + 1, std::memory_order_relaxed, std::memory_order_relaxed ) )
0063         {
0064             return r;
0065         }
0066     }    
0067 }
0068 
0069 class BOOST_SYMBOL_VISIBLE sp_counted_base
0070 {
0071 private:
0072 
0073     sp_counted_base( sp_counted_base const & );
0074     sp_counted_base & operator= ( sp_counted_base const & );
0075 
0076     std::atomic_int_least32_t use_count_;   // #shared
0077     std::atomic_int_least32_t weak_count_;  // #weak + (#shared != 0)
0078 
0079 public:
0080 
0081     sp_counted_base() BOOST_SP_NOEXCEPT: use_count_( 1 ), weak_count_( 1 )
0082     {
0083     }
0084 
0085     virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
0086     {
0087     }
0088 
0089     // dispose() is called when use_count_ drops to zero, to release
0090     // the resources managed by *this.
0091 
0092     virtual void dispose() BOOST_SP_NOEXCEPT = 0;
0093 
0094     // destroy() is called when weak_count_ drops to zero.
0095 
0096     virtual void destroy() BOOST_SP_NOEXCEPT
0097     {
0098         delete this;
0099     }
0100 
0101     virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
0102     virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
0103     virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
0104 
0105     void add_ref_copy() BOOST_SP_NOEXCEPT
0106     {
0107         atomic_increment( &use_count_ );
0108     }
0109 
0110     bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
0111     {
0112         return atomic_conditional_increment( &use_count_ ) != 0;
0113     }
0114 
0115     void release() BOOST_SP_NOEXCEPT
0116     {
0117         if( atomic_decrement( &use_count_ ) == 1 )
0118         {
0119             dispose();
0120             weak_release();
0121         }
0122     }
0123 
0124     void weak_add_ref() BOOST_SP_NOEXCEPT
0125     {
0126         atomic_increment( &weak_count_ );
0127     }
0128 
0129     void weak_release() BOOST_SP_NOEXCEPT
0130     {
0131         if( atomic_decrement( &weak_count_ ) == 1 )
0132         {
0133             destroy();
0134         }
0135     }
0136 
0137     long use_count() const BOOST_SP_NOEXCEPT
0138     {
0139         return use_count_.load( std::memory_order_acquire );
0140     }
0141 };
0142 
0143 } // namespace detail
0144 
0145 } // namespace boost
0146 
0147 #endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED