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_GCC_X86_HPP_INCLUDED
0002 #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_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 //
0011 //  detail/sp_counted_base_gcc_x86.hpp - g++ on 486+ or AMD64
0012 //
0013 //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
0014 //  Copyright 2004-2005 Peter Dimov
0015 //
0016 //  Distributed under the Boost Software License, Version 1.0. (See
0017 //  accompanying file LICENSE_1_0.txt or copy at
0018 //  http://www.boost.org/LICENSE_1_0.txt)
0019 //
0020 //
0021 //  Lock-free algorithm by Alexander Terekhov
0022 //
0023 //  Thanks to Ben Hitchings for the #weak + (#shared != 0)
0024 //  formulation
0025 //
0026 
0027 #include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
0028 #include <boost/smart_ptr/detail/sp_obsolete.hpp>
0029 #include <boost/config.hpp>
0030 
0031 #if defined(BOOST_SP_REPORT_IMPLEMENTATION)
0032 
0033 #include <boost/config/pragma_message.hpp>
0034 BOOST_PRAGMA_MESSAGE("Using g++/x86 sp_counted_base")
0035 
0036 #endif
0037 
0038 BOOST_SP_OBSOLETE()
0039 
0040 namespace boost
0041 {
0042 
0043 namespace detail
0044 {
0045 
0046 inline int atomic_exchange_and_add( int * pw, int dv )
0047 {
0048     // int r = *pw;
0049     // *pw += dv;
0050     // return r;
0051 
0052     int r;
0053 
0054     __asm__ __volatile__
0055     (
0056         "lock\n\t"
0057         "xadd %1, %0":
0058         "=m"( *pw ), "=r"( r ): // outputs (%0, %1)
0059         "m"( *pw ), "1"( dv ): // inputs (%2, %3 == %1)
0060         "memory", "cc" // clobbers
0061     );
0062 
0063     return r;
0064 }
0065 
0066 inline void atomic_increment( int * pw )
0067 {
0068     //atomic_exchange_and_add( pw, 1 );
0069 
0070     __asm__
0071     (
0072         "lock\n\t"
0073         "incl %0":
0074         "=m"( *pw ): // output (%0)
0075         "m"( *pw ): // input (%1)
0076         "cc" // clobbers
0077     );
0078 }
0079 
0080 inline int atomic_conditional_increment( int * pw )
0081 {
0082     // int rv = *pw;
0083     // if( rv != 0 ) ++*pw;
0084     // return rv;
0085 
0086     int rv, tmp;
0087 
0088     __asm__
0089     (
0090         "movl %0, %%eax\n\t"
0091         "0:\n\t"
0092         "test %%eax, %%eax\n\t"
0093         "je 1f\n\t"
0094         "movl %%eax, %2\n\t"
0095         "incl %2\n\t"
0096         "lock\n\t"
0097         "cmpxchgl %2, %0\n\t"
0098         "jne 0b\n\t"
0099         "1:":
0100         "=m"( *pw ), "=&a"( rv ), "=&r"( tmp ): // outputs (%0, %1, %2)
0101         "m"( *pw ): // input (%3)
0102         "cc" // clobbers
0103     );
0104 
0105     return rv;
0106 }
0107 
0108 class BOOST_SYMBOL_VISIBLE sp_counted_base
0109 {
0110 private:
0111 
0112     sp_counted_base( sp_counted_base const & );
0113     sp_counted_base & operator= ( sp_counted_base const & );
0114 
0115     int use_count_;        // #shared
0116     int weak_count_;       // #weak + (#shared != 0)
0117 
0118 public:
0119 
0120     sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
0121     {
0122     }
0123 
0124     virtual ~sp_counted_base() // nothrow
0125     {
0126     }
0127 
0128     // dispose() is called when use_count_ drops to zero, to release
0129     // the resources managed by *this.
0130 
0131     virtual void dispose() = 0; // nothrow
0132 
0133     // destroy() is called when weak_count_ drops to zero.
0134 
0135     virtual void destroy() // nothrow
0136     {
0137         delete this;
0138     }
0139 
0140     virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
0141     virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
0142     virtual void * get_untyped_deleter() = 0;
0143 
0144     void add_ref_copy()
0145     {
0146         atomic_increment( &use_count_ );
0147     }
0148 
0149     bool add_ref_lock() // true on success
0150     {
0151         return atomic_conditional_increment( &use_count_ ) != 0;
0152     }
0153 
0154     void release() // nothrow
0155     {
0156         if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
0157         {
0158             dispose();
0159             weak_release();
0160         }
0161     }
0162 
0163     void weak_add_ref() // nothrow
0164     {
0165         atomic_increment( &weak_count_ );
0166     }
0167 
0168     void weak_release() // nothrow
0169     {
0170         if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
0171         {
0172             destroy();
0173         }
0174     }
0175 
0176     long use_count() const // nothrow
0177     {
0178         return static_cast<int const volatile &>( use_count_ );
0179     }
0180 };
0181 
0182 } // namespace detail
0183 
0184 } // namespace boost
0185 
0186 #endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED