williamr@2: #ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
williamr@2: #define BOOST_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
williamr@2: 
williamr@2: // MS compatible compilers support #pragma once
williamr@2: 
williamr@2: #if defined(_MSC_VER) && (_MSC_VER >= 1020)
williamr@2: # pragma once
williamr@2: #endif
williamr@2: 
williamr@2: //
williamr@2: //  detail/sp_counted_base_cw_x86.hpp - CodeWarrion on 486+
williamr@2: //
williamr@2: //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
williamr@2: //  Copyright 2004-2005 Peter Dimov
williamr@2: //  Copyright 2005 Rene Rivera
williamr@2: //
williamr@2: //  Distributed under the Boost Software License, Version 1.0. (See
williamr@2: //  accompanying file LICENSE_1_0.txt or copy at
williamr@2: //  http://www.boost.org/LICENSE_1_0.txt)
williamr@2: //
williamr@2: //
williamr@2: //  Lock-free algorithm by Alexander Terekhov
williamr@2: //
williamr@2: //  Thanks to Ben Hitchings for the #weak + (#shared != 0)
williamr@2: //  formulation
williamr@2: //
williamr@2: 
williamr@2: #include <typeinfo>
williamr@2: 
williamr@2: namespace boost
williamr@2: {
williamr@2: 
williamr@2: namespace detail
williamr@2: {
williamr@2: 
williamr@2: inline int atomic_exchange_and_add( int * pw, int dv )
williamr@2: {
williamr@2:     // int r = *pw;
williamr@2:     // *pw += dv;
williamr@2:     // return r;
williamr@2: 
williamr@2:     asm
williamr@2:     {
williamr@2:         mov esi, [pw]
williamr@2:         mov eax, dv
williamr@2:         lock xadd dword ptr [esi], eax
williamr@2:     }
williamr@2: }
williamr@2: 
williamr@2: inline void atomic_increment( int * pw )
williamr@2: {
williamr@2:     //atomic_exchange_and_add( pw, 1 );
williamr@2: 
williamr@2:     asm
williamr@2:     {
williamr@2:         mov esi, [pw]
williamr@2:         lock inc dword ptr [esi]
williamr@2:     }
williamr@2: }
williamr@2: 
williamr@2: inline int atomic_conditional_increment( int * pw )
williamr@2: {
williamr@2:     // int rv = *pw;
williamr@2:     // if( rv != 0 ) ++*pw;
williamr@2:     // return rv;
williamr@2: 
williamr@2:     asm
williamr@2:     {
williamr@2:         mov esi, [pw]
williamr@2:         mov eax, dword ptr [esi]
williamr@2:     L0:
williamr@2:         test eax, eax
williamr@2:         je L1
williamr@2:         mov ebx, eax
williamr@2:         inc ebx
williamr@2:         lock cmpxchg dword ptr [esi], ebx
williamr@2:         jne L0
williamr@2:     L1:
williamr@2:     }
williamr@2: }
williamr@2: 
williamr@2: class sp_counted_base
williamr@2: {
williamr@2: private:
williamr@2: 
williamr@2:     sp_counted_base( sp_counted_base const & );
williamr@2:     sp_counted_base & operator= ( sp_counted_base const & );
williamr@2: 
williamr@2:     int use_count_;        // #shared
williamr@2:     int weak_count_;       // #weak + (#shared != 0)
williamr@2: 
williamr@2: public:
williamr@2: 
williamr@2:     sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
williamr@2:     {
williamr@2:     }
williamr@2: 
williamr@2:     virtual ~sp_counted_base() // nothrow
williamr@2:     {
williamr@2:     }
williamr@2: 
williamr@2:     // dispose() is called when use_count_ drops to zero, to release
williamr@2:     // the resources managed by *this.
williamr@2: 
williamr@2:     virtual void dispose() = 0; // nothrow
williamr@2: 
williamr@2:     // destroy() is called when weak_count_ drops to zero.
williamr@2: 
williamr@2:     virtual void destroy() // nothrow
williamr@2:     {
williamr@2:         delete this;
williamr@2:     }
williamr@2: 
williamr@2:     virtual void * get_deleter( std::type_info const & ti ) = 0;
williamr@2: 
williamr@2:     void add_ref_copy()
williamr@2:     {
williamr@2:         atomic_increment( &use_count_ );
williamr@2:     }
williamr@2: 
williamr@2:     bool add_ref_lock() // true on success
williamr@2:     {
williamr@2:         return atomic_conditional_increment( &use_count_ ) != 0;
williamr@2:     }
williamr@2: 
williamr@2:     void release() // nothrow
williamr@2:     {
williamr@2:         if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
williamr@2:         {
williamr@2:             dispose();
williamr@2:             weak_release();
williamr@2:         }
williamr@2:     }
williamr@2: 
williamr@2:     void weak_add_ref() // nothrow
williamr@2:     {
williamr@2:         atomic_increment( &weak_count_ );
williamr@2:     }
williamr@2: 
williamr@2:     void weak_release() // nothrow
williamr@2:     {
williamr@2:         if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
williamr@2:         {
williamr@2:             destroy();
williamr@2:         }
williamr@2:     }
williamr@2: 
williamr@2:     long use_count() const // nothrow
williamr@2:     {
williamr@2:         return static_cast<int const volatile &>( use_count_ );
williamr@2:     }
williamr@2: };
williamr@2: 
williamr@2: } // namespace detail
williamr@2: 
williamr@2: } // namespace boost
williamr@2: 
williamr@2: #endif  // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED