From 5ab6b2485639fdabbd230cd93c3cbd648d32f061 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 23 Nov 2007 17:03:14 +0000 Subject: [PATCH] config, detail, filesystem, system, tools, at 41278. [SVN r41316] --- include/boost/detail/atomic_count.hpp | 16 ++ include/boost/detail/atomic_count_gcc.hpp | 6 +- include/boost/detail/atomic_count_gcc_x86.hpp | 84 +++++++++ include/boost/detail/atomic_count_solaris.hpp | 59 +++++++ include/boost/detail/atomic_count_sync.hpp | 57 ++++++ include/boost/detail/lightweight_mutex.hpp | 4 +- include/boost/detail/shared_count.hpp | 3 +- include/boost/detail/sp_counted_base.hpp | 16 +- .../boost/detail/sp_counted_base_acc_ia64.hpp | 150 ++++++++++++++++ .../boost/detail/sp_counted_base_cw_ppc.hpp | 4 +- .../boost/detail/sp_counted_base_cw_x86.hpp | 4 +- .../boost/detail/sp_counted_base_gcc_ia64.hpp | 4 +- .../boost/detail/sp_counted_base_gcc_ppc.hpp | 4 +- .../detail/sp_counted_base_gcc_sparc.hpp | 166 ++++++++++++++++++ .../boost/detail/sp_counted_base_gcc_x86.hpp | 4 +- include/boost/detail/sp_counted_base_nt.hpp | 4 +- include/boost/detail/sp_counted_base_pt.hpp | 4 +- .../boost/detail/sp_counted_base_solaris.hpp | 113 ++++++++++++ include/boost/detail/sp_counted_base_sync.hpp | 151 ++++++++++++++++ include/boost/detail/sp_counted_base_w32.hpp | 4 +- include/boost/detail/sp_counted_impl.hpp | 11 +- include/boost/detail/sp_typeinfo.hpp | 83 +++++++++ 22 files changed, 918 insertions(+), 33 deletions(-) create mode 100644 include/boost/detail/atomic_count_gcc_x86.hpp create mode 100644 include/boost/detail/atomic_count_solaris.hpp create mode 100644 include/boost/detail/atomic_count_sync.hpp create mode 100644 include/boost/detail/sp_counted_base_acc_ia64.hpp create mode 100644 include/boost/detail/sp_counted_base_gcc_sparc.hpp create mode 100644 include/boost/detail/sp_counted_base_solaris.hpp create mode 100644 include/boost/detail/sp_counted_base_sync.hpp create mode 100644 include/boost/detail/sp_typeinfo.hpp diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 9985b2c..804fd1a 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -90,14 +90,30 @@ typedef long atomic_count; } #elif defined(BOOST_AC_USE_PTHREADS) + # include + +#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) + +# include + #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) + # include + +#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + +# include + #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) + # include + #elif defined(BOOST_HAS_PTHREADS) + # define BOOST_AC_USE_PTHREADS # include + #else // Use #define BOOST_DISABLE_THREADS to avoid the error diff --git a/include/boost/detail/atomic_count_gcc.hpp b/include/boost/detail/atomic_count_gcc.hpp index 9a1820d..1160e44 100644 --- a/include/boost/detail/atomic_count_gcc.hpp +++ b/include/boost/detail/atomic_count_gcc.hpp @@ -17,11 +17,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) -# include -#else -# include -#endif +#include namespace boost { diff --git a/include/boost/detail/atomic_count_gcc_x86.hpp b/include/boost/detail/atomic_count_gcc_x86.hpp new file mode 100644 index 0000000..1312e8c --- /dev/null +++ b/include/boost/detail/atomic_count_gcc_x86.hpp @@ -0,0 +1,84 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED + +// +// boost/detail/atomic_count_gcc_x86.hpp +// +// atomic_count for g++ on 486+/AMD64 +// +// Copyright 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( long v ) : value_( static_cast< int >( v ) ) {} + + void operator++() + { + __asm__ + ( + "lock\n\t" + "incl %0": + "+m"( value_ ): // output (%0) + : // inputs + "cc" // clobbers + ); + } + + long operator--() + { + return atomic_exchange_and_add( &value_, -1 ) - 1; + } + + operator long() const + { + return atomic_exchange_and_add( &value_, 0 ); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + mutable int value_; + +private: + + static int atomic_exchange_and_add( int * pw, int dv ) + { + // int r = *pw; + // *pw += dv; + // return r; + + int r; + + __asm__ __volatile__ + ( + "lock\n\t" + "xadd %1, %0": + "+m"( *pw ), "=r"( r ): // outputs (%0, %1) + "1"( dv ): // inputs (%2 == %1) + "memory", "cc" // clobbers + ); + + return r; + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_solaris.hpp b/include/boost/detail/atomic_count_solaris.hpp new file mode 100644 index 0000000..8e2907f --- /dev/null +++ b/include/boost/detail/atomic_count_solaris.hpp @@ -0,0 +1,59 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED + +// +// boost/detail/atomic_count_solaris.hpp +// based on: boost/detail/atomic_count_win32.hpp +// +// Copyright (c) 2001-2005 Peter Dimov +// Copyright (c) 2006 Michael van der Westhuizen +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( uint32_t v ): value_( v ) + { + } + + long operator++() + { + return atomic_inc_32_nv( &value_ ); + } + + long operator--() + { + return atomic_dec_32_nv( &value_ ); + } + + operator uint32_t() const + { + return static_cast( value_ ); + } + +private: + + atomic_count( atomic_count const & ); + atomic_count & operator=( atomic_count const & ); + + uint32_t value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_sync.hpp b/include/boost/detail/atomic_count_sync.hpp new file mode 100644 index 0000000..e973fb7 --- /dev/null +++ b/include/boost/detail/atomic_count_sync.hpp @@ -0,0 +1,57 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED + +// +// boost/detail/atomic_count_sync.hpp +// +// atomic_count for g++ 4.1+ +// +// http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html +// +// Copyright 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( long v ) : value_( v ) {} + + void operator++() + { + __sync_add_and_fetch( &value_, 1 ); + } + + long operator--() + { + return __sync_add_and_fetch( &value_, -1 ); + } + + operator long() const + { + return __sync_fetch_and_add( &value_, 0 ); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + mutable long value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index a0936cb..e740d7f 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -30,10 +30,10 @@ #if !defined(BOOST_HAS_THREADS) # include -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -# include #elif defined(BOOST_HAS_PTHREADS) # include +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# include #else // Use #define BOOST_DISABLE_THREADS to avoid the error # error Unrecognized threading platform diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index e139a7d..085b12f 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -32,7 +32,6 @@ #include // std::auto_ptr #include // std::less #include // std::bad_alloc -#include // std::type_info in get_deleter namespace boost { @@ -259,7 +258,7 @@ public: return std::less()( a.pi_, b.pi_ ); } - void * get_deleter(std::type_info const & ti) const + void * get_deleter( sp_typeinfo const & ti ) const { return pi_? pi_->get_deleter( ti ): 0; } diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index bc170ca..f925a5d 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -10,7 +10,7 @@ // // detail/sp_counted_base.hpp // -// Copyright 2005 Peter Dimov +// Copyright 2005, 2006 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -39,14 +39,26 @@ # include +#elif defined(__HP_aCC) && defined(__ia64) + +# include + #elif defined( __MWERKS__ ) && defined( __POWERPC__ ) # include -#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) ) +#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) # include +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + +# include + +#elif defined(__GNUC__) && ( defined( __sparcv8 ) || defined( __sparcv9 ) ) + +# include + #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) # include diff --git a/include/boost/detail/sp_counted_base_acc_ia64.hpp b/include/boost/detail/sp_counted_base_acc_ia64.hpp new file mode 100644 index 0000000..94c015d --- /dev/null +++ b/include/boost/detail/sp_counted_base_acc_ia64.hpp @@ -0,0 +1,150 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED + +// +// detail/sp_counted_base_acc_ia64.hpp - aC++ on HP-UX IA64 +// +// Copyright 2007 Baruch Zilber +// Copyright 2007 Boris Gubenko +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// +// Lock-free algorithm by Alexander Terekhov +// + +#include "sp_typeinfo.hpp" +#include + +namespace boost +{ + +namespace detail +{ + +inline void atomic_increment( int * pw ) +{ + // ++*pw; + + _Asm_fetchadd(_FASZ_W, _SEM_REL, pw, +1, _LDHINT_NONE); +} + +inline int atomic_decrement( int * pw ) +{ + // return --*pw; + + int r = static_cast(_Asm_fetchadd(_FASZ_W, _SEM_REL, pw, -1, _LDHINT_NONE)); + if (1 == r) + { + _Asm_mf(); + } + + return r - 1; +} + +inline int atomic_conditional_increment( int * pw ) +{ + // if( *pw != 0 ) ++*pw; + // return *pw; + + int v = *pw; + + for (;;) + { + if (0 == v) + { + return 0; + } + + _Asm_mov_to_ar(_AREG_CCV, + v, + (_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE)); + int r = static_cast(_Asm_cmpxchg(_SZ_W, _SEM_ACQ, pw, v + 1, _LDHINT_NONE)); + if (r == v) + { + return r + 1; + } + + v = r; + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); // TODO use ld.acq here + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_cw_ppc.hpp b/include/boost/detail/sp_counted_base_cw_ppc.hpp index c56a562..17fb736 100644 --- a/include/boost/detail/sp_counted_base_cw_ppc.hpp +++ b/include/boost/detail/sp_counted_base_cw_ppc.hpp @@ -24,7 +24,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -123,7 +123,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_cw_x86.hpp b/include/boost/detail/sp_counted_base_cw_x86.hpp index 63c9fa2..32dd02c 100644 --- a/include/boost/detail/sp_counted_base_cw_x86.hpp +++ b/include/boost/detail/sp_counted_base_cw_x86.hpp @@ -25,7 +25,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -111,7 +111,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/detail/sp_counted_base_gcc_ia64.hpp index 7f4bd25..70b2a26 100644 --- a/include/boost/detail/sp_counted_base_gcc_ia64.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ia64.hpp @@ -16,7 +16,7 @@ // Lock-free algorithm by Alexander Terekhov // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -110,7 +110,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/detail/sp_counted_base_gcc_ppc.hpp index ca5cf2b..5a488f5 100644 --- a/include/boost/detail/sp_counted_base_gcc_ppc.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ppc.hpp @@ -24,7 +24,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -134,7 +134,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_gcc_sparc.hpp b/include/boost/detail/sp_counted_base_gcc_sparc.hpp new file mode 100644 index 0000000..c6624cf --- /dev/null +++ b/include/boost/detail/sp_counted_base_gcc_sparc.hpp @@ -0,0 +1,166 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_counted_base_gcc_sparc.hpp - g++ on Sparc V8+ +// +// Copyright (c) 2006 Piotr Wyderski +// Copyright (c) 2006 Tomas Puverle +// Copyright (c) 2006 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// Thanks to Michael van der Westhuizen + +#include "sp_typeinfo.hpp" +#include // int32_t + +namespace boost +{ + +namespace detail +{ + +inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ ) +{ + __asm__ __volatile__( "cas %0, %2, %1" + : "+m" (*dest_), "+r" (swap_) + : "r" (compare_) + : "memory" ); + + return swap_; +} + +inline int32_t atomic_fetch_and_add( int32_t * pw, int32_t dv ) +{ + // long r = *pw; + // *pw += dv; + // return r; + + for( ;; ) + { + int32_t r = *pw; + + if( __builtin_expect((compare_and_swap(pw, r, r + dv) == r), 1) ) + { + return r; + } + } +} + +inline void atomic_increment( int32_t * pw ) +{ + atomic_fetch_and_add( pw, 1 ); +} + +inline int32_t atomic_decrement( int32_t * pw ) +{ + return atomic_fetch_and_add( pw, -1 ); +} + +inline int32_t atomic_conditional_increment( int32_t * pw ) +{ + // long r = *pw; + // if( r != 0 ) ++*pw; + // return r; + + for( ;; ) + { + int32_t r = *pw; + + if( r == 0 ) + { + return r; + } + + if( __builtin_expect( ( compare_and_swap( pw, r, r + 1 ) == r ), 1 ) ) + { + return r; + } + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int32_t use_count_; // #shared + int32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return const_cast< int32_t const volatile & >( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/detail/sp_counted_base_gcc_x86.hpp index 0a8e189..7d243de 100644 --- a/include/boost/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/detail/sp_counted_base_gcc_x86.hpp @@ -24,7 +24,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -126,7 +126,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_nt.hpp b/include/boost/detail/sp_counted_base_nt.hpp index 4a4401d..626e06f 100644 --- a/include/boost/detail/sp_counted_base_nt.hpp +++ b/include/boost/detail/sp_counted_base_nt.hpp @@ -18,7 +18,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -58,7 +58,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_pt.hpp b/include/boost/detail/sp_counted_base_pt.hpp index 191064f..6e0835f 100644 --- a/include/boost/detail/sp_counted_base_pt.hpp +++ b/include/boost/detail/sp_counted_base_pt.hpp @@ -18,7 +18,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#include "sp_typeinfo.hpp" #include namespace boost @@ -69,7 +69,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_solaris.hpp b/include/boost/detail/sp_counted_base_solaris.hpp new file mode 100644 index 0000000..58119db --- /dev/null +++ b/include/boost/detail/sp_counted_base_solaris.hpp @@ -0,0 +1,113 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED + +// +// detail/sp_counted_base_solaris.hpp +// based on: detail/sp_counted_base_w32.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// Copyright 2006 Michael van der Westhuizen +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include "sp_typeinfo.hpp" +#include + +namespace boost +{ + +namespace detail +{ + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + uint32_t use_count_; // #shared + uint32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_inc_32( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + for( ;; ) + { + uint32_t tmp = static_cast< uint32_t const volatile& >( use_count_ ); + if( tmp == 0 ) return false; + if( atomic_cas_32( &use_count_, tmp, tmp + 1 ) == tmp ) return true; + } + } + + void release() // nothrow + { + if( atomic_dec_32_nv( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_inc_32( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_dec_32_nv( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_sync.hpp b/include/boost/detail/sp_counted_base_sync.hpp new file mode 100644 index 0000000..bf2a0fb --- /dev/null +++ b/include/boost/detail/sp_counted_base_sync.hpp @@ -0,0 +1,151 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_counted_base_sync.hpp - g++ 4.1+ __sync intrinsics +// +// Copyright (c) 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include "sp_typeinfo.hpp" +#include + +namespace boost +{ + +namespace detail +{ + +#if INT_MAX >= 2147483647 + +typedef int sp_int32_t; + +#else + +typedef long sp_int32_t; + +#endif + +inline void atomic_increment( sp_int32_t * pw ) +{ + __sync_fetch_and_add( pw, 1 ); +} + +inline sp_int32_t atomic_decrement( sp_int32_t * pw ) +{ + return __sync_fetch_and_add( pw, -1 ); +} + +inline sp_int32_t atomic_conditional_increment( sp_int32_t * pw ) +{ + // long r = *pw; + // if( r != 0 ) ++*pw; + // return r; + + sp_int32_t r = *pw; + + for( ;; ) + { + if( r == 0 ) + { + return r; + } + + sp_int32_t r2 = __sync_val_compare_and_swap( pw, r, r + 1 ); + + if( r2 == r ) + { + return r; + } + else + { + r = r2; + } + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + sp_int32_t use_count_; // #shared + sp_int32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return const_cast< sp_int32_t const volatile & >( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_w32.hpp b/include/boost/detail/sp_counted_base_w32.hpp index fb42c4e..4328962 100644 --- a/include/boost/detail/sp_counted_base_w32.hpp +++ b/include/boost/detail/sp_counted_base_w32.hpp @@ -26,7 +26,7 @@ #include #include -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -66,7 +66,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_impl.hpp b/include/boost/detail/sp_counted_impl.hpp index 6963f59..81f92da 100644 --- a/include/boost/detail/sp_counted_impl.hpp +++ b/include/boost/detail/sp_counted_impl.hpp @@ -35,7 +35,6 @@ #include // std::allocator #endif -#include // std::type_info in get_deleter #include // std::size_t namespace boost @@ -79,7 +78,7 @@ public: boost::checked_delete( px_ ); } - virtual void * get_deleter( std::type_info const & ) + virtual void * get_deleter( detail::sp_typeinfo const & ) { return 0; } @@ -145,9 +144,9 @@ public: del( ptr ); } - virtual void * get_deleter( std::type_info const & ti ) + virtual void * get_deleter( detail::sp_typeinfo const & ti ) { - return ti == typeid(D)? &del: 0; + return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast( del ): 0; } #if defined(BOOST_SP_USE_STD_ALLOCATOR) @@ -215,9 +214,9 @@ public: a2.deallocate( this, 1 ); } - virtual void * get_deleter( std::type_info const & ti ) + virtual void * get_deleter( detail::sp_typeinfo const & ti ) { - return ti == typeid( D )? &d_: 0; + return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast( d_ ): 0; } }; diff --git a/include/boost/detail/sp_typeinfo.hpp b/include/boost/detail/sp_typeinfo.hpp new file mode 100644 index 0000000..e78c943 --- /dev/null +++ b/include/boost/detail/sp_typeinfo.hpp @@ -0,0 +1,83 @@ +#ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED +#define BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_typeinfo.hpp +// +// Copyright 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#if defined( BOOST_NO_TYPEID ) + +namespace boost +{ + +namespace detail +{ + +typedef void* sp_typeinfo; + +template struct sp_typeid_ +{ + static char v_; +}; + +template char sp_typeid_< T >::v_; + +template struct sp_typeid_< T const >: sp_typeid_< T > +{ +}; + +template struct sp_typeid_< T volatile >: sp_typeid_< T > +{ +}; + +template struct sp_typeid_< T const volatile >: sp_typeid_< T > +{ +}; + +} // namespace detail + +} // namespace boost + +#define BOOST_SP_TYPEID(T) (&boost::detail::sp_typeid_::v_) + +#else + +#include + +namespace boost +{ + +namespace detail +{ + +#if defined( BOOST_NO_STD_TYPEINFO ) + +typedef ::type_info sp_typeinfo; + +#else + +typedef std::type_info sp_typeinfo; + +#endif + +} // namespace detail + +} // namespace boost + +#define BOOST_SP_TYPEID(T) typeid(T) + +#endif + +#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED