From e38d0daaab2d0326d2733b34f13bb7cec41c879e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 22 Mar 2006 22:46:53 +0000 Subject: [PATCH 001/132] Fix issues on HP-UX (ILP32 model) [SVN r33449] --- .../boost/detail/sp_counted_base_gcc_ia64.hpp | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/include/boost/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/detail/sp_counted_base_gcc_ia64.hpp index efcfd11..7f4bd25 100644 --- a/include/boost/detail/sp_counted_base_gcc_ia64.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ia64.hpp @@ -5,7 +5,7 @@ // detail/sp_counted_base_gcc_ia64.hpp - g++ on IA64 // // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. -// Copyright 2004-2005 Peter Dimov +// Copyright 2004-2006 Peter Dimov // Copyright 2005 Ben Hutchings // // Distributed under the Boost Software License, Version 1.0. (See @@ -24,55 +24,55 @@ namespace boost namespace detail { -inline void atomic_increment( long * pw ) +inline void atomic_increment( int * pw ) { // ++*pw; - long tmp; + int tmp; // No barrier is required here but fetchadd always has an acquire or // release barrier associated with it. We choose release as it should be // cheaper. - __asm__ ("fetchadd8.rel %0=[%2],1" : + __asm__ ("fetchadd4.rel %0=%1,1" : "=r"(tmp), "=m"(*pw) : - "r"(pw), "m"( *pw )); + "m"( *pw )); } -inline long atomic_decrement( long * pw ) +inline int atomic_decrement( int * pw ) { // return --*pw; - long rv; + int rv; - __asm__ (" fetchadd8.rel %0=[%2],-1 ;; \n" + __asm__ (" fetchadd4.rel %0=%1,-1 ;; \n" " cmp.eq p7,p0=1,%0 ;; \n" - "(p7) ld8.acq %0=[%2] " : + "(p7) ld4.acq %0=%1 " : "=&r"(rv), "=m"(*pw) : - "r"(pw), "m"( *pw ) : + "m"( *pw ) : "p7"); return rv; } -inline long atomic_conditional_increment( long * pw ) +inline int atomic_conditional_increment( int * pw ) { // if( *pw != 0 ) ++*pw; // return *pw; - long rv, tmp, tmp2; + int rv, tmp, tmp2; - __asm__ ("0: ld8 %0=[%4] ;; \n" + __asm__ ("0: ld4 %0=%3 ;; \n" " cmp.eq p7,p0=0,%0 ;; \n" "(p7) br.cond.spnt 1f \n" " mov ar.ccv=%0 \n" " add %1=1,%0 ;; \n" - " cmpxchg8.acq %2=[%4],%1,ar.ccv ;; \n" + " cmpxchg4.acq %2=%3,%1,ar.ccv ;; \n" " cmp.ne p7,p0=%0,%2 ;; \n" "(p7) br.cond.spnt 0b \n" " mov %0=%1 ;; \n" "1:" : "=&r"(rv), "=&r"(tmp), "=&r"(tmp2), "=m"(*pw) : - "r"(pw), "m"( *pw ) : + "m"( *pw ) : "ar.ccv", "p7"); return rv; @@ -85,8 +85,8 @@ private: sp_counted_base( sp_counted_base const & ); sp_counted_base & operator= ( sp_counted_base const & ); - long use_count_; // #shared - long weak_count_; // #weak + (#shared != 0) + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) public: @@ -146,7 +146,7 @@ public: long use_count() const // nothrow { - return static_cast( use_count_ ); + return static_cast( use_count_ ); // TODO use ld.acq here } }; From 747c9a1d3e8147fe4310b193d368a7855602b078 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 29 Mar 2006 19:19:14 +0000 Subject: [PATCH 002/132] Rvalue auto_ptr constructor is no longer explicit. [SVN r33526] --- include/boost/shared_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index bab848d..46bf69b 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -236,7 +236,7 @@ public: #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) template - explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() + shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() { typename Ap::element_type * tmp = r.get(); pn = boost::detail::shared_count( r ); From 203764eb51ba0bfb0ac3ea96d23c9e9dc566bc12 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 19 Apr 2006 21:03:18 +0000 Subject: [PATCH 003/132] Fix VC6 codegen issue (Alain Cormier) [SVN r33747] --- include/boost/detail/sp_counted_base_w32.hpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/boost/detail/sp_counted_base_w32.hpp b/include/boost/detail/sp_counted_base_w32.hpp index e84f06e..fb42c4e 100644 --- a/include/boost/detail/sp_counted_base_w32.hpp +++ b/include/boost/detail/sp_counted_base_w32.hpp @@ -25,6 +25,7 @@ // #include +#include #include namespace boost @@ -78,7 +79,19 @@ public: { long tmp = static_cast< long const volatile& >( use_count_ ); if( tmp == 0 ) return false; + +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1200 ) + + // work around a code generation bug + + long tmp2 = tmp + 1; + if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true; + +#else + if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true; + +#endif } } From 4fcee64483d3934311346d3bf5b6bcdb655cdbbd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 May 2006 22:39:34 +0000 Subject: [PATCH 004/132] New, improved and more portable unspecified bool type. I hope. [SVN r33987] --- include/boost/shared_ptr.hpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 46bf69b..7f239b6 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -323,6 +323,8 @@ public: // implicit conversion to "bool" +/* + #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) operator bool () const @@ -330,6 +332,23 @@ public: return px != 0; } +#elif defined( _MANAGED ) + +*/ + + static void unspecified_bool( this_type*** ) + { + } + + typedef void (*unspecified_bool_type)( this_type*** ); + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: unspecified_bool; + } + +/* + #elif \ ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) @@ -352,6 +371,8 @@ public: #endif +*/ + // operator! is redundant, but some compilers need it bool operator! () const // never throws From ffd73c39b37af92071ae2da806a26eadb37d0e76 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 3 Jul 2006 10:02:46 +0000 Subject: [PATCH 005/132] Solaris implementation by Michael van der Westhuizen [SVN r34450] --- include/boost/detail/atomic_count_solaris.hpp | 59 +++++++++ .../boost/detail/sp_counted_base_solaris.hpp | 113 ++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 include/boost/detail/atomic_count_solaris.hpp create mode 100644 include/boost/detail/sp_counted_base_solaris.hpp 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/sp_counted_base_solaris.hpp b/include/boost/detail/sp_counted_base_solaris.hpp new file mode 100644 index 0000000..c23e2e3 --- /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 +#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( std::type_info 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 From 8d2f7fc5efa90421e1e7351e5d19ba56342ee6ea Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 8 Jul 2006 17:44:55 +0000 Subject: [PATCH 006/132] g++/SPARC version by Piotr Wyderski, thanks to Tomas Puverle and Michael van der Westhuizen [SVN r34480] --- include/boost/detail/sp_counted_base.hpp | 6 +- .../detail/sp_counted_base_gcc_sparc.hpp | 166 ++++++++++++++++++ 2 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 include/boost/detail/sp_counted_base_gcc_sparc.hpp diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index bc170ca..d64f239 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 @@ -47,6 +47,10 @@ # 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_gcc_sparc.hpp b/include/boost/detail/sp_counted_base_gcc_sparc.hpp new file mode 100644 index 0000000..dd606f0 --- /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 +#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( std::type_info 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 From 6412de1dd57d5e4bed192ec43b7f6d76b3c0a92a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 10 Jul 2006 13:17:41 +0000 Subject: [PATCH 007/132] TR1 cyclic dependency fixes. [SVN r34499] --- include/boost/shared_array.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index 9216e89..eb69c8e 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -20,6 +20,8 @@ #include #else +#include // TR1 cyclic inclusion fix + #include #include From 39551bdc1a62f9aaca0bbd95e86aa0fd9dd7638a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 11 Jul 2006 23:17:17 +0000 Subject: [PATCH 008/132] A negative test for p > q added. [SVN r34509] --- test/Jamfile | 4 ++-- test/Jamfile.v2 | 1 + test/shared_ptr_compare_fail.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 test/shared_ptr_compare_fail.cpp diff --git a/test/Jamfile b/test/Jamfile index 2bd285c..f2491a8 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -1,6 +1,6 @@ # Boost.SmartPtr Library test Jamfile # -# Copyright (c) 2003-2005 Peter Dimov +# Copyright (c) 2003-2006 Peter Dimov # Copyright (c) 2003 Dave Abrahams # # Permission to copy, use, modify, sell and distribute this software @@ -25,11 +25,11 @@ DEPENDS all : smart_ptr ; [ run shared_from_this_test.cpp : : : <*>-Wno-non-virtual-dtor ] [ run get_deleter_test.cpp ] [ run intrusive_ptr_test.cpp ] - [ run intrusive_ptr_test.cpp ] [ run atomic_count_test.cpp ] [ run lw_mutex_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] [ compile-fail shared_ptr_delete_fail.cpp ] + [ compile-fail shared_ptr_compare_fail.cpp ] [ run shared_ptr_alloc2_test.cpp ] [ run pointer_cast_test.cpp ] [ compile pointer_to_other_test.cpp ] diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0dd4e11..5e950fd 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -24,6 +24,7 @@ import testing ; [ run lw_mutex_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] [ compile-fail shared_ptr_delete_fail.cpp ] + [ compile-fail shared_ptr_compare_fail.cpp ] [ run shared_ptr_alloc2_test.cpp ] [ run pointer_cast_test.cpp ] [ compile pointer_to_other_test.cpp ] diff --git a/test/shared_ptr_compare_fail.cpp b/test/shared_ptr_compare_fail.cpp new file mode 100644 index 0000000..296af14 --- /dev/null +++ b/test/shared_ptr_compare_fail.cpp @@ -0,0 +1,27 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// shared_ptr_compare_fail.cpp - a negative test for "p > q" +// +// Copyright 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) +// + +#include + +int main() +{ + boost::shared_ptr p, q; + p > q; // must fail + return 0; +} From 75bc821afdce2f4a94c78c489e3204a2e9c27074 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 6 Nov 2006 17:25:59 +0000 Subject: [PATCH 009/132] Patch #1551992 (Michael Fink) [SVN r35882] --- include/boost/intrusive_ptr.hpp | 7 ++++++- include/boost/shared_ptr.hpp | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index b03b901..cd1ac11 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -249,6 +249,9 @@ template std::ostream & operator<< (std::ostream & os, intrusive_ptr #else +// in STLport's no-iostreams mode no iostream symbols can be used +#ifndef _STLP_NO_IOSTREAMS + # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL using std::basic_ostream; @@ -261,7 +264,9 @@ template std::basic_ostream & operator<< (std:: return os; } -#endif +#endif // _STLP_NO_IOSTREAMS + +#endif // __GNUC__ < 3 } // namespace boost diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 7f239b6..688d58f 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -512,6 +512,9 @@ template std::ostream & operator<< (std::ostream & os, shared_ptr co #else +// in STLport's no-iostreams mode no iostream symbols can be used +#ifndef _STLP_NO_IOSTREAMS + # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL using std::basic_ostream; @@ -524,7 +527,9 @@ template std::basic_ostream & operator<< (std:: return os; } -#endif +#endif // _STLP_NO_IOSTREAMS + +#endif // __GNUC__ < 3 // get_deleter (experimental) From 41d4167533beed73b28cf3695c0cfbb0b75772de Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Tue, 7 Nov 2006 19:11:57 +0000 Subject: [PATCH 010/132] Add copyright, license [SVN r35905] --- index.html | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index e2e191f..b6b39a0 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,11 @@ Automatic redirection failed, please go to -smart_ptr.htm. +smart_ptr.htm
+

© Copyright Beman Dawes, 2001

+

Distributed under the Boost Software License, Version 1.0. (See accompanying +file LICENSE_1_0.txt or copy +at www.boost.org/LICENSE_1_0.txt) +

- + \ No newline at end of file From 6284a1abef4c61aca70e4e3503a518d52104dd00 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 9 Nov 2006 12:15:23 +0000 Subject: [PATCH 011/132] TR1 conformance fix [SVN r35948] --- include/boost/detail/bad_weak_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/bad_weak_ptr.hpp b/include/boost/detail/bad_weak_ptr.hpp index a08d7b1..93ecec9 100644 --- a/include/boost/detail/bad_weak_ptr.hpp +++ b/include/boost/detail/bad_weak_ptr.hpp @@ -42,7 +42,7 @@ public: virtual char const * what() const throw() { - return "boost::bad_weak_ptr"; + return "tr1::bad_weak_ptr"; } }; From b215e34650ca1691ab4b6d01f1e4cc915515bafe Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 9 Nov 2006 20:17:14 +0000 Subject: [PATCH 012/132] License/copyright edits [SVN r35956] --- enable_shared_from_this.html | 7 +++---- intrusive_ptr.html | 7 +++---- sp_techniques.html | 7 +++---- test/Jamfile | 7 +++---- test/Jamfile.v2 | 7 +++---- 5 files changed, 15 insertions(+), 20 deletions(-) diff --git a/enable_shared_from_this.html b/enable_shared_from_this.html index 166870f..3f35665 100644 --- a/enable_shared_from_this.html +++ b/enable_shared_from_this.html @@ -84,9 +84,8 @@ public:


- Copyright © 2002, 2003 by Peter Dimov. Permission to copy, use, modify, sell - and distribute this document is granted provided this copyright notice appears - in all copies. This document is provided "as is" without express or implied - warranty, and with no claim as to its suitability for any purpose.

+ Copyright © 2002, 2003 by 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.

diff --git a/intrusive_ptr.html b/intrusive_ptr.html index b07be5c..24d8c32 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -278,9 +278,8 @@ intrusive_ptr & operator=(T * r);

$Date$

- Copyright © 2003-2005 Peter Dimov. Permission to copy, use, modify, sell and - distribute this document is granted provided this copyright notice appears in - all copies. This document is provided "as is" without express or implied - warranty, and with no claim as to its suitability for any purpose.

+ Copyright © 2003-2005 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.

diff --git a/sp_techniques.html b/sp_techniques.html index e046275..4b7363b 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -758,9 +758,8 @@ public: all weak pointers will automatically expire.


$Date$

-

Copyright © 2003 Peter Dimov. Permission to copy, use, modify, sell and - distribute this document is granted provided this copyright notice appears in - all copies. This document is provided "as is" without express or implied - warranty, and with no claim as to its suitability for any purpose.

+

Copyright © 2003 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.

diff --git a/test/Jamfile b/test/Jamfile index f2491a8..efc07c3 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -3,10 +3,9 @@ # Copyright (c) 2003-2006 Peter Dimov # Copyright (c) 2003 Dave Abrahams # -# Permission to copy, use, modify, sell and distribute this software -# is granted provided this copyright notice appears in all copies. -# This software is provided "as is" without express or implied -# warranty, and with no claim as to its suitability for any purpose. +# 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) subproject libs/smart_ptr/test ; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5e950fd..55ee95e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -3,10 +3,9 @@ # Copyright (c) 2003-2005 Peter Dimov # Copyright (c) 2003 Dave Abrahams # -# Permission to copy, use, modify, sell and distribute this software -# is granted provided this copyright notice appears in all copies. -# This software is provided "as is" without express or implied -# warranty, and with no claim as to its suitability for any purpose. +# 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) # bring in rules for testing import testing ; From 0609322489d8f473dc387d7a2b0c1201e9359ddd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 9 Nov 2006 20:24:23 +0000 Subject: [PATCH 013/132] License/copyright edits [SVN r35957] --- index.html | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/index.html b/index.html index b6b39a0..c7f709c 100644 --- a/index.html +++ b/index.html @@ -4,11 +4,12 @@ Automatic redirection failed, please go to -smart_ptr.htm
-

© Copyright Beman Dawes, 2001

-

Distributed under the Boost Software License, Version 1.0. (See accompanying -file LICENSE_1_0.txt or copy -at www.boost.org/LICENSE_1_0.txt) -

+smart_ptr.htm. - \ No newline at end of file + + From b440e8545274cad1f12701a33aff4f3ff4a59a98 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 1 Dec 2006 14:24:58 +0000 Subject: [PATCH 014/132] Fixed get_deleter comment [SVN r36229] --- include/boost/shared_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 688d58f..6391b56 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -531,7 +531,7 @@ template std::basic_ostream & operator<< (std:: #endif // __GNUC__ < 3 -// get_deleter (experimental) +// get_deleter #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ From 1c3813ce52b1a605d23c8e0e4a31e47e2291a21f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 10 Dec 2006 21:01:55 +0000 Subject: [PATCH 015/132] BOOST_ASSERTs added (SF patch 1612733 by 'Baraclese') [SVN r36316] --- include/boost/intrusive_ptr.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index cd1ac11..95cca04 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -112,11 +112,13 @@ public: T & operator*() const { + BOOST_ASSERT( p_ != 0 ); return *p_; } T * operator->() const { + BOOST_ASSERT( p_ != 0 ); return p_; } From 97118668e2d71655f2f08b596715c549d8506f44 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 6 Apr 2007 00:21:41 +0000 Subject: [PATCH 016/132] Fix compare_fail failure [SVN r37373] --- include/boost/shared_ptr.hpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 6391b56..78128e6 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -323,8 +323,6 @@ public: // implicit conversion to "bool" -/* - #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) operator bool () const @@ -334,8 +332,6 @@ public: #elif defined( _MANAGED ) -*/ - static void unspecified_bool( this_type*** ) { } @@ -347,8 +343,6 @@ public: return px == 0? 0: unspecified_bool; } -/* - #elif \ ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) @@ -371,8 +365,6 @@ public: #endif -*/ - // operator! is redundant, but some compilers need it bool operator! () const // never throws From 469578e97686f7c89a977ee8fedf5514474d614b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 6 Apr 2007 00:23:17 +0000 Subject: [PATCH 017/132] Fix C++0x ambiguity between boost::shared_ptr and std::shared_ptr [SVN r37374] --- test/smart_ptr_test.cpp | 56 ++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp index 27cba2b..d38c97b 100644 --- a/test/smart_ptr_test.cpp +++ b/test/smart_ptr_test.cpp @@ -51,12 +51,6 @@ Incomplete * get_ptr( boost::shared_ptr& incomplete ) return incomplete.get(); } -using namespace std; -using boost::scoped_ptr; -using boost::scoped_array; -using boost::shared_ptr; -using boost::shared_array; - template void ck( const T* v1, T v2 ) { BOOST_TEST( *v1 == v2 ); } @@ -72,7 +66,7 @@ class UDT { explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; } ~UDT() { --UDT_use_count; - cout << "UDT with value " << value_ << " being destroyed\n"; + std::cout << "UDT with value " << value_ << " being destroyed\n"; } long value() const { return value_; } void value( long v ) { value_ = v;; } @@ -86,16 +80,16 @@ class UDT { class Incomplete; -Incomplete * check_incomplete( scoped_ptr& incomplete ) +Incomplete * check_incomplete( boost::scoped_ptr& incomplete ) { return incomplete.get(); } -Incomplete * check_incomplete( shared_ptr& incomplete, - shared_ptr& i2 ) +Incomplete * check_incomplete( boost::shared_ptr& incomplete, + boost::shared_ptr& i2 ) { incomplete.swap(i2); - cout << incomplete.use_count() << ' ' << incomplete.unique() << '\n'; + std::cout << incomplete.use_count() << ' ' << incomplete.unique() << '\n'; return incomplete.get(); } @@ -107,7 +101,7 @@ void test() // test scoped_ptr with a built-in type long * lp = new long; - scoped_ptr sp ( lp ); + boost::scoped_ptr sp ( lp ); BOOST_TEST( sp.get() == lp ); BOOST_TEST( lp == sp.get() ); BOOST_TEST( &*sp == lp ); @@ -122,7 +116,7 @@ void test() BOOST_TEST( sp.get() == 0 ); // test scoped_ptr with a user defined type - scoped_ptr udt_sp ( new UDT( 999888777 ) ); + boost::scoped_ptr udt_sp ( new UDT( 999888777 ) ); BOOST_TEST( udt_sp->value() == 999888777 ); udt_sp.reset(); udt_sp.reset( new UDT( 111222333 ) ); @@ -132,7 +126,7 @@ void test() // test scoped_array with a build-in type char * sap = new char [ 100 ]; - scoped_array sa ( sap ); + boost::scoped_array sa ( sap ); BOOST_TEST( sa.get() == sap ); BOOST_TEST( sap == sa.get() ); @@ -152,7 +146,7 @@ void test() // test shared_ptr with a built-in type int * ip = new int; - shared_ptr cp ( ip ); + boost::shared_ptr cp ( ip ); BOOST_TEST( ip == cp.get() ); BOOST_TEST( cp.use_count() == 1 ); @@ -162,7 +156,7 @@ void test() ck( static_cast(cp.get()), 54321 ); ck( static_cast(ip), *cp ); - shared_ptr cp2 ( cp ); + boost::shared_ptr cp2 ( cp ); BOOST_TEST( ip == cp2.get() ); BOOST_TEST( cp.use_count() == 2 ); BOOST_TEST( cp2.use_count() == 2 ); @@ -172,7 +166,7 @@ void test() ck( static_cast(cp2.get()), 54321 ); ck( static_cast(ip), *cp2 ); - shared_ptr cp3 ( cp ); + boost::shared_ptr cp3 ( cp ); BOOST_TEST( cp.use_count() == 3 ); BOOST_TEST( cp2.use_count() == 3 ); BOOST_TEST( cp3.use_count() == 3 ); @@ -202,20 +196,20 @@ void test() BOOST_TEST( cp.use_count() == 3 ); BOOST_TEST( *cp == 87654 ); - shared_ptr cp4; + boost::shared_ptr cp4; swap( cp2, cp4 ); BOOST_TEST( cp4.use_count() == 3 ); BOOST_TEST( *cp4 == 87654 ); BOOST_TEST( cp2.get() == 0 ); - set< shared_ptr > scp; + std::set< boost::shared_ptr > scp; scp.insert(cp4); BOOST_TEST( scp.find(cp4) != scp.end() ); - BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr(cp4) ) ); + BOOST_TEST( scp.find(cp4) == scp.find( boost::shared_ptr(cp4) ) ); // test shared_array with a built-in type char * cap = new char [ 100 ]; - shared_array ca ( cap ); + boost::shared_array ca ( cap ); BOOST_TEST( ca.get() == cap ); BOOST_TEST( cap == ca.get() ); BOOST_TEST( &ca[0] == cap ); @@ -227,8 +221,8 @@ void test() BOOST_TEST( ca[0] == 'H' ); BOOST_TEST( ca[30] == 'h' ); - shared_array ca2 ( ca ); - shared_array ca3 ( ca2 ); + boost::shared_array ca2 ( ca ); + boost::shared_array ca3 ( ca2 ); ca[0] = 'N'; ca[4] = 'd'; @@ -246,24 +240,24 @@ void test() ca.reset(); BOOST_TEST( ca.get() == 0 ); - shared_array ca4; + boost::shared_array ca4; swap( ca3, ca4 ); BOOST_TEST( ca4.use_count() == 1 ); BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); BOOST_TEST( ca3.get() == 0 ); - set< shared_array > sca; + std::set< boost::shared_array > sca; sca.insert(ca4); BOOST_TEST( sca.find(ca4) != sca.end() ); - BOOST_TEST( sca.find(ca4) == sca.find( shared_array(ca4) ) ); + BOOST_TEST( sca.find(ca4) == sca.find( boost::shared_array(ca4) ) ); // test shared_array with user defined type - shared_array udta ( new UDT[3] ); + boost::shared_array udta ( new UDT[3] ); udta[0].value( 111 ); udta[1].value( 222 ); udta[2].value( 333 ); - shared_array udta2 ( udta ); + boost::shared_array udta2 ( udta ); BOOST_TEST( udta[0].value() == 111 ); BOOST_TEST( udta[1].value() == 222 ); @@ -280,7 +274,7 @@ void test() // test shared_ptr with a user defined type UDT * up = new UDT; - shared_ptr sup ( up ); + boost::shared_ptr sup ( up ); BOOST_TEST( up == sup.get() ); BOOST_TEST( sup.use_count() == 1 ); @@ -288,7 +282,7 @@ void test() BOOST_TEST( sup->value() == 54321 ); BOOST_TEST( up->value() == 54321 ); - shared_ptr sup2; + boost::shared_ptr sup2; sup2 = sup; BOOST_TEST( sup2->value() == 54321 ); BOOST_TEST( sup.use_count() == 2 ); @@ -298,7 +292,7 @@ void test() BOOST_TEST( sup.use_count() == 2 ); BOOST_TEST( sup2.use_count() == 2 ); - cout << "OK\n"; + std::cout << "OK\n"; new char[12345]; // deliberate memory leak to verify leaks detected } From 54e12d03fdfec63b4d8ff41991c4e64af6b1b4b4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 9 Apr 2007 16:32:45 +0000 Subject: [PATCH 018/132] Aliasing constructor added [SVN r37402] --- include/boost/shared_ptr.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 78128e6..639066e 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -5,7 +5,7 @@ // shared_ptr.hpp // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. -// Copyright (c) 2001-2006 Peter Dimov +// Copyright (c) 2001-2007 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -195,6 +195,12 @@ public: { } + // aliasing + template< class Y > + shared_ptr( shared_ptr const & r, T * p ): px( p ), pn( r.pn ) // never throws + { + } + template shared_ptr(shared_ptr const & r, boost::detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) { From ae6c180be84b59dd8b192f8b7f55668353427e01 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 9 Apr 2007 16:37:30 +0000 Subject: [PATCH 019/132] _MANAGED fix for sp_enable_shared_from_this [SVN r37403] --- include/boost/shared_ptr.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 639066e..69bff58 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -88,6 +88,21 @@ template void sp_enable_shared_from_this( shared_count const & if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); } +#ifdef _MANAGED + +// Avoid C4793, ... causes native code generation + +struct sp_any_pointer +{ + template sp_any_pointer( T* ) {} +}; + +inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer ) +{ +} + +#else // _MANAGED + #ifdef sgi // Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed # pragma set woff 3506 @@ -101,6 +116,8 @@ inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) # pragma reset woff 3506 #endif +#endif // _MANAGED + #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) // rvalue auto_ptr support based on a technique by Dave Abrahams From 6e8f075d429f6682363e6bcdf6f8509242f5c1a2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 9 Apr 2007 18:42:49 +0000 Subject: [PATCH 020/132] make_shared removed [SVN r37404] --- include/boost/weak_ptr.hpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 8f4230f..ae606f2 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -179,12 +179,6 @@ template void swap(weak_ptr & a, weak_ptr & b) a.swap(b); } -// deprecated, provided for backward compatibility -template shared_ptr make_shared(weak_ptr const & r) -{ - return r.lock(); -} - } // namespace boost #ifdef BOOST_MSVC From ce72827dc73ac652ed07002b75f32e0171119c09 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 9 Apr 2007 18:48:47 +0000 Subject: [PATCH 021/132] Aliasing support [SVN r37405] --- include/boost/shared_ptr.hpp | 5 ++ shared_ptr.htm | 13 +++ test/Jamfile | 1 + test/Jamfile.v2 | 1 + test/shared_ptr_alias_test.cpp | 146 +++++++++++++++++++++++++++++++++ 5 files changed, 166 insertions(+) create mode 100644 test/shared_ptr_alias_test.cpp diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 69bff58..b6bf44c 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -327,6 +327,11 @@ public: this_type( p, d, a ).swap( *this ); } + template void reset( shared_ptr const & r, T * p ) + { + this_type( r, p ).swap( *this ); + } + reference operator* () const // never throws { BOOST_ASSERT(px != 0); diff --git a/shared_ptr.htm b/shared_ptr.htm index 71cb9c9..e2626fc 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -111,6 +111,7 @@ void bad() shared_ptr(shared_ptr const & r); // never throws template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws + template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p); // never throws template<class Y> explicit shared_ptr(weak_ptr<Y> const & r); template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r); @@ -122,6 +123,7 @@ void bad() template<class Y> void reset(Y * p); template<class Y, class D> void reset(Y * p, D d); template<class Y, class D, class A> void reset(Y * p, D d, A a); + template<class Y> void reset(shared_ptr<Y> const & r, T * p); // never throws T & operator*() const; // never throws T * operator->() const; // never throws @@ -253,6 +255,13 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r); // never r.use_count().

Throws: nothing.

+
template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p); // never throws
+
+

Effects: constructs a shared_ptr that shares ownership with + r and stores p.

+

Postconditions: get() == p && use_count() == r.use_count().

+

Throws: nothing.

+
template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);

Effects: Constructs a shared_ptr that shares ownership with @@ -328,6 +337,10 @@ q = p;

Effects: Equivalent to shared_ptr(p, d, a).swap(*this).

+
template<class Y> void reset(shared_ptr<Y> const & r, T * p); // never throws
+
+

Effects: Equivalent to shared_ptr(r, p).swap(*this).

+

indirection

T & operator*() const; // never throws
diff --git a/test/Jamfile b/test/Jamfile index efc07c3..a28d75d 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -33,6 +33,7 @@ DEPENDS all : smart_ptr ; [ run pointer_cast_test.cpp ] [ compile pointer_to_other_test.cpp ] [ run auto_ptr_rv_test.cpp ] + [ run shared_ptr_alias_test.cpp ] ; # this one is too slow to run unless explicitly requested, and ALL diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 55ee95e..63708b7 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -28,5 +28,6 @@ import testing ; [ run pointer_cast_test.cpp ] [ compile pointer_to_other_test.cpp ] [ run auto_ptr_rv_test.cpp ] + [ run shared_ptr_alias_test.cpp ] ; } diff --git a/test/shared_ptr_alias_test.cpp b/test/shared_ptr_alias_test.cpp new file mode 100644 index 0000000..83d866f --- /dev/null +++ b/test/shared_ptr_alias_test.cpp @@ -0,0 +1,146 @@ +#include + +// shared_ptr_alias_test.cpp +// +// 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 +#include +#include +#include + +// + +class incomplete; + +struct X +{ + int v_; + + explicit X( int v ): v_( v ) + { + } + + ~X() + { + v_ = 0; + } +}; + +int main() +{ + { + int m = 0; + boost::shared_ptr< int > p; + boost::shared_ptr< int > p2( p, &m ); + + BOOST_TEST( p2.get() == &m ); + BOOST_TEST( p2? true: false ); + BOOST_TEST( !!p2 ); + BOOST_TEST( p2.use_count() == p.use_count() ); + BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); + + p2.reset( p, 0 ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST( p2? false: true ); + BOOST_TEST( !p2 ); + BOOST_TEST( p2.use_count() == p.use_count() ); + BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); + } + + { + int m = 0; + boost::shared_ptr< int > p( new int ); + boost::shared_ptr< int const > p2( p, &m ); + + BOOST_TEST( p2.get() == &m ); + BOOST_TEST( p2? true: false ); + BOOST_TEST( !!p2 ); + BOOST_TEST( p2.use_count() == p.use_count() ); + BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); + + boost::shared_ptr< int volatile > p3; + p2.reset( p3, 0 ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST( p2? false: true ); + BOOST_TEST( !p2 ); + BOOST_TEST( p2.use_count() == p3.use_count() ); + BOOST_TEST( !( p3 < p2 ) && !( p2 < p3 ) ); + } + + { + boost::shared_ptr< int > p( new int ); + boost::shared_ptr< void const > p2( p, 0 ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST( p2? false: true ); + BOOST_TEST( !p2 ); + BOOST_TEST( p2.use_count() == p.use_count() ); + BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); + + int m = 0; + boost::shared_ptr< void volatile > p3; + + p2.reset( p3, &m ); + + BOOST_TEST( p2.get() == &m ); + BOOST_TEST( p2? true: false ); + BOOST_TEST( !!p2 ); + BOOST_TEST( p2.use_count() == p3.use_count() ); + BOOST_TEST( !( p3 < p2 ) && !( p2 < p3 ) ); + } + + { + boost::shared_ptr< incomplete > p; + boost::shared_ptr< incomplete > p2( p, 0 ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST( p2? false: true ); + BOOST_TEST( !p2 ); + BOOST_TEST( p2.use_count() == p.use_count() ); + BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); + + p2.reset( p, 0 ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST( p2? false: true ); + BOOST_TEST( !p2 ); + BOOST_TEST( p2.use_count() == p.use_count() ); + BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); + } + + { + boost::shared_ptr< X > p( new X( 5 ) ); + boost::shared_ptr< int const > p2( p, &p->v_ ); + + BOOST_TEST( p2.get() == &p->v_ ); + BOOST_TEST( p2? true: false ); + BOOST_TEST( !!p2 ); + BOOST_TEST( p2.use_count() == p.use_count() ); + BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); + + p.reset(); + BOOST_TEST( *p2 == 5 ); + + boost::shared_ptr< X const > p3( new X( 8 ) ); + p2.reset( p3, &p3->v_ ); + + BOOST_TEST( p2.get() == &p3->v_ ); + BOOST_TEST( p2? true: false ); + BOOST_TEST( !!p2 ); + BOOST_TEST( p2.use_count() == p3.use_count() ); + BOOST_TEST( !( p3 < p2 ) && !( p2 < p3 ) ); + + p3.reset(); + BOOST_TEST( *p2 == 8 ); + } + + return boost::report_errors(); +} From 26f83e75efd86d86a259072987dbfd27df834a57 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 9 Apr 2007 21:35:07 +0000 Subject: [PATCH 022/132] intrusive_ptr::reset added [SVN r37406] --- include/boost/intrusive_ptr.hpp | 5 +++++ intrusive_ptr.html | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 95cca04..c4ec407 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -105,6 +105,11 @@ public: return *this; } + void reset( T * rhs ) + { + this_type( rhs ).swap( *this ); + } + T * get() const { return p_; diff --git a/intrusive_ptr.html b/intrusive_ptr.html index 24d8c32..c4eb899 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -61,7 +61,8 @@ intrusive_ptr & operator=(intrusive_ptr const & r); template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r); - template<class Y> intrusive_ptr & operator=(T * r); + intrusive_ptr & operator=(T * r); + void reset(T * r); T & operator*() const; // never throws T * operator->() const; // never throws @@ -146,6 +147,11 @@ intrusive_ptr & operator=(T * r);

Effects: Equivalent to intrusive_ptr(r).swap(*this).

Returns: *this.

+

reset

+
void reset(T * r);
+
+

Effects: Equivalent to intrusive_ptr(r).swap(*this).

+

indirection

T & operator*() const; // never throws
From 745dbedbaa233486da8c89819cd2297d98084a16 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 9 Apr 2007 22:24:37 +0000 Subject: [PATCH 023/132] Fix CW regression re strcmp, strcpy [SVN r37407] --- test/smart_ptr_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp index d38c97b..0c29c9c 100644 --- a/test/smart_ptr_test.cpp +++ b/test/smart_ptr_test.cpp @@ -40,9 +40,9 @@ #include -#include #include #include +#include class Incomplete; From 66a25bd4a953717e19c9f6598645f9a434e1b029 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 13 Apr 2007 22:04:22 +0000 Subject: [PATCH 024/132] Move support [SVN r37434] --- include/boost/shared_ptr.hpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index b6bf44c..b8072ba 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -306,6 +306,38 @@ public: #endif // BOOST_NO_AUTO_PTR +// Move support + +#if defined( BOOST_HAS_RVALUE_REFS ) + + shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws + { + pn.swap( r.pn ); + } + + template + shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws + { + pn.swap( r.pn ); + } + + shared_ptr & operator=( shared_ptr && r ) // never throws + { + px = r.px; + pn.swap( r.pn ); + return *this; + } + + template + shared_ptr & operator=( shared_ptr && r ) // never throws + { + px = r.px; + pn.swap( r.pn ); + return *this; + } + +#endif + void reset() // never throws in 1.30+ { this_type().swap(*this); From 86d3f0aba7a094ab62a13da442cdd2ca13bd7623 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 15 Apr 2007 02:47:45 +0000 Subject: [PATCH 025/132] Changed move constructors/assignments to leave the source empty [SVN r37439] --- include/boost/shared_ptr.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index b8072ba..ec38248 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -313,26 +313,26 @@ public: shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws { pn.swap( r.pn ); + r.px = 0; } template shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws { pn.swap( r.pn ); + r.px = 0; } shared_ptr & operator=( shared_ptr && r ) // never throws { - px = r.px; - pn.swap( r.pn ); + this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); return *this; } template shared_ptr & operator=( shared_ptr && r ) // never throws { - px = r.px; - pn.swap( r.pn ); + this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); return *this; } From 4d45e5b9b527c8ac3a9e8566dd671848eb276829 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 28 Apr 2007 15:49:13 +0000 Subject: [PATCH 026/132] Move tests added [SVN r37526] --- test/Jamfile | 4 +- test/Jamfile.v2 | 4 +- test/shared_ptr_move_test.cpp | 95 +++++++++++++++++++++++++++++ test/shared_ptr_rv_test.cpp | 110 ++++++++++++++++++++++++++++++++++ 4 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 test/shared_ptr_move_test.cpp create mode 100644 test/shared_ptr_rv_test.cpp diff --git a/test/Jamfile b/test/Jamfile index a28d75d..a1db7b7 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -1,6 +1,6 @@ # Boost.SmartPtr Library test Jamfile # -# Copyright (c) 2003-2006 Peter Dimov +# Copyright (c) 2003-2007 Peter Dimov # Copyright (c) 2003 Dave Abrahams # # Distributed under the Boost Software License, Version 1.0. (See @@ -34,6 +34,8 @@ DEPENDS all : smart_ptr ; [ compile pointer_to_other_test.cpp ] [ run auto_ptr_rv_test.cpp ] [ run shared_ptr_alias_test.cpp ] + [ run shared_ptr_rv_test.cpp ] + [ run shared_ptr_move_test.cpp ] ; # this one is too slow to run unless explicitly requested, and ALL diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 63708b7..2d96a46 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,6 +1,6 @@ # Boost.SmartPtr Library test Jamfile # -# Copyright (c) 2003-2005 Peter Dimov +# Copyright (c) 2003-2007 Peter Dimov # Copyright (c) 2003 Dave Abrahams # # Distributed under the Boost Software License, Version 1.0. (See @@ -29,5 +29,7 @@ import testing ; [ compile pointer_to_other_test.cpp ] [ run auto_ptr_rv_test.cpp ] [ run shared_ptr_alias_test.cpp ] + [ run shared_ptr_rv_test.cpp ] + [ run shared_ptr_move_test.cpp ] ; } diff --git a/test/shared_ptr_move_test.cpp b/test/shared_ptr_move_test.cpp new file mode 100644 index 0000000..8814d3d --- /dev/null +++ b/test/shared_ptr_move_test.cpp @@ -0,0 +1,95 @@ +// +// shared_ptr_move_test.cpp +// +// 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 +#include + +struct X +{ + static long instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const & ); + X & operator=( X const & ); +}; + +long X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( new X ); + BOOST_TEST( X::instances == 1 ); + + boost::shared_ptr p2( static_cast< boost::shared_ptr && >( p ) ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + boost::shared_ptr p3( static_cast< boost::shared_ptr && >( p2 ) ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p2.get() == 0 ); + + p3.reset(); + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr p( new X ); + BOOST_TEST( X::instances == 1 ); + + boost::shared_ptr p2; + p2 = static_cast< boost::shared_ptr && >( p ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + boost::shared_ptr p3; + p3 = static_cast< boost::shared_ptr && >( p2 ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p2.get() == 0 ); + + p3.reset(); + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr p( new X ); + BOOST_TEST( X::instances == 1 ); + + boost::shared_ptr p2( new X ); + BOOST_TEST( X::instances == 2 ); + p2 = static_cast< boost::shared_ptr && >( p ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + boost::shared_ptr p3( new X ); + BOOST_TEST( X::instances == 2 ); + p3 = static_cast< boost::shared_ptr && >( p2 ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p2.get() == 0 ); + + p3.reset(); + BOOST_TEST( X::instances == 0 ); + } + + return boost::report_errors(); +} diff --git a/test/shared_ptr_rv_test.cpp b/test/shared_ptr_rv_test.cpp new file mode 100644 index 0000000..fe77259 --- /dev/null +++ b/test/shared_ptr_rv_test.cpp @@ -0,0 +1,110 @@ +// +// shared_ptr_rv_test.cpp +// +// 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 +#include + +struct X +{ + static long instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + + static boost::shared_ptr create() + { + return boost::shared_ptr( new X ); + } + +private: + + X( X const & ); + X & operator=( X const & ); +}; + +long X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +} From ffba68221b86c8ed1b668099dbff86d7f414b57f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 28 Apr 2007 16:15:13 +0000 Subject: [PATCH 027/132] Use __sync intrinsics on g++ 4.1+ [SVN r37527] --- include/boost/detail/atomic_count.hpp | 2 + include/boost/detail/atomic_count_sync.hpp | 57 ++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 include/boost/detail/atomic_count_sync.hpp diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 9985b2c..823b929 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -93,6 +93,8 @@ typedef long atomic_count; # 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) 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 From f980da560a7b37d4e1dcc08284650a4577cfde22 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 28 Apr 2007 18:13:12 +0000 Subject: [PATCH 028/132] Use __sync intrinsics on g++ 4.1+ [SVN r37528] --- include/boost/detail/sp_counted_base.hpp | 4 + include/boost/detail/sp_counted_base_sync.hpp | 151 ++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 include/boost/detail/sp_counted_base_sync.hpp diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index d64f239..e9d6ac9 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -47,6 +47,10 @@ # include +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + +# include + #elif defined(__GNUC__) && ( defined( __sparcv8 ) || defined( __sparcv9 ) ) # include 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..5aaa917 --- /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 +#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( std::type_info 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 From 5b57eff9b880698022432c1916cf6c852844734a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 8 May 2007 20:14:38 +0000 Subject: [PATCH 029/132] atomic_count_gcc_x86 added since _sync doesn't work on i386 [SVN r37637] --- include/boost/detail/atomic_count.hpp | 14 ++++ include/boost/detail/atomic_count_gcc_x86.hpp | 84 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 include/boost/detail/atomic_count_gcc_x86.hpp diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 823b929..804fd1a 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -90,16 +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_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 From 4ba37fce955295fc163e651134b9aad38d95446c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 23 May 2007 23:22:45 +0000 Subject: [PATCH 030/132] Negative test for conversion to void* [SVN r37756] --- test/Jamfile | 1 + test/Jamfile.v2 | 1 + test/shared_ptr_pv_fail.cpp | 31 +++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 test/shared_ptr_pv_fail.cpp diff --git a/test/Jamfile b/test/Jamfile index a1db7b7..b3fcac9 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -36,6 +36,7 @@ DEPENDS all : smart_ptr ; [ run shared_ptr_alias_test.cpp ] [ run shared_ptr_rv_test.cpp ] [ run shared_ptr_move_test.cpp ] + [ compile-fail shared_ptr_pv_fail.cpp ] ; # this one is too slow to run unless explicitly requested, and ALL diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 2d96a46..b980bfc 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -31,5 +31,6 @@ import testing ; [ run shared_ptr_alias_test.cpp ] [ run shared_ptr_rv_test.cpp ] [ run shared_ptr_move_test.cpp ] + [ compile-fail shared_ptr_pv_fail.cpp ] ; } diff --git a/test/shared_ptr_pv_fail.cpp b/test/shared_ptr_pv_fail.cpp new file mode 100644 index 0000000..924e657 --- /dev/null +++ b/test/shared_ptr_pv_fail.cpp @@ -0,0 +1,31 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// shared_ptr_pv_fail.cpp - a negative test for converting a shared_ptr to void* +// +// 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 + +void f( void* ) +{ +} + +int main() +{ + boost::shared_ptr p; + f( p ); // must fail + return 0; +} From ed8db8b5f20b48386a3637200b1de35d91f04bb8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 6 Jun 2007 16:39:52 +0000 Subject: [PATCH 031/132] Switched to BSL, Darin Adler has given blanket permission [SVN r37917] --- compatibility.htm | 7 +++---- scoped_array.htm | 9 ++++----- scoped_ptr.htm | 9 ++++----- shared_array.htm | 9 ++++----- shared_ptr.htm | 7 +++---- smart_ptr.htm | 9 ++++----- weak_ptr.htm | 8 +++----- 7 files changed, 25 insertions(+), 33 deletions(-) diff --git a/compatibility.htm b/compatibility.htm index 71662ce..d520bd1 100644 --- a/compatibility.htm +++ b/compatibility.htm @@ -81,9 +81,8 @@

Revised 1 February 2002

-

Copyright 2002 Darin Adler. Permission to copy, use, modify, sell and distribute - this document is granted provided this copyright notice appears in all copies. - This document is provided "as is" without express or implied warranty, and with - no claim as to its suitability for any purpose.

+

Copyright 2002 Darin Adler. 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.

diff --git a/scoped_array.htm b/scoped_array.htm index 93b1cf9..2d03509 100644 --- a/scoped_array.htm +++ b/scoped_array.htm @@ -108,10 +108,9 @@

Revised 09 January 2003

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Permission to copy, use, modify, sell and - distribute this document is granted provided this copyright notice appears in - all copies. This document is provided "as is" without express or implied - warranty, and with no claim as to its suitability for any purpose.

+

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005 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.

diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 1c6458d..fc5785c 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -173,10 +173,9 @@ Buckle my shoe

Revised 09 January 2003

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Permission to copy, use, modify, sell and - distribute this document is granted provided this copyright notice appears in - all copies. This document is provided "as is" without express or implied - warranty, and with no claim as to its suitability for any purpose.

+

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005 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.

diff --git a/shared_array.htm b/shared_array.htm index 7c61f53..87bf61e 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -177,10 +177,9 @@ template<class T>

Revised 09 January 2003

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Permission to copy, use, modify, sell and - distribute this document is granted provided this copyright notice appears in - all copies. This document is provided "as is" without express or implied - warranty, and with no claim as to its suitability for any purpose.

+

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005 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.

diff --git a/shared_ptr.htm b/shared_ptr.htm index e2626fc..e108278 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -709,9 +709,8 @@ int * p = a.release();

$Date$

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Permission to copy, use, modify, sell and - distribute this document is granted provided this copyright notice appears in - all copies. This document is provided "as is" without express or implied - warranty, and with no claim as to its suitability for any purpose.

+ Copyright 2002-2005 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.

diff --git a/smart_ptr.htm b/smart_ptr.htm index 14f456b..5fb0e8d 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -177,10 +177,9 @@ and an extensive bibliography.


$Date$

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Permission to copy, use, modify, sell and distribute this document is granted - provided this copyright notice appears in all copies. This document is provided - "as is" without express or implied warranty, and with no claim as to its - suitability for any purpose.

+

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + 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.

diff --git a/weak_ptr.htm b/weak_ptr.htm index 68dc980..0fa87f7 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -235,10 +235,8 @@ public:

$Date$

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Permission to copy, use, modify, sell and - distribute this document is granted provided this copyright notice appears in - all copies. This document is provided "as is" without express or implied - warranty, and with no claim as to its suitability for any purpose.

- + Copyright 2002-2005 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.

From ecb41cb1506ca1ff0664e5e1346e5ce35beaba43 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 4 Jul 2007 16:35:44 +0000 Subject: [PATCH 032/132] sp_unary_addr_test added (reported by Scott French) [SVN r38137] --- include/boost/detail/sp_counted_impl.hpp | 4 +- test/Jamfile | 1 + test/Jamfile.v2 | 1 + test/sp_unary_addr_test.cpp | 62 ++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 test/sp_unary_addr_test.cpp diff --git a/include/boost/detail/sp_counted_impl.hpp b/include/boost/detail/sp_counted_impl.hpp index 6963f59..919b5dc 100644 --- a/include/boost/detail/sp_counted_impl.hpp +++ b/include/boost/detail/sp_counted_impl.hpp @@ -147,7 +147,7 @@ public: virtual void * get_deleter( std::type_info const & ti ) { - return ti == typeid(D)? &del: 0; + return ti == typeid(D)? &reinterpret_cast( del ): 0; } #if defined(BOOST_SP_USE_STD_ALLOCATOR) @@ -217,7 +217,7 @@ public: virtual void * get_deleter( std::type_info const & ti ) { - return ti == typeid( D )? &d_: 0; + return ti == typeid( D )? &reinterpret_cast( d_ ): 0; } }; diff --git a/test/Jamfile b/test/Jamfile index b3fcac9..71b5df7 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -37,6 +37,7 @@ DEPENDS all : smart_ptr ; [ run shared_ptr_rv_test.cpp ] [ run shared_ptr_move_test.cpp ] [ compile-fail shared_ptr_pv_fail.cpp ] + [ run sp_unary_addr_test.cpp ] ; # this one is too slow to run unless explicitly requested, and ALL diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index b980bfc..e6b49d7 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -32,5 +32,6 @@ import testing ; [ run shared_ptr_rv_test.cpp ] [ run shared_ptr_move_test.cpp ] [ compile-fail shared_ptr_pv_fail.cpp ] + [ run sp_unary_addr_test.cpp ] ; } diff --git a/test/sp_unary_addr_test.cpp b/test/sp_unary_addr_test.cpp new file mode 100644 index 0000000..4522640 --- /dev/null +++ b/test/sp_unary_addr_test.cpp @@ -0,0 +1,62 @@ +// +// sp_unary_addr_test.cpp +// +// 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 +#include +#include + +struct deleter +{ +private: + + void operator& (); + void operator& () const; + +public: + + int data; + + deleter(): data( 17041 ) + { + } + + void operator()( void * ) + { + } +}; + +struct X +{ +}; + +int main() +{ + X x; + + { + boost::shared_ptr p( &x, deleter() ); + + deleter * q = boost::get_deleter( p ); + + BOOST_TEST( q != 0 ); + BOOST_TEST( q != 0 && q->data == 17041 ); + } + + { + boost::shared_ptr p( &x, deleter(), std::allocator() ); + + deleter * q = boost::get_deleter( p ); + + BOOST_TEST( q != 0 ); + BOOST_TEST( q != 0 && q->data == 17041 ); + } + + return boost::report_errors(); +} From 6646d8acd27ec4aec1e7ec79d929e4781acaac3d Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Wed, 8 Aug 2007 19:02:26 +0000 Subject: [PATCH 033/132] Remove V1 Jamfiles [SVN r38516] --- test/Jamfile | 52 ---------------------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 test/Jamfile diff --git a/test/Jamfile b/test/Jamfile deleted file mode 100644 index 71b5df7..0000000 --- a/test/Jamfile +++ /dev/null @@ -1,52 +0,0 @@ -# Boost.SmartPtr Library test Jamfile -# -# Copyright (c) 2003-2007 Peter Dimov -# Copyright (c) 2003 Dave Abrahams -# -# 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) - -subproject libs/smart_ptr/test ; - -# bring in rules for testing -import testing ; - -# Make tests run by default. -DEPENDS all : smart_ptr ; - -{ - test-suite "smart_ptr" - : [ run smart_ptr_test.cpp ] - [ run shared_ptr_basic_test.cpp : : : <*>-Wno-non-virtual-dtor ] - [ run shared_ptr_test.cpp : : : <*>-Wno-non-virtual-dtor ] - [ run weak_ptr_test.cpp ] - [ run shared_from_this_test.cpp : : : <*>-Wno-non-virtual-dtor ] - [ run get_deleter_test.cpp ] - [ run intrusive_ptr_test.cpp ] - [ run atomic_count_test.cpp ] - [ run lw_mutex_test.cpp ] - [ compile-fail shared_ptr_assign_fail.cpp ] - [ compile-fail shared_ptr_delete_fail.cpp ] - [ compile-fail shared_ptr_compare_fail.cpp ] - [ run shared_ptr_alloc2_test.cpp ] - [ run pointer_cast_test.cpp ] - [ compile pointer_to_other_test.cpp ] - [ run auto_ptr_rv_test.cpp ] - [ run shared_ptr_alias_test.cpp ] - [ run shared_ptr_rv_test.cpp ] - [ run shared_ptr_move_test.cpp ] - [ compile-fail shared_ptr_pv_fail.cpp ] - [ run sp_unary_addr_test.cpp ] - ; - - # this one is too slow to run unless explicitly requested, and ALL - # tests are run by default when this file is subincluded from - # boost/status, so it's guarded from that case. It will only be - # built from this directory when the targets "test" (all tests) or - # "shared_ptr_alloc_test" are requested. - if [ in-invocation-subdir ] - { - run shared_ptr_alloc_test.cpp ; - } -} From bca336bf35e98958e4d9df5841c11c7193db47eb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 26 Aug 2007 19:42:50 +0000 Subject: [PATCH 034/132] Updated the unspecified_bool_type to match shared_ptr. [SVN r38975] --- include/boost/shared_array.hpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index eb69c8e..3b82f35 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -103,7 +103,23 @@ public: return px != 0; } -#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) +#elif defined( _MANAGED ) + + static void unspecified_bool( this_type*** ) + { + } + + typedef void (*unspecified_bool_type)( this_type*** ); + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: unspecified_bool; + } + +#elif \ + ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ + ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) + typedef T * (this_type::*unspecified_bool_type)() const; operator unspecified_bool_type() const // never throws From e0ca42bb88f333ffd4d6cd029bfe3309af33b66e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 26 Aug 2007 20:34:40 +0000 Subject: [PATCH 035/132] BOOST_NO_TYPEID support (#1108). [SVN r38976] --- include/boost/detail/shared_count.hpp | 3 +- .../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 | 4 +- .../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 | 4 +- include/boost/detail/sp_counted_base_sync.hpp | 4 +- include/boost/detail/sp_counted_base_w32.hpp | 4 +- include/boost/detail/sp_counted_impl.hpp | 11 ++- include/boost/detail/sp_typeinfo.hpp | 83 +++++++++++++++++++ 14 files changed, 111 insertions(+), 30 deletions(-) create mode 100644 include/boost/detail/sp_typeinfo.hpp 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_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 index dd606f0..c6624cf 100644 --- a/include/boost/detail/sp_counted_base_gcc_sparc.hpp +++ b/include/boost/detail/sp_counted_base_gcc_sparc.hpp @@ -19,7 +19,7 @@ // // Thanks to Michael van der Westhuizen -#include +#include "sp_typeinfo.hpp" #include // int32_t namespace boost @@ -119,7 +119,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_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 index c23e2e3..58119db 100644 --- a/include/boost/detail/sp_counted_base_solaris.hpp +++ b/include/boost/detail/sp_counted_base_solaris.hpp @@ -20,7 +20,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" #include namespace boost @@ -61,7 +61,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_sync.hpp b/include/boost/detail/sp_counted_base_sync.hpp index 5aaa917..bf2a0fb 100644 --- a/include/boost/detail/sp_counted_base_sync.hpp +++ b/include/boost/detail/sp_counted_base_sync.hpp @@ -15,7 +15,7 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt -#include +#include "sp_typeinfo.hpp" #include namespace boost @@ -104,7 +104,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_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 919b5dc..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)? &reinterpret_cast( 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 )? &reinterpret_cast( 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 From b2354d0a5e96ce33ef2eb2d145198b9060bc153c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 26 Aug 2007 20:35:52 +0000 Subject: [PATCH 036/132] BOOST_NO_TYPEID support (#1108). [SVN r38977] --- include/boost/shared_ptr.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index ec38248..fca726f 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -453,9 +453,9 @@ public: return pn < rhs.pn; } - void * _internal_get_deleter(std::type_info const & ti) const + void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const { - return pn.get_deleter(ti); + return pn.get_deleter( ti ); } // Tasteless as this may seem, making all members public allows member templates @@ -594,7 +594,7 @@ template std::basic_ostream & operator<< (std:: template D * get_deleter(shared_ptr const & p) { - void const * q = p._internal_get_deleter(typeid(D)); + void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D)); return const_cast(static_cast(q)); } @@ -602,7 +602,7 @@ template D * get_deleter(shared_ptr const & p) template D * get_deleter(shared_ptr const & p) { - return static_cast(p._internal_get_deleter(typeid(D))); + return static_cast(p._internal_get_deleter(BOOST_SP_TYPEID(D))); } #endif From f5ce4dbc4cb00fe4d3574bfe1f88357c196c1656 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 11 Sep 2007 20:58:19 +0000 Subject: [PATCH 037/132] Fixes #1243 [SVN r39199] --- include/boost/detail/lightweight_mutex.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 5a85c1f0f2f26e6fc3c5536ddc8d8459304fa774 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 14 Sep 2007 19:19:09 +0000 Subject: [PATCH 038/132] CINT support (Nils Krumnack) [SVN r39282] --- include/boost/shared_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index fca726f..9c1365f 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -383,7 +383,7 @@ public: // implicit conversion to "bool" -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) +#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) ) || defined(__CINT__) operator bool () const { From 9db307eda567bae43a6d48893efb85bd51dc2b50 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 20 Sep 2007 20:46:56 +0000 Subject: [PATCH 039/132] defined(__ppc) added (Daniel P Furlani) [SVN r39427] --- include/boost/detail/sp_counted_base.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index e9d6ac9..dee9966 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -43,7 +43,7 @@ # include -#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) ) +#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) # include From f49a2fb1e173d847091fd59d8472a05bfd6339b7 Mon Sep 17 00:00:00 2001 From: Boris Gubenko Date: Tue, 30 Oct 2007 12:43:47 +0000 Subject: [PATCH 040/132] add support for aC++ on HP-UX ia64 [SVN r40603] --- include/boost/detail/sp_counted_base.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index dee9966..f925a5d 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -39,6 +39,10 @@ # include +#elif defined(__HP_aCC) && defined(__ia64) + +# include + #elif defined( __MWERKS__ ) && defined( __POWERPC__ ) # include From 9e41d1f1942bbe271637ad70337dfa2c150b3bc8 Mon Sep 17 00:00:00 2001 From: Boris Gubenko Date: Tue, 30 Oct 2007 12:48:44 +0000 Subject: [PATCH 041/132] add support for aC++ on HP-UX ia64 [SVN r40604] --- .../boost/detail/sp_counted_base_acc_ia64.hpp | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 include/boost/detail/sp_counted_base_acc_ia64.hpp 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..baeefaf --- /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_gcc_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 From 7b5beeedded2b214f9a04164e35ce2b1e70da1e2 Mon Sep 17 00:00:00 2001 From: Boris Gubenko Date: Tue, 30 Oct 2007 12:58:36 +0000 Subject: [PATCH 042/132] fix typo in comment [SVN r40605] --- include/boost/detail/sp_counted_base_acc_ia64.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/sp_counted_base_acc_ia64.hpp b/include/boost/detail/sp_counted_base_acc_ia64.hpp index baeefaf..94c015d 100644 --- a/include/boost/detail/sp_counted_base_acc_ia64.hpp +++ b/include/boost/detail/sp_counted_base_acc_ia64.hpp @@ -2,7 +2,7 @@ #define BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED // -// detail/sp_counted_base_gcc_ia64.hpp - aC++ on HP-UX IA64 +// detail/sp_counted_base_acc_ia64.hpp - aC++ on HP-UX IA64 // // Copyright 2007 Baruch Zilber // Copyright 2007 Boris Gubenko From f854829d869d4fe97fa4b9bc3c07832b53f84b6b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 2 Nov 2007 23:46:04 +0000 Subject: [PATCH 043/132] Port unspecified_bool fix for Sun 5.8 from RC_1_34 [SVN r40708] --- include/boost/shared_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 9c1365f..98393c2 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -383,7 +383,7 @@ public: // implicit conversion to "bool" -#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) ) || defined(__CINT__) +#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) ) || defined(__CINT__) operator bool () const { From e6f6ec9fa350265b96c4d0a240dcffa10d6f53f0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 7 Nov 2007 22:47:55 +0000 Subject: [PATCH 044/132] Attempt unspecified bool fix for Sun 5.7-5.9 [SVN r40914] --- include/boost/shared_ptr.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 98393c2..5e1abd8 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -383,7 +383,7 @@ public: // implicit conversion to "bool" -#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) ) || defined(__CINT__) +#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) operator bool () const { @@ -405,7 +405,8 @@ public: #elif \ ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ - ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) + ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \ + ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) ) typedef T * (this_type::*unspecified_bool_type)() const; From b2a3c9e59df684c2d4721ae1cc1d2afbbb60141a Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 10 Feb 2008 14:56:22 +0000 Subject: [PATCH 045/132] Link to people pages on the website, as they've been removed from the download. [SVN r43209] --- smarttests.htm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/smarttests.htm b/smarttests.htm index e7cedff..1833719 100644 --- a/smarttests.htm +++ b/smarttests.htm @@ -21,10 +21,10 @@ mailing list and the tests which this page describes were performed to provide a guide for current and future investigations into smart pointer implementation strategies.

-

Thanks are due to Dave Abrahams, +

Thanks are due to Dave Abrahams, Gavin Collings, -Greg Colvin and -Beman Dawes +Greg Colvin and +Beman Dawes for test code and trial implementations, the final version of which can be found in .zip format here.

Description

From 7ca6d86bdc403d191213009b6f291ed321ba3496 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 10 Feb 2008 15:02:17 +0000 Subject: [PATCH 046/132] Point links to the pages that used to be in 'more' to the site. [SVN r43210] --- smart_ptr.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smart_ptr.htm b/smart_ptr.htm index 5fb0e8d..497c63f 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -105,7 +105,7 @@ and that is thrown only by functions which are explicitly documented as possibly throwing std::bad_alloc.

Exception-specifications

-

Exception-specifications are not used; see +

Exception-specifications are not used; see exception-specification rationale.

All the smart pointer templates contain member functions which can never throw exceptions, because they neither throw exceptions themselves nor call other From f596092bac04939f1f4a3d50a1d71474dc0bbff8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 19 Feb 2008 13:18:58 +0000 Subject: [PATCH 047/132] Fixes #1590. [SVN r43316] --- shared_ptr.htm | 10 +++++----- test/shared_ptr_test.cpp | 12 ++++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index e108278..a752629 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -373,8 +373,8 @@ q = p;

long use_count() const; // never throws

Returns: the number of shared_ptr objects, *this included, - that share ownership with *this, or an unspecified nonnegative - value when *this is empty.

+ that share ownership with *this, or 0 when *this + is empty.

Throws: nothing.

Notes: use_count() is not necessarily efficient. Use only for debugging and testing purposes, not for production code.

@@ -709,8 +709,8 @@ int * p = a.release();

$Date$

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 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.

+ Copyright 2002-2005 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.

diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp index 2f852ea..f697192 100644 --- a/test/shared_ptr_test.cpp +++ b/test/shared_ptr_test.cpp @@ -62,6 +62,7 @@ void default_constructor() BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 0); } { @@ -69,6 +70,7 @@ void default_constructor() BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 0); } { @@ -76,6 +78,7 @@ void default_constructor() BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 0); } } @@ -1565,6 +1568,7 @@ void plain_reset() BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 0); } { @@ -1573,6 +1577,7 @@ void plain_reset() BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 0); } { @@ -1581,6 +1586,7 @@ void plain_reset() BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 0); } { @@ -1589,6 +1595,7 @@ void plain_reset() BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 0); } { @@ -1597,6 +1604,7 @@ void plain_reset() BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 0); } { @@ -1605,6 +1613,7 @@ void plain_reset() BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 0); } { @@ -1615,6 +1624,7 @@ void plain_reset() BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 0); BOOST_TEST(X::instances == 0); } @@ -1624,6 +1634,7 @@ void plain_reset() BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 0); } { @@ -1634,6 +1645,7 @@ void plain_reset() BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 0); BOOST_TEST(X::instances == 0); } } From a055d9829e66c190012fbe1c9ec3f752208df9e6 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 19 Feb 2008 14:01:13 +0000 Subject: [PATCH 048/132] Fixes #1444. [SVN r43317] --- include/boost/scoped_array.hpp | 3 +++ include/boost/scoped_ptr.hpp | 3 +++ test/Jamfile.v2 | 2 ++ test/scoped_array_eq_fail.cpp | 27 +++++++++++++++++++++++++++ test/scoped_ptr_eq_fail.cpp | 27 +++++++++++++++++++++++++++ 5 files changed, 62 insertions(+) create mode 100644 test/scoped_array_eq_fail.cpp create mode 100644 test/scoped_ptr_eq_fail.cpp diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index 667dfff..fcb80f6 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -46,6 +46,9 @@ private: typedef scoped_array this_type; + void operator==( scoped_array const& ) const; + void operator!=( scoped_array const& ) const; + public: typedef T element_type; diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 651deed..279cec3 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -47,6 +47,9 @@ private: typedef scoped_ptr this_type; + void operator==( scoped_ptr const& ) const; + void operator!=( scoped_ptr const& ) const; + public: typedef T element_type; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e6b49d7..9aa248f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -33,5 +33,7 @@ import testing ; [ run shared_ptr_move_test.cpp ] [ compile-fail shared_ptr_pv_fail.cpp ] [ run sp_unary_addr_test.cpp ] + [ compile-fail scoped_ptr_eq_fail.cpp ] + [ compile-fail scoped_array_eq_fail.cpp ] ; } diff --git a/test/scoped_array_eq_fail.cpp b/test/scoped_array_eq_fail.cpp new file mode 100644 index 0000000..6c7f214 --- /dev/null +++ b/test/scoped_array_eq_fail.cpp @@ -0,0 +1,27 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// scoped_array_eq_fail.cpp - a negative test for "p == q" +// +// Copyright (c) 2008 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 + +int main() +{ + boost::scoped_array p, q; + p == q; // must fail + return 0; +} diff --git a/test/scoped_ptr_eq_fail.cpp b/test/scoped_ptr_eq_fail.cpp new file mode 100644 index 0000000..0d6ade4 --- /dev/null +++ b/test/scoped_ptr_eq_fail.cpp @@ -0,0 +1,27 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// scoped_ptr_eq_fail.cpp - a negative test for "p == q" +// +// Copyright (c) 2008 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 + +int main() +{ + boost::scoped_ptr p, q; + p == q; // must fail + return 0; +} From 3a4dc43924cbf6be6378491cd16c2945d37cadbb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 19 Feb 2008 14:26:36 +0000 Subject: [PATCH 049/132] Fix #398, as long as the macros BOOST_NO_STD_TYPEINFO and BOOST_NO_IOSTREAM are defined. I don't know how Boost.Config needs to be changed to autodetect eVC4 and set these on its own. [SVN r43318] --- include/boost/shared_ptr.hpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 5e1abd8..fa08d35 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -31,7 +31,14 @@ #include // for std::swap #include // for std::less #include // for std::bad_cast + +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) #include // for std::basic_ostream +#else +#include +#endif +#endif #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash # pragma warning(push) @@ -555,6 +562,8 @@ template inline T * get_pointer(shared_ptr const & p) // operator<< +#if !defined(BOOST_NO_IOSTREAM) + #if defined(__GNUC__) && (__GNUC__ < 3) template std::ostream & operator<< (std::ostream & os, shared_ptr const & p) @@ -584,6 +593,8 @@ template std::basic_ostream & operator<< (std:: #endif // __GNUC__ < 3 +#endif // !defined(BOOST_NO_IOSTREAM) + // get_deleter #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ From 2eb3991630d138b43b4e4ea13da2efa444a1e21c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 19 Mar 2008 19:39:50 +0000 Subject: [PATCH 050/132] Regression test for enable_shared_from_this. [SVN r43733] --- test/Jamfile.v2 | 1 + test/esft_regtest.cpp | 136 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 test/esft_regtest.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 9aa248f..cd51539 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -35,5 +35,6 @@ import testing ; [ run sp_unary_addr_test.cpp ] [ compile-fail scoped_ptr_eq_fail.cpp ] [ compile-fail scoped_array_eq_fail.cpp ] + [ run esft_regtest.cpp ] ; } diff --git a/test/esft_regtest.cpp b/test/esft_regtest.cpp new file mode 100644 index 0000000..0e3036c --- /dev/null +++ b/test/esft_regtest.cpp @@ -0,0 +1,136 @@ +// +// esft_regtest.cpp +// +// A regression test for enable_shared_from_this +// +// Copyright (c) 2008 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 +#include +#include +#include +#include + +class X: public boost::enable_shared_from_this< X > +{ +private: + + int destroyed_; + int deleted_; + int expected_; + +private: + + X( X const& ); + X& operator=( X const& ); + +public: + + static int instances; + +public: + + explicit X( int expected ): destroyed_( 0 ), deleted_( 0 ), expected_( expected ) + { + ++instances; + } + + ~X() + { + BOOST_TEST( deleted_ == expected_ ); + BOOST_TEST( destroyed_ == 0 ); + ++destroyed_; + --instances; + } + + typedef void (*deleter_type)( X* ); + + static void deleter( X * px ) + { + ++px->deleted_; + } + + static void deleter2( X * px ) + { + ++px->deleted_; + delete px; + } +}; + +int X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + X x( 0 ); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + std::auto_ptr px( new X( 0 ) ); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr px( new X( 0 ) ); + BOOST_TEST( X::instances == 1 ); + + boost::weak_ptr wp( px ); + BOOST_TEST( !wp.expired() ); + + px.reset(); + + BOOST_TEST( wp.expired() ); + } + + BOOST_TEST( X::instances == 0 ); + + { + X x( 1 ); + boost::shared_ptr px( &x, X::deleter ); + BOOST_TEST( X::instances == 1 ); + + X::deleter_type * pd = boost::get_deleter( px ); + BOOST_TEST( pd != 0 && *pd == X::deleter ); + + boost::weak_ptr wp( px ); + BOOST_TEST( !wp.expired() ); + + px.reset(); + + BOOST_TEST( wp.expired() ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr px( new X( 1 ), X::deleter2 ); + BOOST_TEST( X::instances == 1 ); + + X::deleter_type * pd = boost::get_deleter( px ); + BOOST_TEST( pd != 0 && *pd == X::deleter2 ); + + boost::weak_ptr wp( px ); + BOOST_TEST( !wp.expired() ); + + px.reset(); + + BOOST_TEST( wp.expired() ); + } + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +} From 1c2d780f9ef00068a75635fbdcde2f64de2d7aed Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Thu, 20 Mar 2008 19:32:43 +0000 Subject: [PATCH 051/132] Added support for calling enable_shared_from_this::shared_from_this in constructors. Closes #1696. [SVN r43738] --- include/boost/enable_shared_from_this.hpp | 51 ++++++-- include/boost/shared_ptr.hpp | 83 ++++++++++--- test/Jamfile.v2 | 1 + test/esft_constructor_test.cpp | 144 ++++++++++++++++++++++ 4 files changed, 252 insertions(+), 27 deletions(-) create mode 100644 test/esft_constructor_test.cpp diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 4e49f1f..06c8bc7 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -23,9 +23,32 @@ namespace boost template class enable_shared_from_this { +// dynamic cast to template type doesn't work in constructor, so we have +// to use lazy initialization + void init_internal_shared_once() const + { + if(owned() == false && _internal_shared_this == 0) + { + _internal_shared_this = shared_ptr(dynamic_cast(const_cast(this)), + detail::sp_deleter_wrapper(), detail::ignore_enable_shared_from_this_tag()); + BOOST_ASSERT(_internal_shared_this.get() == this); + _internal_weak_this = _internal_shared_this; + } + } + + bool owned() const + { + return _owned; + } + + typedef T _internal_element_type; // for bcc 5.5.1 + mutable shared_ptr<_internal_element_type> _internal_shared_this; + mutable weak_ptr<_internal_element_type> _internal_weak_this; + mutable bool _owned; protected: - enable_shared_from_this() + enable_shared_from_this(): + _owned(false) { } @@ -38,14 +61,20 @@ protected: return *this; } - ~enable_shared_from_this() +// virtual destructor because we need a vtable for dynamic_cast from base to derived to work + virtual ~enable_shared_from_this() { +// make sure no dangling shared_ptr objects were created by the +// user calling shared_from_this() but never passing ownership of the object +// to a shared_ptr. + BOOST_ASSERT(owned() || _internal_shared_this.use_count() <= 1); } public: shared_ptr shared_from_this() { + init_internal_shared_once(); shared_ptr p(_internal_weak_this); BOOST_ASSERT(p.get() == this); return p; @@ -53,19 +82,21 @@ public: shared_ptr shared_from_this() const { + init_internal_shared_once(); shared_ptr p(_internal_weak_this); BOOST_ASSERT(p.get() == this); return p; } -// Note: No, you don't need to initialize _internal_weak_this -// -// Please read the documentation, not the code -// -// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html - - typedef T _internal_element_type; // for bcc 5.5.1 - mutable weak_ptr<_internal_element_type> _internal_weak_this; + template + void _internal_accept_owner(shared_ptr &owner) const + { + init_internal_shared_once(); + get_deleter(_internal_shared_this)->set_deleter(owner); + owner = _internal_shared_this; + _internal_shared_this.reset(); + _owned = true; + } }; } // namespace boost diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index fa08d35..5ab6452 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -48,6 +48,7 @@ namespace boost { +template class shared_ptr; template class weak_ptr; template class enable_shared_from_this; @@ -90,9 +91,14 @@ template<> struct shared_ptr_traits // enable_shared_from_this support -template void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this const * pe, Y const * px ) +struct ignore_enable_shared_from_this_tag {}; + +template void sp_enable_shared_from_this( boost::shared_ptr * ptr, boost::enable_shared_from_this const * pe ) { - if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); + if(pe != 0) + { + pe->_internal_accept_owner(*ptr); + } } #ifdef _MANAGED @@ -104,7 +110,7 @@ struct sp_any_pointer template sp_any_pointer( T* ) {} }; -inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer ) +inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer ) { } @@ -115,7 +121,7 @@ inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_poin # pragma set woff 3506 #endif -inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) +inline void sp_enable_shared_from_this( ... ) { } @@ -136,7 +142,7 @@ template< class T, class R > struct sp_enable_if_auto_ptr template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R > { typedef R type; -}; +}; #endif @@ -172,7 +178,7 @@ public: template explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { - boost::detail::sp_enable_shared_from_this( pn, p, p ); + boost::detail::sp_enable_shared_from_this( this, p ); } // @@ -183,14 +189,14 @@ public: template shared_ptr(Y * p, D d): px(p), pn(p, d) { - boost::detail::sp_enable_shared_from_this( pn, p, p ); + boost::detail::sp_enable_shared_from_this( this, p ); } // As above, but with allocator. A's copy constructor shall not throw. template shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) { - boost::detail::sp_enable_shared_from_this( pn, p, p ); + boost::detail::sp_enable_shared_from_this( this, p ); } // generated copy constructor, assignment, destructor are fine... @@ -253,6 +259,12 @@ public: } } +// constructor that doesn't trigger enable_shared_from_this code, needed +// for enable_shared_from_this internal implementation + template shared_ptr(Y * p, D d, detail::ignore_enable_shared_from_this_tag tag): + px(p), pn(p, d) + {} + #ifndef BOOST_NO_AUTO_PTR template @@ -260,7 +272,7 @@ public: { Y * tmp = r.get(); pn = boost::detail::shared_count(r); - boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); + boost::detail::sp_enable_shared_from_this( this, tmp ); } #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) @@ -270,7 +282,7 @@ public: { typename Ap::element_type * tmp = r.get(); pn = boost::detail::shared_count( r ); - boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); + boost::detail::sp_enable_shared_from_this( this, tmp ); } @@ -382,7 +394,7 @@ public: BOOST_ASSERT(px != 0); return px; } - + T * get() const // never throws { return px; @@ -416,13 +428,13 @@ public: ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) ) typedef T * (this_type::*unspecified_bool_type)() const; - + operator unspecified_bool_type() const // never throws { return px == 0? 0: &this_type::get; } -#else +#else typedef T * this_type::*unspecified_bool_type; @@ -583,7 +595,7 @@ using std::basic_ostream; template basic_ostream & operator<< (basic_ostream & os, shared_ptr const & p) # else template std::basic_ostream & operator<< (std::basic_ostream & os, shared_ptr const & p) -# endif +# endif { os << p.get(); return os; @@ -597,6 +609,8 @@ template std::basic_ostream & operator<< (std:: // get_deleter +namespace detail +{ #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) ) @@ -604,7 +618,7 @@ template std::basic_ostream & operator<< (std:: // g++ 2.9x doesn't allow static_cast(void *) // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it -template D * get_deleter(shared_ptr const & p) +template D * basic_get_deleter(shared_ptr const & p) { void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D)); return const_cast(static_cast(q)); @@ -612,18 +626,53 @@ template D * get_deleter(shared_ptr const & p) #else -template D * get_deleter(shared_ptr const & p) +template D * basic_get_deleter(shared_ptr const & p) { return static_cast(p._internal_get_deleter(BOOST_SP_TYPEID(D))); } #endif +class sp_deleter_wrapper +{ + shared_ptr _deleter; +public: + sp_deleter_wrapper() + {} + void set_deleter(const shared_ptr &deleter) + { + _deleter = deleter; + } + void operator()(const void *) + { + BOOST_ASSERT(_deleter.use_count() <= 1); + _deleter.reset(); + } + template + D* get_deleter() const + { + return boost::detail::basic_get_deleter(_deleter); + } +}; + +} // namespace detail + +template D * get_deleter(shared_ptr const & p) +{ + D *del = detail::basic_get_deleter(p); + if(del == 0) + { + detail::sp_deleter_wrapper *del_wrapper = detail::basic_get_deleter(p); + if(del_wrapper) del = del_wrapper->get_deleter(); + } + return del; +} + } // namespace boost #ifdef BOOST_MSVC # pragma warning(pop) -#endif +#endif #endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index cd51539..837c83c 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -36,5 +36,6 @@ import testing ; [ compile-fail scoped_ptr_eq_fail.cpp ] [ compile-fail scoped_array_eq_fail.cpp ] [ run esft_regtest.cpp ] + [ run esft_constructor_test.cpp ] ; } diff --git a/test/esft_constructor_test.cpp b/test/esft_constructor_test.cpp new file mode 100644 index 0000000..88fbe68 --- /dev/null +++ b/test/esft_constructor_test.cpp @@ -0,0 +1,144 @@ +// +// esft_constructor_test.cpp +// +// A test for the new enable_shared_from_this support for calling +// shared_from_this from constructors (that is, prior to the +// object's ownership being passed to an external shared_ptr). +// +// Copyright (c) 2008 Frank Mori Hess +// Copyright (c) 2008 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 +#include +#include +#include +#include + +class X: public boost::enable_shared_from_this< X > +{ +private: + + int destroyed_; + int deleted_; + int expected_; + +private: + + X( X const& ); + X& operator=( X const& ); + +public: + + static int instances; + +public: + + explicit X( int expected, boost::shared_ptr *early_px = 0 ): destroyed_( 0 ), deleted_( 0 ), expected_( expected ) + { + ++instances; + if( early_px ) *early_px = shared_from_this(); + } + + ~X() + { + BOOST_TEST( deleted_ == expected_ ); + BOOST_TEST( destroyed_ == 0 ); + ++destroyed_; + --instances; + } + + typedef void (*deleter_type)( X* ); + + static void deleter( X * px ) + { + ++px->deleted_; + } + + static void deleter2( X * px ) + { + ++px->deleted_; + delete px; + } +}; + +int X::instances = 0; + +template +bool are_shared_owners(const boost::shared_ptr &a, const boost::shared_ptr &b) +{ + return a && !(a < b) && !(b < a); +} + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr early_px; + X* x = new X( 1, &early_px ); + BOOST_TEST( early_px.use_count() > 0 ); + BOOST_TEST( boost::get_deleter(early_px) == 0 ); + boost::shared_ptr px( x, &X::deleter2 ); + BOOST_TEST( early_px.use_count() == 2 && px.use_count() == 2 ); + BOOST_TEST(are_shared_owners(early_px, px)); + px.reset(); + BOOST_TEST( early_px.use_count() == 1 ); + BOOST_TEST( X::instances == 1 ); + X::deleter_type *pd = boost::get_deleter(early_px); + BOOST_TEST(pd && *pd == &X::deleter2 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr early_px; + X* x = new X( 1, &early_px ); + boost::weak_ptr early_weak_px = early_px; + early_px.reset(); + BOOST_TEST( !early_weak_px.expired() ); + boost::shared_ptr px( x, &X::deleter2 ); + BOOST_TEST( px.use_count() == 1 ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST(are_shared_owners(early_weak_px.lock(), px)); + px.reset(); + BOOST_TEST( early_weak_px.expired() ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr early_px; + X x( 1, &early_px ); + BOOST_TEST( early_px.use_count() > 0 ); + boost::shared_ptr px( &x, &X::deleter ); + BOOST_TEST( early_px.use_count() == 2 && px.use_count() == 2 ); + early_px.reset(); + BOOST_TEST( px.use_count() == 1 ); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::weak_ptr early_weak_px; + { + boost::shared_ptr early_px; + X x( 0, &early_px ); + early_weak_px = early_px; + early_px.reset(); + BOOST_TEST( !early_weak_px.expired() ); + BOOST_TEST( X::instances == 1 ); + } + BOOST_TEST( early_weak_px.expired() ); + } + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +} From 5b17f88f0e2310be9d6f57085dfd24fab91000db Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 20 Mar 2008 22:10:52 +0000 Subject: [PATCH 052/132] Initialize _owned in the copy constructor as well. [SVN r43739] --- include/boost/enable_shared_from_this.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 06c8bc7..f109aa3 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -45,6 +45,7 @@ template class enable_shared_from_this mutable shared_ptr<_internal_element_type> _internal_shared_this; mutable weak_ptr<_internal_element_type> _internal_weak_this; mutable bool _owned; + protected: enable_shared_from_this(): @@ -52,7 +53,8 @@ protected: { } - enable_shared_from_this(enable_shared_from_this const &) + enable_shared_from_this(enable_shared_from_this const &): + _owned(false) { } From b30aa1468a3bf3f3e599fd611b6558773ee4fb54 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Fri, 21 Mar 2008 19:19:25 +0000 Subject: [PATCH 053/132] Worked around compilation error in boost::get_deleter when using old versions of g++. [SVN r43766] --- include/boost/shared_ptr.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 5ab6452..c570791 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -663,7 +663,9 @@ template D * get_deleter(shared_ptr const & p) if(del == 0) { detail::sp_deleter_wrapper *del_wrapper = detail::basic_get_deleter(p); - if(del_wrapper) del = del_wrapper->get_deleter(); +// The following get_deleter method call is fully qualified because +// older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter() + if(del_wrapper) del = del_wrapper->::boost::detail::sp_deleter_wrapper::get_deleter(); } return del; } From f22516d650db81410c56edc2fb375884543c13e9 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Fri, 21 Mar 2008 21:12:21 +0000 Subject: [PATCH 054/132] Fixed bogus test failure caused by new enable_shared_from_this features. [SVN r43782] --- test/shared_from_this_test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/shared_from_this_test.cpp b/test/shared_from_this_test.cpp index 5107cb1..61515bd 100644 --- a/test/shared_from_this_test.cpp +++ b/test/shared_from_this_test.cpp @@ -133,7 +133,8 @@ void test3() try { boost::shared_ptr r = v2.shared_from_this(); - BOOST_ERROR("v2.shared_from_this() failed to throw"); + BOOST_TEST( p < r || r < p ); + BOOST_TEST( r.get() == &v2 ); } catch(boost::bad_weak_ptr const &) { From d7448b574684207f62326f8ebe3adc526bf20566 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Sun, 23 Mar 2008 14:51:40 +0000 Subject: [PATCH 055/132] Added a little more test code for new enable_shared_from_this behavior. [SVN r43804] --- test/esft_constructor_test.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/esft_constructor_test.cpp b/test/esft_constructor_test.cpp index 88fbe68..068f236 100644 --- a/test/esft_constructor_test.cpp +++ b/test/esft_constructor_test.cpp @@ -75,6 +75,9 @@ bool are_shared_owners(const boost::shared_ptr &a, const boost::shared_ptr return a && !(a < b) && !(b < a); } +struct Y: public boost::enable_shared_from_this +{}; + int main() { BOOST_TEST( X::instances == 0 ); @@ -121,6 +124,14 @@ int main() early_px.reset(); BOOST_TEST( px.use_count() == 1 ); BOOST_TEST( X::instances == 1 ); + px.reset(); + try + { + x.shared_from_this(); + BOOST_ERROR("x did not throw bad_weak_ptr"); + } + catch( const boost::bad_weak_ptr &err) + {} } BOOST_TEST( X::instances == 0 ); @@ -140,5 +151,19 @@ int main() BOOST_TEST( X::instances == 0 ); + { + boost::shared_ptr px(new Y()); + Y y(*px); + px.reset(); + try + { + y.shared_from_this(); + } + catch( const boost::bad_weak_ptr &err) + { + BOOST_ERROR("y threw bad_weak_ptr"); + } + } + return boost::report_errors(); } From d17a0964071ba0707cfacd240d3f16cd4a691353 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Mon, 24 Mar 2008 15:07:00 +0000 Subject: [PATCH 056/132] Fixed compile error with new enable_shared_from_this code, reported by Tim Blechmann [SVN r43823] --- include/boost/enable_shared_from_this.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index f109aa3..9a71ae2 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -95,7 +95,7 @@ public: { init_internal_shared_once(); get_deleter(_internal_shared_this)->set_deleter(owner); - owner = _internal_shared_this; + owner = dynamic_pointer_cast(_internal_shared_this); _internal_shared_this.reset(); _owned = true; } From af7d4fabad5b9b3a2c0678771397bcd71863cff1 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 24 Mar 2008 16:00:28 +0000 Subject: [PATCH 057/132] New enable_shared_from_this tests, fix. [SVN r43829] --- include/boost/enable_shared_from_this.hpp | 2 +- test/esft_regtest.cpp | 38 ++++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 9a71ae2..f378272 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -95,7 +95,7 @@ public: { init_internal_shared_once(); get_deleter(_internal_shared_this)->set_deleter(owner); - owner = dynamic_pointer_cast(_internal_shared_this); + owner.reset( _internal_shared_this, owner.get() ); _internal_shared_this.reset(); _owned = true; } diff --git a/test/esft_regtest.cpp b/test/esft_regtest.cpp index 0e3036c..8bc8cd6 100644 --- a/test/esft_regtest.cpp +++ b/test/esft_regtest.cpp @@ -16,6 +16,7 @@ #include #include #include +#include class X: public boost::enable_shared_from_this< X > { @@ -65,7 +66,7 @@ public: int X::instances = 0; -int main() +void test() { BOOST_TEST( X::instances == 0 ); @@ -131,6 +132,41 @@ int main() } BOOST_TEST( X::instances == 0 ); +} + +struct V: public boost::enable_shared_from_this +{ + virtual ~V() {} + std::string m_; +}; + +struct V2 +{ + virtual ~V2() {} + std::string m2_; +}; + +struct W: V2, V +{ +}; + +void test2() +{ + boost::shared_ptr p( new W ); +} + +void test3() +{ + V * p = new W; + boost::shared_ptr pv( p ); + BOOST_TEST( pv.get() == p ); +} + +int main() +{ + test(); + test2(); + test3(); return boost::report_errors(); } From dc6a8f069643b5dda0ef1b113a6d3852a83be464 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 25 Mar 2008 15:46:40 +0000 Subject: [PATCH 058/132] _internal_accept_owner now checks if _owned isn't already true. [SVN r43856] --- include/boost/enable_shared_from_this.hpp | 16 ++++++++++++---- test/esft_regtest.cpp | 12 ++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index f378272..2ead3fd 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -94,10 +94,18 @@ public: void _internal_accept_owner(shared_ptr &owner) const { init_internal_shared_once(); - get_deleter(_internal_shared_this)->set_deleter(owner); - owner.reset( _internal_shared_this, owner.get() ); - _internal_shared_this.reset(); - _owned = true; + + if( !_owned ) + { + detail::sp_deleter_wrapper * pd = get_deleter(_internal_shared_this); + BOOST_ASSERT( pd != 0 ); + pd->set_deleter(owner); + + owner.reset( _internal_shared_this, owner.get() ); + _internal_shared_this.reset(); + + _owned = true; + } } }; diff --git a/test/esft_regtest.cpp b/test/esft_regtest.cpp index 8bc8cd6..35f672e 100644 --- a/test/esft_regtest.cpp +++ b/test/esft_regtest.cpp @@ -162,11 +162,23 @@ void test3() BOOST_TEST( pv.get() == p ); } +struct null_deleter +{ + void operator()( void const* ) const {} +}; + +void test4() +{ + boost::shared_ptr pv( new V ); + boost::shared_ptr pv2( pv.get(), null_deleter() ); +} + int main() { test(); test2(); test3(); + test4(); return boost::report_errors(); } From 5df69a894665afa2c31ee18b906968f3cbabb313 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 26 Mar 2008 18:34:29 +0000 Subject: [PATCH 059/132] Added "Throws: nothing" to get_deleter. [SVN r43873] --- shared_ptr.htm | 1 + 1 file changed, 1 insertion(+) diff --git a/shared_ptr.htm b/shared_ptr.htm index a752629..5b4444f 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -522,6 +522,7 @@ q = p;

Returns: If *this owns a deleter d of type (cv-unqualified) D, returns &d; otherwise returns 0.

+

Throws: nothing.

Example

See shared_ptr_example.cpp for a From b08789b784200611bc0e340668bec6c26851c692 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 27 Mar 2008 22:13:55 +0000 Subject: [PATCH 060/132] Silence unused parameter warning. [SVN r43887] --- include/boost/shared_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index c570791..1c0ad80 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -261,7 +261,7 @@ public: // constructor that doesn't trigger enable_shared_from_this code, needed // for enable_shared_from_this internal implementation - template shared_ptr(Y * p, D d, detail::ignore_enable_shared_from_this_tag tag): + template shared_ptr(Y * p, D d, detail::ignore_enable_shared_from_this_tag): px(p), pn(p, d) {} From bb076d67e66ac3c317a87b11be56ee8b658d094b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 27 Mar 2008 22:20:11 +0000 Subject: [PATCH 061/132] detail::yield(k) added. [SVN r43888] --- include/boost/detail/yield_k.hpp | 132 +++++++++++++++++++++++++++++++ test/Jamfile.v2 | 1 + test/yield_k_test.cpp | 23 ++++++ 3 files changed, 156 insertions(+) create mode 100644 include/boost/detail/yield_k.hpp create mode 100644 test/yield_k_test.cpp diff --git a/include/boost/detail/yield_k.hpp b/include/boost/detail/yield_k.hpp new file mode 100644 index 0000000..08dfc8f --- /dev/null +++ b/include/boost/detail/yield_k.hpp @@ -0,0 +1,132 @@ +#ifndef BOOST_DETAIL_YIELD_K_HPP_INCLUDED +#define BOOST_DETAIL_YIELD_K_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/yield_k.hpp +// +// Copyright (c) 2008 Peter Dimov +// +// void yield( unsigned k ); +// +// Typical use: +// +// for( unsigned k = 0; !try_lock(); ++k ) yield( k ); +// +// 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( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) + +#if defined( BOOST_USE_WINDOWS_H ) +# include +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1310 + extern "C" void _mm_pause(); +#endif + +namespace boost +{ + +namespace detail +{ + +#if !defined( BOOST_USE_WINDOWS_H ) + extern "C" void __stdcall Sleep( unsigned ms ); +#endif + +void yield( unsigned k ) +{ + if( k < 4 ) + { + } +#if defined(_MSC_VER) && _MSC_VER >= 1310 + else if( k < 16 ) + { + _mm_pause(); + } +#endif + else if( k < 32 ) + { + Sleep( 0 ); + } + else + { + Sleep( 1 ); + } +} + +} // namespace detail + +} // namespace boost + +#elif defined( BOOST_HAS_PTHREADS ) + +#include +#include + +namespace boost +{ + +namespace detail +{ + +void yield( unsigned k ) +{ + if( k < 4 ) + { + } +#if defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) + else if( k < 16 ) + { + __asm__ __volatile__( "rep; nop" ::: "memory" ); + } +#endif + else if( k < 32 || k & 1 ) + { + sched_yield(); + } + else + { + struct timespec rqtp = { 0 }; + + rqtp.tv_sec = 0; + rqtp.tv_nsec = 1000; + + nanosleep( &rqtp, 0 ); + } +} + +} // namespace detail + +} // namespace boost + +#else + +namespace boost +{ + +namespace detail +{ + +inline void yield( unsigned ) +{ +} + +} // namespace detail + +} // namespace boost + +#endif + +#endif // #ifndef BOOST_DETAIL_YIELD_K_HPP_INCLUDED diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 837c83c..13109da 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -37,5 +37,6 @@ import testing ; [ compile-fail scoped_array_eq_fail.cpp ] [ run esft_regtest.cpp ] [ run esft_constructor_test.cpp ] + [ run yield_k_test.cpp ] ; } diff --git a/test/yield_k_test.cpp b/test/yield_k_test.cpp new file mode 100644 index 0000000..1e6ab13 --- /dev/null +++ b/test/yield_k_test.cpp @@ -0,0 +1,23 @@ +// +// yield_k_test.cpp +// +// Copyright 2008 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 + +// Sanity check only + +int main() +{ + for( unsigned k = 0; k < 256; ++k ) + { + boost::detail::yield( k ); + } + + return 0; +} From 24527051177db895b8fc14ca0f6da2efc4166604 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 28 Mar 2008 20:44:45 +0000 Subject: [PATCH 062/132] Missing "inline" added. [SVN r43916] --- include/boost/detail/yield_k.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/detail/yield_k.hpp b/include/boost/detail/yield_k.hpp index 08dfc8f..e3f6917 100644 --- a/include/boost/detail/yield_k.hpp +++ b/include/boost/detail/yield_k.hpp @@ -45,7 +45,7 @@ namespace detail extern "C" void __stdcall Sleep( unsigned ms ); #endif -void yield( unsigned k ) +inline void yield( unsigned k ) { if( k < 4 ) { @@ -81,7 +81,7 @@ namespace boost namespace detail { -void yield( unsigned k ) +inline void yield( unsigned k ) { if( k < 4 ) { From 6ef32e1627ad1378e930dc25fa7cc09efb87c141 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 30 Mar 2008 16:33:58 +0000 Subject: [PATCH 063/132] boost::detail::spinlock added. [SVN r43950] --- include/boost/detail/spinlock.hpp | 43 +++++++++++ include/boost/detail/spinlock_pt.hpp | 79 +++++++++++++++++++++ include/boost/detail/spinlock_sync.hpp | 83 ++++++++++++++++++++++ include/boost/detail/spinlock_w32.hpp | 98 ++++++++++++++++++++++++++ test/Jamfile.v2 | 1 + test/spinlock_test.cpp | 46 ++++++++++++ 6 files changed, 350 insertions(+) create mode 100644 include/boost/detail/spinlock.hpp create mode 100644 include/boost/detail/spinlock_pt.hpp create mode 100644 include/boost/detail/spinlock_sync.hpp create mode 100644 include/boost/detail/spinlock_w32.hpp create mode 100644 test/spinlock_test.cpp diff --git a/include/boost/detail/spinlock.hpp b/include/boost/detail/spinlock.hpp new file mode 100644 index 0000000..605fccb --- /dev/null +++ b/include/boost/detail/spinlock.hpp @@ -0,0 +1,43 @@ +#ifndef BOOST_DETAIL_SPINLOCK_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/spinlock.hpp +// +// Copyright (c) 2008 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) +// +// struct spinlock +// { +// void lock(); +// bool try_lock(); +// void unlock(); +// +// class scoped_lock; +// }; +// +// #define BOOST_DETAIL_SPINLOCK_INIT +// + +#include + +#if defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) +# include +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# include +#elif defined(BOOST_HAS_PTHREADS) +# include +#else +# error Unrecognized threading platform +#endif + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_pt.hpp b/include/boost/detail/spinlock_pt.hpp new file mode 100644 index 0000000..dfb2d6f --- /dev/null +++ b/include/boost/detail/spinlock_pt.hpp @@ -0,0 +1,79 @@ +#ifndef BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 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 + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + pthread_mutex_t v_; + +public: + + bool try_lock() + { + return pthread_mutex_trylock( &v_ ) == 0; + } + + void lock() + { + pthread_mutex_lock( &v_ ); + } + + void unlock() + { + pthread_mutex_unlock( &v_ ); + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT { PTHREAD_MUTEX_INITIALIZER } + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_sync.hpp b/include/boost/detail/spinlock_sync.hpp new file mode 100644 index 0000000..d602365 --- /dev/null +++ b/include/boost/detail/spinlock_sync.hpp @@ -0,0 +1,83 @@ +#ifndef BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 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 + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + int v_; + +public: + + bool try_lock() + { + int r = __sync_lock_test_and_set( &v_, 1 ); + return r == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + __sync_lock_release( &v_ ); + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {0} + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_w32.hpp b/include/boost/detail/spinlock_w32.hpp new file mode 100644 index 0000000..5d0b824 --- /dev/null +++ b/include/boost/detail/spinlock_w32.hpp @@ -0,0 +1,98 @@ +#ifndef BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 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 +#include + +#if defined( _MSC_VER ) && _MSC_VER >= 1310 + extern "C" void _ReadWriteBarrier(); +# pragma intrinsic( _ReadWriteBarrier ) +#endif + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + long v_; + +public: + + bool try_lock() + { + long r = BOOST_INTERLOCKED_EXCHANGE( &v_, 1 ); + +#if defined( _MSC_VER ) && _MSC_VER >= 1310 + _ReadWriteBarrier(); +#endif + + return r == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { +#if defined( _MSC_VER ) && _MSC_VER >= 1310 + _ReadWriteBarrier(); +#endif + + *const_cast< long volatile* >( &v_ ) = 0; + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {0} + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 13109da..d3b92a3 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -38,5 +38,6 @@ import testing ; [ run esft_regtest.cpp ] [ run esft_constructor_test.cpp ] [ run yield_k_test.cpp ] + [ run spinlock_test.cpp ] ; } diff --git a/test/spinlock_test.cpp b/test/spinlock_test.cpp new file mode 100644 index 0000000..faec048 --- /dev/null +++ b/test/spinlock_test.cpp @@ -0,0 +1,46 @@ +// +// spinlock_test.cpp +// +// Copyright 2008 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 +#include + +// Sanity check only + +static boost::detail::spinlock sp = BOOST_DETAIL_SPINLOCK_INIT; +static boost::detail::spinlock sp2 = BOOST_DETAIL_SPINLOCK_INIT; + +int main() +{ + BOOST_TEST( sp.try_lock() ); + BOOST_TEST( !sp.try_lock() ); + BOOST_TEST( sp2.try_lock() ); + BOOST_TEST( !sp.try_lock() ); + BOOST_TEST( !sp2.try_lock() ); + sp.unlock(); + sp2.unlock(); + + sp.lock(); + BOOST_TEST( !sp.try_lock() ); + sp2.lock(); + BOOST_TEST( !sp.try_lock() ); + BOOST_TEST( !sp2.try_lock() ); + sp.unlock(); + sp2.unlock(); + + { + boost::detail::spinlock::scoped_lock lock( sp ); + BOOST_TEST( !sp.try_lock() ); + boost::detail::spinlock::scoped_lock lock2( sp2 ); + BOOST_TEST( !sp.try_lock() ); + BOOST_TEST( !sp2.try_lock() ); + } + + return boost::report_errors(); +} From 515be965bdf067184b794014fed37560b914fd30 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 2 Apr 2008 21:42:52 +0000 Subject: [PATCH 064/132] Fix #1759 in trunk. [SVN r44004] --- include/boost/detail/sp_counted_base_acc_ia64.hpp | 2 +- include/boost/detail/sp_counted_base_cw_ppc.hpp | 2 +- include/boost/detail/sp_counted_base_cw_x86.hpp | 2 +- include/boost/detail/sp_counted_base_gcc_ia64.hpp | 2 +- include/boost/detail/sp_counted_base_gcc_ppc.hpp | 2 +- include/boost/detail/sp_counted_base_gcc_sparc.hpp | 2 +- include/boost/detail/sp_counted_base_gcc_x86.hpp | 2 +- include/boost/detail/sp_counted_base_nt.hpp | 2 +- include/boost/detail/sp_counted_base_pt.hpp | 2 +- include/boost/detail/sp_counted_base_solaris.hpp | 2 +- include/boost/detail/sp_counted_base_sync.hpp | 2 +- include/boost/detail/sp_counted_base_w32.hpp | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/boost/detail/sp_counted_base_acc_ia64.hpp b/include/boost/detail/sp_counted_base_acc_ia64.hpp index 94c015d..c956b8e 100644 --- a/include/boost/detail/sp_counted_base_acc_ia64.hpp +++ b/include/boost/detail/sp_counted_base_acc_ia64.hpp @@ -15,7 +15,7 @@ // Lock-free algorithm by Alexander Terekhov // -#include "sp_typeinfo.hpp" +#include #include namespace boost diff --git a/include/boost/detail/sp_counted_base_cw_ppc.hpp b/include/boost/detail/sp_counted_base_cw_ppc.hpp index 17fb736..3f43252 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 "sp_typeinfo.hpp" +#include namespace boost { diff --git a/include/boost/detail/sp_counted_base_cw_x86.hpp b/include/boost/detail/sp_counted_base_cw_x86.hpp index 32dd02c..b2e3f9b 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 "sp_typeinfo.hpp" +#include namespace boost { diff --git a/include/boost/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/detail/sp_counted_base_gcc_ia64.hpp index 70b2a26..7535295 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 "sp_typeinfo.hpp" +#include namespace boost { diff --git a/include/boost/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/detail/sp_counted_base_gcc_ppc.hpp index 5a488f5..cea2740 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 "sp_typeinfo.hpp" +#include namespace boost { diff --git a/include/boost/detail/sp_counted_base_gcc_sparc.hpp b/include/boost/detail/sp_counted_base_gcc_sparc.hpp index c6624cf..2afca16 100644 --- a/include/boost/detail/sp_counted_base_gcc_sparc.hpp +++ b/include/boost/detail/sp_counted_base_gcc_sparc.hpp @@ -19,7 +19,7 @@ // // Thanks to Michael van der Westhuizen -#include "sp_typeinfo.hpp" +#include #include // int32_t namespace boost diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/detail/sp_counted_base_gcc_x86.hpp index 7d243de..8bf3171 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 "sp_typeinfo.hpp" +#include namespace boost { diff --git a/include/boost/detail/sp_counted_base_nt.hpp b/include/boost/detail/sp_counted_base_nt.hpp index 626e06f..dc7a042 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 "sp_typeinfo.hpp" +#include namespace boost { diff --git a/include/boost/detail/sp_counted_base_pt.hpp b/include/boost/detail/sp_counted_base_pt.hpp index 6e0835f..cd30de9 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 "sp_typeinfo.hpp" +#include #include namespace boost diff --git a/include/boost/detail/sp_counted_base_solaris.hpp b/include/boost/detail/sp_counted_base_solaris.hpp index 58119db..a747b39 100644 --- a/include/boost/detail/sp_counted_base_solaris.hpp +++ b/include/boost/detail/sp_counted_base_solaris.hpp @@ -20,7 +20,7 @@ // formulation // -#include "sp_typeinfo.hpp" +#include #include namespace boost diff --git a/include/boost/detail/sp_counted_base_sync.hpp b/include/boost/detail/sp_counted_base_sync.hpp index bf2a0fb..c01c3c5 100644 --- a/include/boost/detail/sp_counted_base_sync.hpp +++ b/include/boost/detail/sp_counted_base_sync.hpp @@ -15,7 +15,7 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt -#include "sp_typeinfo.hpp" +#include #include namespace boost diff --git a/include/boost/detail/sp_counted_base_w32.hpp b/include/boost/detail/sp_counted_base_w32.hpp index 4328962..f990393 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 "sp_typeinfo.hpp" +#include namespace boost { From acb6824ef724f0e32f4a38a4f8aeacc99c4ce63d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 5 Apr 2008 15:06:31 +0000 Subject: [PATCH 065/132] spinlock_nt.hpp added, Cygwin fixes. [SVN r44055] --- include/boost/detail/spinlock.hpp | 4 +- include/boost/detail/spinlock_nt.hpp | 67 ++++++++++++++++++++++++++++ include/boost/detail/yield_k.hpp | 3 +- test/Jamfile.v2 | 1 + test/spinlock_test.cpp | 17 +------ test/spinlock_try_test.cpp | 46 +++++++++++++++++++ 6 files changed, 120 insertions(+), 18 deletions(-) create mode 100644 include/boost/detail/spinlock_nt.hpp create mode 100644 test/spinlock_try_test.cpp diff --git a/include/boost/detail/spinlock.hpp b/include/boost/detail/spinlock.hpp index 605fccb..4fbf553 100644 --- a/include/boost/detail/spinlock.hpp +++ b/include/boost/detail/spinlock.hpp @@ -32,10 +32,12 @@ #if defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) # include -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include #elif defined(BOOST_HAS_PTHREADS) # include +#elif !defined(BOOST_HAS_THREADS) +# include #else # error Unrecognized threading platform #endif diff --git a/include/boost/detail/spinlock_nt.hpp b/include/boost/detail/spinlock_nt.hpp new file mode 100644 index 0000000..106c7e7 --- /dev/null +++ b/include/boost/detail/spinlock_nt.hpp @@ -0,0 +1,67 @@ +#ifndef BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 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 spinlock +{ +public: + + inline bool try_lock() + { + return true; + } + + inline void lock() + { + } + + inline void unlock() + { + } + +public: + + class scoped_lock + { + private: + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & /*sp*/ ) + { + } + + ~scoped_lock() + { + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {} + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED diff --git a/include/boost/detail/yield_k.hpp b/include/boost/detail/yield_k.hpp index e3f6917..fea98d4 100644 --- a/include/boost/detail/yield_k.hpp +++ b/include/boost/detail/yield_k.hpp @@ -25,7 +25,7 @@ #include -#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) +#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) #if defined( BOOST_USE_WINDOWS_H ) # include @@ -33,6 +33,7 @@ #if defined(_MSC_VER) && _MSC_VER >= 1310 extern "C" void _mm_pause(); +# pragma intrinsic( _mm_pause ) #endif namespace boost diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d3b92a3..d77a4b3 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -39,5 +39,6 @@ import testing ; [ run esft_constructor_test.cpp ] [ run yield_k_test.cpp ] [ run spinlock_test.cpp ] + [ run spinlock_try_test.cpp ] ; } diff --git a/test/spinlock_test.cpp b/test/spinlock_test.cpp index faec048..0820b96 100644 --- a/test/spinlock_test.cpp +++ b/test/spinlock_test.cpp @@ -9,7 +9,6 @@ // #include -#include // Sanity check only @@ -18,29 +17,15 @@ static boost::detail::spinlock sp2 = BOOST_DETAIL_SPINLOCK_INIT; int main() { - BOOST_TEST( sp.try_lock() ); - BOOST_TEST( !sp.try_lock() ); - BOOST_TEST( sp2.try_lock() ); - BOOST_TEST( !sp.try_lock() ); - BOOST_TEST( !sp2.try_lock() ); - sp.unlock(); - sp2.unlock(); - sp.lock(); - BOOST_TEST( !sp.try_lock() ); sp2.lock(); - BOOST_TEST( !sp.try_lock() ); - BOOST_TEST( !sp2.try_lock() ); sp.unlock(); sp2.unlock(); { boost::detail::spinlock::scoped_lock lock( sp ); - BOOST_TEST( !sp.try_lock() ); boost::detail::spinlock::scoped_lock lock2( sp2 ); - BOOST_TEST( !sp.try_lock() ); - BOOST_TEST( !sp2.try_lock() ); } - return boost::report_errors(); + return 0; } diff --git a/test/spinlock_try_test.cpp b/test/spinlock_try_test.cpp new file mode 100644 index 0000000..59e3390 --- /dev/null +++ b/test/spinlock_try_test.cpp @@ -0,0 +1,46 @@ +// +// spinlock_try_test.cpp +// +// Copyright 2008 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 +#include + +// Sanity check only + +static boost::detail::spinlock sp = BOOST_DETAIL_SPINLOCK_INIT; +static boost::detail::spinlock sp2 = BOOST_DETAIL_SPINLOCK_INIT; + +int main() +{ + BOOST_TEST( sp.try_lock() ); + BOOST_TEST( !sp.try_lock() ); + BOOST_TEST( sp2.try_lock() ); + BOOST_TEST( !sp.try_lock() ); + BOOST_TEST( !sp2.try_lock() ); + sp.unlock(); + sp2.unlock(); + + sp.lock(); + BOOST_TEST( !sp.try_lock() ); + sp2.lock(); + BOOST_TEST( !sp.try_lock() ); + BOOST_TEST( !sp2.try_lock() ); + sp.unlock(); + sp2.unlock(); + + { + boost::detail::spinlock::scoped_lock lock( sp ); + BOOST_TEST( !sp.try_lock() ); + boost::detail::spinlock::scoped_lock lock2( sp2 ); + BOOST_TEST( !sp.try_lock() ); + BOOST_TEST( !sp2.try_lock() ); + } + + return boost::report_errors(); +} From 373c52efa330eff0c9d02a579968b9d0ee7eb14b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 5 Apr 2008 15:23:28 +0000 Subject: [PATCH 066/132] BOOST_SMT_PAUSE factored out. [SVN r44056] --- include/boost/detail/yield_k.hpp | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/include/boost/detail/yield_k.hpp b/include/boost/detail/yield_k.hpp index fea98d4..d856d57 100644 --- a/include/boost/detail/yield_k.hpp +++ b/include/boost/detail/yield_k.hpp @@ -25,17 +25,29 @@ #include +// BOOST_SMT_PAUSE + +#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) + +extern "C" void _mm_pause(); +#pragma intrinsic( _mm_pause ) + +#define BOOST_SMT_PAUSE _mm_pause(); + +#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) + +#define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" ::: "memory" ); + +#endif + +// + #if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) #if defined( BOOST_USE_WINDOWS_H ) # include #endif -#if defined(_MSC_VER) && _MSC_VER >= 1310 - extern "C" void _mm_pause(); -# pragma intrinsic( _mm_pause ) -#endif - namespace boost { @@ -51,10 +63,10 @@ inline void yield( unsigned k ) if( k < 4 ) { } -#if defined(_MSC_VER) && _MSC_VER >= 1310 +#if defined( BOOST_SMT_PAUSE ) else if( k < 16 ) { - _mm_pause(); + BOOST_SMT_PAUSE } #endif else if( k < 32 ) @@ -87,10 +99,10 @@ inline void yield( unsigned k ) if( k < 4 ) { } -#if defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) +#if defined( BOOST_SMT_PAUSE ) else if( k < 16 ) { - __asm__ __volatile__( "rep; nop" ::: "memory" ); + BOOST_SMT_PAUSE } #endif else if( k < 32 || k & 1 ) From 6b25c577122e2126f577d736db6a0c5374c6135d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 5 Apr 2008 16:32:49 +0000 Subject: [PATCH 067/132] BOOST_COMPILER_FENCE factored out. [SVN r44058] --- include/boost/detail/spinlock_w32.hpp | 35 +++++++++++++++++++-------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/include/boost/detail/spinlock_w32.hpp b/include/boost/detail/spinlock_w32.hpp index 5d0b824..76cfe8f 100644 --- a/include/boost/detail/spinlock_w32.hpp +++ b/include/boost/detail/spinlock_w32.hpp @@ -18,11 +18,31 @@ #include #include -#if defined( _MSC_VER ) && _MSC_VER >= 1310 - extern "C" void _ReadWriteBarrier(); -# pragma intrinsic( _ReadWriteBarrier ) +// BOOST_COMPILER_FENCE + +#if defined(__INTEL_COMPILER) + +#define BOOST_COMPILER_FENCE __memory_barrier(); + +#elif defined( _MSC_VER ) && _MSC_VER >= 1310 + +extern "C" void _ReadWriteBarrier(); +#pragma intrinsic( _ReadWriteBarrier ) + +#define BOOST_COMPILER_FENCE _ReadWriteBarrier(); + +#elif defined(__GNUC__) + +#define BOOST_COMPILER_FENCE __asm__ __volatile__( "" ::: "memory" ); + +#else + +#define BOOST_COMPILER_FENCE + #endif +// + namespace boost { @@ -41,9 +61,7 @@ public: { long r = BOOST_INTERLOCKED_EXCHANGE( &v_, 1 ); -#if defined( _MSC_VER ) && _MSC_VER >= 1310 - _ReadWriteBarrier(); -#endif + BOOST_COMPILER_FENCE return r == 0; } @@ -58,10 +76,7 @@ public: void unlock() { -#if defined( _MSC_VER ) && _MSC_VER >= 1310 - _ReadWriteBarrier(); -#endif - + BOOST_COMPILER_FENCE *const_cast< long volatile* >( &v_ ) = 0; } From 4880292c07fd89a78fb9d070ee3c8b77f56f55aa Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 6 Apr 2008 16:23:42 +0000 Subject: [PATCH 068/132] Add MT runs of yield_k_test and spinlock_try_test. [SVN r44073] --- test/Jamfile.v2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d77a4b3..5c0a459 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -38,7 +38,9 @@ import testing ; [ run esft_regtest.cpp ] [ run esft_constructor_test.cpp ] [ run yield_k_test.cpp ] + [ run yield_k_test.cpp : : : multi : yield_k_test.mt ] [ run spinlock_test.cpp ] [ run spinlock_try_test.cpp ] + [ run spinlock_try_test.cpp : : : multi : spinlock_try_test.mt ] ; } From 748b1baee8420f381e95fd7b1cea384bef7bde09 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 6 Apr 2008 16:53:11 +0000 Subject: [PATCH 069/132] detail/spinlock_pool.hpp added. [SVN r44074] --- include/boost/detail/spinlock_pool.hpp | 85 ++++++++++++++++++++++++++ test/Jamfile.v2 | 1 + test/spinlock_pool_test.cpp | 30 +++++++++ 3 files changed, 116 insertions(+) create mode 100644 include/boost/detail/spinlock_pool.hpp create mode 100644 test/spinlock_pool_test.cpp diff --git a/include/boost/detail/spinlock_pool.hpp b/include/boost/detail/spinlock_pool.hpp new file mode 100644 index 0000000..b50ccb5 --- /dev/null +++ b/include/boost/detail/spinlock_pool.hpp @@ -0,0 +1,85 @@ +#ifndef BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/spinlock_pool.hpp +// +// Copyright (c) 2008 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) +// +// spinlock_pool<0> is reserved for atomic<>, when/if it arrives +// spinlock_pool<1> is reserved for shared_ptr reference counts +// spinlock_pool<2> is reserved for shared_ptr atomic access +// + +#include + +namespace boost +{ + +namespace detail +{ + +template< int I > class spinlock_pool +{ +private: + + static spinlock pool_[ 41 ]; + +public: + + static spinlock & spinlock_for( void * pv ) + { + size_t i = reinterpret_cast< size_t >( pv ) % 41; + return pool_[ i ]; + } + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( void * pv ): sp_( spinlock_for( pv ) ) + { + sp_.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +template< int I > spinlock spinlock_pool< I >::pool_[ 41 ] = +{ + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT +}; + +} // namespace detail +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5c0a459..0ccc984 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -42,5 +42,6 @@ import testing ; [ run spinlock_test.cpp ] [ run spinlock_try_test.cpp ] [ run spinlock_try_test.cpp : : : multi : spinlock_try_test.mt ] + [ run spinlock_pool_test.cpp ] ; } diff --git a/test/spinlock_pool_test.cpp b/test/spinlock_pool_test.cpp new file mode 100644 index 0000000..00e7558 --- /dev/null +++ b/test/spinlock_pool_test.cpp @@ -0,0 +1,30 @@ +// +// spinlock_pool_test.cpp +// +// Copyright 2008 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 + +// Sanity check only + +int main() +{ + int x = 0; + + { + boost::detail::spinlock_pool<0>::scoped_lock lock( &x ); + ++x; + } + + { + boost::detail::spinlock_pool<1>::scoped_lock lock( &x ); + boost::detail::spinlock_pool<2>::scoped_lock lock2( &x ); + } + + return 0; +} From b4885a1dd6df5aa0e6652123ccc44ca22290fcdd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 9 Apr 2008 17:49:20 +0000 Subject: [PATCH 070/132] Proper try_lock semantics. [SVN r44132] --- include/boost/detail/spinlock_nt.hpp | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/include/boost/detail/spinlock_nt.hpp b/include/boost/detail/spinlock_nt.hpp index 106c7e7..f03ba08 100644 --- a/include/boost/detail/spinlock_nt.hpp +++ b/include/boost/detail/spinlock_nt.hpp @@ -15,6 +15,8 @@ // http://www.boost.org/LICENSE_1_0.txt) // +#include + namespace boost { @@ -23,19 +25,35 @@ namespace detail class spinlock { +public: + + bool locked_; + public: inline bool try_lock() { - return true; + if( locked_ ) + { + return false; + } + else + { + locked_ = true; + return true; + } } inline void lock() { + BOOST_ASSERT( !locked_ ); + locked_ = true; } inline void unlock() { + BOOST_ASSERT( locked_ ); + locked_ = false; } public: @@ -44,17 +62,21 @@ public: { private: + spinlock & sp_; + scoped_lock( scoped_lock const & ); scoped_lock & operator=( scoped_lock const & ); public: - explicit scoped_lock( spinlock & /*sp*/ ) + explicit scoped_lock( spinlock & sp ): sp_( sp ) { + sp.lock(); } ~scoped_lock() { + sp_.unlock(); } }; }; @@ -62,6 +84,6 @@ public: } // namespace detail } // namespace boost -#define BOOST_DETAIL_SPINLOCK_INIT {} +#define BOOST_DETAIL_SPINLOCK_INIT { false } #endif // #ifndef BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED From d8296b393300828ea3077c1763f694eea3ad7ec2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 9 Apr 2008 19:58:54 +0000 Subject: [PATCH 071/132] sp_counted_base_spin.hpp added, enabled by BOOST_SP_USE_SPINLOCK. [SVN r44137] --- include/boost/detail/sp_counted_base.hpp | 4 + include/boost/detail/sp_counted_base_spin.hpp | 131 ++++++++++++++++++ include/boost/detail/spinlock_pool.hpp | 4 +- 3 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 include/boost/detail/sp_counted_base_spin.hpp diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index f925a5d..241b2de 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -23,6 +23,10 @@ # include +#elif defined( BOOST_SP_USE_SPINLOCK ) + +# include + #elif defined( BOOST_SP_USE_PTHREADS ) # include diff --git a/include/boost/detail/sp_counted_base_spin.hpp b/include/boost/detail/sp_counted_base_spin.hpp new file mode 100644 index 0000000..610a468 --- /dev/null +++ b/include/boost/detail/sp_counted_base_spin.hpp @@ -0,0 +1,131 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_spin.hpp - spinlock pool atomic emulation +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2008 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 +#include + +namespace boost +{ + +namespace detail +{ + +inline int atomic_exchange_and_add( int * pw, int dv ) +{ + spinlock_pool<1>::scoped_lock lock( pw ); + + int r = *pw; + *pw += dv; + return r; +} + +inline void atomic_increment( int * pw ) +{ + spinlock_pool<1>::scoped_lock lock( pw ); + ++*pw; +} + +inline int atomic_conditional_increment( int * pw ) +{ + spinlock_pool<1>::scoped_lock lock( pw ); + + int rv = *pw; + if( rv != 0 ) ++*pw; + return rv; +} + +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_exchange_and_add( &use_count_, -1 ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + spinlock_pool<1>::scoped_lock lock( &use_count_ ); + return use_count_; + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_pool.hpp b/include/boost/detail/spinlock_pool.hpp index b50ccb5..92d26cb 100644 --- a/include/boost/detail/spinlock_pool.hpp +++ b/include/boost/detail/spinlock_pool.hpp @@ -37,7 +37,7 @@ private: public: - static spinlock & spinlock_for( void * pv ) + static spinlock & spinlock_for( void const * pv ) { size_t i = reinterpret_cast< size_t >( pv ) % 41; return pool_[ i ]; @@ -54,7 +54,7 @@ public: public: - explicit scoped_lock( void * pv ): sp_( spinlock_for( pv ) ) + explicit scoped_lock( void const * pv ): sp_( spinlock_for( pv ) ) { sp_.lock(); } From e4f638025c4117221420e7b453ce99b8b1646b6f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 9 Apr 2008 21:08:39 +0000 Subject: [PATCH 072/132] spinlock_gcc_arm.hpp added. [SVN r44138] --- include/boost/detail/spinlock.hpp | 4 +- include/boost/detail/spinlock_gcc_arm.hpp | 85 +++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 include/boost/detail/spinlock_gcc_arm.hpp diff --git a/include/boost/detail/spinlock.hpp b/include/boost/detail/spinlock.hpp index 4fbf553..e273647 100644 --- a/include/boost/detail/spinlock.hpp +++ b/include/boost/detail/spinlock.hpp @@ -30,7 +30,9 @@ #include -#if defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) +#if defined(__GNUC__) && defined( __arm__ ) +# include +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include diff --git a/include/boost/detail/spinlock_gcc_arm.hpp b/include/boost/detail/spinlock_gcc_arm.hpp new file mode 100644 index 0000000..2bb656a --- /dev/null +++ b/include/boost/detail/spinlock_gcc_arm.hpp @@ -0,0 +1,85 @@ +#ifndef BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED + +// +// Copyright (c) 2008 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 + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + int v_; + +public: + + bool try_lock() + { + int r; + + __asm__ __volatile__( + "swp %0, %1, [%2]": + "=r"( r ): // outputs + "r"( 1 ), "r"( &v_ ): // inputs + "memory", "cc" ); + + return r == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + __asm__ __volatile__( "" ::: "memory" ); + *const_cast< int volatile* >( &v_ ) = 0; + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {0} + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED From dbd62686a3c5de9252d8a16b3ac25b984b0706cc Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 9 Apr 2008 23:19:22 +0000 Subject: [PATCH 073/132] ARM assembly fix. [SVN r44140] --- include/boost/detail/spinlock_gcc_arm.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/spinlock_gcc_arm.hpp b/include/boost/detail/spinlock_gcc_arm.hpp index 2bb656a..c21163b 100644 --- a/include/boost/detail/spinlock_gcc_arm.hpp +++ b/include/boost/detail/spinlock_gcc_arm.hpp @@ -31,7 +31,7 @@ public: __asm__ __volatile__( "swp %0, %1, [%2]": - "=r"( r ): // outputs + "=&r"( r ): // outputs "r"( 1 ), "r"( &v_ ): // inputs "memory", "cc" ); From f85a1bf4063886595140599287d0821d37afeab7 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Apr 2008 14:27:22 +0000 Subject: [PATCH 074/132] shared_ptr::lock no longer requires exceptions. [SVN r44344] --- include/boost/detail/shared_count.hpp | 19 +++++++++++++++++++ include/boost/shared_ptr.hpp | 9 +++++++++ include/boost/weak_ptr.hpp | 26 +------------------------- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 085b12f..1eae671 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -46,6 +46,8 @@ int const weak_count_id = 0x298C38A4; #endif +struct sp_nothrow_tag {}; + class weak_count; class shared_count @@ -216,6 +218,7 @@ public: } explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 + shared_count( weak_count const & r, sp_nothrow_tag ); // constructs an empty *this when r.use_count() == 0 shared_count & operator= (shared_count const & r) // nothrow { @@ -248,6 +251,11 @@ public: return use_count() == 1; } + bool empty() const // nothrow + { + return pi_ == 0; + } + friend inline bool operator==(shared_count const & a, shared_count const & b) { return a.pi_ == b.pi_; @@ -364,6 +372,17 @@ inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ ) } } +inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ ) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif +{ + if( pi_ != 0 && !pi_->add_ref_lock() ) + { + pi_ = 0; + } +} + } // namespace detail } // namespace boost diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 1c0ad80..4b23ec1 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -220,6 +220,15 @@ public: px = r.px; } + template + shared_ptr( weak_ptr const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws + { + if( !pn.empty() ) + { + px = r.px; + } + } + template shared_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws { diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index ae606f2..4335738 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -93,31 +93,7 @@ public: shared_ptr lock() const // never throws { -#if defined(BOOST_HAS_THREADS) - - // optimization: avoid throw overhead - if(expired()) - { - return shared_ptr(); - } - - try - { - return shared_ptr(*this); - } - catch(bad_weak_ptr const &) - { - // Q: how can we get here? - // A: another thread may have invalidated r after the use_count test above. - return shared_ptr(); - } - -#else - - // optimization: avoid try/catch overhead when single threaded - return expired()? shared_ptr(): shared_ptr(*this); - -#endif + return shared_ptr( *this, boost::detail::sp_nothrow_tag() ); } long use_count() const // never throws From 4094c2353733dfd9fe568f642d701cce994cdedb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Apr 2008 18:22:18 +0000 Subject: [PATCH 075/132] sp_accept_owner added. [SVN r44353] --- include/boost/enable_shared_from_this.hpp | 26 +++- include/boost/shared_ptr.hpp | 91 ++++++-------- test/Jamfile.v2 | 1 + test/esft_constructor_test.cpp | 2 +- test/sp_accept_owner_test.cpp | 146 ++++++++++++++++++++++ 5 files changed, 207 insertions(+), 59 deletions(-) create mode 100644 test/sp_accept_owner_test.cpp diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 2ead3fd..23ec297 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -27,10 +27,10 @@ template class enable_shared_from_this // to use lazy initialization void init_internal_shared_once() const { - if(owned() == false && _internal_shared_this == 0) + if( !owned() && _internal_shared_this.get() == 0 ) { - _internal_shared_this = shared_ptr(dynamic_cast(const_cast(this)), - detail::sp_deleter_wrapper(), detail::ignore_enable_shared_from_this_tag()); + T * p = dynamic_cast(const_cast(this)); + _internal_shared_this = shared_ptr( p, detail::sp_deleter_wrapper() ); BOOST_ASSERT(_internal_shared_this.get() == this); _internal_weak_this = _internal_shared_this; } @@ -109,6 +109,26 @@ public: } }; +template< class T, class Y > inline void sp_accept_owner( boost::shared_ptr * ptr, boost::enable_shared_from_this const * pe ) +{ + if( pe != 0 ) + { + pe->_internal_accept_owner( *ptr ); + } +} + +template< class T, class Y > inline void sp_accept_owner( boost::shared_ptr * ptr, boost::enable_shared_from_this const * pe, void * /*pd*/ ) +{ + if( pe != 0 ) + { + pe->_internal_accept_owner( *ptr ); + } +} + +template< class T, class Y > inline void sp_accept_owner( boost::shared_ptr * /*ptr*/, boost::enable_shared_from_this const * /*pe*/, boost::detail::sp_deleter_wrapper * /*pd*/ ) +{ +} + } // namespace boost #endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 4b23ec1..2c9c3e6 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -50,7 +50,6 @@ namespace boost template class shared_ptr; template class weak_ptr; -template class enable_shared_from_this; namespace detail { @@ -89,48 +88,6 @@ template<> struct shared_ptr_traits #endif -// enable_shared_from_this support - -struct ignore_enable_shared_from_this_tag {}; - -template void sp_enable_shared_from_this( boost::shared_ptr * ptr, boost::enable_shared_from_this const * pe ) -{ - if(pe != 0) - { - pe->_internal_accept_owner(*ptr); - } -} - -#ifdef _MANAGED - -// Avoid C4793, ... causes native code generation - -struct sp_any_pointer -{ - template sp_any_pointer( T* ) {} -}; - -inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer ) -{ -} - -#else // _MANAGED - -#ifdef sgi -// Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed -# pragma set woff 3506 -#endif - -inline void sp_enable_shared_from_this( ... ) -{ -} - -#ifdef sgi -# pragma reset woff 3506 -#endif - -#endif // _MANAGED - #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) // rvalue auto_ptr support based on a technique by Dave Abrahams @@ -148,6 +105,32 @@ template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R } // namespace detail +// sp_accept_owner + +#ifdef _MANAGED + +// Avoid C4793, ... causes native code generation + +struct sp_any_pointer +{ + template sp_any_pointer( T* ) {} +}; + +inline void sp_accept_owner( sp_any_pointer, sp_any_pointer ) +{ +} + +inline void sp_accept_owner( sp_any_pointer, sp_any_pointer, sp_any_pointer ) +{ +} + +#else // _MANAGED + +inline void sp_accept_owner( ... ) +{ +} + +#endif // _MANAGED // // shared_ptr @@ -178,7 +161,7 @@ public: template explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { - boost::detail::sp_enable_shared_from_this( this, p ); + sp_accept_owner( this, p ); } // @@ -187,16 +170,18 @@ public: // shared_ptr will release p by calling d(p) // - template shared_ptr(Y * p, D d): px(p), pn(p, d) + template shared_ptr( Y * p, D d ): px( p ), pn( p, d ) { - boost::detail::sp_enable_shared_from_this( this, p ); + D * pd = static_cast( pn.get_deleter( BOOST_SP_TYPEID(D) ) ); + sp_accept_owner( this, p, pd ); } // As above, but with allocator. A's copy constructor shall not throw. template shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) { - boost::detail::sp_enable_shared_from_this( this, p ); + D * pd = static_cast( pn.get_deleter( BOOST_SP_TYPEID(D) ) ); + sp_accept_owner( this, p, pd ); } // generated copy constructor, assignment, destructor are fine... @@ -268,12 +253,6 @@ public: } } -// constructor that doesn't trigger enable_shared_from_this code, needed -// for enable_shared_from_this internal implementation - template shared_ptr(Y * p, D d, detail::ignore_enable_shared_from_this_tag): - px(p), pn(p, d) - {} - #ifndef BOOST_NO_AUTO_PTR template @@ -281,7 +260,8 @@ public: { Y * tmp = r.get(); pn = boost::detail::shared_count(r); - boost::detail::sp_enable_shared_from_this( this, tmp ); + + sp_accept_owner( this, tmp ); } #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) @@ -291,7 +271,8 @@ public: { typename Ap::element_type * tmp = r.get(); pn = boost::detail::shared_count( r ); - boost::detail::sp_enable_shared_from_this( this, tmp ); + + sp_accept_owner( this, tmp ); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0ccc984..499f9b9 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -43,5 +43,6 @@ import testing ; [ run spinlock_try_test.cpp ] [ run spinlock_try_test.cpp : : : multi : spinlock_try_test.mt ] [ run spinlock_pool_test.cpp ] + [ run sp_accept_owner_test.cpp ] ; } diff --git a/test/esft_constructor_test.cpp b/test/esft_constructor_test.cpp index 068f236..737123e 100644 --- a/test/esft_constructor_test.cpp +++ b/test/esft_constructor_test.cpp @@ -72,7 +72,7 @@ int X::instances = 0; template bool are_shared_owners(const boost::shared_ptr &a, const boost::shared_ptr &b) { - return a && !(a < b) && !(b < a); + return !(a < b) && !(b < a); } struct Y: public boost::enable_shared_from_this diff --git a/test/sp_accept_owner_test.cpp b/test/sp_accept_owner_test.cpp new file mode 100644 index 0000000..e8d1b32 --- /dev/null +++ b/test/sp_accept_owner_test.cpp @@ -0,0 +1,146 @@ +// +// sp_accept_owner_test.cpp +// +// Copyright (c) 2008 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 +#include +#include + +namespace N +{ + +struct D; + +struct X +{ + X * px_; + + D * pd_; + void * pv_; + + X(): px_( 0 ), pd_( 0 ), pv_( 0 ) + { + } +}; + +struct D +{ + template void operator()( T * p ) const { delete p; } +}; + +} // namespace N + +#if !defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) + +namespace N +{ + +#else + +namespace boost +{ + +#endif + +template inline void sp_accept_owner( boost::shared_ptr * ps, ::N::X * px ) +{ + std::cout << "sp_accept_owner( " << ps << ", " << px << " )\n"; + + BOOST_TEST( ps->get() == px ); + + if( px != 0 ) + { + px->px_ = px; + } +} + +template inline void sp_accept_owner( boost::shared_ptr * ps, ::N::X * px, ::N::D * pd ) +{ + std::cout << "sp_accept_owner( " << ps << ", " << px << ", (D*)" << pd << " )\n"; + + BOOST_TEST( ps->get() == px ); + + if( px != 0 ) + { + px->px_ = px; + px->pd_ = pd; + } +} + +template inline void sp_accept_owner( boost::shared_ptr * ps, ::N::X * px, void * pv ) +{ + std::cout << "sp_accept_owner( " << ps << ", " << px << ", (void*)" << pv << " )\n"; + + BOOST_TEST( ps->get() == px ); + + if( px != 0 ) + { + px->px_ = px; + px->pv_ = pv; + } +} + +} // namespace N or boost + +struct D2 +{ + template void operator()( T * p ) const { delete p; } +}; + +template void test( T* = 0 ) +{ + { + boost::shared_ptr p( static_cast< T* >( 0 ) ); + } + + { + T * p = new T; + boost::shared_ptr q( p ); + + BOOST_TEST( q->px_ == p ); + BOOST_TEST( q->pd_ == 0 ); + BOOST_TEST( q->pv_ == 0 ); + } + + { + T * p = new T; + boost::shared_ptr q( p, N::D() ); + + BOOST_TEST( q->px_ == p ); + BOOST_TEST( q->pd_ != 0 ); + BOOST_TEST( q->pv_ == 0 ); + } + + { + T * p = new T; + boost::shared_ptr q( p, D2() ); + + BOOST_TEST( q->px_ == p ); + BOOST_TEST( q->pd_ == 0 ); + BOOST_TEST( q->pv_ != 0 ); + } +} + +namespace N2 +{ + +struct Y: public virtual N::X +{ +}; + +} // namespace N2 + +int main() +{ + test(); + test(); + + return boost::report_errors(); +} From b45d011d5ae88f7519f43419cd4eb24941d8ce04 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 13 Apr 2008 15:35:40 +0000 Subject: [PATCH 076/132] Honor BOOST_DISABLE_THREADS; route GCC/ARM to the spinlock implementation; fall back to the spinlock implementation instead of using pthread_mutex. [SVN r44369] --- include/boost/detail/sp_counted_base.hpp | 30 ++++++------------------ 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index 241b2de..775dd61 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -20,65 +20,49 @@ #include #if defined( BOOST_SP_DISABLE_THREADS ) - # include #elif defined( BOOST_SP_USE_SPINLOCK ) - # include #elif defined( BOOST_SP_USE_PTHREADS ) - # include -#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) +#elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 ) +# include +#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) # include -//~ #elif defined( __MWERKS__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) - -//~ # include - #elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER ) - # include #elif defined(__HP_aCC) && defined(__ia64) - # include #elif defined( __MWERKS__ ) && defined( __POWERPC__ ) - # include #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) - # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) +#elif defined(__GNUC__) && defined( __arm__ ) +# 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 #elif !defined( BOOST_HAS_THREADS ) - # include -#elif defined( BOOST_HAS_PTHREADS ) - -# include - #else - -// Use #define BOOST_DISABLE_THREADS to avoid the error -# error Unrecognized threading platform +# include #endif From 16828c9c0ab9b5d471f27704b5e69c9e718f1d40 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 15 Apr 2008 19:02:13 +0000 Subject: [PATCH 077/132] Disabled sync use for hppa. [SVN r44441] --- include/boost/detail/sp_counted_base.hpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index 775dd61..6d733d0 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -46,10 +46,7 @@ #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) # include -#elif defined(__GNUC__) && defined( __arm__ ) -# include - -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) # include #elif defined(__GNUC__) && ( defined( __sparcv8 ) || defined( __sparcv9 ) ) From 9365853fde3061acbdd11b74b0218b80d9ef4ce0 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Wed, 16 Apr 2008 00:06:29 +0000 Subject: [PATCH 078/132] Avoid needless overhead of wrapping owner's deleter in deleter_wrapper if shared_from_this has not been called yet, as Peter suggested earlier. [SVN r44448] --- include/boost/enable_shared_from_this.hpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 23ec297..99c68ba 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -93,17 +93,21 @@ public: template void _internal_accept_owner(shared_ptr &owner) const { - init_internal_shared_once(); - if( !_owned ) { - detail::sp_deleter_wrapper * pd = get_deleter(_internal_shared_this); - BOOST_ASSERT( pd != 0 ); - pd->set_deleter(owner); - - owner.reset( _internal_shared_this, owner.get() ); - _internal_shared_this.reset(); + if( !_internal_shared_this ) + { + T * p = dynamic_cast(const_cast(this)); + _internal_weak_this = shared_ptr(owner, p); + }else + { + detail::sp_deleter_wrapper * pd = get_deleter(_internal_shared_this); + BOOST_ASSERT( pd != 0 ); + pd->set_deleter(owner); + owner.reset( _internal_shared_this, owner.get() ); + _internal_shared_this.reset(); + } _owned = true; } } From 3a578ac7c147d1bf0fa232fdac66562aa680841b Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Thu, 17 Apr 2008 13:40:44 +0000 Subject: [PATCH 079/132] Added another BOOST_ASSERT to enable_shared_from_this::_internal_accept_owner. [SVN r44499] --- include/boost/enable_shared_from_this.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 99c68ba..f474714 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -101,6 +101,7 @@ public: _internal_weak_this = shared_ptr(owner, p); }else { + BOOST_ASSERT(owner.unique()); // no weak_ptrs to owner should exist either, but there's no way to check that detail::sp_deleter_wrapper * pd = get_deleter(_internal_shared_this); BOOST_ASSERT( pd != 0 ); pd->set_deleter(owner); From 35f2af947c02bdf639c4dae29fb6b104e6633197 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Sat, 19 Apr 2008 16:28:00 +0000 Subject: [PATCH 080/132] Changed #includes to avoid circular dependencies between shared_ptr and TR1. [SVN r44595] --- include/boost/detail/shared_count.hpp | 7 +++++-- include/boost/shared_ptr.hpp | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 1eae671..4a71f20 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -28,8 +28,11 @@ #include #include #include - -#include // std::auto_ptr +// In order to avoid circular dependencies with Boost.TR1 +// we make sure that our include of doesn't try to +// pull in the TR1 headers: that's why we use this header +// rather than including directly: +#include // std::auto_ptr #include // std::less #include // std::bad_alloc diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 2c9c3e6..dc39c7a 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -20,7 +20,11 @@ #include #else -#include // for std::auto_ptr +// In order to avoid circular dependencies with Boost.TR1 +// we make sure that our include of doesn't try to +// pull in the TR1 headers: that's why we use this header +// rather than including directly: +#include // std::auto_ptr #include #include From 04be979670d977b2deda77ca5ee9900d2196b3a8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 20 Apr 2008 14:59:12 +0000 Subject: [PATCH 081/132] Atomic access added. [SVN r44636] --- include/boost/memory_order.hpp | 35 ++++++++++++++ include/boost/shared_ptr.hpp | 64 +++++++++++++++++++++++++ test/Jamfile.v2 | 1 + test/sp_atomic_test.cpp | 87 ++++++++++++++++++++++++++++++++++ 4 files changed, 187 insertions(+) create mode 100644 include/boost/memory_order.hpp create mode 100644 test/sp_atomic_test.cpp diff --git a/include/boost/memory_order.hpp b/include/boost/memory_order.hpp new file mode 100644 index 0000000..be5a9ce --- /dev/null +++ b/include/boost/memory_order.hpp @@ -0,0 +1,35 @@ +#ifndef BOOST_MEMORY_ORDER_HPP_INCLUDED +#define BOOST_MEMORY_ORDER_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// boost/memory_order.hpp +// +// Defines enum boost::memory_order per the C++0x working draft +// +// Copyright (c) 2008 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 +{ + +enum memory_order +{ + memory_order_relaxed = 0, + memory_order_acquire = 1, + memory_order_release = 2, + memory_order_acq_rel = 3, // acquire | release + memory_order_seq_cst = 7, // acq_rel | 4 +}; + +} // namespace boost + +#endif // #ifndef BOOST_MEMORY_ORDER_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index dc39c7a..9d92fd7 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -32,6 +32,11 @@ #include #include +#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) +#include +#include +#endif + #include // for std::swap #include // for std::less #include // for std::bad_cast @@ -472,6 +477,65 @@ public: return pn.get_deleter( ti ); } + // atomic access + +#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) + + shared_ptr atomic_load( memory_order /*mo*/ = memory_order_seq_cst ) const + { + boost::detail::spinlock_pool<2>::scoped_lock lock( this ); + return *this; + } + + void atomic_store( shared_ptr r, memory_order /*mo*/ = memory_order_seq_cst ) + { + boost::detail::spinlock_pool<2>::scoped_lock lock( this ); + swap( r ); + } + + shared_ptr atomic_swap( shared_ptr r, memory_order /*mo*/ = memory_order_seq_cst ) + { + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( this ); + + sp.lock(); + swap( r ); + sp.unlock(); + + return r; // return std::move(r) + } + + bool atomic_compare_swap( shared_ptr & v, shared_ptr w ) + { + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( this ); + + sp.lock(); + + if( px == v.px && pn == v.pn ) + { + swap( w ); + + sp.unlock(); + + return true; + } + else + { + shared_ptr tmp( *this ); + + sp.unlock(); + + tmp.swap( v ); + return false; + } + } + + inline bool atomic_compare_swap( shared_ptr & v, shared_ptr w, memory_order /*success*/, memory_order /*failure*/ ) + { + return atomic_compare_swap( v, w ); // std::move( w ) + } + +#endif + // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 499f9b9..ca14dd1 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -44,5 +44,6 @@ import testing ; [ run spinlock_try_test.cpp : : : multi : spinlock_try_test.mt ] [ run spinlock_pool_test.cpp ] [ run sp_accept_owner_test.cpp ] + [ run sp_atomic_test.cpp ] ; } diff --git a/test/sp_atomic_test.cpp b/test/sp_atomic_test.cpp new file mode 100644 index 0000000..c1113da --- /dev/null +++ b/test/sp_atomic_test.cpp @@ -0,0 +1,87 @@ +#include + +// sp_atomic_test.cpp +// +// Copyright (c) 2008 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 +#include + +// + +struct X +{ +}; + +#define BOOST_TEST_SP_EQ( p, q ) BOOST_TEST( p == q && !( p < q ) && !( q < p ) ) + +int main() +{ + boost::shared_ptr px( new X ); + + { + boost::shared_ptr p2 = px.atomic_load(); + BOOST_TEST_SP_EQ( p2, px ); + + boost::shared_ptr px2( new X ); + px.atomic_store( px2 ); + BOOST_TEST_SP_EQ( px, px2 ); + + p2 = px.atomic_load(); + BOOST_TEST_SP_EQ( p2, px ); + BOOST_TEST_SP_EQ( p2, px2 ); + + boost::shared_ptr px3( new X ); + boost::shared_ptr p3 = px.atomic_swap( px3 ); + BOOST_TEST_SP_EQ( p3, px2 ); + BOOST_TEST_SP_EQ( px, px3 ); + + boost::shared_ptr px4( new X ); + boost::shared_ptr cmp; + + bool r = px.atomic_compare_swap( cmp, px4 ); + BOOST_TEST( !r ); + BOOST_TEST_SP_EQ( px, px3 ); + BOOST_TEST_SP_EQ( cmp, px3 ); + + r = px.atomic_compare_swap( cmp, px4 ); + BOOST_TEST( r ); + BOOST_TEST_SP_EQ( px, px4 ); + } + + // + + px.reset(); + + { + boost::shared_ptr p2 = px.atomic_load( boost::memory_order_acquire ); + BOOST_TEST_SP_EQ( p2, px ); + + boost::shared_ptr px2( new X ); + px.atomic_store( px2, boost::memory_order_release ); + BOOST_TEST_SP_EQ( px, px2 ); + + boost::shared_ptr p3 = px.atomic_swap( boost::shared_ptr(), boost::memory_order_acq_rel ); + BOOST_TEST_SP_EQ( p3, px2 ); + BOOST_TEST_SP_EQ( px, p2 ); + + boost::shared_ptr px4( new X ); + boost::shared_ptr cmp( px2 ); + + bool r = px.atomic_compare_swap( cmp, px4, boost::memory_order_acquire, boost::memory_order_relaxed ); + BOOST_TEST( !r ); + BOOST_TEST_SP_EQ( px, p2 ); + BOOST_TEST_SP_EQ( cmp, p2 ); + + r = px.atomic_compare_swap( cmp, px4, boost::memory_order_release, boost::memory_order_acquire ); + BOOST_TEST( r ); + BOOST_TEST_SP_EQ( px, px4 ); + } + + return boost::report_errors(); +} From 71fa2cd658c930d09e150d6499c3a65e2d14ce0b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 20 Apr 2008 15:37:08 +0000 Subject: [PATCH 082/132] Factored out boost/detail/lightweight_thread.hpp. [SVN r44638] --- test/shared_ptr_mt_test.cpp | 143 +++++++----------------------------- test/weak_ptr_mt_test.cpp | 132 +++++---------------------------- 2 files changed, 46 insertions(+), 229 deletions(-) diff --git a/test/shared_ptr_mt_test.cpp b/test/shared_ptr_mt_test.cpp index fa31894..50a9f51 100644 --- a/test/shared_ptr_mt_test.cpp +++ b/test/shared_ptr_mt_test.cpp @@ -7,167 +7,76 @@ #pragma warning(disable: 4514) // unreferenced inline removed #endif -// // shared_ptr_mt_test.cpp - tests shared_ptr with multiple threads // // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2008 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) -// +// 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 #include #include -#include -#include #include #include -// 'portable' thread framework - -class abstract_thread -{ -public: - - virtual ~abstract_thread() {} - virtual void run() = 0; -}; - -#if !defined(BOOST_HAS_PTHREADS) && defined(BOOST_HAS_WINTHREADS) - -char const * title = "Using Windows threads"; - -#include -#include - -typedef HANDLE pthread_t; - -unsigned __stdcall common_thread_routine(void * pv) -{ - abstract_thread * pt = static_cast(pv); - pt->run(); - delete pt; - return 0; -} - -int pthread_create(pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg) -{ - HANDLE h = (HANDLE)_beginthreadex(0, 0, start_routine, arg, 0, 0); - - if(h != 0) - { - *thread = h; - return 0; - } - else - { - return 1; // return errno; - } -} - -int pthread_join(pthread_t thread, void ** /*value_ptr*/) -{ - ::WaitForSingleObject(thread, INFINITE); - ::CloseHandle(thread); - return 0; -} - -#else - -char const * title = "Using POSIX threads"; - -#include - -extern "C" void * common_thread_routine(void * pv) -{ - abstract_thread * pt = static_cast(pv); - pt->run(); - delete pt; - return 0; -} - -#endif - -// - -template class thread: public abstract_thread -{ -public: - - explicit thread(F f): f_(f) - { - } - - void run() - { - f_(); - } - -private: - - F f_; -}; - -template pthread_t createThread(F f) -{ - std::auto_ptr p(new thread(f)); - - pthread_t r; - - if(pthread_create(&r, 0, common_thread_routine, p.get()) == 0) - { - p.release(); - return r; - } - - throw std::runtime_error("createThread failed."); -} +#include // int const n = 1024 * 1024; -void test(boost::shared_ptr const & pi) +void test( boost::shared_ptr const & pi ) { std::vector< boost::shared_ptr > v; - for(int i = 0; i < n; ++i) + for( int i = 0; i < n; ++i ) { - v.push_back(pi); + v.push_back( pi ); } } int const m = 16; // threads +#if defined( BOOST_HAS_PTHREADS ) + +char const * thmodel = "POSIX"; + +#else + +char const * thmodel = "Windows"; + +#endif + int main() { using namespace std; // printf, clock_t, clock - printf("%s: %d threads, %d iterations: ", title, m, n); + printf( "Using %s threads: %d threads, %d iterations: ", thmodel, m, n ); - boost::shared_ptr pi(new int(42)); + boost::shared_ptr pi( new int(42) ); clock_t t = clock(); - pthread_t a[m]; + pthread_t a[ m ]; - for(int i = 0; i < m; ++i) + for( int i = 0; i < m; ++i ) { - a[i] = createThread( boost::bind(test, pi) ); + boost::detail::lw_thread_create( a[ i ], boost::bind( test, pi ) ); } - for(int j = 0; j < m; ++j) + for( int j = 0; j < m; ++j ) { - pthread_join(a[j], 0); + pthread_join( a[j], 0 ); } t = clock() - t; - printf("\n\n%.3f seconds.\n", static_cast(t) / CLOCKS_PER_SEC); + printf( "\n\n%.3f seconds.\n", static_cast(t) / CLOCKS_PER_SEC ); return 0; } diff --git a/test/weak_ptr_mt_test.cpp b/test/weak_ptr_mt_test.cpp index 442c591..04439e6 100644 --- a/test/weak_ptr_mt_test.cpp +++ b/test/weak_ptr_mt_test.cpp @@ -7,128 +7,26 @@ #pragma warning(disable: 4514) // unreferenced inline removed #endif -// // weak_ptr_mt_test.cpp // // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. -// Copyright 2005 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) +// Copyright 2005, 2008 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 #include #include #include -#include -#include #include #include #include -// 'portable' thread framework - -class abstract_thread -{ -public: - - virtual ~abstract_thread() {} - virtual void run() = 0; -}; - -#if !defined(BOOST_HAS_PTHREADS) && defined(BOOST_HAS_WINTHREADS) - -char const * title = "Using Windows threads"; - -#include -#include - -typedef HANDLE pthread_t; - -unsigned __stdcall common_thread_routine(void * pv) -{ - abstract_thread * pt = static_cast(pv); - pt->run(); - delete pt; - return 0; -} - -int pthread_create(pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg) -{ - HANDLE h = (HANDLE)_beginthreadex(0, 0, start_routine, arg, 0, 0); - - if(h != 0) - { - *thread = h; - return 0; - } - else - { - return 1; // return errno; - } -} - -int pthread_join(pthread_t thread, void ** /*value_ptr*/) -{ - ::WaitForSingleObject(thread, INFINITE); - ::CloseHandle(thread); - return 0; -} - -#else - -char const * title = "Using POSIX threads"; - -#include - -extern "C" void * common_thread_routine(void * pv) -{ - abstract_thread * pt = static_cast(pv); - pt->run(); - delete pt; - return 0; -} - -#endif - -// - -template class thread: public abstract_thread -{ -public: - - explicit thread(F f): f_(f) - { - } - - void run() - { - f_(); - } - -private: - - F f_; -}; - -template pthread_t createThread(F f) -{ - std::auto_ptr p(new thread(f)); - - pthread_t r; - - if(pthread_create(&r, 0, common_thread_routine, p.get()) == 0) - { - p.release(); - return r; - } - - throw std::runtime_error("createThread failed."); -} +#include // @@ -177,11 +75,21 @@ void test( std::vector< boost::shared_ptr > & v ) printf( "\n%d locks, %d forced rebinds, %d normal rebinds.", s, f, r ); } +#if defined( BOOST_HAS_PTHREADS ) + +char const * thmodel = "POSIX"; + +#else + +char const * thmodel = "Windows"; + +#endif + int main() { using namespace std; // printf, clock_t, clock - printf("%s: %d threads, %d * %d iterations: ", title, m, n, k ); + printf("Using %s threads: %d threads, %d * %d iterations: ", thmodel, m, n, k ); std::vector< boost::shared_ptr > v( k ); @@ -192,16 +100,16 @@ int main() clock_t t = clock(); - pthread_t a[m]; + pthread_t a[ m ]; - for(int i = 0; i < m; ++i) + for( int i = 0; i < m; ++i ) { - a[i] = createThread( boost::bind( test, v ) ); + boost::detail::lw_thread_create( a[ i ], boost::bind( test, v ) ); } v.resize( 0 ); // kill original copies - for(int j = 0; j < m; ++j) + for( int j = 0; j < m; ++j ) { pthread_join( a[j], 0 ); } From 7802c695ef79b27fcc9c152efdf8c0b8ea49be2b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 20 Apr 2008 17:00:58 +0000 Subject: [PATCH 083/132] sp_atomic_mt_test.cpp added. [SVN r44640] --- test/sp_atomic_mt_test.cpp | 184 +++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 test/sp_atomic_mt_test.cpp diff --git a/test/sp_atomic_mt_test.cpp b/test/sp_atomic_mt_test.cpp new file mode 100644 index 0000000..bef549d --- /dev/null +++ b/test/sp_atomic_mt_test.cpp @@ -0,0 +1,184 @@ +//#define USE_MUTEX +//#define USE_RWLOCK + +#include + +#include +#include + +#if defined( USE_RWLOCK ) +#include +#include +#endif + +#include +#include +#include + +#include +#include + +// + +int const n = 1024 * 1024; + +struct X +{ + int v_; // version + + unsigned a_; + unsigned b_; + + X(): v_( 0 ), a_( 1 ), b_( 1 ) + { + } + + int get() const + { + return a_ * 7 + b_ * 11; + } + + void set() + { + int tmp = get(); + + b_ = a_; + a_ = tmp; + + ++v_; + } +}; + +static boost::shared_ptr ps( new X ); + +static boost::detail::lightweight_mutex lm; + +#if defined( USE_RWLOCK ) +static boost::shared_mutex rw; +#endif + +static int tr = 0; + +void reader( int r ) +{ + int k = 0; + unsigned s = 0; + + for( int i = 0; i < n; ++k ) + { +#if defined( USE_MUTEX ) + + boost::detail::lightweight_mutex::scoped_lock lock( lm ); + + s += ps->get(); + + BOOST_TEST( ps->v_ >= i ); + i = ps->v_; + +#elif defined( USE_RWLOCK ) + + boost::shared_lock lock( rw ); + + s += ps->get(); + + BOOST_TEST( ps->v_ >= i ); + i = ps->v_; + +#else + + boost::shared_ptr p2 = ps.atomic_load(); + + s += p2->get(); + + BOOST_TEST( p2->v_ >= i ); + i = p2->v_; + +#endif + } + + printf( "Reader %d: %9d iterations (%6.3fx), %u\n", r, k, (double)k / n, s ); + + boost::detail::lightweight_mutex::scoped_lock lock( lm ); + tr += k; +} + +void writer() +{ + for( int i = 0; i < n; ++i ) + { +#if defined( USE_MUTEX ) + + boost::detail::lightweight_mutex::scoped_lock lock( lm ); + + BOOST_TEST( ps->v_ == i ); + ps->set(); + +#elif defined( USE_RWLOCK ) + + boost::unique_lock lock( rw ); + + BOOST_TEST( ps->v_ == i ); + ps->set(); + +#else + + boost::shared_ptr p2( new X( *ps ) ); + + BOOST_TEST( p2->v_ == i ); + p2->set(); + + ps.atomic_store( p2 ); + +#endif + } +} + +#if defined( BOOST_HAS_PTHREADS ) + char const * thmodel = "POSIX"; +#else + char const * thmodel = "Windows"; +#endif + +int const mr = 8; // reader threads +int const mw = 1; // writer thread + +#if defined( USE_MUTEX ) + char const * prim = "mutex"; +#elif defined( USE_RWLOCK ) + char const * prim = "rwlock"; +#else + char const * prim = "atomics"; +#endif + +int main() +{ + using namespace std; // printf, clock_t, clock + + printf( "Using %s threads: %dR + %dW threads, %d iterations, %s\n\n", thmodel, mr, mw, n, prim ); + + clock_t t = clock(); + + pthread_t a[ mr+mw ]; + + for( int i = 0; i < mr; ++i ) + { + boost::detail::lw_thread_create( a[ i ], boost::bind( reader, i ) ); + } + + for( int i = mr; i < mr+mw; ++i ) + { + boost::detail::lw_thread_create( a[ i ], writer ); + } + + for( int j = 0; j < mr+mw; ++j ) + { + pthread_join( a[ j ], 0 ); + } + + t = clock() - t; + + double ts = static_cast( t ) / CLOCKS_PER_SEC; + printf( "%.3f seconds, %.3f reads per microsecond.\n", ts, tr / ts / 1e+6 ); + + return boost::report_errors(); +} From ca344809ba368a530a2de04abef36e06f91acd38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Hunold?= Date: Mon, 21 Apr 2008 08:07:55 +0000 Subject: [PATCH 084/132] Remove trailing comma at end of enumerator list (gcc 4.x -pedantic error) [SVN r44686] --- include/boost/memory_order.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/memory_order.hpp b/include/boost/memory_order.hpp index be5a9ce..2524e8a 100644 --- a/include/boost/memory_order.hpp +++ b/include/boost/memory_order.hpp @@ -27,7 +27,7 @@ enum memory_order memory_order_acquire = 1, memory_order_release = 2, memory_order_acq_rel = 3, // acquire | release - memory_order_seq_cst = 7, // acq_rel | 4 + memory_order_seq_cst = 7 // acq_rel | 4 }; } // namespace boost From b541145a60607d5ea9b03f56aa5b069b28efa5d4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 21 Apr 2008 23:01:51 +0000 Subject: [PATCH 085/132] Honor BOOST_NO_TEMPLATED_IOSTREAMS. [SVN r44707] --- include/boost/shared_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 9d92fd7..5697339 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -634,7 +634,7 @@ template inline T * get_pointer(shared_ptr const & p) #if !defined(BOOST_NO_IOSTREAM) -#if defined(__GNUC__) && (__GNUC__ < 3) +#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) template std::ostream & operator<< (std::ostream & os, shared_ptr const & p) { From e12ed6864b99f6b4eae0be9b6068774dcb6be753 Mon Sep 17 00:00:00 2001 From: Daniel Frey Date: Tue, 22 Apr 2008 06:31:32 +0000 Subject: [PATCH 086/132] Avoid unneccessary increment/decrement of reference count [SVN r44711] --- include/boost/detail/shared_count.hpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 4a71f20..2745649 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -324,9 +324,13 @@ public: weak_count & operator= (shared_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; - if(tmp != 0) tmp->weak_add_ref(); - if(pi_ != 0) pi_->weak_release(); - pi_ = tmp; + + if( tmp != pi_ ) + { + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); + pi_ = tmp; + } return *this; } @@ -334,9 +338,13 @@ public: weak_count & operator= (weak_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; - if(tmp != 0) tmp->weak_add_ref(); - if(pi_ != 0) pi_->weak_release(); - pi_ = tmp; + + if( tmp != pi_ ) + { + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); + pi_ = tmp; + } return *this; } From 9e92c6354cc8dcf3b39b6a92810c7cfd9e638df9 Mon Sep 17 00:00:00 2001 From: Daniel Frey Date: Tue, 22 Apr 2008 19:48:39 +0000 Subject: [PATCH 087/132] Reduce enable_shared_from_this overhead [SVN r44724] --- include/boost/detail/shared_count.hpp | 12 ++++++++++++ include/boost/enable_shared_from_this.hpp | 19 ++++++++----------- include/boost/shared_ptr.hpp | 15 +++++++++++++++ 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 2745649..e1ca96a 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -220,6 +220,18 @@ public: if( pi_ != 0 ) pi_->add_ref_copy(); } +#if defined( BOOST_HAS_RVALUE_REFS ) + + shared_count(shared_count && r): pi_(r.pi_) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + r.pi_ = 0; + } + +#endif + explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 shared_count( weak_count const & r, sp_nothrow_tag ); // constructs an empty *this when r.use_count() == 0 diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index f474714..65ddf87 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -13,7 +13,7 @@ // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html // -#include +#include #include #include #include @@ -32,7 +32,7 @@ template class enable_shared_from_this T * p = dynamic_cast(const_cast(this)); _internal_shared_this = shared_ptr( p, detail::sp_deleter_wrapper() ); BOOST_ASSERT(_internal_shared_this.get() == this); - _internal_weak_this = _internal_shared_this; + _internal_weak_count = _internal_shared_this.get_shared_count(); } } @@ -43,7 +43,7 @@ template class enable_shared_from_this typedef T _internal_element_type; // for bcc 5.5.1 mutable shared_ptr<_internal_element_type> _internal_shared_this; - mutable weak_ptr<_internal_element_type> _internal_weak_this; + mutable detail::weak_count _internal_weak_count; mutable bool _owned; protected: @@ -77,17 +77,15 @@ public: shared_ptr shared_from_this() { init_internal_shared_once(); - shared_ptr p(_internal_weak_this); - BOOST_ASSERT(p.get() == this); - return p; + T * p = dynamic_cast(this); + return shared_ptr( detail::shared_count( _internal_weak_count ), p ); } shared_ptr shared_from_this() const { init_internal_shared_once(); - shared_ptr p(_internal_weak_this); - BOOST_ASSERT(p.get() == this); - return p; + T const * p = dynamic_cast(this); + return shared_ptr( detail::shared_count( _internal_weak_count ), p ); } template @@ -97,8 +95,7 @@ public: { if( !_internal_shared_this ) { - T * p = dynamic_cast(const_cast(this)); - _internal_weak_this = shared_ptr(owner, p); + _internal_weak_count = owner.get_shared_count(); }else { BOOST_ASSERT(owner.unique()); // no weak_ptrs to owner should exist either, but there's no way to check that diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 5697339..88fab8f 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -228,6 +228,11 @@ public: { } + template + shared_ptr(detail::shared_count const & c, Y * p): px(p), pn(c) // never throws + { + } + // aliasing template< class Y > shared_ptr( shared_ptr const & r, T * p ): px( p ), pn( r.pn ) // never throws @@ -341,6 +346,11 @@ public: r.px = 0; } + template + shared_ptr(detail::shared_count && c, Y * p): px(p), pn( static_cast< detail::shared_count && >( c ) ) // never throws + { + } + shared_ptr & operator=( shared_ptr && r ) // never throws { this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); @@ -467,6 +477,11 @@ public: pn.swap(other.pn); } + detail::shared_count const & get_shared_count() const // never throws + { + return pn; + } + template bool _internal_less(shared_ptr const & rhs) const { return pn < rhs.pn; From 93545d5cf21225cac4fc9e2188579c213ae93ac9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 23 Apr 2008 00:33:58 +0000 Subject: [PATCH 088/132] Silence an g++ -Wextra warning. [SVN r44728] --- include/boost/detail/yield_k.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/boost/detail/yield_k.hpp b/include/boost/detail/yield_k.hpp index d856d57..0d964a7 100644 --- a/include/boost/detail/yield_k.hpp +++ b/include/boost/detail/yield_k.hpp @@ -111,7 +111,11 @@ inline void yield( unsigned k ) } else { - struct timespec rqtp = { 0 }; + // g++ -Wextra warns on {} or {0} + struct timespec rqtp = { 0, 0 }; + + // POSIX says that timespec has tv_sec and tv_nsec + // But it doesn't guarantee order or placement rqtp.tv_sec = 0; rqtp.tv_nsec = 1000; From 77f2d3f61420df9759a4d32eef6e2196a2407e60 Mon Sep 17 00:00:00 2001 From: Daniel Frey Date: Wed, 23 Apr 2008 06:12:39 +0000 Subject: [PATCH 089/132] Reduce enable_shared_from_this overhead (replace _internal_shared_ptr by _internal_shared_count) [SVN r44730] --- include/boost/enable_shared_from_this.hpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 65ddf87..66f43f8 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -27,12 +27,11 @@ template class enable_shared_from_this // to use lazy initialization void init_internal_shared_once() const { - if( !owned() && _internal_shared_this.get() == 0 ) + if( !owned() && _internal_shared_count.empty() ) { T * p = dynamic_cast(const_cast(this)); - _internal_shared_this = shared_ptr( p, detail::sp_deleter_wrapper() ); - BOOST_ASSERT(_internal_shared_this.get() == this); - _internal_weak_count = _internal_shared_this.get_shared_count(); + detail::shared_count( p, detail::sp_deleter_wrapper() ).swap(_internal_shared_count); + _internal_weak_count = _internal_shared_count; } } @@ -41,8 +40,7 @@ template class enable_shared_from_this return _owned; } - typedef T _internal_element_type; // for bcc 5.5.1 - mutable shared_ptr<_internal_element_type> _internal_shared_this; + mutable detail::shared_count _internal_shared_count; mutable detail::weak_count _internal_weak_count; mutable bool _owned; @@ -69,7 +67,7 @@ protected: // make sure no dangling shared_ptr objects were created by the // user calling shared_from_this() but never passing ownership of the object // to a shared_ptr. - BOOST_ASSERT(owned() || _internal_shared_this.use_count() <= 1); + BOOST_ASSERT(owned() || _internal_shared_count.use_count() <= 1); } public: @@ -93,18 +91,19 @@ public: { if( !_owned ) { - if( !_internal_shared_this ) + if( _internal_shared_count.empty() ) { _internal_weak_count = owner.get_shared_count(); }else { BOOST_ASSERT(owner.unique()); // no weak_ptrs to owner should exist either, but there's no way to check that - detail::sp_deleter_wrapper * pd = get_deleter(_internal_shared_this); + typedef detail::sp_deleter_wrapper D; + D * pd = static_cast(_internal_shared_count.get_deleter(BOOST_SP_TYPEID(D))); BOOST_ASSERT( pd != 0 ); pd->set_deleter(owner); - owner.reset( _internal_shared_this, owner.get() ); - _internal_shared_this.reset(); + shared_ptr( _internal_shared_count, owner.get() ).swap( owner ); + detail::shared_count().swap(_internal_shared_count); } _owned = true; } From 8b3907ae811554608fe17581a04f66faa80f9519 Mon Sep 17 00:00:00 2001 From: Daniel Frey Date: Wed, 23 Apr 2008 19:32:44 +0000 Subject: [PATCH 090/132] Remove dynamic_cast in init_internal_shared_once() [SVN r44744] --- include/boost/enable_shared_from_this.hpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 66f43f8..bac9764 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -23,14 +23,11 @@ namespace boost template class enable_shared_from_this { -// dynamic cast to template type doesn't work in constructor, so we have -// to use lazy initialization void init_internal_shared_once() const { if( !owned() && _internal_shared_count.empty() ) { - T * p = dynamic_cast(const_cast(this)); - detail::shared_count( p, detail::sp_deleter_wrapper() ).swap(_internal_shared_count); + detail::shared_count( (void*)0, detail::sp_deleter_wrapper() ).swap(_internal_shared_count); _internal_weak_count = _internal_shared_count; } } From 2251b1d2df3d85e162a29a1999fd1fb9521b5b77 Mon Sep 17 00:00:00 2001 From: Daniel Frey Date: Sat, 26 Apr 2008 06:36:59 +0000 Subject: [PATCH 091/132] No need for the new ctors to be templates [SVN r44772] --- include/boost/shared_ptr.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 88fab8f..1aa6ecc 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -228,8 +228,7 @@ public: { } - template - shared_ptr(detail::shared_count const & c, Y * p): px(p), pn(c) // never throws + shared_ptr(detail::shared_count const & c, T * p): px(p), pn(c) // never throws { } @@ -346,8 +345,7 @@ public: r.px = 0; } - template - shared_ptr(detail::shared_count && c, Y * p): px(p), pn( static_cast< detail::shared_count && >( c ) ) // never throws + shared_ptr(detail::shared_count && c, T * p): px(p), pn( static_cast< detail::shared_count && >( c ) ) // never throws { } From 7dc6b3d8102f14109ee8ea7574f359914f0c72a9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 26 Apr 2008 13:39:52 +0000 Subject: [PATCH 092/132] Added a few more tests. [SVN r44775] --- test/esft_regtest.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/esft_regtest.cpp b/test/esft_regtest.cpp index 35f672e..cc180a2 100644 --- a/test/esft_regtest.cpp +++ b/test/esft_regtest.cpp @@ -160,6 +160,7 @@ void test3() V * p = new W; boost::shared_ptr pv( p ); BOOST_TEST( pv.get() == p ); + BOOST_TEST( pv.use_count() == 1 ); } struct null_deleter @@ -171,6 +172,41 @@ void test4() { boost::shared_ptr pv( new V ); boost::shared_ptr pv2( pv.get(), null_deleter() ); + BOOST_TEST( pv2.get() == pv.get() ); + BOOST_TEST( pv2.use_count() == 1 ); +} + +void test5() +{ + V v; + + boost::shared_ptr p1( &v, null_deleter() ); + BOOST_TEST( p1.get() == &v ); + BOOST_TEST( p1.use_count() == 1 ); + + try + { + p1->shared_from_this(); + } + catch( ... ) + { + BOOST_ERROR( "p1->shared_from_this() failed" ); + } + + p1.reset(); + + boost::shared_ptr p2( &v, null_deleter() ); + BOOST_TEST( p2.get() == &v ); + BOOST_TEST( p2.use_count() == 1 ); + + try + { + p2->shared_from_this(); + } + catch( ... ) + { + BOOST_ERROR( "p2->shared_from_this() failed" ); + } } int main() @@ -179,6 +215,7 @@ int main() test2(); test3(); test4(); + test5(); return boost::report_errors(); } From 6f8dc5923c11e580556c2518e89edfb224ddb287 Mon Sep 17 00:00:00 2001 From: Daniel Frey Date: Sat, 26 Apr 2008 15:42:13 +0000 Subject: [PATCH 093/132] Added new reset()-counterparts for the new ctors [SVN r44777] --- include/boost/shared_ptr.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 1aa6ecc..4710b02 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -390,6 +390,18 @@ public: this_type( r, p ).swap( *this ); } + void reset( detail::shared_count const & c, T * p ) + { + this_type( c, p ).swap( *this ); + } + +#if defined( BOOST_HAS_RVALUE_REFS ) + void reset( detail::shared_count && c, T * p ) + { + this_type( static_cast< detail::shared_count && >( c ), p ).swap( *this ); + } +#endif + reference operator* () const // never throws { BOOST_ASSERT(px != 0); From a01e4c3f83514c5f0cc933359b31f536f0376876 Mon Sep 17 00:00:00 2001 From: Daniel Frey Date: Sat, 26 Apr 2008 19:59:11 +0000 Subject: [PATCH 094/132] Refactored and optimized enable_shared_from_this [SVN r44782] --- include/boost/detail/shared_count.hpp | 5 ++ include/boost/enable_shared_from_this.hpp | 103 ++++++++++------------ 2 files changed, 52 insertions(+), 56 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index e1ca96a..57d1ee9 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -373,6 +373,11 @@ public: return pi_ != 0? pi_->use_count(): 0; } + bool empty() const // nothrow + { + return pi_ == 0; + } + friend inline bool operator==(weak_count const & a, weak_count const & b) { return a.pi_ == b.pi_; diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index bac9764..c4649af 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -13,7 +13,6 @@ // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html // -#include #include #include #include @@ -21,35 +20,19 @@ namespace boost { -template class enable_shared_from_this +template< class T > class enable_shared_from_this; +template< class T, class Y > void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ); +template< class T, class Y > void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ); + +template< class T > class enable_shared_from_this { - void init_internal_shared_once() const - { - if( !owned() && _internal_shared_count.empty() ) - { - detail::shared_count( (void*)0, detail::sp_deleter_wrapper() ).swap(_internal_shared_count); - _internal_weak_count = _internal_shared_count; - } - } - - bool owned() const - { - return _owned; - } - - mutable detail::shared_count _internal_shared_count; - mutable detail::weak_count _internal_weak_count; - mutable bool _owned; - protected: - enable_shared_from_this(): - _owned(false) + enable_shared_from_this() { } - enable_shared_from_this(enable_shared_from_this const &): - _owned(false) + enable_shared_from_this(enable_shared_from_this const &) { } @@ -64,69 +47,77 @@ protected: // make sure no dangling shared_ptr objects were created by the // user calling shared_from_this() but never passing ownership of the object // to a shared_ptr. - BOOST_ASSERT(owned() || _internal_shared_count.use_count() <= 1); + BOOST_ASSERT( _shared_count.use_count() <= 1 ); } public: shared_ptr shared_from_this() { - init_internal_shared_once(); - T * p = dynamic_cast(this); - return shared_ptr( detail::shared_count( _internal_weak_count ), p ); + init_weak_once(); + T * p = dynamic_cast( this ); + return shared_ptr( detail::shared_count( _weak_count ), p ); } shared_ptr shared_from_this() const { - init_internal_shared_once(); - T const * p = dynamic_cast(this); - return shared_ptr( detail::shared_count( _internal_weak_count ), p ); + init_weak_once(); + T const * p = dynamic_cast( this ); + return shared_ptr( detail::shared_count( _weak_count ), p ); + } + +private: + + mutable detail::weak_count _weak_count; + mutable detail::shared_count _shared_count; + + void init_weak_once() const + { + if( _weak_count.empty() ) + { + detail::shared_count( (void*)0, detail::sp_deleter_wrapper() ).swap( _shared_count ); + _weak_count = _shared_count; + } } template - void _internal_accept_owner(shared_ptr &owner) const + void sp_accept_owner( shared_ptr & owner ) const { - if( !_owned ) + if( _weak_count.use_count() == 0 ) { - if( _internal_shared_count.empty() ) - { - _internal_weak_count = owner.get_shared_count(); - }else - { - BOOST_ASSERT(owner.unique()); // no weak_ptrs to owner should exist either, but there's no way to check that - typedef detail::sp_deleter_wrapper D; - D * pd = static_cast(_internal_shared_count.get_deleter(BOOST_SP_TYPEID(D))); - BOOST_ASSERT( pd != 0 ); - pd->set_deleter(owner); - - shared_ptr( _internal_shared_count, owner.get() ).swap( owner ); - detail::shared_count().swap(_internal_shared_count); - } - _owned = true; + _weak_count = owner.get_shared_count(); + }else if( !_shared_count.empty() ) + { + BOOST_ASSERT( owner.unique() ); // no weak_ptrs to owner should exist either, but there's no way to check that + typedef detail::sp_deleter_wrapper D; + D * pd = static_cast( _shared_count.get_deleter( BOOST_SP_TYPEID(D) ) ); + BOOST_ASSERT( pd != 0 ); + pd->set_deleter( owner ); + owner.reset( _shared_count, owner.get() ); + detail::shared_count().swap( _shared_count ); } } + + template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ); + template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ); }; -template< class T, class Y > inline void sp_accept_owner( boost::shared_ptr * ptr, boost::enable_shared_from_this const * pe ) +template< class T, class Y > inline void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ) { if( pe != 0 ) { - pe->_internal_accept_owner( *ptr ); + pe->sp_accept_owner( *ptr ); } } -template< class T, class Y > inline void sp_accept_owner( boost::shared_ptr * ptr, boost::enable_shared_from_this const * pe, void * /*pd*/ ) +template< class T, class Y > inline void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ) { if( pe != 0 ) { - pe->_internal_accept_owner( *ptr ); + pe->sp_accept_owner( *ptr ); } } -template< class T, class Y > inline void sp_accept_owner( boost::shared_ptr * /*ptr*/, boost::enable_shared_from_this const * /*pe*/, boost::detail::sp_deleter_wrapper * /*pd*/ ) -{ -} - } // namespace boost #endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED From e3422efec60dc9eb70bf8dafd53ffdc957615016 Mon Sep 17 00:00:00 2001 From: Daniel Frey Date: Mon, 28 Apr 2008 07:17:11 +0000 Subject: [PATCH 095/132] Improved sp_deleter_wrapper implementation [SVN r44837] --- include/boost/enable_shared_from_this.hpp | 5 ++--- include/boost/shared_ptr.hpp | 23 +++++++++-------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index c4649af..323a687 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -89,10 +89,9 @@ private: }else if( !_shared_count.empty() ) { BOOST_ASSERT( owner.unique() ); // no weak_ptrs to owner should exist either, but there's no way to check that - typedef detail::sp_deleter_wrapper D; - D * pd = static_cast( _shared_count.get_deleter( BOOST_SP_TYPEID(D) ) ); + detail::sp_deleter_wrapper * pd = detail::basic_get_deleter( _shared_count ); BOOST_ASSERT( pd != 0 ); - pd->set_deleter( owner ); + pd->set_deleter( owner.get_shared_count() ); owner.reset( _shared_count, owner.get() ); detail::shared_count().swap( _shared_count ); } diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 4710b02..9256351 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -497,11 +497,6 @@ public: return pn < rhs.pn; } - void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const - { - return pn.get_deleter( ti ); - } - // atomic access #if !defined(BOOST_SP_NO_ATOMIC_ACCESS) @@ -701,35 +696,35 @@ namespace detail // g++ 2.9x doesn't allow static_cast(void *) // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it -template D * basic_get_deleter(shared_ptr const & p) +template D * basic_get_deleter(shared_count const & c) { - void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D)); + void const * q = c.get_deleter(BOOST_SP_TYPEID(D)); return const_cast(static_cast(q)); } #else -template D * basic_get_deleter(shared_ptr const & p) +template D * basic_get_deleter(shared_count const & c) { - return static_cast(p._internal_get_deleter(BOOST_SP_TYPEID(D))); + return static_cast(c.get_deleter(BOOST_SP_TYPEID(D))); } #endif class sp_deleter_wrapper { - shared_ptr _deleter; + detail::shared_count _deleter; public: sp_deleter_wrapper() {} - void set_deleter(const shared_ptr &deleter) + void set_deleter(shared_count const &deleter) { _deleter = deleter; } void operator()(const void *) { BOOST_ASSERT(_deleter.use_count() <= 1); - _deleter.reset(); + detail::shared_count().swap( _deleter ); } template D* get_deleter() const @@ -742,10 +737,10 @@ public: template D * get_deleter(shared_ptr const & p) { - D *del = detail::basic_get_deleter(p); + D *del = detail::basic_get_deleter(p.get_shared_count()); if(del == 0) { - detail::sp_deleter_wrapper *del_wrapper = detail::basic_get_deleter(p); + detail::sp_deleter_wrapper *del_wrapper = detail::basic_get_deleter(p.get_shared_count()); // The following get_deleter method call is fully qualified because // older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter() if(del_wrapper) del = del_wrapper->::boost::detail::sp_deleter_wrapper::get_deleter(); From f13591ef2b98a9b0158faff458a200861e9ba7cd Mon Sep 17 00:00:00 2001 From: Anthony Williams Date: Mon, 28 Apr 2008 09:00:58 +0000 Subject: [PATCH 096/132] Added detail::try_lock_wrapper for use as scoped_try_lock typedefs, to fix issue #1873 [SVN r44838] --- test/Jamfile.v2 | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index ca14dd1..d66fbc3 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -45,5 +45,6 @@ import testing ; [ run spinlock_pool_test.cpp ] [ run sp_accept_owner_test.cpp ] [ run sp_atomic_test.cpp ] + [ run sp_atomic_mt_test.cpp : : : multi /boost/thread//boost_thread ] ; } From 4bb747fb273ae01395c3821511bfa62b78c9d0f6 Mon Sep 17 00:00:00 2001 From: Anthony Williams Date: Mon, 28 Apr 2008 09:04:40 +0000 Subject: [PATCH 097/132] reverted accidental change [SVN r44839] --- test/Jamfile.v2 | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d66fbc3..ca14dd1 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -45,6 +45,5 @@ import testing ; [ run spinlock_pool_test.cpp ] [ run sp_accept_owner_test.cpp ] [ run sp_atomic_test.cpp ] - [ run sp_atomic_mt_test.cpp : : : multi /boost/thread//boost_thread ] ; } From 357d3c4d5429f8e2f74d52b0e80c43598728d7a4 Mon Sep 17 00:00:00 2001 From: Daniel Frey Date: Tue, 29 Apr 2008 05:32:13 +0000 Subject: [PATCH 098/132] Fixed comment to reflect the intention and the current code [SVN r44873] --- include/boost/enable_shared_from_this.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 323a687..55f94ac 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -44,10 +44,7 @@ protected: // virtual destructor because we need a vtable for dynamic_cast from base to derived to work virtual ~enable_shared_from_this() { -// make sure no dangling shared_ptr objects were created by the -// user calling shared_from_this() but never passing ownership of the object -// to a shared_ptr. - BOOST_ASSERT( _shared_count.use_count() <= 1 ); + BOOST_ASSERT( _shared_count.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist } public: @@ -92,6 +89,7 @@ private: detail::sp_deleter_wrapper * pd = detail::basic_get_deleter( _shared_count ); BOOST_ASSERT( pd != 0 ); pd->set_deleter( owner.get_shared_count() ); + owner.reset( _shared_count, owner.get() ); detail::shared_count().swap( _shared_count ); } From 18a6c1add8a306aaa9c8e8b32f42b098cae6e1b0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 1 May 2008 16:50:39 +0000 Subject: [PATCH 099/132] make_shared added; tweaks for old compilers; fixes #1884. [SVN r44979] --- include/boost/detail/shared_count.hpp | 9 +- include/boost/detail/spinlock_w32.hpp | 2 +- include/boost/detail/yield_k.hpp | 2 +- include/boost/make_shared.hpp | 433 ++++++++++++++++++++++++++ test/Jamfile.v2 | 1 + test/make_shared_test.cpp | 334 ++++++++++++++++++++ 6 files changed, 778 insertions(+), 3 deletions(-) create mode 100644 include/boost/make_shared.hpp create mode 100644 test/make_shared_test.cpp diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 57d1ee9..ee39355 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -104,11 +104,18 @@ public: #endif } - template shared_count(P p, D d): pi_(0) +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) + template shared_count( Y * p, D d ): pi_(0) +#else + template shared_count( P p, D d ): pi_(0) +#endif #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) + typedef Y* P; +#endif #ifndef BOOST_NO_EXCEPTIONS try diff --git a/include/boost/detail/spinlock_w32.hpp b/include/boost/detail/spinlock_w32.hpp index 76cfe8f..aa416c3 100644 --- a/include/boost/detail/spinlock_w32.hpp +++ b/include/boost/detail/spinlock_w32.hpp @@ -33,7 +33,7 @@ extern "C" void _ReadWriteBarrier(); #elif defined(__GNUC__) -#define BOOST_COMPILER_FENCE __asm__ __volatile__( "" ::: "memory" ); +#define BOOST_COMPILER_FENCE __asm__ __volatile__( "" : : : "memory" ); #else diff --git a/include/boost/detail/yield_k.hpp b/include/boost/detail/yield_k.hpp index 0d964a7..d97542d 100644 --- a/include/boost/detail/yield_k.hpp +++ b/include/boost/detail/yield_k.hpp @@ -36,7 +36,7 @@ extern "C" void _mm_pause(); #elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) -#define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" ::: "memory" ); +#define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" ); #endif diff --git a/include/boost/make_shared.hpp b/include/boost/make_shared.hpp new file mode 100644 index 0000000..cc3685b --- /dev/null +++ b/include/boost/make_shared.hpp @@ -0,0 +1,433 @@ +#ifndef BOOST_MAKE_SHARED_HPP_INCLUDED +#define BOOST_MAKE_SHARED_HPP_INCLUDED + +// make_shared.hpp +// +// Copyright (c) 2007, 2008 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 +// +// See http://www.boost.org/libs/smart_ptr/make_shared.html +// for documentation. + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + +namespace detail +{ + +template< std::size_t N, std::size_t A > struct sp_aligned_storage +{ + union type + { + char data_[ N ]; + typename boost::type_with_alignment< A >::type align_; + }; +}; + +template< class T > class sp_ms_deleter +{ +private: + + typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type; + + bool initialized_; + storage_type storage_; + +private: + + void destroy() + { + if( initialized_ ) + { + reinterpret_cast< T* >( storage_.data_ )->~T(); + initialized_ = false; + } + } + +public: + + sp_ms_deleter(): initialized_( false ) + { + } + + ~sp_ms_deleter() + { + destroy(); + } + + void operator()( T * ) + { + destroy(); + } + + void * address() + { + return storage_.data_; + } + + void set_initialized() + { + initialized_ = true; + } +}; + +template< class T > T forward( T t ) +{ + return t; +} + +} // namespace detail + +// Zero-argument versions +// +// Used even when variadic templates are available because of the new T() vs new T issue + +template< class T > boost::shared_ptr< T > make_shared() +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T(); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T(); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) + +// Variadic templates, rvalue reference + +template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && ... args ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( detail::forward( args )... ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Args && ... args ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( detail::forward( args )... ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +#else + +// C++03 version + +template< class T, class A1 > +boost::shared_ptr< T > make_shared( A1 const & a1 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +#endif + +} // namespace boost + +#endif // #ifndef BOOST_MAKE_SHARED_HPP_INCLUDED diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index ca14dd1..86d0289 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -45,5 +45,6 @@ import testing ; [ run spinlock_pool_test.cpp ] [ run sp_accept_owner_test.cpp ] [ run sp_atomic_test.cpp ] + [ run make_shared_test.cpp ] ; } diff --git a/test/make_shared_test.cpp b/test/make_shared_test.cpp new file mode 100644 index 0000000..efb809f --- /dev/null +++ b/test/make_shared_test.cpp @@ -0,0 +1,334 @@ +// make_shared_test.cpp +// +// Copyright (c) 2007, 2008 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 +#include +#include +#include + +class X +{ +private: + + X( X const & ); + X & operator=( X const & ); + +public: + + static int instances; + + int v; + + explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 ) + { + ++instances; + } + + ~X() + { + --instances; + } +}; + +int X::instances = 0; + +int main() +{ + { + boost::shared_ptr< int > pi = boost::make_shared< int >(); + + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( *pi == 0 ); + } + + { + boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator() ); + + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( *pi == 0 ); + } + + { + boost::shared_ptr< int > pi = boost::make_shared< int >( 5 ); + + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( *pi == 5 ); + } + + { + boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator(), 5 ); + + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( *pi == 5 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > pi = boost::make_shared< X >(); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 0 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator() ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 0 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7, 8 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + return boost::report_errors(); +} From 440fcb7ba0d379ce1e14a11da2d04fbcb145a385 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 2 May 2008 19:44:56 +0000 Subject: [PATCH 100/132] missing workaround.hpp include added [SVN r45040] --- include/boost/detail/shared_count.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index ee39355..9e9b1ba 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -28,6 +28,7 @@ #include #include #include +#include // In order to avoid circular dependencies with Boost.TR1 // we make sure that our include of doesn't try to // pull in the TR1 headers: that's why we use this header From 0c4aaef77cefde9ad1680e05271f80a02f84195e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 3 May 2008 15:07:58 +0000 Subject: [PATCH 101/132] Fix #1106. [SVN r45068] --- include/boost/detail/sp_convertible.hpp | 60 ++++++++++++++++++++++ include/boost/intrusive_ptr.hpp | 31 +++++++++-- include/boost/shared_ptr.hpp | 17 ++++++- include/boost/weak_ptr.hpp | 22 +++++++- test/Jamfile.v2 | 3 ++ test/ip_convertible_test.cpp | 54 ++++++++++++++++++++ test/sp_convertible_test.cpp | 66 ++++++++++++++++++++++++ test/wp_convertible_test.cpp | 68 +++++++++++++++++++++++++ 8 files changed, 314 insertions(+), 7 deletions(-) create mode 100644 include/boost/detail/sp_convertible.hpp create mode 100644 test/ip_convertible_test.cpp create mode 100644 test/sp_convertible_test.cpp create mode 100644 test/wp_convertible_test.cpp diff --git a/include/boost/detail/sp_convertible.hpp b/include/boost/detail/sp_convertible.hpp new file mode 100644 index 0000000..00463b3 --- /dev/null +++ b/include/boost/detail/sp_convertible.hpp @@ -0,0 +1,60 @@ +#ifndef BOOST_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED +#define BOOST_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_convertible.hpp +// +// Copyright 2008 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 + +namespace boost +{ + +namespace detail +{ + +template< class Y, class T > struct sp_convertible +{ + typedef char (&yes) [1]; + typedef char (&no) [2]; + + static yes f( T* ); + static no f( ... ); + + enum _vt { value = sizeof( f( (Y*)0 ) ) == sizeof(yes) }; +}; + +struct sp_empty +{ +}; + +template< bool > struct sp_enable_if_convertible_impl; + +template<> struct sp_enable_if_convertible_impl +{ + typedef sp_empty type; +}; + +template<> struct sp_enable_if_convertible_impl +{ +}; + +template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_if_convertible_impl< sp_convertible< Y, T >::value > +{ +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index c4ec407..ace808b 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -23,8 +23,19 @@ #include #include +#if !defined( BOOST_NO_SFINAE ) +#include +#endif + #include // for std::less + +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) #include // for std::basic_ostream +#else +#include +#endif +#endif namespace boost @@ -66,9 +77,19 @@ public: #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) - template intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.get()) + template +#if !defined( BOOST_NO_SFINAE ) + + intrusive_ptr( intrusive_ptr const & rhs, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + intrusive_ptr( intrusive_ptr const & rhs ) + +#endif + : p_( rhs.get() ) { - if(p_ != 0) intrusive_ptr_add_ref(p_); + if( p_ != 0 ) intrusive_ptr_add_ref( p_ ); } #endif @@ -246,7 +267,9 @@ template intrusive_ptr dynamic_pointer_cast(intrusive_ptr std::ostream & operator<< (std::ostream & os, intrusive_ptr const & p) { @@ -275,6 +298,8 @@ template std::basic_ostream & operator<< (std:: #endif // __GNUC__ < 3 +#endif // !defined(BOOST_NO_IOSTREAM) + } // namespace boost #ifdef BOOST_MSVC diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 9256351..7245cac 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -32,6 +32,10 @@ #include #include +#if !defined( BOOST_NO_SFINAE ) +#include +#endif + #if !defined(BOOST_SP_NO_ATOMIC_ACCESS) #include #include @@ -224,11 +228,20 @@ public: } template - shared_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws +#if !defined( BOOST_NO_SFINAE ) + + shared_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + shared_ptr( shared_ptr const & r ) + +#endif + : px( r.px ), pn( r.pn ) // never throws { } - shared_ptr(detail::shared_count const & c, T * p): px(p), pn(c) // never throws + shared_ptr( detail::shared_count const & c, T * p ): px( p ), pn( c ) // never throws { } diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 4335738..aadb60a 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -61,13 +61,31 @@ public: // template - weak_ptr(weak_ptr const & r): pn(r.pn) // never throws +#if !defined( BOOST_NO_SFINAE ) + + weak_ptr( weak_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + weak_ptr( weak_ptr const & r ) + +#endif + : pn(r.pn) // never throws { px = r.lock().get(); } template - weak_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws +#if !defined( BOOST_NO_SFINAE ) + + weak_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + weak_ptr( shared_ptr const & r ) + +#endif + : px( r.px ), pn( r.pn ) // never throws { } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 86d0289..3e10e73 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -46,5 +46,8 @@ import testing ; [ run sp_accept_owner_test.cpp ] [ run sp_atomic_test.cpp ] [ run make_shared_test.cpp ] + [ run sp_convertible_test.cpp ] + [ run wp_convertible_test.cpp ] + [ run ip_convertible_test.cpp ] ; } diff --git a/test/ip_convertible_test.cpp b/test/ip_convertible_test.cpp new file mode 100644 index 0000000..081f7b0 --- /dev/null +++ b/test/ip_convertible_test.cpp @@ -0,0 +1,54 @@ +#include + +// wp_convertible_test.cpp +// +// Copyright (c) 2008 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 +#include + +// + +struct W +{ +}; + +void intrusive_ptr_add_ref( W* ) +{ +} + +void intrusive_ptr_release( W* ) +{ +} + +struct X: public virtual W +{ +}; + +struct Y: public virtual W +{ +}; + +struct Z: public X +{ +}; + +int f( boost::intrusive_ptr ) +{ + return 1; +} + +int f( boost::intrusive_ptr ) +{ + return 2; +} + +int main() +{ + BOOST_TEST( 1 == f( boost::intrusive_ptr() ) ); + return boost::report_errors(); +} diff --git a/test/sp_convertible_test.cpp b/test/sp_convertible_test.cpp new file mode 100644 index 0000000..165d55f --- /dev/null +++ b/test/sp_convertible_test.cpp @@ -0,0 +1,66 @@ +#include + +// sp_convertible_test.cpp +// +// Copyright (c) 2008 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 +#include + +// + +class incomplete; + +struct X +{ +}; + +struct Y +{ +}; + +struct Z: public X +{ +}; + +int f( boost::shared_ptr ) +{ + return 1; +} + +int f( boost::shared_ptr ) +{ + return 2; +} + +int f( boost::shared_ptr ) +{ + return 3; +} + +int g( boost::shared_ptr ) +{ + return 4; +} + +int g( boost::shared_ptr ) +{ + return 5; +} + +int g( boost::shared_ptr ) +{ + return 6; +} + +int main() +{ + BOOST_TEST( 1 == f( boost::shared_ptr() ) ); + BOOST_TEST( 4 == g( boost::shared_ptr() ) ); + + return boost::report_errors(); +} diff --git a/test/wp_convertible_test.cpp b/test/wp_convertible_test.cpp new file mode 100644 index 0000000..cceacda --- /dev/null +++ b/test/wp_convertible_test.cpp @@ -0,0 +1,68 @@ +#include + +// wp_convertible_test.cpp +// +// Copyright (c) 2008 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 +#include + +// + +class incomplete; + +struct X +{ +}; + +struct Y +{ +}; + +struct Z: public X +{ +}; + +int f( boost::weak_ptr ) +{ + return 1; +} + +int f( boost::weak_ptr ) +{ + return 2; +} + +int f( boost::weak_ptr ) +{ + return 3; +} + +int g( boost::weak_ptr ) +{ + return 4; +} + +int g( boost::weak_ptr ) +{ + return 5; +} + +int g( boost::weak_ptr ) +{ + return 6; +} + +int main() +{ + BOOST_TEST( 1 == f( boost::weak_ptr() ) ); + BOOST_TEST( 1 == f( boost::shared_ptr() ) ); + BOOST_TEST( 4 == g( boost::weak_ptr() ) ); + BOOST_TEST( 4 == g( boost::shared_ptr() ) ); + + return boost::report_errors(); +} From da323af72dcd0dea62d0c41a5d79178be03d45dd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 3 May 2008 15:33:06 +0000 Subject: [PATCH 102/132] Fixes for old compilers. [SVN r45069] --- include/boost/detail/spinlock_pool.hpp | 4 +++- include/boost/enable_shared_from_this.hpp | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/boost/detail/spinlock_pool.hpp b/include/boost/detail/spinlock_pool.hpp index 92d26cb..a264b1a 100644 --- a/include/boost/detail/spinlock_pool.hpp +++ b/include/boost/detail/spinlock_pool.hpp @@ -21,7 +21,9 @@ // spinlock_pool<2> is reserved for shared_ptr atomic access // +#include #include +#include namespace boost { @@ -39,7 +41,7 @@ public: static spinlock & spinlock_for( void const * pv ) { - size_t i = reinterpret_cast< size_t >( pv ) % 41; + std::size_t i = reinterpret_cast< std::size_t >( pv ) % 41; return pool_[ i ]; } diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 55f94ac..10accd6 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -13,9 +13,10 @@ // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html // +#include #include #include -#include +#include namespace boost { @@ -77,6 +78,12 @@ private: } } +#if defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, <= 0x551 ) + +public: + +#endif + template void sp_accept_owner( shared_ptr & owner ) const { From 83c43617af8faae0cf211133387718f4dcea3956 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 3 May 2008 19:29:01 +0000 Subject: [PATCH 103/132] Fixes for MSVC 6.0. [SVN r45085] --- include/boost/shared_ptr.hpp | 13 ++- test/Jamfile.v2 | 1 + test/allocate_shared_test.cpp | 189 ++++++++++++++++++++++++++++++++++ test/make_shared_test.cpp | 145 -------------------------- test/smart_ptr_test.cpp | 4 + test/sp_unary_addr_test.cpp | 5 + 6 files changed, 209 insertions(+), 148 deletions(-) create mode 100644 test/allocate_shared_test.cpp diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 7245cac..90a6d5b 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -748,16 +748,23 @@ public: } // namespace detail -template D * get_deleter(shared_ptr const & p) +template D * get_deleter( shared_ptr const & p ) { - D *del = detail::basic_get_deleter(p.get_shared_count()); - if(del == 0) + D *del = detail::basic_get_deleter( p.get_shared_count() ); + +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) +#else + + if( del == 0 ) { detail::sp_deleter_wrapper *del_wrapper = detail::basic_get_deleter(p.get_shared_count()); // The following get_deleter method call is fully qualified because // older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter() if(del_wrapper) del = del_wrapper->::boost::detail::sp_deleter_wrapper::get_deleter(); } + +#endif + return del; } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 3e10e73..8520861 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -49,5 +49,6 @@ import testing ; [ run sp_convertible_test.cpp ] [ run wp_convertible_test.cpp ] [ run ip_convertible_test.cpp ] + [ run allocate_shared_test.cpp ] ; } diff --git a/test/allocate_shared_test.cpp b/test/allocate_shared_test.cpp new file mode 100644 index 0000000..71ee948 --- /dev/null +++ b/test/allocate_shared_test.cpp @@ -0,0 +1,189 @@ +// allocate_shared_test.cpp +// +// Copyright (c) 2007, 2008 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 +#include +#include +#include + +class X +{ +private: + + X( X const & ); + X & operator=( X const & ); + +public: + + static int instances; + + int v; + + explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 ) + { + ++instances; + } + + ~X() + { + --instances; + } +}; + +int X::instances = 0; + +int main() +{ + { + boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator() ); + + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( *pi == 0 ); + } + + { + boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator(), 5 ); + + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( *pi == 5 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator() ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 0 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7, 8 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + return boost::report_errors(); +} diff --git a/test/make_shared_test.cpp b/test/make_shared_test.cpp index efb809f..9930e31 100644 --- a/test/make_shared_test.cpp +++ b/test/make_shared_test.cpp @@ -46,13 +46,6 @@ int main() BOOST_TEST( *pi == 0 ); } - { - boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator() ); - - BOOST_TEST( pi.get() != 0 ); - BOOST_TEST( *pi == 0 ); - } - { boost::shared_ptr< int > pi = boost::make_shared< int >( 5 ); @@ -60,13 +53,6 @@ int main() BOOST_TEST( *pi == 5 ); } - { - boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator(), 5 ); - - BOOST_TEST( pi.get() != 0 ); - BOOST_TEST( *pi == 5 ); - } - BOOST_TEST( X::instances == 0 ); { @@ -82,20 +68,6 @@ int main() BOOST_TEST( X::instances == 0 ); } - - { - boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator() ); - boost::weak_ptr wp( pi ); - - BOOST_TEST( X::instances == 1 ); - BOOST_TEST( pi.get() != 0 ); - BOOST_TEST( pi->v == 0 ); - - pi.reset(); - - BOOST_TEST( X::instances == 0 ); - } - { boost::shared_ptr< X > pi = boost::make_shared< X >( 1 ); boost::weak_ptr wp( pi ); @@ -109,19 +81,6 @@ int main() BOOST_TEST( X::instances == 0 ); } - { - boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1 ); - boost::weak_ptr wp( pi ); - - BOOST_TEST( X::instances == 1 ); - BOOST_TEST( pi.get() != 0 ); - BOOST_TEST( pi->v == 1 ); - - pi.reset(); - - BOOST_TEST( X::instances == 0 ); - } - { boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2 ); boost::weak_ptr wp( pi ); @@ -135,19 +94,6 @@ int main() BOOST_TEST( X::instances == 0 ); } - { - boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2 ); - boost::weak_ptr wp( pi ); - - BOOST_TEST( X::instances == 1 ); - BOOST_TEST( pi.get() != 0 ); - BOOST_TEST( pi->v == 1+2 ); - - pi.reset(); - - BOOST_TEST( X::instances == 0 ); - } - { boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3 ); boost::weak_ptr wp( pi ); @@ -161,19 +107,6 @@ int main() BOOST_TEST( X::instances == 0 ); } - { - boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3 ); - boost::weak_ptr wp( pi ); - - BOOST_TEST( X::instances == 1 ); - BOOST_TEST( pi.get() != 0 ); - BOOST_TEST( pi->v == 1+2+3 ); - - pi.reset(); - - BOOST_TEST( X::instances == 0 ); - } - { boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4 ); boost::weak_ptr wp( pi ); @@ -187,19 +120,6 @@ int main() BOOST_TEST( X::instances == 0 ); } - { - boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4 ); - boost::weak_ptr wp( pi ); - - BOOST_TEST( X::instances == 1 ); - BOOST_TEST( pi.get() != 0 ); - BOOST_TEST( pi->v == 1+2+3+4 ); - - pi.reset(); - - BOOST_TEST( X::instances == 0 ); - } - { boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5 ); boost::weak_ptr wp( pi ); @@ -213,19 +133,6 @@ int main() BOOST_TEST( X::instances == 0 ); } - { - boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5 ); - boost::weak_ptr wp( pi ); - - BOOST_TEST( X::instances == 1 ); - BOOST_TEST( pi.get() != 0 ); - BOOST_TEST( pi->v == 1+2+3+4+5 ); - - pi.reset(); - - BOOST_TEST( X::instances == 0 ); - } - { boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6 ); boost::weak_ptr wp( pi ); @@ -239,19 +146,6 @@ int main() BOOST_TEST( X::instances == 0 ); } - { - boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6 ); - boost::weak_ptr wp( pi ); - - BOOST_TEST( X::instances == 1 ); - BOOST_TEST( pi.get() != 0 ); - BOOST_TEST( pi->v == 1+2+3+4+5+6 ); - - pi.reset(); - - BOOST_TEST( X::instances == 0 ); - } - { boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7 ); boost::weak_ptr wp( pi ); @@ -265,19 +159,6 @@ int main() BOOST_TEST( X::instances == 0 ); } - { - boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7 ); - boost::weak_ptr wp( pi ); - - BOOST_TEST( X::instances == 1 ); - BOOST_TEST( pi.get() != 0 ); - BOOST_TEST( pi->v == 1+2+3+4+5+6+7 ); - - pi.reset(); - - BOOST_TEST( X::instances == 0 ); - } - { boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8 ); boost::weak_ptr wp( pi ); @@ -291,19 +172,6 @@ int main() BOOST_TEST( X::instances == 0 ); } - { - boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7, 8 ); - boost::weak_ptr wp( pi ); - - BOOST_TEST( X::instances == 1 ); - BOOST_TEST( pi.get() != 0 ); - BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 ); - - pi.reset(); - - BOOST_TEST( X::instances == 0 ); - } - { boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); boost::weak_ptr wp( pi ); @@ -317,18 +185,5 @@ int main() BOOST_TEST( X::instances == 0 ); } - { - boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7, 8, 9 ); - boost::weak_ptr wp( pi ); - - BOOST_TEST( X::instances == 1 ); - BOOST_TEST( pi.get() != 0 ); - BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 ); - - pi.reset(); - - BOOST_TEST( X::instances == 0 ); - } - return boost::report_errors(); } diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp index 0c29c9c..8832deb 100644 --- a/test/smart_ptr_test.cpp +++ b/test/smart_ptr_test.cpp @@ -196,6 +196,10 @@ void test() BOOST_TEST( cp.use_count() == 3 ); BOOST_TEST( *cp == 87654 ); +#if defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) + using boost::swap; +#endif + boost::shared_ptr cp4; swap( cp2, cp4 ); BOOST_TEST( cp4.use_count() == 3 ); diff --git a/test/sp_unary_addr_test.cpp b/test/sp_unary_addr_test.cpp index 4522640..a4007a2 100644 --- a/test/sp_unary_addr_test.cpp +++ b/test/sp_unary_addr_test.cpp @@ -49,6 +49,9 @@ int main() BOOST_TEST( q != 0 && q->data == 17041 ); } +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) +#else + { boost::shared_ptr p( &x, deleter(), std::allocator() ); @@ -58,5 +61,7 @@ int main() BOOST_TEST( q != 0 && q->data == 17041 ); } +#endif + return boost::report_errors(); } From d13f1d8694c9cdc86761f33a3be971afbee4975f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 3 May 2008 19:43:52 +0000 Subject: [PATCH 104/132] More fixes for MSVC 6.0. [SVN r45086] --- include/boost/shared_ptr.hpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 90a6d5b..02f2f4f 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -740,7 +740,11 @@ public: detail::shared_count().swap( _deleter ); } template +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) + D* get_deleter( D* ) const +#else D* get_deleter() const +#endif { return boost::detail::basic_get_deleter(_deleter); } @@ -752,18 +756,25 @@ template D * get_deleter( shared_ptr const & p ) { D *del = detail::basic_get_deleter( p.get_shared_count() ); -#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) -#else - if( del == 0 ) { detail::sp_deleter_wrapper *del_wrapper = detail::basic_get_deleter(p.get_shared_count()); -// The following get_deleter method call is fully qualified because -// older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter() - if(del_wrapper) del = del_wrapper->::boost::detail::sp_deleter_wrapper::get_deleter(); - } + +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) + + if( del_wrapper ) del = del_wrapper->get_deleter( (D*)0 ); + +#elif defined( __GNUC__ ) && BOOST_WORKAROUND( __GNUC__, < 4 ) + + if( del_wrapper ) del = del_wrapper->::boost::detail::sp_deleter_wrapper::get_deleter(); + +#else + + if( del_wrapper ) del = del_wrapper->get_deleter(); #endif + } + return del; } From efdc390bc9b05a5f536d8b97ac97da9c76508bd9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 3 May 2008 20:12:25 +0000 Subject: [PATCH 105/132] intrusive_ptr::reset() added. [SVN r45089] --- include/boost/intrusive_ptr.hpp | 5 +++++ intrusive_ptr.html | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index ace808b..8982fe9 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -126,6 +126,11 @@ public: return *this; } + void reset() + { + this_type().swap( *this ); + } + void reset( T * rhs ) { this_type( rhs ).swap( *this ); diff --git a/intrusive_ptr.html b/intrusive_ptr.html index c4eb899..16097dd 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -62,6 +62,8 @@ intrusive_ptr & operator=(intrusive_ptr const & r); template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r); intrusive_ptr & operator=(T * r); + + void reset(); void reset(T * r); T & operator*() const; // never throws @@ -148,6 +150,10 @@ intrusive_ptr & operator=(T * r);

Returns: *this.

reset

+
void reset();
+
+

Effects: Equivalent to intrusive_ptr().swap(*this).

+
void reset(T * r);

Effects: Equivalent to intrusive_ptr(r).swap(*this).

From f0f9f72be6005f1413ce57c50ef96e45e80ce599 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 3 May 2008 22:47:35 +0000 Subject: [PATCH 106/132] sp_atomic_mt2_test.cpp added. [SVN r45094] --- test/sp_atomic_mt2_test.cpp | 247 ++++++++++++++++++++++++++++++++++++ test/sp_atomic_mt_test.cpp | 7 + 2 files changed, 254 insertions(+) create mode 100644 test/sp_atomic_mt2_test.cpp diff --git a/test/sp_atomic_mt2_test.cpp b/test/sp_atomic_mt2_test.cpp new file mode 100644 index 0000000..c865359 --- /dev/null +++ b/test/sp_atomic_mt2_test.cpp @@ -0,0 +1,247 @@ + +// Copyright (c) 2008 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 + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +// + +static void next_value( unsigned & v ) +{ + v = v % 2? 3 * v + 1: v / 2; +} + +struct X +{ + std::vector v_; + + explicit X( std::size_t n ): v_( n ) + { + for( std::size_t i = 0; i < n; ++i ) + { + v_[ i ] = i; + } + } + + unsigned get() const + { + return std::accumulate( v_.begin(), v_.end(), 0 ); + } + + void set() + { + std::for_each( v_.begin(), v_.end(), next_value ); + } +}; + +static boost::shared_ptr ps; + +static boost::detail::lightweight_mutex lm; +static boost::shared_mutex rw; + +enum prim_type +{ + pt_mutex, + pt_rwlock, + pt_atomics +}; + +int read_access( prim_type pt ) +{ + switch( pt ) + { + case pt_mutex: + { + boost::detail::lightweight_mutex::scoped_lock lock( lm ); + return ps->get(); + } + + case pt_rwlock: + { + boost::shared_lock lock( rw ); + return ps->get(); + } + + case pt_atomics: + { + boost::shared_ptr p2 = ps.atomic_load(); + return p2->get(); + } + } +} + +void write_access( prim_type pt ) +{ + switch( pt ) + { + case pt_mutex: + { + boost::detail::lightweight_mutex::scoped_lock lock( lm ); + ps->set(); + } + break; + + case pt_rwlock: + { + boost::unique_lock lock( rw ); + ps->set(); + } + break; + + case pt_atomics: + { + boost::shared_ptr p1 = ps.atomic_load(); + + for( ;; ) + { + boost::shared_ptr p2( new X( *p1 ) ); + p2->set(); + + if( ps.atomic_compare_swap( p1, p2 ) ) break; + } + } + break; + } +} + +void worker( int k, prim_type pt, int n, int r ) +{ + ++r; + + unsigned s = 0, nr = 0, nw = 0; + + for( int i = 0; i < n; ++i ) + { + if( i % r ) + { + s += read_access( pt ); + ++nr; + } + else + { + write_access( pt ); + ++s; + ++nw; + } + } + + printf( "Worker %2d: %u:%u, %10u\n", k, nr, nw, s ); +} + +#if defined( BOOST_HAS_PTHREADS ) + char const * thmodel = "POSIX"; +#else + char const * thmodel = "Windows"; +#endif + +char const * pt_to_string( prim_type pt ) +{ + switch( pt ) + { + case pt_mutex: + + return "mutex"; + + case pt_rwlock: + + return "rwlock"; + + case pt_atomics: + + return "atomics"; + } +} + +static void handle_pt_option( std::string const & opt, prim_type & pt, prim_type pt2 ) +{ + if( opt == pt_to_string( pt2 ) ) + { + pt = pt2; + } +} + +static void handle_int_option( std::string const & opt, std::string const & prefix, int & k, int kmin, int kmax ) +{ + if( opt.substr( 0, prefix.size() ) == prefix ) + { + int v = atoi( opt.substr( prefix.size() ).c_str() ); + + if( v >= kmin && v <= kmax ) + { + k = v; + } + } +} + +int main( int ac, char const * av[] ) +{ + using namespace std; // printf, clock_t, clock + + int m = 4; // threads + int n = 10000; // vector size + int k = 1000000; // iterations + int r = 100; // read/write ratio, r:1 + + prim_type pt = pt_atomics; + + for( int i = 1; i < ac; ++i ) + { + handle_pt_option( av[i], pt, pt_mutex ); + handle_pt_option( av[i], pt, pt_rwlock ); + handle_pt_option( av[i], pt, pt_atomics ); + + handle_int_option( av[i], "n=", n, 1, INT_MAX ); + handle_int_option( av[i], "size=", n, 1, INT_MAX ); + + handle_int_option( av[i], "k=", k, 1, INT_MAX ); + handle_int_option( av[i], "iterations=", k, 1, INT_MAX ); + + handle_int_option( av[i], "m=", m, 1, INT_MAX ); + handle_int_option( av[i], "threads=", m, 1, INT_MAX ); + + handle_int_option( av[i], "r=", r, 1, INT_MAX ); + handle_int_option( av[i], "ratio=", r, 1, INT_MAX ); + } + + printf( "%s: threads=%d size=%d iterations=%d ratio=%d %s\n\n", thmodel, m, n, k, r, pt_to_string( pt ) ); + + ps.reset( new X( n ) ); + + clock_t t = clock(); + + std::vector a( m ); + + for( int i = 0; i < m; ++i ) + { + boost::detail::lw_thread_create( a[ i ], boost::bind( worker, i, pt, k, r ) ); + } + + for( int j = 0; j < m; ++j ) + { + pthread_join( a[ j ], 0 ); + } + + t = clock() - t; + + double ts = static_cast( t ) / CLOCKS_PER_SEC; + printf( "%.3f seconds, %.3f accesses per microsecond.\n", ts, m * k / ts / 1e+6 ); +} diff --git a/test/sp_atomic_mt_test.cpp b/test/sp_atomic_mt_test.cpp index bef549d..143df98 100644 --- a/test/sp_atomic_mt_test.cpp +++ b/test/sp_atomic_mt_test.cpp @@ -1,3 +1,10 @@ + +// Copyright (c) 2008 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 + //#define USE_MUTEX //#define USE_RWLOCK From 2f1b1acc7a7ce6d3956fff629acc50e2cc791897 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 6 May 2008 18:58:15 +0000 Subject: [PATCH 107/132] Fix g++ 3.2 regression. [SVN r45177] --- include/boost/detail/sp_convertible.hpp | 12 ++++++++++++ include/boost/intrusive_ptr.hpp | 5 +---- include/boost/shared_ptr.hpp | 5 +---- include/boost/weak_ptr.hpp | 4 ++-- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/include/boost/detail/sp_convertible.hpp b/include/boost/detail/sp_convertible.hpp index 00463b3..798497c 100644 --- a/include/boost/detail/sp_convertible.hpp +++ b/include/boost/detail/sp_convertible.hpp @@ -17,6 +17,16 @@ #include +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( BOOST_NO_SFINAE ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ < 303 ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + namespace boost { @@ -57,4 +67,6 @@ template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_i } // namespace boost +#endif // !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + #endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 8982fe9..77a603e 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -22,10 +22,7 @@ #include #include - -#if !defined( BOOST_NO_SFINAE ) #include -#endif #include // for std::less @@ -78,7 +75,7 @@ public: #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) template -#if !defined( BOOST_NO_SFINAE ) +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) intrusive_ptr( intrusive_ptr const & rhs, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 02f2f4f..2c20ecc 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -31,10 +31,7 @@ #include #include #include - -#if !defined( BOOST_NO_SFINAE ) #include -#endif #if !defined(BOOST_SP_NO_ATOMIC_ACCESS) #include @@ -228,7 +225,7 @@ public: } template -#if !defined( BOOST_NO_SFINAE ) +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) shared_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index aadb60a..b300813 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -61,7 +61,7 @@ public: // template -#if !defined( BOOST_NO_SFINAE ) +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) weak_ptr( weak_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) @@ -76,7 +76,7 @@ public: } template -#if !defined( BOOST_NO_SFINAE ) +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) weak_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) From 4b0490c0ae03c03a4f6793b012dfdaa399d36c6e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 7 May 2008 10:15:16 +0000 Subject: [PATCH 108/132] Fix sp_convertible_test.cpp failure in C++0x mode. [SVN r45194] --- include/boost/shared_ptr.hpp | 12 ++++++++++-- test/sp_convertible_test.cpp | 5 +++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 2c20ecc..3bf00b1 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -349,7 +349,16 @@ public: } template - shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + shared_ptr( shared_ptr && r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + shared_ptr( shared_ptr && r ) + +#endif + : px( r.px ), pn() // never throws { pn.swap( r.pn ); r.px = 0; @@ -772,7 +781,6 @@ template D * get_deleter( shared_ptr const & p ) #endif } - return del; } diff --git a/test/sp_convertible_test.cpp b/test/sp_convertible_test.cpp index 165d55f..7f49e1f 100644 --- a/test/sp_convertible_test.cpp +++ b/test/sp_convertible_test.cpp @@ -59,7 +59,12 @@ int g( boost::shared_ptr ) int main() { + boost::shared_ptr p1; + BOOST_TEST( 1 == f( p1 ) ); BOOST_TEST( 1 == f( boost::shared_ptr() ) ); + + boost::shared_ptr p2; + BOOST_TEST( 4 == g( p2 ) ); BOOST_TEST( 4 == g( boost::shared_ptr() ) ); return boost::report_errors(); From d52878df885d5b3127af6f9cf87fd4f40c3e2104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 8 May 2008 19:08:38 +0000 Subject: [PATCH 109/132] Replaced non-ascii characters, ticket 1736 [SVN r45224] --- include/boost/pointer_cast.hpp | 2 +- include/boost/pointer_to_other.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/pointer_cast.hpp b/include/boost/pointer_cast.hpp index 5a5bec0..6e532eb 100644 --- a/include/boost/pointer_cast.hpp +++ b/include/boost/pointer_cast.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2005. +// (C) Copyright Ion Gaztanaga 2005. // 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) diff --git a/include/boost/pointer_to_other.hpp b/include/boost/pointer_to_other.hpp index 1cf2627..8516734 100644 --- a/include/boost/pointer_to_other.hpp +++ b/include/boost/pointer_to_other.hpp @@ -4,7 +4,7 @@ // // pointer_to_other.hpp // -// (C) Copyright Ion Gaztañaga 2005. +// (C) Copyright Ion Gaztanaga 2005. // Copyright (c) 2005 Peter Dimov. // // Distributed under the Boost Software License, Version 1.0. From d2610796164870db794fa3e96b4be204e1b1393b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 8 May 2008 19:22:16 +0000 Subject: [PATCH 110/132] Replaced non-ascii characters, ticket 1736 [SVN r45225] --- test/pointer_cast_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pointer_cast_test.cpp b/test/pointer_cast_test.cpp index 0d5d652..6e4620c 100644 --- a/test/pointer_cast_test.cpp +++ b/test/pointer_cast_test.cpp @@ -1,7 +1,7 @@ // // pointer_cast_test.cpp - a test for boost/pointer_cast.hpp // -// Copyright (c) 2005 Ion Gaztañaga +// Copyright (c) 2005 Ion Gaztanaga // Copyright (c) 2005 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See From 05e050abe0080528e4dec4ad8ec07f739d661391 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 13 May 2008 23:53:12 +0000 Subject: [PATCH 111/132] Disable sp_convertible for Borland 5.x. [SVN r45346] --- include/boost/detail/sp_convertible.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/detail/sp_convertible.hpp b/include/boost/detail/sp_convertible.hpp index 798497c..017217b 100644 --- a/include/boost/detail/sp_convertible.hpp +++ b/include/boost/detail/sp_convertible.hpp @@ -25,6 +25,10 @@ # define BOOST_SP_NO_SP_CONVERTIBLE #endif +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x600 ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) namespace boost From 31685fe5516eca027bd5b2d78ff4d00cb945b20e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 14 May 2008 00:21:28 +0000 Subject: [PATCH 112/132] Updated Borland workaround to properly use BOOST_NO_MEMBER_TEMPLATE_FRIENDS. [SVN r45347] --- include/boost/enable_shared_from_this.hpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 10accd6..b624ee9 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -21,10 +21,14 @@ namespace boost { +#if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) + template< class T > class enable_shared_from_this; template< class T, class Y > void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ); template< class T, class Y > void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ); +#endif + template< class T > class enable_shared_from_this { protected: @@ -78,7 +82,12 @@ private: } } -#if defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, <= 0x551 ) +#if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) + + template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ); + template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ); + +#else public: @@ -90,7 +99,8 @@ public: if( _weak_count.use_count() == 0 ) { _weak_count = owner.get_shared_count(); - }else if( !_shared_count.empty() ) + } + else if( !_shared_count.empty() ) { BOOST_ASSERT( owner.unique() ); // no weak_ptrs to owner should exist either, but there's no way to check that detail::sp_deleter_wrapper * pd = detail::basic_get_deleter( _shared_count ); @@ -101,9 +111,6 @@ public: detail::shared_count().swap( _shared_count ); } } - - template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ); - template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ); }; template< class T, class Y > inline void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ) From 83e2510ce572dc38d3e68ce6c8af293246f24da6 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Fri, 16 May 2008 11:12:32 +0000 Subject: [PATCH 113/132] Use the "no_tr1" version of : addition of Boost.Exception support to throw_exception has created new cyclic dependencies with Boost.TR1. [SVN r45422] --- include/boost/intrusive_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 77a603e..338e672 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -24,7 +24,7 @@ #include #include -#include // for std::less +#include // for std::less #if !defined(BOOST_NO_IOSTREAM) #if !defined(BOOST_NO_IOSFWD) From 2bfe13c9c4fd7be06a5c5e9c6b43ed1c39c6cbb8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 19 May 2008 15:09:54 +0000 Subject: [PATCH 114/132] Renamed CRITICAL_SECTION to critical_section to avoid ambiguity. [SVN r45545] --- include/boost/detail/lwm_win32_cs.hpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/include/boost/detail/lwm_win32_cs.hpp b/include/boost/detail/lwm_win32_cs.hpp index 4ee0a71..8142069 100644 --- a/include/boost/detail/lwm_win32_cs.hpp +++ b/include/boost/detail/lwm_win32_cs.hpp @@ -29,7 +29,7 @@ namespace detail #ifndef BOOST_USE_WINDOWS_H -struct CRITICAL_SECTION +struct critical_section { struct critical_section_debug * DebugInfo; long LockCount; @@ -43,10 +43,14 @@ struct CRITICAL_SECTION #endif }; -extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(CRITICAL_SECTION *); -extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(CRITICAL_SECTION *); -extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(CRITICAL_SECTION *); -extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(CRITICAL_SECTION *); +extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(critical_section *); + +#else + +typedef ::CRITICAL_SECTION critical_section; #endif // #ifndef BOOST_USE_WINDOWS_H @@ -54,7 +58,7 @@ class lightweight_mutex { private: - CRITICAL_SECTION cs_; + critical_section cs_; lightweight_mutex(lightweight_mutex const &); lightweight_mutex & operator=(lightweight_mutex const &); From 366472fc35a1f6138abf333c8e2c20bfcc05b300 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 23 May 2008 20:29:14 +0000 Subject: [PATCH 115/132] Fix #1938 in trunk [SVN r45690] --- include/boost/detail/sp_counted_base_sync.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/detail/sp_counted_base_sync.hpp b/include/boost/detail/sp_counted_base_sync.hpp index c01c3c5..d72dac2 100644 --- a/include/boost/detail/sp_counted_base_sync.hpp +++ b/include/boost/detail/sp_counted_base_sync.hpp @@ -18,6 +18,10 @@ #include #include +#if defined( __ia64__ ) && defined( __INTEL_COMPILER ) +# include +#endif + namespace boost { From 2a92df56f2dee5579de8bd6ca5acae6bb7d54d2a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 2 Jun 2008 20:01:30 +0000 Subject: [PATCH 116/132] #include in spinlock_sync.hpp as well. [SVN r46055] --- include/boost/detail/spinlock_sync.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/detail/spinlock_sync.hpp b/include/boost/detail/spinlock_sync.hpp index d602365..a752396 100644 --- a/include/boost/detail/spinlock_sync.hpp +++ b/include/boost/detail/spinlock_sync.hpp @@ -17,6 +17,10 @@ #include +#if defined( __ia64__ ) && defined( __INTEL_COMPILER ) +# include +#endif + namespace boost { From 77ab95317165f72ed473c45370532ba84909d95a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 16:07:20 +0000 Subject: [PATCH 117/132] Updated atomic access syntax to match N2674 and the WD. [SVN r47357] --- include/boost/shared_ptr.hpp | 139 +++++++++++++++++++++-------------- test/sp_atomic_mt2_test.cpp | 6 +- test/sp_atomic_mt_test.cpp | 4 +- test/sp_atomic_test.cpp | 22 +++--- 4 files changed, 98 insertions(+), 73 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 3bf00b1..e1704ea 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -5,7 +5,7 @@ // shared_ptr.hpp // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. -// Copyright (c) 2001-2007 Peter Dimov +// Copyright (c) 2001-2008 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -516,65 +516,11 @@ public: return pn < rhs.pn; } - // atomic access - -#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) - - shared_ptr atomic_load( memory_order /*mo*/ = memory_order_seq_cst ) const + bool _internal_equiv( shared_ptr const & r ) const { - boost::detail::spinlock_pool<2>::scoped_lock lock( this ); - return *this; + return px == r.px && pn == r.pn; } - void atomic_store( shared_ptr r, memory_order /*mo*/ = memory_order_seq_cst ) - { - boost::detail::spinlock_pool<2>::scoped_lock lock( this ); - swap( r ); - } - - shared_ptr atomic_swap( shared_ptr r, memory_order /*mo*/ = memory_order_seq_cst ) - { - boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( this ); - - sp.lock(); - swap( r ); - sp.unlock(); - - return r; // return std::move(r) - } - - bool atomic_compare_swap( shared_ptr & v, shared_ptr w ) - { - boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( this ); - - sp.lock(); - - if( px == v.px && pn == v.pn ) - { - swap( w ); - - sp.unlock(); - - return true; - } - else - { - shared_ptr tmp( *this ); - - sp.unlock(); - - tmp.swap( v ); - return false; - } - } - - inline bool atomic_compare_swap( shared_ptr & v, shared_ptr w, memory_order /*success*/, memory_order /*failure*/ ) - { - return atomic_compare_swap( v, w ); // std::move( w ) - } - -#endif - // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) @@ -784,6 +730,85 @@ template D * get_deleter( shared_ptr const & p ) return del; } +// atomic access + +#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) + +template inline bool atomic_is_lock_free( shared_ptr const * /*p*/ ) +{ + return false; +} + +template shared_ptr atomic_load( shared_ptr const * p ) +{ + boost::detail::spinlock_pool<2>::scoped_lock lock( p ); + return *p; +} + +template inline shared_ptr atomic_load_explicit( shared_ptr const * p, memory_order /*mo*/ ) +{ + return atomic_load( p ); +} + +template void atomic_store( shared_ptr * p, shared_ptr r ) +{ + boost::detail::spinlock_pool<2>::scoped_lock lock( p ); + p->swap( r ); +} + +template inline void atomic_store_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) +{ + atomic_store( p, r ); // std::move( r ) +} + +template shared_ptr atomic_exchange( shared_ptr * p, shared_ptr r ) +{ + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); + + sp.lock(); + p->swap( r ); + sp.unlock(); + + return r; // return std::move( r ) +} + +template shared_ptr atomic_exchange_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) +{ + return atomic_exchange( p, r ); // std::move( r ) +} + +template bool atomic_compare_exchange( shared_ptr * p, shared_ptr * v, shared_ptr w ) +{ + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); + + sp.lock(); + + if( p->_internal_equiv( *v ) ) + { + p->swap( w ); + + sp.unlock(); + + return true; + } + else + { + shared_ptr tmp( *p ); + + sp.unlock(); + + tmp.swap( *v ); + return false; + } +} + +template inline bool atomic_compare_exchange_explicit( shared_ptr * p, shared_ptr * v, shared_ptr w, memory_order /*success*/, memory_order /*failure*/ ) +{ + return atomic_compare_exchange( p, v, w ); // std::move( w ) +} + +#endif + } // namespace boost #ifdef BOOST_MSVC diff --git a/test/sp_atomic_mt2_test.cpp b/test/sp_atomic_mt2_test.cpp index c865359..6a2e44e 100644 --- a/test/sp_atomic_mt2_test.cpp +++ b/test/sp_atomic_mt2_test.cpp @@ -83,7 +83,7 @@ int read_access( prim_type pt ) case pt_atomics: { - boost::shared_ptr p2 = ps.atomic_load(); + boost::shared_ptr p2 = boost::atomic_load( &ps ); return p2->get(); } } @@ -109,14 +109,14 @@ void write_access( prim_type pt ) case pt_atomics: { - boost::shared_ptr p1 = ps.atomic_load(); + boost::shared_ptr p1 = boost::atomic_load( &ps ); for( ;; ) { boost::shared_ptr p2( new X( *p1 ) ); p2->set(); - if( ps.atomic_compare_swap( p1, p2 ) ) break; + if( boost::atomic_compare_exchange( &ps, &p1, p2 ) ) break; } } break; diff --git a/test/sp_atomic_mt_test.cpp b/test/sp_atomic_mt_test.cpp index 143df98..0f0bf68 100644 --- a/test/sp_atomic_mt_test.cpp +++ b/test/sp_atomic_mt_test.cpp @@ -93,7 +93,7 @@ void reader( int r ) #else - boost::shared_ptr p2 = ps.atomic_load(); + boost::shared_ptr p2 = boost::atomic_load( &ps ); s += p2->get(); @@ -134,7 +134,7 @@ void writer() BOOST_TEST( p2->v_ == i ); p2->set(); - ps.atomic_store( p2 ); + boost::atomic_store( &ps, p2 ); #endif } diff --git a/test/sp_atomic_test.cpp b/test/sp_atomic_test.cpp index c1113da..c8c3586 100644 --- a/test/sp_atomic_test.cpp +++ b/test/sp_atomic_test.cpp @@ -25,31 +25,31 @@ int main() boost::shared_ptr px( new X ); { - boost::shared_ptr p2 = px.atomic_load(); + boost::shared_ptr p2 = boost::atomic_load( &px ); BOOST_TEST_SP_EQ( p2, px ); boost::shared_ptr px2( new X ); - px.atomic_store( px2 ); + boost::atomic_store( &px, px2 ); BOOST_TEST_SP_EQ( px, px2 ); - p2 = px.atomic_load(); + p2 = boost::atomic_load( &px ); BOOST_TEST_SP_EQ( p2, px ); BOOST_TEST_SP_EQ( p2, px2 ); boost::shared_ptr px3( new X ); - boost::shared_ptr p3 = px.atomic_swap( px3 ); + boost::shared_ptr p3 = boost::atomic_exchange( &px, px3 ); BOOST_TEST_SP_EQ( p3, px2 ); BOOST_TEST_SP_EQ( px, px3 ); boost::shared_ptr px4( new X ); boost::shared_ptr cmp; - bool r = px.atomic_compare_swap( cmp, px4 ); + bool r = boost::atomic_compare_exchange( &px, &cmp, px4 ); BOOST_TEST( !r ); BOOST_TEST_SP_EQ( px, px3 ); BOOST_TEST_SP_EQ( cmp, px3 ); - r = px.atomic_compare_swap( cmp, px4 ); + r = boost::atomic_compare_exchange( &px, &cmp, px4 ); BOOST_TEST( r ); BOOST_TEST_SP_EQ( px, px4 ); } @@ -59,26 +59,26 @@ int main() px.reset(); { - boost::shared_ptr p2 = px.atomic_load( boost::memory_order_acquire ); + boost::shared_ptr p2 = boost::atomic_load_explicit( &px, boost::memory_order_acquire ); BOOST_TEST_SP_EQ( p2, px ); boost::shared_ptr px2( new X ); - px.atomic_store( px2, boost::memory_order_release ); + boost::atomic_store_explicit( &px, px2, boost::memory_order_release ); BOOST_TEST_SP_EQ( px, px2 ); - boost::shared_ptr p3 = px.atomic_swap( boost::shared_ptr(), boost::memory_order_acq_rel ); + boost::shared_ptr p3 = boost::atomic_exchange_explicit( &px, boost::shared_ptr(), boost::memory_order_acq_rel ); BOOST_TEST_SP_EQ( p3, px2 ); BOOST_TEST_SP_EQ( px, p2 ); boost::shared_ptr px4( new X ); boost::shared_ptr cmp( px2 ); - bool r = px.atomic_compare_swap( cmp, px4, boost::memory_order_acquire, boost::memory_order_relaxed ); + bool r = boost::atomic_compare_exchange_explicit( &px, &cmp, px4, boost::memory_order_acquire, boost::memory_order_relaxed ); BOOST_TEST( !r ); BOOST_TEST_SP_EQ( px, p2 ); BOOST_TEST_SP_EQ( cmp, p2 ); - r = px.atomic_compare_swap( cmp, px4, boost::memory_order_release, boost::memory_order_acquire ); + r = boost::atomic_compare_exchange_explicit( &px, &cmp, px4, boost::memory_order_release, boost::memory_order_acquire ); BOOST_TEST( r ); BOOST_TEST_SP_EQ( px, px4 ); } From 8c7954a53a7aa8652bdb364e9e4f5d89fe4885c8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 23 Jul 2008 20:04:52 +0000 Subject: [PATCH 118/132] Untabify. [SVN r47736] --- test/spinlock_pool_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spinlock_pool_test.cpp b/test/spinlock_pool_test.cpp index 00e7558..c1ce2b3 100644 --- a/test/spinlock_pool_test.cpp +++ b/test/spinlock_pool_test.cpp @@ -17,7 +17,7 @@ int main() int x = 0; { - boost::detail::spinlock_pool<0>::scoped_lock lock( &x ); + boost::detail::spinlock_pool<0>::scoped_lock lock( &x ); ++x; } From e3b9389a245fc8e27af3140539fb330550dbdc5f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:17:29 +0000 Subject: [PATCH 119/132] Fix #2338. [SVN r48832] --- src/sp_collector.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sp_collector.cpp b/src/sp_collector.cpp index 6f933c2..bb69ae8 100644 --- a/src/sp_collector.cpp +++ b/src/sp_collector.cpp @@ -104,6 +104,8 @@ static void find_unreachable_objects_impl(map_type const & m, map2_type & m2) BOOST_ASSERT(p->use_count() != 0); // there should be no inactive counts in the map + m2[ i->first ]; + scan_and_count(i->second.first, i->second.second, m, m2); } @@ -121,7 +123,7 @@ static void find_unreachable_objects_impl(map_type const & m, map2_type & m2) if(p->use_count() != i->second) open.push_back(p); } - std::cout << "... " << m2.size() << " objects in open.\n"; + std::cout << "... " << open.size() << " objects in open.\n"; for(open_type::iterator j = open.begin(); j != open.end(); ++j) { From a97cd2d0cc39594fbee056b4408ca1bc72848f3a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:21:56 +0000 Subject: [PATCH 120/132] Fix #2337. [SVN r48833] --- include/boost/detail/atomic_count_sync.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/detail/atomic_count_sync.hpp b/include/boost/detail/atomic_count_sync.hpp index e973fb7..676d3f9 100644 --- a/include/boost/detail/atomic_count_sync.hpp +++ b/include/boost/detail/atomic_count_sync.hpp @@ -15,6 +15,10 @@ // http://www.boost.org/LICENSE_1_0.txt) // +#if defined( __ia64__ ) && defined( __INTEL_COMPILER ) +# include +#endif + namespace boost { From 2b2557933889470a1123d1cbb75c0327116f39cb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:31:13 +0000 Subject: [PATCH 121/132] Fix #2310. [SVN r48834] --- include/boost/detail/spinlock.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/detail/spinlock.hpp b/include/boost/detail/spinlock.hpp index e273647..8a73999 100644 --- a/include/boost/detail/spinlock.hpp +++ b/include/boost/detail/spinlock.hpp @@ -30,9 +30,9 @@ #include -#if defined(__GNUC__) && defined( __arm__ ) +#if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ ) # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include From 2fb567b3f2a0af74ad2275815b559ec220c9b5e5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:37:13 +0000 Subject: [PATCH 122/132] Fix #2336. [SVN r48835] --- include/boost/detail/atomic_count.hpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 804fd1a..b731fcc 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -90,23 +90,18 @@ 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 ) - +#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) # include #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) - # include #elif defined(BOOST_HAS_PTHREADS) From 6175baf858dada6cc5276dc2b02b9797afd50038 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:43:14 +0000 Subject: [PATCH 123/132] Fix #2000. [SVN r48836] --- include/boost/detail/atomic_count.hpp | 2 +- include/boost/detail/sp_counted_base.hpp | 2 +- include/boost/detail/spinlock.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index b731fcc..c53a63b 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -98,7 +98,7 @@ typedef long atomic_count; #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) # include -#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) +#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # include #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index 6d733d0..d576a49 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -46,7 +46,7 @@ #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # include #elif defined(__GNUC__) && ( defined( __sparcv8 ) || defined( __sparcv9 ) ) diff --git a/include/boost/detail/spinlock.hpp b/include/boost/detail/spinlock.hpp index 8a73999..d4e5bce 100644 --- a/include/boost/detail/spinlock.hpp +++ b/include/boost/detail/spinlock.hpp @@ -32,7 +32,7 @@ #if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ ) # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include From f5990cab6590df57bbab982122caa0ea7842024f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:49:18 +0000 Subject: [PATCH 124/132] Fix #1758. V9 is the default for g++ 4.2 or later, on 4.1 and earlier do not attempt to use CAS on V8. [SVN r48837] --- include/boost/detail/sp_counted_base.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index d576a49..c25a57f 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -49,7 +49,7 @@ #elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # include -#elif defined(__GNUC__) && ( defined( __sparcv8 ) || defined( __sparcv9 ) ) +#elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) ) # include #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) From 774332f85acc11f32964e6a3bd7f6d66cfd24cef Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:53:53 +0000 Subject: [PATCH 125/132] Fix #2263. See also [48835]. [SVN r48838] --- include/boost/detail/spinlock.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/spinlock.hpp b/include/boost/detail/spinlock.hpp index d4e5bce..346fb3c 100644 --- a/include/boost/detail/spinlock.hpp +++ b/include/boost/detail/spinlock.hpp @@ -32,7 +32,7 @@ #if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ ) # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include From 395766e2d376169c1f1dcb72c8179fdb585c9549 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:59:07 +0000 Subject: [PATCH 126/132] Fix #2315. [SVN r48839] --- shared_array.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared_array.htm b/shared_array.htm index 87bf61e..320a54a 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -47,7 +47,7 @@ void reset(T * p = 0); template<class D> void reset(T * p, D d); - T & operator[](std::ptrdiff_t i) const() const; // never throws + T & operator[](std::ptrdiff_t i) const; // never throws T * get() const; // never throws bool unique() const; // never throws From ed79000ea832a1bc2d0dfcf7ec1e6ffb72fc707c Mon Sep 17 00:00:00 2001 From: Nicola Musatti Date: Mon, 6 Oct 2008 20:17:18 +0000 Subject: [PATCH 127/132] Patch from Ticket #2342 [SVN r49153] --- include/boost/detail/sp_convertible.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/sp_convertible.hpp b/include/boost/detail/sp_convertible.hpp index 017217b..2c1539b 100644 --- a/include/boost/detail/sp_convertible.hpp +++ b/include/boost/detail/sp_convertible.hpp @@ -25,7 +25,7 @@ # define BOOST_SP_NO_SP_CONVERTIBLE #endif -#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x600 ) +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ <= 0x610 ) # define BOOST_SP_NO_SP_CONVERTIBLE #endif From d9b9921d236f43d3d1f01521224ae044d0845b71 Mon Sep 17 00:00:00 2001 From: "Michael A. Jackson" Date: Sat, 1 Nov 2008 13:15:41 +0000 Subject: [PATCH 128/132] Continuing merge of CMake build system files into trunk with the encouragement of Doug Gregor [SVN r49510] --- CMakeLists.txt | 30 ++++++++++++++++++++++++++++++ module.cmake | 1 + test/CMakeLists.txt | 15 +++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 module.cmake create mode 100644 test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..abe2fc7 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,30 @@ +#---------------------------------------------------------------------------- +# This file was automatically generated from the original CMakeLists.txt file +# Add a variable to hold the headers for the library +set (lib_headers + enable_shared_from_this.hpp + pointer_cast.hpp + scoped_array.hpp + scoped_ptr.hpp + shared_array.hpp + shared_ptr.hpp + weak_ptr.hpp +) + +# Add a library target to the build system +boost_library_project( + smart_ptr + # SRCDIRS + TESTDIRS test + HEADERS ${lib_headers} + # DOCDIRS + DESCRIPTION "Five smart pointer class templates." + MODULARIZED + AUTHORS "Greg Colvin" + "Beman Dawes " + "Peter Dimov " + "Darin Adler" + # MAINTAINERS +) + + diff --git a/module.cmake b/module.cmake new file mode 100644 index 0000000..d83266c --- /dev/null +++ b/module.cmake @@ -0,0 +1 @@ +boost_module(smart_ptr DEPENDS utility) \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..67eee62 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,15 @@ +boost_test_run(smart_ptr_test) +boost_test_run(shared_ptr_basic_test) +boost_test_run(shared_ptr_test) +boost_test_run(weak_ptr_test) +boost_test_run(shared_from_this_test) +boost_test_run(get_deleter_test) +boost_test_run(intrusive_ptr_test) +boost_test_run(atomic_count_test) +boost_test_run(lw_mutex_test) +boost_test_compile_fail(shared_ptr_assign_fail) +boost_test_compile_fail(shared_ptr_delete_fail) +boost_test_run(shared_ptr_alloc2_test) +boost_test_run(pointer_cast_test) +boost_test_compile(pointer_to_other_test) +boost_test_run(auto_ptr_rv_test) From c40b30664750da870f97be7c616e6c4ba5186f20 Mon Sep 17 00:00:00 2001 From: "Michael A. Jackson" Date: Fri, 7 Nov 2008 17:02:56 +0000 Subject: [PATCH 129/132] Updating CMake files to latest trunk. Added dependency information for regression tests and a few new macros for internal use. [SVN r49627] --- test/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 67eee62..7ddae31 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,3 +1,6 @@ +boost_additional_test_dependencies(tokenizer BOOST_DEPENDS test intrusive) + + boost_test_run(smart_ptr_test) boost_test_run(shared_ptr_basic_test) boost_test_run(shared_ptr_test) From 13f91c15f030ebcc1eca28e7bdd4d439b97d4771 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 28 Feb 2009 20:02:12 +0000 Subject: [PATCH 130/132] Sync enable_shared_from_this.hpp and shared_ptr.hpp with release. [SVN r51485] --- include/boost/enable_shared_from_this.hpp | 95 +++--------- include/boost/shared_ptr.hpp | 177 +++++++--------------- 2 files changed, 71 insertions(+), 201 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index b624ee9..4e49f1f 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -13,23 +13,15 @@ // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html // -#include +#include #include #include -#include +#include namespace boost { -#if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) - -template< class T > class enable_shared_from_this; -template< class T, class Y > void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ); -template< class T, class Y > void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ); - -#endif - -template< class T > class enable_shared_from_this +template class enable_shared_from_this { protected: @@ -46,89 +38,36 @@ protected: return *this; } -// virtual destructor because we need a vtable for dynamic_cast from base to derived to work - virtual ~enable_shared_from_this() + ~enable_shared_from_this() { - BOOST_ASSERT( _shared_count.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist } public: shared_ptr shared_from_this() { - init_weak_once(); - T * p = dynamic_cast( this ); - return shared_ptr( detail::shared_count( _weak_count ), p ); + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(p.get() == this); + return p; } shared_ptr shared_from_this() const { - init_weak_once(); - T const * p = dynamic_cast( this ); - return shared_ptr( detail::shared_count( _weak_count ), p ); + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(p.get() == this); + return p; } -private: +// Note: No, you don't need to initialize _internal_weak_this +// +// Please read the documentation, not the code +// +// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html - mutable detail::weak_count _weak_count; - mutable detail::shared_count _shared_count; - - void init_weak_once() const - { - if( _weak_count.empty() ) - { - detail::shared_count( (void*)0, detail::sp_deleter_wrapper() ).swap( _shared_count ); - _weak_count = _shared_count; - } - } - -#if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) - - template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ); - template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ); - -#else - -public: - -#endif - - template - void sp_accept_owner( shared_ptr & owner ) const - { - if( _weak_count.use_count() == 0 ) - { - _weak_count = owner.get_shared_count(); - } - else if( !_shared_count.empty() ) - { - BOOST_ASSERT( owner.unique() ); // no weak_ptrs to owner should exist either, but there's no way to check that - detail::sp_deleter_wrapper * pd = detail::basic_get_deleter( _shared_count ); - BOOST_ASSERT( pd != 0 ); - pd->set_deleter( owner.get_shared_count() ); - - owner.reset( _shared_count, owner.get() ); - detail::shared_count().swap( _shared_count ); - } - } + typedef T _internal_element_type; // for bcc 5.5.1 + mutable weak_ptr<_internal_element_type> _internal_weak_this; }; -template< class T, class Y > inline void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ) -{ - if( pe != 0 ) - { - pe->sp_accept_owner( *ptr ); - } -} - -template< class T, class Y > inline void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ) -{ - if( pe != 0 ) - { - pe->sp_accept_owner( *ptr ); - } -} - } // namespace boost #endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index e1704ea..ad2bc17 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -58,8 +58,8 @@ namespace boost { -template class shared_ptr; template class weak_ptr; +template class enable_shared_from_this; namespace detail { @@ -98,6 +98,43 @@ template<> struct shared_ptr_traits #endif +// enable_shared_from_this support + +template void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this const * pe, Y const * px ) +{ + if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); +} + +#ifdef _MANAGED + +// Avoid C4793, ... causes native code generation + +struct sp_any_pointer +{ + template sp_any_pointer( T* ) {} +}; + +inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer ) +{ +} + +#else // _MANAGED + +#ifdef sgi +// Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed +# pragma set woff 3506 +#endif + +inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) +{ +} + +#ifdef sgi +# pragma reset woff 3506 +#endif + +#endif // _MANAGED + #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) // rvalue auto_ptr support based on a technique by Dave Abrahams @@ -109,38 +146,12 @@ template< class T, class R > struct sp_enable_if_auto_ptr template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R > { typedef R type; -}; +}; #endif } // namespace detail -// sp_accept_owner - -#ifdef _MANAGED - -// Avoid C4793, ... causes native code generation - -struct sp_any_pointer -{ - template sp_any_pointer( T* ) {} -}; - -inline void sp_accept_owner( sp_any_pointer, sp_any_pointer ) -{ -} - -inline void sp_accept_owner( sp_any_pointer, sp_any_pointer, sp_any_pointer ) -{ -} - -#else // _MANAGED - -inline void sp_accept_owner( ... ) -{ -} - -#endif // _MANAGED // // shared_ptr @@ -171,7 +182,7 @@ public: template explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { - sp_accept_owner( this, p ); + boost::detail::sp_enable_shared_from_this( pn, p, p ); } // @@ -180,18 +191,16 @@ public: // shared_ptr will release p by calling d(p) // - template shared_ptr( Y * p, D d ): px( p ), pn( p, d ) + template shared_ptr(Y * p, D d): px(p), pn(p, d) { - D * pd = static_cast( pn.get_deleter( BOOST_SP_TYPEID(D) ) ); - sp_accept_owner( this, p, pd ); + boost::detail::sp_enable_shared_from_this( pn, p, p ); } // As above, but with allocator. A's copy constructor shall not throw. template shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) { - D * pd = static_cast( pn.get_deleter( BOOST_SP_TYPEID(D) ) ); - sp_accept_owner( this, p, pd ); + boost::detail::sp_enable_shared_from_this( pn, p, p ); } // generated copy constructor, assignment, destructor are fine... @@ -238,10 +247,6 @@ public: { } - shared_ptr( detail::shared_count const & c, T * p ): px( p ), pn( c ) // never throws - { - } - // aliasing template< class Y > shared_ptr( shared_ptr const & r, T * p ): px( p ), pn( r.pn ) // never throws @@ -283,8 +288,7 @@ public: { Y * tmp = r.get(); pn = boost::detail::shared_count(r); - - sp_accept_owner( this, tmp ); + boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); } #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) @@ -294,8 +298,7 @@ public: { typename Ap::element_type * tmp = r.get(); pn = boost::detail::shared_count( r ); - - sp_accept_owner( this, tmp ); + boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); } @@ -364,10 +367,6 @@ public: r.px = 0; } - shared_ptr(detail::shared_count && c, T * p): px(p), pn( static_cast< detail::shared_count && >( c ) ) // never throws - { - } - shared_ptr & operator=( shared_ptr && r ) // never throws { this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); @@ -409,18 +408,6 @@ public: this_type( r, p ).swap( *this ); } - void reset( detail::shared_count const & c, T * p ) - { - this_type( c, p ).swap( *this ); - } - -#if defined( BOOST_HAS_RVALUE_REFS ) - void reset( detail::shared_count && c, T * p ) - { - this_type( static_cast< detail::shared_count && >( c ), p ).swap( *this ); - } -#endif - reference operator* () const // never throws { BOOST_ASSERT(px != 0); @@ -506,16 +493,16 @@ public: pn.swap(other.pn); } - detail::shared_count const & get_shared_count() const // never throws - { - return pn; - } - template bool _internal_less(shared_ptr const & rhs) const { return pn < rhs.pn; } + void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const + { + return pn.get_deleter( ti ); + } + bool _internal_equiv( shared_ptr const & r ) const { return px == r.px && pn == r.pn; @@ -652,8 +639,6 @@ template std::basic_ostream & operator<< (std:: // get_deleter -namespace detail -{ #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) ) @@ -661,75 +646,21 @@ namespace detail // g++ 2.9x doesn't allow static_cast(void *) // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it -template D * basic_get_deleter(shared_count const & c) +template D * get_deleter(shared_ptr const & p) { - void const * q = c.get_deleter(BOOST_SP_TYPEID(D)); + void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D)); return const_cast(static_cast(q)); } #else -template D * basic_get_deleter(shared_count const & c) +template D * get_deleter(shared_ptr const & p) { - return static_cast(c.get_deleter(BOOST_SP_TYPEID(D))); + return static_cast(p._internal_get_deleter(BOOST_SP_TYPEID(D))); } #endif -class sp_deleter_wrapper -{ - detail::shared_count _deleter; -public: - sp_deleter_wrapper() - {} - void set_deleter(shared_count const &deleter) - { - _deleter = deleter; - } - void operator()(const void *) - { - BOOST_ASSERT(_deleter.use_count() <= 1); - detail::shared_count().swap( _deleter ); - } - template -#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) - D* get_deleter( D* ) const -#else - D* get_deleter() const -#endif - { - return boost::detail::basic_get_deleter(_deleter); - } -}; - -} // namespace detail - -template D * get_deleter( shared_ptr const & p ) -{ - D *del = detail::basic_get_deleter( p.get_shared_count() ); - - if( del == 0 ) - { - detail::sp_deleter_wrapper *del_wrapper = detail::basic_get_deleter(p.get_shared_count()); - -#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) - - if( del_wrapper ) del = del_wrapper->get_deleter( (D*)0 ); - -#elif defined( __GNUC__ ) && BOOST_WORKAROUND( __GNUC__, < 4 ) - - if( del_wrapper ) del = del_wrapper->::boost::detail::sp_deleter_wrapper::get_deleter(); - -#else - - if( del_wrapper ) del = del_wrapper->get_deleter(); - -#endif - } - - return del; -} - // atomic access #if !defined(BOOST_SP_NO_ATOMIC_ACCESS) From 10f6ff8b77db528ca6ca6896b6786cba87956745 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 28 Feb 2009 21:08:25 +0000 Subject: [PATCH 131/132] Sync smart_ptr/test/Jamfile.v2 with release. [SVN r51486] --- test/Jamfile.v2 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 8520861..5f68e20 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -36,19 +36,17 @@ import testing ; [ compile-fail scoped_ptr_eq_fail.cpp ] [ compile-fail scoped_array_eq_fail.cpp ] [ run esft_regtest.cpp ] - [ run esft_constructor_test.cpp ] [ run yield_k_test.cpp ] [ run yield_k_test.cpp : : : multi : yield_k_test.mt ] [ run spinlock_test.cpp ] [ run spinlock_try_test.cpp ] [ run spinlock_try_test.cpp : : : multi : spinlock_try_test.mt ] [ run spinlock_pool_test.cpp ] - [ run sp_accept_owner_test.cpp ] - [ run sp_atomic_test.cpp ] [ run make_shared_test.cpp ] [ run sp_convertible_test.cpp ] [ run wp_convertible_test.cpp ] [ run ip_convertible_test.cpp ] [ run allocate_shared_test.cpp ] + [ run sp_atomic_test.cpp ] ; } From 0da6902267567d27056b2bd67540f2a819bbec11 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 1 Mar 2009 16:00:42 +0000 Subject: [PATCH 132/132] Move smart_ptr into boost/smart_ptr/*.hpp (refs #2239). [SVN r51509] --- include/boost/detail/atomic_count.hpp | 106 +-- include/boost/detail/lightweight_mutex.hpp | 28 +- include/boost/enable_shared_from_this.hpp | 63 +- include/boost/intrusive_ptr.hpp | 301 +------ include/boost/make_shared.hpp | 418 +--------- include/boost/scoped_array.hpp | 124 +-- include/boost/scoped_ptr.hpp | 146 +--- include/boost/shared_array.hpp | 176 +--- include/boost/shared_ptr.hpp | 734 +---------------- .../{detail => smart_ptr}/bad_weak_ptr.hpp | 8 +- .../boost/smart_ptr/detail/atomic_count.hpp | 119 +++ .../detail/atomic_count_gcc.hpp | 6 +- .../detail/atomic_count_gcc_x86.hpp | 6 +- .../detail/atomic_count_pthreads.hpp | 6 +- .../detail/atomic_count_solaris.hpp | 6 +- .../detail/atomic_count_sync.hpp | 6 +- .../detail/atomic_count_win32.hpp | 6 +- .../smart_ptr/detail/lightweight_mutex.hpp | 42 + .../boost/{ => smart_ptr}/detail/lwm_nop.hpp | 6 +- .../{ => smart_ptr}/detail/lwm_pthreads.hpp | 6 +- .../{ => smart_ptr}/detail/lwm_win32_cs.hpp | 6 +- .../smart_ptr/detail/quick_allocator.hpp | 198 +++++ .../detail/shared_array_nmt.hpp | 8 +- .../{ => smart_ptr}/detail/shared_count.hpp | 12 +- .../{ => smart_ptr}/detail/shared_ptr_nmt.hpp | 8 +- .../{ => smart_ptr}/detail/sp_convertible.hpp | 6 +- .../detail/sp_counted_base.hpp | 34 +- .../detail/sp_counted_base_acc_ia64.hpp | 6 +- .../detail/sp_counted_base_cw_ppc.hpp | 6 +- .../detail/sp_counted_base_cw_x86.hpp | 6 +- .../detail/sp_counted_base_gcc_ia64.hpp | 6 +- .../detail/sp_counted_base_gcc_ppc.hpp | 6 +- .../detail/sp_counted_base_gcc_sparc.hpp | 6 +- .../detail/sp_counted_base_gcc_x86.hpp | 6 +- .../detail/sp_counted_base_nt.hpp | 6 +- .../detail/sp_counted_base_pt.hpp | 6 +- .../detail/sp_counted_base_solaris.hpp | 6 +- .../detail/sp_counted_base_spin.hpp | 8 +- .../detail/sp_counted_base_sync.hpp | 6 +- .../detail/sp_counted_base_w32.hpp | 6 +- .../detail/sp_counted_impl.hpp | 10 +- .../boost/{ => smart_ptr}/detail/spinlock.hpp | 16 +- .../detail/spinlock_gcc_arm.hpp | 8 +- .../{ => smart_ptr}/detail/spinlock_nt.hpp | 6 +- .../{ => smart_ptr}/detail/spinlock_pool.hpp | 8 +- .../{ => smart_ptr}/detail/spinlock_pt.hpp | 6 +- .../{ => smart_ptr}/detail/spinlock_sync.hpp | 8 +- .../{ => smart_ptr}/detail/spinlock_w32.hpp | 8 +- .../boost/{ => smart_ptr}/detail/yield_k.hpp | 8 +- .../smart_ptr/enable_shared_from_this.hpp | 73 ++ include/boost/smart_ptr/intrusive_ptr.hpp | 311 ++++++++ include/boost/smart_ptr/make_shared.hpp | 433 ++++++++++ include/boost/smart_ptr/scoped_array.hpp | 138 ++++ include/boost/smart_ptr/scoped_ptr.hpp | 160 ++++ include/boost/smart_ptr/shared_array.hpp | 193 +++++ include/boost/smart_ptr/shared_ptr.hpp | 751 ++++++++++++++++++ include/boost/smart_ptr/weak_ptr.hpp | 182 +++++ include/boost/weak_ptr.hpp | 172 +--- test/spinlock_pool_test.cpp | 2 +- 59 files changed, 2770 insertions(+), 2388 deletions(-) rename include/boost/{detail => smart_ptr}/bad_weak_ptr.hpp (86%) create mode 100644 include/boost/smart_ptr/detail/atomic_count.hpp rename include/boost/{ => smart_ptr}/detail/atomic_count_gcc.hpp (85%) rename include/boost/{ => smart_ptr}/detail/atomic_count_gcc_x86.hpp (87%) rename include/boost/{ => smart_ptr}/detail/atomic_count_pthreads.hpp (88%) rename include/boost/{ => smart_ptr}/detail/atomic_count_solaris.hpp (82%) rename include/boost/{ => smart_ptr}/detail/atomic_count_sync.hpp (83%) rename include/boost/{ => smart_ptr}/detail/atomic_count_win32.hpp (83%) create mode 100644 include/boost/smart_ptr/detail/lightweight_mutex.hpp rename include/boost/{ => smart_ptr}/detail/lwm_nop.hpp (76%) rename include/boost/{ => smart_ptr}/detail/lwm_pthreads.hpp (88%) rename include/boost/{ => smart_ptr}/detail/lwm_win32_cs.hpp (91%) create mode 100644 include/boost/smart_ptr/detail/quick_allocator.hpp rename include/boost/{ => smart_ptr}/detail/shared_array_nmt.hpp (92%) rename include/boost/{ => smart_ptr}/detail/shared_count.hpp (96%) rename include/boost/{ => smart_ptr}/detail/shared_ptr_nmt.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_convertible.hpp (89%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base.hpp (57%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_acc_ia64.hpp (92%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_cw_ppc.hpp (92%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_cw_x86.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_gcc_ia64.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_gcc_ppc.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_gcc_sparc.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_gcc_x86.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_nt.hpp (90%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_pt.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_solaris.hpp (91%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_spin.hpp (90%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_sync.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_w32.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_impl.hpp (94%) rename include/boost/{ => smart_ptr}/detail/spinlock.hpp (70%) rename include/boost/{ => smart_ptr}/detail/spinlock_gcc_arm.hpp (84%) rename include/boost/{ => smart_ptr}/detail/spinlock_nt.hpp (87%) rename include/boost/{ => smart_ptr}/detail/spinlock_pool.hpp (91%) rename include/boost/{ => smart_ptr}/detail/spinlock_pt.hpp (86%) rename include/boost/{ => smart_ptr}/detail/spinlock_sync.hpp (84%) rename include/boost/{ => smart_ptr}/detail/spinlock_w32.hpp (88%) rename include/boost/{ => smart_ptr}/detail/yield_k.hpp (92%) create mode 100644 include/boost/smart_ptr/enable_shared_from_this.hpp create mode 100644 include/boost/smart_ptr/intrusive_ptr.hpp create mode 100644 include/boost/smart_ptr/make_shared.hpp create mode 100644 include/boost/smart_ptr/scoped_array.hpp create mode 100644 include/boost/smart_ptr/scoped_ptr.hpp create mode 100644 include/boost/smart_ptr/shared_array.hpp create mode 100644 include/boost/smart_ptr/shared_ptr.hpp create mode 100644 include/boost/smart_ptr/weak_ptr.hpp diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index c53a63b..5411c7a 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -12,108 +12,10 @@ // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // -// 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) -// -// typedef boost::detail::atomic_count; -// -// atomic_count a(n); -// -// (n is convertible to long) -// -// Effects: Constructs an atomic_count with an initial value of n -// -// a; -// -// Returns: (long) the current value of a -// -// ++a; -// -// Effects: Atomically increments the value of a -// Returns: nothing -// -// --a; -// -// Effects: Atomically decrements the value of a -// Returns: (long) zero if the new value of a is zero, -// unspecified non-zero value otherwise (usually the new value) -// -// Important note: when --a returns zero, it must act as a -// read memory barrier (RMB); i.e. the calling thread must -// have a synchronized view of the memory -// -// On Intel IA-32 (x86) memory is always synchronized, so this -// is not a problem. -// -// On many architectures the atomic instructions already act as -// a memory barrier. -// -// This property is necessary for proper reference counting, since -// a thread can update the contents of a shared object, then -// release its reference, and another thread may immediately -// release the last reference causing object destruction. -// -// The destructor needs to have a synchronized view of the -// object to perform proper cleanup. -// -// Original example by Alexander Terekhov: -// -// Given: -// -// - a mutable shared object OBJ; -// - two threads THREAD1 and THREAD2 each holding -// a private smart_ptr object pointing to that OBJ. -// -// t1: THREAD1 updates OBJ (thread-safe via some synchronization) -// and a few cycles later (after "unlock") destroys smart_ptr; -// -// t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization -// with respect to shared mutable object OBJ; OBJ destructors -// are called driven by smart_ptr interface... -// +// 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 - -#ifndef BOOST_HAS_THREADS - -namespace boost -{ - -namespace detail -{ - -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 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) -# 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 -#error Unrecognized threading platform - -#endif +#include #endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index e740d7f..b7a7f6d 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -12,31 +12,11 @@ // // Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd. // -// 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) -// -// typedef boost::detail::lightweight_mutex; -// -// boost::detail::lightweight_mutex is a header-only implementation of -// a subset of the Mutex concept requirements: -// -// http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex -// -// It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX. +// 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_HAS_THREADS) -# 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 -#endif +#include #endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 4e49f1f..b1bb63d 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -6,68 +6,13 @@ // // Copyright (c) 2002 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) +// 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 // // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html // -#include -#include -#include -#include - -namespace boost -{ - -template class enable_shared_from_this -{ -protected: - - enable_shared_from_this() - { - } - - enable_shared_from_this(enable_shared_from_this const &) - { - } - - enable_shared_from_this & operator=(enable_shared_from_this const &) - { - return *this; - } - - ~enable_shared_from_this() - { - } - -public: - - shared_ptr shared_from_this() - { - shared_ptr p(_internal_weak_this); - BOOST_ASSERT(p.get() == this); - return p; - } - - shared_ptr shared_from_this() const - { - shared_ptr p(_internal_weak_this); - BOOST_ASSERT(p.get() == this); - return p; - } - -// Note: No, you don't need to initialize _internal_weak_this -// -// Please read the documentation, not the code -// -// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html - - typedef T _internal_element_type; // for bcc 5.5.1 - mutable weak_ptr<_internal_element_type> _internal_weak_this; -}; - -} // namespace boost +#include #endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 338e672..63036dc 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -6,306 +6,13 @@ // // Copyright (c) 2001, 2002 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) +// 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 // // See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation. // -#include - -#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash -# pragma warning(push) -# pragma warning(disable:4284) // odd return type for operator-> -#endif - -#include -#include -#include - -#include // for std::less - -#if !defined(BOOST_NO_IOSTREAM) -#if !defined(BOOST_NO_IOSFWD) -#include // for std::basic_ostream -#else -#include -#endif -#endif - - -namespace boost -{ - -// -// intrusive_ptr -// -// A smart pointer that uses intrusive reference counting. -// -// Relies on unqualified calls to -// -// void intrusive_ptr_add_ref(T * p); -// void intrusive_ptr_release(T * p); -// -// (p != 0) -// -// The object is responsible for destroying itself. -// - -template class intrusive_ptr -{ -private: - - typedef intrusive_ptr this_type; - -public: - - typedef T element_type; - - intrusive_ptr(): p_(0) - { - } - - intrusive_ptr(T * p, bool add_ref = true): p_(p) - { - if(p_ != 0 && add_ref) intrusive_ptr_add_ref(p_); - } - -#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) - - template -#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) - - intrusive_ptr( intrusive_ptr const & rhs, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) - -#else - - intrusive_ptr( intrusive_ptr const & rhs ) - -#endif - : p_( rhs.get() ) - { - if( p_ != 0 ) intrusive_ptr_add_ref( p_ ); - } - -#endif - - intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_) - { - if(p_ != 0) intrusive_ptr_add_ref(p_); - } - - ~intrusive_ptr() - { - if(p_ != 0) intrusive_ptr_release(p_); - } - -#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) - - template intrusive_ptr & operator=(intrusive_ptr const & rhs) - { - this_type(rhs).swap(*this); - return *this; - } - -#endif - - intrusive_ptr & operator=(intrusive_ptr const & rhs) - { - this_type(rhs).swap(*this); - return *this; - } - - intrusive_ptr & operator=(T * rhs) - { - this_type(rhs).swap(*this); - return *this; - } - - void reset() - { - this_type().swap( *this ); - } - - void reset( T * rhs ) - { - this_type( rhs ).swap( *this ); - } - - T * get() const - { - return p_; - } - - T & operator*() const - { - BOOST_ASSERT( p_ != 0 ); - return *p_; - } - - T * operator->() const - { - BOOST_ASSERT( p_ != 0 ); - return p_; - } - -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) - - operator bool () const - { - return p_ != 0; - } - -#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return p_ == 0? 0: &this_type::get; - } - -#else - - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type () const - { - return p_ == 0? 0: &this_type::p_; - } - -#endif - - // operator! is a Borland-specific workaround - bool operator! () const - { - return p_ == 0; - } - - void swap(intrusive_ptr & rhs) - { - T * tmp = p_; - p_ = rhs.p_; - rhs.p_ = tmp; - } - -private: - - T * p_; -}; - -template inline bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) -{ - return a.get() == b.get(); -} - -template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) -{ - return a.get() != b.get(); -} - -template inline bool operator==(intrusive_ptr const & a, U * b) -{ - return a.get() == b; -} - -template inline bool operator!=(intrusive_ptr const & a, U * b) -{ - return a.get() != b; -} - -template inline bool operator==(T * a, intrusive_ptr const & b) -{ - return a == b.get(); -} - -template inline bool operator!=(T * a, intrusive_ptr const & b) -{ - return a != b.get(); -} - -#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 - -// Resolve the ambiguity between our op!= and the one in rel_ops - -template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) -{ - return a.get() != b.get(); -} - -#endif - -template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) -{ - return std::less()(a.get(), b.get()); -} - -template void swap(intrusive_ptr & lhs, intrusive_ptr & rhs) -{ - lhs.swap(rhs); -} - -// mem_fn support - -template T * get_pointer(intrusive_ptr const & p) -{ - return p.get(); -} - -template intrusive_ptr static_pointer_cast(intrusive_ptr const & p) -{ - return static_cast(p.get()); -} - -template intrusive_ptr const_pointer_cast(intrusive_ptr const & p) -{ - return const_cast(p.get()); -} - -template intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & p) -{ - return dynamic_cast(p.get()); -} - -// operator<< - -#if !defined(BOOST_NO_IOSTREAM) - -#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) - -template std::ostream & operator<< (std::ostream & os, intrusive_ptr const & p) -{ - os << p.get(); - return os; -} - -#else - -// in STLport's no-iostreams mode no iostream symbols can be used -#ifndef _STLP_NO_IOSTREAMS - -# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) -// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL -using std::basic_ostream; -template basic_ostream & operator<< (basic_ostream & os, intrusive_ptr const & p) -# else -template std::basic_ostream & operator<< (std::basic_ostream & os, intrusive_ptr const & p) -# endif -{ - os << p.get(); - return os; -} - -#endif // _STLP_NO_IOSTREAMS - -#endif // __GNUC__ < 3 - -#endif // !defined(BOOST_NO_IOSTREAM) - -} // namespace boost - -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif +#include #endif // #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED diff --git a/include/boost/make_shared.hpp b/include/boost/make_shared.hpp index cc3685b..c04938f 100644 --- a/include/boost/make_shared.hpp +++ b/include/boost/make_shared.hpp @@ -12,422 +12,6 @@ // See http://www.boost.org/libs/smart_ptr/make_shared.html // for documentation. -#include -#include -#include -#include -#include -#include - -namespace boost -{ - -namespace detail -{ - -template< std::size_t N, std::size_t A > struct sp_aligned_storage -{ - union type - { - char data_[ N ]; - typename boost::type_with_alignment< A >::type align_; - }; -}; - -template< class T > class sp_ms_deleter -{ -private: - - typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type; - - bool initialized_; - storage_type storage_; - -private: - - void destroy() - { - if( initialized_ ) - { - reinterpret_cast< T* >( storage_.data_ )->~T(); - initialized_ = false; - } - } - -public: - - sp_ms_deleter(): initialized_( false ) - { - } - - ~sp_ms_deleter() - { - destroy(); - } - - void operator()( T * ) - { - destroy(); - } - - void * address() - { - return storage_.data_; - } - - void set_initialized() - { - initialized_ = true; - } -}; - -template< class T > T forward( T t ) -{ - return t; -} - -} // namespace detail - -// Zero-argument versions -// -// Used even when variadic templates are available because of the new T() vs new T issue - -template< class T > boost::shared_ptr< T > make_shared() -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T(); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T(); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) - -// Variadic templates, rvalue reference - -template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && ... args ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( detail::forward( args )... ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Args && ... args ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( detail::forward( args )... ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -#else - -// C++03 version - -template< class T, class A1 > -boost::shared_ptr< T > make_shared( A1 const & a1 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2, class A3 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2, class A3 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2, class A3, class A4 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2, class A3, class A4 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5, class A6 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -#endif - -} // namespace boost +#include #endif // #ifndef BOOST_MAKE_SHARED_HPP_INCLUDED diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index fcb80f6..c02fa31 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -11,128 +11,6 @@ // http://www.boost.org/libs/smart_ptr/scoped_array.htm // -#include -#include -#include // in case ptrdiff_t not in std - -#include - -#include // for std::ptrdiff_t - -namespace boost -{ - -// Debug hooks - -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - -void sp_array_constructor_hook(void * p); -void sp_array_destructor_hook(void * p); - -#endif - -// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to -// is guaranteed, either on destruction of the scoped_array or via an explicit -// reset(). Use shared_array or std::vector if your needs are more complex. - -template class scoped_array // noncopyable -{ -private: - - T * ptr; - - scoped_array(scoped_array const &); - scoped_array & operator=(scoped_array const &); - - typedef scoped_array this_type; - - void operator==( scoped_array const& ) const; - void operator!=( scoped_array const& ) const; - -public: - - typedef T element_type; - - explicit scoped_array(T * p = 0) : ptr(p) // never throws - { -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_array_constructor_hook(ptr); -#endif - } - - ~scoped_array() // never throws - { -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_array_destructor_hook(ptr); -#endif - boost::checked_array_delete(ptr); - } - - void reset(T * p = 0) // never throws - { - BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors - this_type(p).swap(*this); - } - - T & operator[](std::ptrdiff_t i) const // never throws - { - BOOST_ASSERT(ptr != 0); - BOOST_ASSERT(i >= 0); - return ptr[i]; - } - - T * get() const // never throws - { - return ptr; - } - - // implicit conversion to "bool" - -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) - - operator bool () const - { - return ptr != 0; - } - -#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return ptr == 0? 0: &this_type::get; - } - -#else - - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type() const // never throws - { - return ptr == 0? 0: &this_type::ptr; - } - -#endif - - bool operator! () const // never throws - { - return ptr == 0; - } - - void swap(scoped_array & b) // never throws - { - T * tmp = b.ptr; - b.ptr = ptr; - ptr = tmp; - } - -}; - -template inline void swap(scoped_array & a, scoped_array & b) // never throws -{ - a.swap(b); -} - -} // namespace boost +#include #endif // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 279cec3..cb916da 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -11,150 +11,6 @@ // http://www.boost.org/libs/smart_ptr/scoped_ptr.htm // -#include -#include -#include - -#ifndef BOOST_NO_AUTO_PTR -# include // for std::auto_ptr -#endif - -namespace boost -{ - -// Debug hooks - -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - -void sp_scalar_constructor_hook(void * p); -void sp_scalar_destructor_hook(void * p); - -#endif - -// scoped_ptr mimics a built-in pointer except that it guarantees deletion -// of the object pointed to, either on destruction of the scoped_ptr or via -// an explicit reset(). scoped_ptr is a simple solution for simple needs; -// use shared_ptr or std::auto_ptr if your needs are more complex. - -template class scoped_ptr // noncopyable -{ -private: - - T * ptr; - - scoped_ptr(scoped_ptr const &); - scoped_ptr & operator=(scoped_ptr const &); - - typedef scoped_ptr this_type; - - void operator==( scoped_ptr const& ) const; - void operator!=( scoped_ptr const& ) const; - -public: - - typedef T element_type; - - explicit scoped_ptr(T * p = 0): ptr(p) // never throws - { -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_scalar_constructor_hook(ptr); -#endif - } - -#ifndef BOOST_NO_AUTO_PTR - - explicit scoped_ptr(std::auto_ptr p): ptr(p.release()) // never throws - { -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_scalar_constructor_hook(ptr); -#endif - } - -#endif - - ~scoped_ptr() // never throws - { -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_scalar_destructor_hook(ptr); -#endif - boost::checked_delete(ptr); - } - - void reset(T * p = 0) // never throws - { - BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors - this_type(p).swap(*this); - } - - T & operator*() const // never throws - { - BOOST_ASSERT(ptr != 0); - return *ptr; - } - - T * operator->() const // never throws - { - BOOST_ASSERT(ptr != 0); - return ptr; - } - - T * get() const // never throws - { - return ptr; - } - - // implicit conversion to "bool" - -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) - - operator bool () const - { - return ptr != 0; - } - -#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return ptr == 0? 0: &this_type::get; - } - -#else - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type() const // never throws - { - return ptr == 0? 0: &this_type::ptr; - } - -#endif - - bool operator! () const // never throws - { - return ptr == 0; - } - - void swap(scoped_ptr & b) // never throws - { - T * tmp = b.ptr; - b.ptr = ptr; - ptr = tmp; - } -}; - -template inline void swap(scoped_ptr & a, scoped_ptr & b) // never throws -{ - a.swap(b); -} - -// get_pointer(p) is a generic way to say p.get() - -template inline T * get_pointer(scoped_ptr const & p) -{ - return p.get(); -} - -} // namespace boost +#include #endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index 3b82f35..0700ce4 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -14,180 +14,6 @@ // See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation. // -#include // for broken compiler workarounds - -#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) -#include -#else - -#include // TR1 cyclic inclusion fix - -#include -#include - -#include -#include - -#include // for std::ptrdiff_t -#include // for std::swap -#include // for std::less - -namespace boost -{ - -// -// shared_array -// -// shared_array extends shared_ptr to arrays. -// The array pointed to is deleted when the last shared_array pointing to it -// is destroyed or reset. -// - -template class shared_array -{ -private: - - // Borland 5.5.1 specific workarounds - typedef checked_array_deleter deleter; - typedef shared_array this_type; - -public: - - typedef T element_type; - - explicit shared_array(T * p = 0): px(p), pn(p, deleter()) - { - } - - // - // Requirements: D's copy constructor must not throw - // - // shared_array will release p by calling d(p) - // - - template shared_array(T * p, D d): px(p), pn(p, d) - { - } - -// generated copy constructor, assignment, destructor are fine - - void reset(T * p = 0) - { - BOOST_ASSERT(p == 0 || p != px); - this_type(p).swap(*this); - } - - template void reset(T * p, D d) - { - this_type(p, d).swap(*this); - } - - T & operator[] (std::ptrdiff_t i) const // never throws - { - BOOST_ASSERT(px != 0); - BOOST_ASSERT(i >= 0); - return px[i]; - } - - T * get() const // never throws - { - return px; - } - - // implicit conversion to "bool" - -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) - - operator bool () const - { - return px != 0; - } - -#elif defined( _MANAGED ) - - static void unspecified_bool( this_type*** ) - { - } - - typedef void (*unspecified_bool_type)( this_type*** ); - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: unspecified_bool; - } - -#elif \ - ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ - ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) - - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: &this_type::get; - } - -#else - - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: &this_type::px; - } - -#endif - - bool operator! () const // never throws - { - return px == 0; - } - - bool unique() const // never throws - { - return pn.unique(); - } - - long use_count() const // never throws - { - return pn.use_count(); - } - - void swap(shared_array & other) // never throws - { - std::swap(px, other.px); - pn.swap(other.pn); - } - -private: - - T * px; // contained pointer - detail::shared_count pn; // reference counter - -}; // shared_array - -template inline bool operator==(shared_array const & a, shared_array const & b) // never throws -{ - return a.get() == b.get(); -} - -template inline bool operator!=(shared_array const & a, shared_array const & b) // never throws -{ - return a.get() != b.get(); -} - -template inline bool operator<(shared_array const & a, shared_array const & b) // never throws -{ - return std::less()(a.get(), b.get()); -} - -template void swap(shared_array & a, shared_array & b) // never throws -{ - a.swap(b); -} - -} // namespace boost - -#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#include #endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index ad2bc17..d31978c 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -14,738 +14,6 @@ // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. // -#include // for broken compiler workarounds - -#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) -#include -#else - -// In order to avoid circular dependencies with Boost.TR1 -// we make sure that our include of doesn't try to -// pull in the TR1 headers: that's why we use this header -// rather than including directly: -#include // std::auto_ptr - -#include -#include -#include -#include -#include -#include - -#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) -#include -#include -#endif - -#include // for std::swap -#include // for std::less -#include // for std::bad_cast - -#if !defined(BOOST_NO_IOSTREAM) -#if !defined(BOOST_NO_IOSFWD) -#include // for std::basic_ostream -#else -#include -#endif -#endif - -#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash -# pragma warning(push) -# pragma warning(disable:4284) // odd return type for operator-> -#endif - -namespace boost -{ - -template class weak_ptr; -template class enable_shared_from_this; - -namespace detail -{ - -struct static_cast_tag {}; -struct const_cast_tag {}; -struct dynamic_cast_tag {}; -struct polymorphic_cast_tag {}; - -template struct shared_ptr_traits -{ - typedef T & reference; -}; - -template<> struct shared_ptr_traits -{ - typedef void reference; -}; - -#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) - -template<> struct shared_ptr_traits -{ - typedef void reference; -}; - -template<> struct shared_ptr_traits -{ - typedef void reference; -}; - -template<> struct shared_ptr_traits -{ - typedef void reference; -}; - -#endif - -// enable_shared_from_this support - -template void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this const * pe, Y const * px ) -{ - if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); -} - -#ifdef _MANAGED - -// Avoid C4793, ... causes native code generation - -struct sp_any_pointer -{ - template sp_any_pointer( T* ) {} -}; - -inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer ) -{ -} - -#else // _MANAGED - -#ifdef sgi -// Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed -# pragma set woff 3506 -#endif - -inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) -{ -} - -#ifdef sgi -# pragma reset woff 3506 -#endif - -#endif // _MANAGED - -#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) - -// rvalue auto_ptr support based on a technique by Dave Abrahams - -template< class T, class R > struct sp_enable_if_auto_ptr -{ -}; - -template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R > -{ - typedef R type; -}; - -#endif - -} // namespace detail - - -// -// shared_ptr -// -// An enhanced relative of scoped_ptr with reference counted copy semantics. -// The object pointed to is deleted when the last shared_ptr pointing to it -// is destroyed or reset. -// - -template class shared_ptr -{ -private: - - // Borland 5.5.1 specific workaround - typedef shared_ptr this_type; - -public: - - typedef T element_type; - typedef T value_type; - typedef T * pointer; - typedef typename boost::detail::shared_ptr_traits::reference reference; - - shared_ptr(): px(0), pn() // never throws in 1.30+ - { - } - - template - explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete - { - boost::detail::sp_enable_shared_from_this( pn, p, p ); - } - - // - // Requirements: D's copy constructor must not throw - // - // shared_ptr will release p by calling d(p) - // - - template shared_ptr(Y * p, D d): px(p), pn(p, d) - { - boost::detail::sp_enable_shared_from_this( pn, p, p ); - } - - // As above, but with allocator. A's copy constructor shall not throw. - - template shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) - { - boost::detail::sp_enable_shared_from_this( pn, p, p ); - } - -// generated copy constructor, assignment, destructor are fine... - -// except that Borland C++ has a bug, and g++ with -Wsynth warns -#if defined(__BORLANDC__) || defined(__GNUC__) - - shared_ptr & operator=(shared_ptr const & r) // never throws - { - px = r.px; - pn = r.pn; // shared_count::op= doesn't throw - return *this; - } - -#endif - - template - explicit shared_ptr(weak_ptr const & r): pn(r.pn) // may throw - { - // it is now safe to copy r.px, as pn(r.pn) did not throw - px = r.px; - } - - template - shared_ptr( weak_ptr const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws - { - if( !pn.empty() ) - { - px = r.px; - } - } - - template -#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) - - shared_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) - -#else - - shared_ptr( shared_ptr const & r ) - -#endif - : px( r.px ), pn( r.pn ) // never throws - { - } - - // aliasing - template< class Y > - shared_ptr( shared_ptr const & r, T * p ): px( p ), pn( r.pn ) // never throws - { - } - - template - shared_ptr(shared_ptr const & r, boost::detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) - { - } - - template - shared_ptr(shared_ptr const & r, boost::detail::const_cast_tag): px(const_cast(r.px)), pn(r.pn) - { - } - - template - shared_ptr(shared_ptr const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) - { - if(px == 0) // need to allocate new counter -- the cast failed - { - pn = boost::detail::shared_count(); - } - } - - template - shared_ptr(shared_ptr const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) - { - if(px == 0) - { - boost::throw_exception(std::bad_cast()); - } - } - -#ifndef BOOST_NO_AUTO_PTR - - template - explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn() - { - Y * tmp = r.get(); - pn = boost::detail::shared_count(r); - boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); - } - -#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) - - template - shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() - { - typename Ap::element_type * tmp = r.get(); - pn = boost::detail::shared_count( r ); - boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); - } - - -#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -#endif // BOOST_NO_AUTO_PTR - -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) - - template - shared_ptr & operator=(shared_ptr const & r) // never throws - { - px = r.px; - pn = r.pn; // shared_count::op= doesn't throw - return *this; - } - -#endif - -#ifndef BOOST_NO_AUTO_PTR - - template - shared_ptr & operator=( std::auto_ptr & r ) - { - this_type(r).swap(*this); - return *this; - } - -#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) - - template - typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r ) - { - this_type( r ).swap( *this ); - return *this; - } - - -#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -#endif // BOOST_NO_AUTO_PTR - -// Move support - -#if defined( BOOST_HAS_RVALUE_REFS ) - - shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws - { - pn.swap( r.pn ); - r.px = 0; - } - - template -#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) - - shared_ptr( shared_ptr && r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) - -#else - - shared_ptr( shared_ptr && r ) - -#endif - : px( r.px ), pn() // never throws - { - pn.swap( r.pn ); - r.px = 0; - } - - shared_ptr & operator=( shared_ptr && r ) // never throws - { - this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); - return *this; - } - - template - shared_ptr & operator=( shared_ptr && r ) // never throws - { - this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); - return *this; - } - -#endif - - void reset() // never throws in 1.30+ - { - this_type().swap(*this); - } - - template void reset(Y * p) // Y must be complete - { - BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors - this_type(p).swap(*this); - } - - template void reset( Y * p, D d ) - { - this_type( p, d ).swap( *this ); - } - - template void reset( Y * p, D d, A a ) - { - this_type( p, d, a ).swap( *this ); - } - - template void reset( shared_ptr const & r, T * p ) - { - this_type( r, p ).swap( *this ); - } - - reference operator* () const // never throws - { - BOOST_ASSERT(px != 0); - return *px; - } - - T * operator-> () const // never throws - { - BOOST_ASSERT(px != 0); - return px; - } - - T * get() const // never throws - { - return px; - } - - // implicit conversion to "bool" - -#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) - - operator bool () const - { - return px != 0; - } - -#elif defined( _MANAGED ) - - static void unspecified_bool( this_type*** ) - { - } - - typedef void (*unspecified_bool_type)( this_type*** ); - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: unspecified_bool; - } - -#elif \ - ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ - ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \ - ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) ) - - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: &this_type::get; - } - -#else - - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: &this_type::px; - } - -#endif - - // operator! is redundant, but some compilers need it - - bool operator! () const // never throws - { - return px == 0; - } - - bool unique() const // never throws - { - return pn.unique(); - } - - long use_count() const // never throws - { - return pn.use_count(); - } - - void swap(shared_ptr & other) // never throws - { - std::swap(px, other.px); - pn.swap(other.pn); - } - - template bool _internal_less(shared_ptr const & rhs) const - { - return pn < rhs.pn; - } - - void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const - { - return pn.get_deleter( ti ); - } - - bool _internal_equiv( shared_ptr const & r ) const - { - return px == r.px && pn == r.pn; - } - -// Tasteless as this may seem, making all members public allows member templates -// to work in the absence of member template friends. (Matthew Langston) - -#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS - -private: - - template friend class shared_ptr; - template friend class weak_ptr; - - -#endif - - T * px; // contained pointer - boost::detail::shared_count pn; // reference counter - -}; // shared_ptr - -template inline bool operator==(shared_ptr const & a, shared_ptr const & b) -{ - return a.get() == b.get(); -} - -template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) -{ - return a.get() != b.get(); -} - -#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 - -// Resolve the ambiguity between our op!= and the one in rel_ops - -template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) -{ - return a.get() != b.get(); -} - -#endif - -template inline bool operator<(shared_ptr const & a, shared_ptr const & b) -{ - return a._internal_less(b); -} - -template inline void swap(shared_ptr & a, shared_ptr & b) -{ - a.swap(b); -} - -template shared_ptr static_pointer_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::static_cast_tag()); -} - -template shared_ptr const_pointer_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::const_cast_tag()); -} - -template shared_ptr dynamic_pointer_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::dynamic_cast_tag()); -} - -// shared_*_cast names are deprecated. Use *_pointer_cast instead. - -template shared_ptr shared_static_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::static_cast_tag()); -} - -template shared_ptr shared_dynamic_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::dynamic_cast_tag()); -} - -template shared_ptr shared_polymorphic_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::polymorphic_cast_tag()); -} - -template shared_ptr shared_polymorphic_downcast(shared_ptr const & r) -{ - BOOST_ASSERT(dynamic_cast(r.get()) == r.get()); - return shared_static_cast(r); -} - -// get_pointer() enables boost::mem_fn to recognize shared_ptr - -template inline T * get_pointer(shared_ptr const & p) -{ - return p.get(); -} - -// operator<< - -#if !defined(BOOST_NO_IOSTREAM) - -#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) - -template std::ostream & operator<< (std::ostream & os, shared_ptr const & p) -{ - os << p.get(); - return os; -} - -#else - -// in STLport's no-iostreams mode no iostream symbols can be used -#ifndef _STLP_NO_IOSTREAMS - -# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) -// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL -using std::basic_ostream; -template basic_ostream & operator<< (basic_ostream & os, shared_ptr const & p) -# else -template std::basic_ostream & operator<< (std::basic_ostream & os, shared_ptr const & p) -# endif -{ - os << p.get(); - return os; -} - -#endif // _STLP_NO_IOSTREAMS - -#endif // __GNUC__ < 3 - -#endif // !defined(BOOST_NO_IOSTREAM) - -// get_deleter - -#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ - ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ - ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) ) - -// g++ 2.9x doesn't allow static_cast(void *) -// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it - -template D * get_deleter(shared_ptr const & p) -{ - void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D)); - return const_cast(static_cast(q)); -} - -#else - -template D * get_deleter(shared_ptr const & p) -{ - return static_cast(p._internal_get_deleter(BOOST_SP_TYPEID(D))); -} - -#endif - -// atomic access - -#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) - -template inline bool atomic_is_lock_free( shared_ptr const * /*p*/ ) -{ - return false; -} - -template shared_ptr atomic_load( shared_ptr const * p ) -{ - boost::detail::spinlock_pool<2>::scoped_lock lock( p ); - return *p; -} - -template inline shared_ptr atomic_load_explicit( shared_ptr const * p, memory_order /*mo*/ ) -{ - return atomic_load( p ); -} - -template void atomic_store( shared_ptr * p, shared_ptr r ) -{ - boost::detail::spinlock_pool<2>::scoped_lock lock( p ); - p->swap( r ); -} - -template inline void atomic_store_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) -{ - atomic_store( p, r ); // std::move( r ) -} - -template shared_ptr atomic_exchange( shared_ptr * p, shared_ptr r ) -{ - boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); - - sp.lock(); - p->swap( r ); - sp.unlock(); - - return r; // return std::move( r ) -} - -template shared_ptr atomic_exchange_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) -{ - return atomic_exchange( p, r ); // std::move( r ) -} - -template bool atomic_compare_exchange( shared_ptr * p, shared_ptr * v, shared_ptr w ) -{ - boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); - - sp.lock(); - - if( p->_internal_equiv( *v ) ) - { - p->swap( w ); - - sp.unlock(); - - return true; - } - else - { - shared_ptr tmp( *p ); - - sp.unlock(); - - tmp.swap( *v ); - return false; - } -} - -template inline bool atomic_compare_exchange_explicit( shared_ptr * p, shared_ptr * v, shared_ptr w, memory_order /*success*/, memory_order /*failure*/ ) -{ - return atomic_compare_exchange( p, v, w ); // std::move( w ) -} - -#endif - -} // namespace boost - -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif - -#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#include #endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED diff --git a/include/boost/detail/bad_weak_ptr.hpp b/include/boost/smart_ptr/bad_weak_ptr.hpp similarity index 86% rename from include/boost/detail/bad_weak_ptr.hpp rename to include/boost/smart_ptr/bad_weak_ptr.hpp index 93ecec9..3e0a1b7 100644 --- a/include/boost/detail/bad_weak_ptr.hpp +++ b/include/boost/smart_ptr/bad_weak_ptr.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_BAD_WEAK_PTR_HPP_INCLUDED -#define BOOST_BAD_WEAK_PTR_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED +#define BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -8,7 +8,7 @@ #endif // -// detail/bad_weak_ptr.hpp +// boost/smart_ptr/bad_weak_ptr.hpp // // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. // @@ -56,4 +56,4 @@ public: # pragma warn .8026 // Functions with excep. spec. are not expanded inline #endif -#endif // #ifndef BOOST_BAD_WEAK_PTR_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/atomic_count.hpp b/include/boost/smart_ptr/detail/atomic_count.hpp new file mode 100644 index 0000000..91236e4 --- /dev/null +++ b/include/boost/smart_ptr/detail/atomic_count.hpp @@ -0,0 +1,119 @@ +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/atomic_count.hpp - thread/SMP safe reference counter +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// 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) +// +// typedef boost::detail::atomic_count; +// +// atomic_count a(n); +// +// (n is convertible to long) +// +// Effects: Constructs an atomic_count with an initial value of n +// +// a; +// +// Returns: (long) the current value of a +// +// ++a; +// +// Effects: Atomically increments the value of a +// Returns: nothing +// +// --a; +// +// Effects: Atomically decrements the value of a +// Returns: (long) zero if the new value of a is zero, +// unspecified non-zero value otherwise (usually the new value) +// +// Important note: when --a returns zero, it must act as a +// read memory barrier (RMB); i.e. the calling thread must +// have a synchronized view of the memory +// +// On Intel IA-32 (x86) memory is always synchronized, so this +// is not a problem. +// +// On many architectures the atomic instructions already act as +// a memory barrier. +// +// This property is necessary for proper reference counting, since +// a thread can update the contents of a shared object, then +// release its reference, and another thread may immediately +// release the last reference causing object destruction. +// +// The destructor needs to have a synchronized view of the +// object to perform proper cleanup. +// +// Original example by Alexander Terekhov: +// +// Given: +// +// - a mutable shared object OBJ; +// - two threads THREAD1 and THREAD2 each holding +// a private smart_ptr object pointing to that OBJ. +// +// t1: THREAD1 updates OBJ (thread-safe via some synchronization) +// and a few cycles later (after "unlock") destroys smart_ptr; +// +// t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization +// with respect to shared mutable object OBJ; OBJ destructors +// are called driven by smart_ptr interface... +// + +#include + +#ifndef BOOST_HAS_THREADS + +namespace boost +{ + +namespace detail +{ + +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 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) +# 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 +#error Unrecognized threading platform + +#endif + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_gcc.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp similarity index 85% rename from include/boost/detail/atomic_count_gcc.hpp rename to include/boost/smart_ptr/detail/atomic_count_gcc.hpp index 1160e44..6abfdf2 100644 --- a/include/boost/detail/atomic_count_gcc.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED -#define BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED // // boost/detail/atomic_count_gcc.hpp @@ -65,4 +65,4 @@ private: } // namespace boost -#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_gcc_x86.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp similarity index 87% rename from include/boost/detail/atomic_count_gcc_x86.hpp rename to include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp index 1312e8c..4fd1c57 100644 --- a/include/boost/detail/atomic_count_gcc_x86.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED -#define BOOST_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED // // boost/detail/atomic_count_gcc_x86.hpp @@ -81,4 +81,4 @@ private: } // namespace boost -#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_pthreads.hpp b/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp similarity index 88% rename from include/boost/detail/atomic_count_pthreads.hpp rename to include/boost/smart_ptr/detail/atomic_count_pthreads.hpp index 7ed055f..d8118f0 100644 --- a/include/boost/detail/atomic_count_pthreads.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED -#define BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED // // boost/detail/atomic_count_pthreads.hpp @@ -93,4 +93,4 @@ private: } // namespace boost -#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_solaris.hpp b/include/boost/smart_ptr/detail/atomic_count_solaris.hpp similarity index 82% rename from include/boost/detail/atomic_count_solaris.hpp rename to include/boost/smart_ptr/detail/atomic_count_solaris.hpp index 8e2907f..a13bcfb 100644 --- a/include/boost/detail/atomic_count_solaris.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_solaris.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED -#define BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED // // boost/detail/atomic_count_solaris.hpp @@ -56,4 +56,4 @@ private: } // namespace boost -#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_sync.hpp b/include/boost/smart_ptr/detail/atomic_count_sync.hpp similarity index 83% rename from include/boost/detail/atomic_count_sync.hpp rename to include/boost/smart_ptr/detail/atomic_count_sync.hpp index 676d3f9..f2d22fb 100644 --- a/include/boost/detail/atomic_count_sync.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_sync.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED -#define BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED // // boost/detail/atomic_count_sync.hpp @@ -58,4 +58,4 @@ private: } // namespace boost -#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_win32.hpp b/include/boost/smart_ptr/detail/atomic_count_win32.hpp similarity index 83% rename from include/boost/detail/atomic_count_win32.hpp rename to include/boost/smart_ptr/detail/atomic_count_win32.hpp index 0de2537..60a0569 100644 --- a/include/boost/detail/atomic_count_win32.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_win32.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED -#define BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -60,4 +60,4 @@ private: } // namespace boost -#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/lightweight_mutex.hpp b/include/boost/smart_ptr/detail/lightweight_mutex.hpp new file mode 100644 index 0000000..a2fc281 --- /dev/null +++ b/include/boost/smart_ptr/detail/lightweight_mutex.hpp @@ -0,0 +1,42 @@ +#ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/lightweight_mutex.hpp - lightweight mutex +// +// Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd. +// +// 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) +// +// typedef boost::detail::lightweight_mutex; +// +// boost::detail::lightweight_mutex is a header-only implementation of +// a subset of the Mutex concept requirements: +// +// http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex +// +// It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX. +// + +#include + +#if !defined(BOOST_HAS_THREADS) +# 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 +#endif + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED diff --git a/include/boost/detail/lwm_nop.hpp b/include/boost/smart_ptr/detail/lwm_nop.hpp similarity index 76% rename from include/boost/detail/lwm_nop.hpp rename to include/boost/smart_ptr/detail/lwm_nop.hpp index c73ab68..521a88e 100644 --- a/include/boost/detail/lwm_nop.hpp +++ b/include/boost/smart_ptr/detail/lwm_nop.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED -#define BOOST_DETAIL_LWM_NOP_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -34,4 +34,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED diff --git a/include/boost/detail/lwm_pthreads.hpp b/include/boost/smart_ptr/detail/lwm_pthreads.hpp similarity index 88% rename from include/boost/detail/lwm_pthreads.hpp rename to include/boost/smart_ptr/detail/lwm_pthreads.hpp index a5bf75b..fc20dbb 100644 --- a/include/boost/detail/lwm_pthreads.hpp +++ b/include/boost/smart_ptr/detail/lwm_pthreads.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED -#define BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -83,4 +83,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED diff --git a/include/boost/detail/lwm_win32_cs.hpp b/include/boost/smart_ptr/detail/lwm_win32_cs.hpp similarity index 91% rename from include/boost/detail/lwm_win32_cs.hpp rename to include/boost/smart_ptr/detail/lwm_win32_cs.hpp index 8142069..00477e4 100644 --- a/include/boost/detail/lwm_win32_cs.hpp +++ b/include/boost/smart_ptr/detail/lwm_win32_cs.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED -#define BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -105,4 +105,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/quick_allocator.hpp b/include/boost/smart_ptr/detail/quick_allocator.hpp new file mode 100644 index 0000000..6d136f8 --- /dev/null +++ b/include/boost/smart_ptr/detail/quick_allocator.hpp @@ -0,0 +1,198 @@ +#ifndef BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/quick_allocator.hpp +// +// Copyright (c) 2003 David Abrahams +// Copyright (c) 2003 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 + +#include +#include +#include + +#include // ::operator new, ::operator delete +#include // std::size_t + +namespace boost +{ + +namespace detail +{ + +template union freeblock +{ + typedef typename boost::type_with_alignment::type aligner_type; + aligner_type aligner; + char bytes[size]; + freeblock * next; +}; + +template struct allocator_impl +{ + typedef freeblock block; + + // It may seem odd to use such small pages. + // + // However, on a typical Windows implementation that uses + // the OS allocator, "normal size" pages interact with the + // "ordinary" operator new, slowing it down dramatically. + // + // 512 byte pages are handled by the small object allocator, + // and don't interfere with ::new. + // + // The other alternative is to use much bigger pages (1M.) + // + // It is surprisingly easy to hit pathological behavior by + // varying the page size. g++ 2.96 on Red Hat Linux 7.2, + // for example, passionately dislikes 496. 512 seems OK. + +#if defined(BOOST_QA_PAGE_SIZE) + + enum { items_per_page = BOOST_QA_PAGE_SIZE / size }; + +#else + + enum { items_per_page = 512 / size }; // 1048560 / size + +#endif + +#ifdef BOOST_HAS_THREADS + + static lightweight_mutex & mutex() + { + static lightweight_mutex m; + return m; + } + + static lightweight_mutex * mutex_init; + +#endif + + static block * free; + static block * page; + static unsigned last; + + static inline void * alloc() + { +#ifdef BOOST_HAS_THREADS + lightweight_mutex::scoped_lock lock( mutex() ); +#endif + if(block * x = free) + { + free = x->next; + return x; + } + else + { + if(last == items_per_page) + { + // "Listen to me carefully: there is no memory leak" + // -- Scott Meyers, Eff C++ 2nd Ed Item 10 + page = ::new block[items_per_page]; + last = 0; + } + + return &page[last++]; + } + } + + static inline void * alloc(std::size_t n) + { + if(n != size) // class-specific new called for a derived object + { + return ::operator new(n); + } + else + { +#ifdef BOOST_HAS_THREADS + lightweight_mutex::scoped_lock lock( mutex() ); +#endif + if(block * x = free) + { + free = x->next; + return x; + } + else + { + if(last == items_per_page) + { + page = ::new block[items_per_page]; + last = 0; + } + + return &page[last++]; + } + } + } + + static inline void dealloc(void * pv) + { + if(pv != 0) // 18.4.1.1/13 + { +#ifdef BOOST_HAS_THREADS + lightweight_mutex::scoped_lock lock( mutex() ); +#endif + block * pb = static_cast(pv); + pb->next = free; + free = pb; + } + } + + static inline void dealloc(void * pv, std::size_t n) + { + if(n != size) // class-specific delete called for a derived object + { + ::operator delete(pv); + } + else if(pv != 0) // 18.4.1.1/13 + { +#ifdef BOOST_HAS_THREADS + lightweight_mutex::scoped_lock lock( mutex() ); +#endif + block * pb = static_cast(pv); + pb->next = free; + free = pb; + } + } +}; + +#ifdef BOOST_HAS_THREADS + +template + lightweight_mutex * allocator_impl::mutex_init = &allocator_impl::mutex(); + +#endif + +template + freeblock * allocator_impl::free = 0; + +template + freeblock * allocator_impl::page = 0; + +template + unsigned allocator_impl::last = allocator_impl::items_per_page; + +template +struct quick_allocator: public allocator_impl< sizeof(T), boost::alignment_of::value > +{ +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED diff --git a/include/boost/detail/shared_array_nmt.hpp b/include/boost/smart_ptr/detail/shared_array_nmt.hpp similarity index 92% rename from include/boost/detail/shared_array_nmt.hpp rename to include/boost/smart_ptr/detail/shared_array_nmt.hpp index 13ca6ac..450c9bc 100644 --- a/include/boost/detail/shared_array_nmt.hpp +++ b/include/boost/smart_ptr/detail/shared_array_nmt.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED -#define BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED // // detail/shared_array_nmt.hpp - shared_array.hpp without member templates @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include // for std::ptrdiff_t #include // for std::swap @@ -148,4 +148,4 @@ template void swap(shared_array & a, shared_array & b) } // namespace boost -#endif // #ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED diff --git a/include/boost/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp similarity index 96% rename from include/boost/detail/shared_count.hpp rename to include/boost/smart_ptr/detail/shared_count.hpp index 9e9b1ba..3384faa 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/smart_ptr/detail/shared_count.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED -#define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -25,9 +25,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include // In order to avoid circular dependencies with Boost.TR1 // we make sure that our include of doesn't try to @@ -427,4 +427,4 @@ inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( # pragma warn .8027 // Functions containing try are not expanded inline #endif -#endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED diff --git a/include/boost/detail/shared_ptr_nmt.hpp b/include/boost/smart_ptr/detail/shared_ptr_nmt.hpp similarity index 93% rename from include/boost/detail/shared_ptr_nmt.hpp rename to include/boost/smart_ptr/detail/shared_ptr_nmt.hpp index 0780e30..afc1ec0 100644 --- a/include/boost/detail/shared_ptr_nmt.hpp +++ b/include/boost/smart_ptr/detail/shared_ptr_nmt.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED -#define BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED // // detail/shared_ptr_nmt.hpp - shared_ptr.hpp without member templates @@ -17,7 +17,7 @@ #include #include #include -#include +#include #ifndef BOOST_NO_AUTO_PTR # include // for std::auto_ptr @@ -179,4 +179,4 @@ template inline T * get_pointer(shared_ptr const & p) } // namespace boost -#endif // #ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED diff --git a/include/boost/detail/sp_convertible.hpp b/include/boost/smart_ptr/detail/sp_convertible.hpp similarity index 89% rename from include/boost/detail/sp_convertible.hpp rename to include/boost/smart_ptr/detail/sp_convertible.hpp index 2c1539b..7d9502d 100644 --- a/include/boost/detail/sp_convertible.hpp +++ b/include/boost/smart_ptr/detail/sp_convertible.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED -#define BOOST_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -73,4 +73,4 @@ template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_i #endif // !defined( BOOST_SP_NO_SP_CONVERTIBLE ) -#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp similarity index 57% rename from include/boost/detail/sp_counted_base.hpp rename to include/boost/smart_ptr/detail/sp_counted_base.hpp index c25a57f..1352346 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -20,47 +20,47 @@ #include #if defined( BOOST_SP_DISABLE_THREADS ) -# include +# include #elif defined( BOOST_SP_USE_SPINLOCK ) -# include +# include #elif defined( BOOST_SP_USE_PTHREADS ) -# include +# include #elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 ) -# include +# include #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) -# include +# include #elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER ) -# include +# include #elif defined(__HP_aCC) && defined(__ia64) -# include +# include #elif defined( __MWERKS__ ) && defined( __POWERPC__ ) -# include +# include #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) -# include +# include #elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) -# include +# include #elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) ) -# include +# include #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) -# include +# include #elif !defined( BOOST_HAS_THREADS ) -# include +# include #else -# include +# include #endif -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_acc_ia64.hpp b/include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp similarity index 92% rename from include/boost/detail/sp_counted_base_acc_ia64.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp index c956b8e..dffd995 100644 --- a/include/boost/detail/sp_counted_base_acc_ia64.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED // // detail/sp_counted_base_acc_ia64.hpp - aC++ on HP-UX IA64 @@ -147,4 +147,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_cw_ppc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp similarity index 92% rename from include/boost/detail/sp_counted_base_cw_ppc.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp index 3f43252..51ac56a 100644 --- a/include/boost/detail/sp_counted_base_cw_ppc.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -167,4 +167,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_cw_x86.hpp b/include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_cw_x86.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp index b2e3f9b..1234e78 100644 --- a/include/boost/detail/sp_counted_base_cw_x86.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -155,4 +155,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_gcc_ia64.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp index 7535295..d122a49 100644 --- a/include/boost/detail/sp_counted_base_gcc_ia64.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED // // detail/sp_counted_base_gcc_ia64.hpp - g++ on IA64 @@ -154,4 +154,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_gcc_ppc.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp index cea2740..7f5c414 100644 --- a/include/boost/detail/sp_counted_base_gcc_ppc.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -178,4 +178,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_gcc_sparc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_gcc_sparc.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp index 2afca16..8af6f0a 100644 --- a/include/boost/detail/sp_counted_base_gcc_sparc.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -163,4 +163,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_gcc_x86.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp index 8bf3171..4d7fa8d 100644 --- a/include/boost/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -170,4 +170,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_nt.hpp b/include/boost/smart_ptr/detail/sp_counted_base_nt.hpp similarity index 90% rename from include/boost/detail/sp_counted_base_nt.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_nt.hpp index dc7a042..dfd70e7 100644 --- a/include/boost/detail/sp_counted_base_nt.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_nt.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -104,4 +104,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_pt.hpp b/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_pt.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_pt.hpp index cd30de9..3c56fec 100644 --- a/include/boost/detail/sp_counted_base_pt.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -132,4 +132,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_solaris.hpp b/include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp similarity index 91% rename from include/boost/detail/sp_counted_base_solaris.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp index a747b39..d1b6bec 100644 --- a/include/boost/detail/sp_counted_base_solaris.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED // // detail/sp_counted_base_solaris.hpp @@ -110,4 +110,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_spin.hpp b/include/boost/smart_ptr/detail/sp_counted_base_spin.hpp similarity index 90% rename from include/boost/detail/sp_counted_base_spin.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_spin.hpp index 610a468..bbd11e6 100644 --- a/include/boost/detail/sp_counted_base_spin.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_spin.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -19,7 +19,7 @@ // #include -#include +#include namespace boost { @@ -128,4 +128,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_sync.hpp b/include/boost/smart_ptr/detail/sp_counted_base_sync.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_sync.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_sync.hpp index d72dac2..41f654e 100644 --- a/include/boost/detail/sp_counted_base_sync.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_sync.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -152,4 +152,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_w32.hpp b/include/boost/smart_ptr/detail/sp_counted_base_w32.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_w32.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_w32.hpp index f990393..06aa456 100644 --- a/include/boost/detail/sp_counted_base_w32.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_w32.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -127,4 +127,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp similarity index 94% rename from include/boost/detail/sp_counted_impl.hpp rename to include/boost/smart_ptr/detail/sp_counted_impl.hpp index 81f92da..397421a 100644 --- a/include/boost/detail/sp_counted_impl.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -25,10 +25,10 @@ #endif #include -#include +#include #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) -#include +#include #endif #if defined(BOOST_SP_USE_STD_ALLOCATOR) @@ -228,4 +228,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED diff --git a/include/boost/detail/spinlock.hpp b/include/boost/smart_ptr/detail/spinlock.hpp similarity index 70% rename from include/boost/detail/spinlock.hpp rename to include/boost/smart_ptr/detail/spinlock.hpp index 346fb3c..9c6cb9f 100644 --- a/include/boost/detail/spinlock.hpp +++ b/include/boost/smart_ptr/detail/spinlock.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SPINLOCK_HPP_INCLUDED -#define BOOST_DETAIL_SPINLOCK_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -31,17 +31,17 @@ #include #if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ ) -# include +# include #elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) -# include +# include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# include +# include #elif defined(BOOST_HAS_PTHREADS) -# include +# include #elif !defined(BOOST_HAS_THREADS) -# include +# include #else # error Unrecognized threading platform #endif -#endif // #ifndef BOOST_DETAIL_SPINLOCK_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_gcc_arm.hpp b/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp similarity index 84% rename from include/boost/detail/spinlock_gcc_arm.hpp rename to include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp index c21163b..ba6c511 100644 --- a/include/boost/detail/spinlock_gcc_arm.hpp +++ b/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED -#define BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED // // Copyright (c) 2008 Peter Dimov @@ -9,7 +9,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#include namespace boost { @@ -82,4 +82,4 @@ public: #define BOOST_DETAIL_SPINLOCK_INIT {0} -#endif // #ifndef BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_nt.hpp b/include/boost/smart_ptr/detail/spinlock_nt.hpp similarity index 87% rename from include/boost/detail/spinlock_nt.hpp rename to include/boost/smart_ptr/detail/spinlock_nt.hpp index f03ba08..1f399d0 100644 --- a/include/boost/detail/spinlock_nt.hpp +++ b/include/boost/smart_ptr/detail/spinlock_nt.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED -#define BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -86,4 +86,4 @@ public: #define BOOST_DETAIL_SPINLOCK_INIT { false } -#endif // #ifndef BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_pool.hpp b/include/boost/smart_ptr/detail/spinlock_pool.hpp similarity index 91% rename from include/boost/detail/spinlock_pool.hpp rename to include/boost/smart_ptr/detail/spinlock_pool.hpp index a264b1a..0e2e08a 100644 --- a/include/boost/detail/spinlock_pool.hpp +++ b/include/boost/smart_ptr/detail/spinlock_pool.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED -#define BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -22,7 +22,7 @@ // #include -#include +#include #include namespace boost @@ -84,4 +84,4 @@ template< int I > spinlock spinlock_pool< I >::pool_[ 41 ] = } // namespace detail } // namespace boost -#endif // #ifndef BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_pt.hpp b/include/boost/smart_ptr/detail/spinlock_pt.hpp similarity index 86% rename from include/boost/detail/spinlock_pt.hpp rename to include/boost/smart_ptr/detail/spinlock_pt.hpp index dfb2d6f..f9cabfc 100644 --- a/include/boost/detail/spinlock_pt.hpp +++ b/include/boost/smart_ptr/detail/spinlock_pt.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED -#define BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -76,4 +76,4 @@ public: #define BOOST_DETAIL_SPINLOCK_INIT { PTHREAD_MUTEX_INITIALIZER } -#endif // #ifndef BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_sync.hpp b/include/boost/smart_ptr/detail/spinlock_sync.hpp similarity index 84% rename from include/boost/detail/spinlock_sync.hpp rename to include/boost/smart_ptr/detail/spinlock_sync.hpp index a752396..a7145c5 100644 --- a/include/boost/detail/spinlock_sync.hpp +++ b/include/boost/smart_ptr/detail/spinlock_sync.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED -#define BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -15,7 +15,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#include #if defined( __ia64__ ) && defined( __INTEL_COMPILER ) # include @@ -84,4 +84,4 @@ public: #define BOOST_DETAIL_SPINLOCK_INIT {0} -#endif // #ifndef BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_w32.hpp b/include/boost/smart_ptr/detail/spinlock_w32.hpp similarity index 88% rename from include/boost/detail/spinlock_w32.hpp rename to include/boost/smart_ptr/detail/spinlock_w32.hpp index aa416c3..fb97629 100644 --- a/include/boost/detail/spinlock_w32.hpp +++ b/include/boost/smart_ptr/detail/spinlock_w32.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED -#define BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -16,7 +16,7 @@ // #include -#include +#include // BOOST_COMPILER_FENCE @@ -110,4 +110,4 @@ public: #define BOOST_DETAIL_SPINLOCK_INIT {0} -#endif // #ifndef BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED diff --git a/include/boost/detail/yield_k.hpp b/include/boost/smart_ptr/detail/yield_k.hpp similarity index 92% rename from include/boost/detail/yield_k.hpp rename to include/boost/smart_ptr/detail/yield_k.hpp index d97542d..a956cc0 100644 --- a/include/boost/detail/yield_k.hpp +++ b/include/boost/smart_ptr/detail/yield_k.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_YIELD_K_HPP_INCLUDED -#define BOOST_DETAIL_YIELD_K_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -8,7 +8,7 @@ #endif // -// boost/detail/yield_k.hpp +// yield_k.hpp // // Copyright (c) 2008 Peter Dimov // @@ -146,4 +146,4 @@ inline void yield( unsigned ) #endif -#endif // #ifndef BOOST_DETAIL_YIELD_K_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED diff --git a/include/boost/smart_ptr/enable_shared_from_this.hpp b/include/boost/smart_ptr/enable_shared_from_this.hpp new file mode 100644 index 0000000..ed9aadd --- /dev/null +++ b/include/boost/smart_ptr/enable_shared_from_this.hpp @@ -0,0 +1,73 @@ +#ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED +#define BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED + +// +// enable_shared_from_this.hpp +// +// Copyright (c) 2002 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) +// +// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html +// + +#include +#include +#include +#include + +namespace boost +{ + +template class enable_shared_from_this +{ +protected: + + enable_shared_from_this() + { + } + + enable_shared_from_this(enable_shared_from_this const &) + { + } + + enable_shared_from_this & operator=(enable_shared_from_this const &) + { + return *this; + } + + ~enable_shared_from_this() + { + } + +public: + + shared_ptr shared_from_this() + { + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(p.get() == this); + return p; + } + + shared_ptr shared_from_this() const + { + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(p.get() == this); + return p; + } + +// Note: No, you don't need to initialize _internal_weak_this +// +// Please read the documentation, not the code +// +// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html + + typedef T _internal_element_type; // for bcc 5.5.1 + mutable weak_ptr<_internal_element_type> _internal_weak_this; +}; + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp new file mode 100644 index 0000000..f5acae3 --- /dev/null +++ b/include/boost/smart_ptr/intrusive_ptr.hpp @@ -0,0 +1,311 @@ +#ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED +#define BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED + +// +// intrusive_ptr.hpp +// +// Copyright (c) 2001, 2002 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) +// +// See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation. +// + +#include + +#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash +# pragma warning(push) +# pragma warning(disable:4284) // odd return type for operator-> +#endif + +#include +#include +#include + +#include // for std::less + +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) +#include // for std::basic_ostream +#else +#include +#endif +#endif + + +namespace boost +{ + +// +// intrusive_ptr +// +// A smart pointer that uses intrusive reference counting. +// +// Relies on unqualified calls to +// +// void intrusive_ptr_add_ref(T * p); +// void intrusive_ptr_release(T * p); +// +// (p != 0) +// +// The object is responsible for destroying itself. +// + +template class intrusive_ptr +{ +private: + + typedef intrusive_ptr this_type; + +public: + + typedef T element_type; + + intrusive_ptr(): p_(0) + { + } + + intrusive_ptr(T * p, bool add_ref = true): p_(p) + { + if(p_ != 0 && add_ref) intrusive_ptr_add_ref(p_); + } + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + intrusive_ptr( intrusive_ptr const & rhs, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + intrusive_ptr( intrusive_ptr const & rhs ) + +#endif + : p_( rhs.get() ) + { + if( p_ != 0 ) intrusive_ptr_add_ref( p_ ); + } + +#endif + + intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_) + { + if(p_ != 0) intrusive_ptr_add_ref(p_); + } + + ~intrusive_ptr() + { + if(p_ != 0) intrusive_ptr_release(p_); + } + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) + + template intrusive_ptr & operator=(intrusive_ptr const & rhs) + { + this_type(rhs).swap(*this); + return *this; + } + +#endif + + intrusive_ptr & operator=(intrusive_ptr const & rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + intrusive_ptr & operator=(T * rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + void reset() + { + this_type().swap( *this ); + } + + void reset( T * rhs ) + { + this_type( rhs ).swap( *this ); + } + + T * get() const + { + return p_; + } + + T & operator*() const + { + BOOST_ASSERT( p_ != 0 ); + return *p_; + } + + T * operator->() const + { + BOOST_ASSERT( p_ != 0 ); + return p_; + } + +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return p_ != 0; + } + +#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return p_ == 0? 0: &this_type::get; + } + +#else + + typedef T * this_type::*unspecified_bool_type; + + operator unspecified_bool_type () const + { + return p_ == 0? 0: &this_type::p_; + } + +#endif + + // operator! is a Borland-specific workaround + bool operator! () const + { + return p_ == 0; + } + + void swap(intrusive_ptr & rhs) + { + T * tmp = p_; + p_ = rhs.p_; + rhs.p_ = tmp; + } + +private: + + T * p_; +}; + +template inline bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator==(intrusive_ptr const & a, U * b) +{ + return a.get() == b; +} + +template inline bool operator!=(intrusive_ptr const & a, U * b) +{ + return a.get() != b; +} + +template inline bool operator==(T * a, intrusive_ptr const & b) +{ + return a == b.get(); +} + +template inline bool operator!=(T * a, intrusive_ptr const & b) +{ + return a != b.get(); +} + +#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 + +// Resolve the ambiguity between our op!= and the one in rel_ops + +template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() != b.get(); +} + +#endif + +template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return std::less()(a.get(), b.get()); +} + +template void swap(intrusive_ptr & lhs, intrusive_ptr & rhs) +{ + lhs.swap(rhs); +} + +// mem_fn support + +template T * get_pointer(intrusive_ptr const & p) +{ + return p.get(); +} + +template intrusive_ptr static_pointer_cast(intrusive_ptr const & p) +{ + return static_cast(p.get()); +} + +template intrusive_ptr const_pointer_cast(intrusive_ptr const & p) +{ + return const_cast(p.get()); +} + +template intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & p) +{ + return dynamic_cast(p.get()); +} + +// operator<< + +#if !defined(BOOST_NO_IOSTREAM) + +#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) + +template std::ostream & operator<< (std::ostream & os, intrusive_ptr const & p) +{ + os << p.get(); + return os; +} + +#else + +// in STLport's no-iostreams mode no iostream symbols can be used +#ifndef _STLP_NO_IOSTREAMS + +# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) +// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL +using std::basic_ostream; +template basic_ostream & operator<< (basic_ostream & os, intrusive_ptr const & p) +# else +template std::basic_ostream & operator<< (std::basic_ostream & os, intrusive_ptr const & p) +# endif +{ + os << p.get(); + return os; +} + +#endif // _STLP_NO_IOSTREAMS + +#endif // __GNUC__ < 3 + +#endif // !defined(BOOST_NO_IOSTREAM) + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED diff --git a/include/boost/smart_ptr/make_shared.hpp b/include/boost/smart_ptr/make_shared.hpp new file mode 100644 index 0000000..58e38d2 --- /dev/null +++ b/include/boost/smart_ptr/make_shared.hpp @@ -0,0 +1,433 @@ +#ifndef BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED +#define BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED + +// make_shared.hpp +// +// Copyright (c) 2007, 2008 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 +// +// See http://www.boost.org/libs/smart_ptr/make_shared.html +// for documentation. + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + +namespace detail +{ + +template< std::size_t N, std::size_t A > struct sp_aligned_storage +{ + union type + { + char data_[ N ]; + typename boost::type_with_alignment< A >::type align_; + }; +}; + +template< class T > class sp_ms_deleter +{ +private: + + typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type; + + bool initialized_; + storage_type storage_; + +private: + + void destroy() + { + if( initialized_ ) + { + reinterpret_cast< T* >( storage_.data_ )->~T(); + initialized_ = false; + } + } + +public: + + sp_ms_deleter(): initialized_( false ) + { + } + + ~sp_ms_deleter() + { + destroy(); + } + + void operator()( T * ) + { + destroy(); + } + + void * address() + { + return storage_.data_; + } + + void set_initialized() + { + initialized_ = true; + } +}; + +template< class T > T forward( T t ) +{ + return t; +} + +} // namespace detail + +// Zero-argument versions +// +// Used even when variadic templates are available because of the new T() vs new T issue + +template< class T > boost::shared_ptr< T > make_shared() +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T(); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T(); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) + +// Variadic templates, rvalue reference + +template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && ... args ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( detail::forward( args )... ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Args && ... args ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( detail::forward( args )... ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +#else + +// C++03 version + +template< class T, class A1 > +boost::shared_ptr< T > make_shared( A1 const & a1 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +#endif + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED diff --git a/include/boost/smart_ptr/scoped_array.hpp b/include/boost/smart_ptr/scoped_array.hpp new file mode 100644 index 0000000..23c2f87 --- /dev/null +++ b/include/boost/smart_ptr/scoped_array.hpp @@ -0,0 +1,138 @@ +#ifndef BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED +#define BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 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) +// +// http://www.boost.org/libs/smart_ptr/scoped_array.htm +// + +#include +#include +#include // in case ptrdiff_t not in std + +#include + +#include // for std::ptrdiff_t + +namespace boost +{ + +// Debug hooks + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +void sp_array_constructor_hook(void * p); +void sp_array_destructor_hook(void * p); + +#endif + +// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to +// is guaranteed, either on destruction of the scoped_array or via an explicit +// reset(). Use shared_array or std::vector if your needs are more complex. + +template class scoped_array // noncopyable +{ +private: + + T * ptr; + + scoped_array(scoped_array const &); + scoped_array & operator=(scoped_array const &); + + typedef scoped_array this_type; + + void operator==( scoped_array const& ) const; + void operator!=( scoped_array const& ) const; + +public: + + typedef T element_type; + + explicit scoped_array(T * p = 0) : ptr(p) // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_array_constructor_hook(ptr); +#endif + } + + ~scoped_array() // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_array_destructor_hook(ptr); +#endif + boost::checked_array_delete(ptr); + } + + void reset(T * p = 0) // never throws + { + BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors + this_type(p).swap(*this); + } + + T & operator[](std::ptrdiff_t i) const // never throws + { + BOOST_ASSERT(ptr != 0); + BOOST_ASSERT(i >= 0); + return ptr[i]; + } + + T * get() const // never throws + { + return ptr; + } + + // implicit conversion to "bool" + +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return ptr != 0; + } + +#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return ptr == 0? 0: &this_type::get; + } + +#else + + typedef T * this_type::*unspecified_bool_type; + + operator unspecified_bool_type() const // never throws + { + return ptr == 0? 0: &this_type::ptr; + } + +#endif + + bool operator! () const // never throws + { + return ptr == 0; + } + + void swap(scoped_array & b) // never throws + { + T * tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } + +}; + +template inline void swap(scoped_array & a, scoped_array & b) // never throws +{ + a.swap(b); +} + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED diff --git a/include/boost/smart_ptr/scoped_ptr.hpp b/include/boost/smart_ptr/scoped_ptr.hpp new file mode 100644 index 0000000..518a254 --- /dev/null +++ b/include/boost/smart_ptr/scoped_ptr.hpp @@ -0,0 +1,160 @@ +#ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED +#define BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 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) +// +// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm +// + +#include +#include +#include + +#ifndef BOOST_NO_AUTO_PTR +# include // for std::auto_ptr +#endif + +namespace boost +{ + +// Debug hooks + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +void sp_scalar_constructor_hook(void * p); +void sp_scalar_destructor_hook(void * p); + +#endif + +// scoped_ptr mimics a built-in pointer except that it guarantees deletion +// of the object pointed to, either on destruction of the scoped_ptr or via +// an explicit reset(). scoped_ptr is a simple solution for simple needs; +// use shared_ptr or std::auto_ptr if your needs are more complex. + +template class scoped_ptr // noncopyable +{ +private: + + T * ptr; + + scoped_ptr(scoped_ptr const &); + scoped_ptr & operator=(scoped_ptr const &); + + typedef scoped_ptr this_type; + + void operator==( scoped_ptr const& ) const; + void operator!=( scoped_ptr const& ) const; + +public: + + typedef T element_type; + + explicit scoped_ptr(T * p = 0): ptr(p) // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_constructor_hook(ptr); +#endif + } + +#ifndef BOOST_NO_AUTO_PTR + + explicit scoped_ptr(std::auto_ptr p): ptr(p.release()) // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_constructor_hook(ptr); +#endif + } + +#endif + + ~scoped_ptr() // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_destructor_hook(ptr); +#endif + boost::checked_delete(ptr); + } + + void reset(T * p = 0) // never throws + { + BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors + this_type(p).swap(*this); + } + + T & operator*() const // never throws + { + BOOST_ASSERT(ptr != 0); + return *ptr; + } + + T * operator->() const // never throws + { + BOOST_ASSERT(ptr != 0); + return ptr; + } + + T * get() const // never throws + { + return ptr; + } + + // implicit conversion to "bool" + +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return ptr != 0; + } + +#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return ptr == 0? 0: &this_type::get; + } + +#else + typedef T * this_type::*unspecified_bool_type; + + operator unspecified_bool_type() const // never throws + { + return ptr == 0? 0: &this_type::ptr; + } + +#endif + + bool operator! () const // never throws + { + return ptr == 0; + } + + void swap(scoped_ptr & b) // never throws + { + T * tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } +}; + +template inline void swap(scoped_ptr & a, scoped_ptr & b) // never throws +{ + a.swap(b); +} + +// get_pointer(p) is a generic way to say p.get() + +template inline T * get_pointer(scoped_ptr const & p) +{ + return p.get(); +} + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp new file mode 100644 index 0000000..7d68aa2 --- /dev/null +++ b/include/boost/smart_ptr/shared_array.hpp @@ -0,0 +1,193 @@ +#ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED +#define BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED + +// +// shared_array.hpp +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 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) +// +// See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation. +// + +#include // for broken compiler workarounds + +#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#include +#else + +#include // TR1 cyclic inclusion fix + +#include +#include + +#include +#include + +#include // for std::ptrdiff_t +#include // for std::swap +#include // for std::less + +namespace boost +{ + +// +// shared_array +// +// shared_array extends shared_ptr to arrays. +// The array pointed to is deleted when the last shared_array pointing to it +// is destroyed or reset. +// + +template class shared_array +{ +private: + + // Borland 5.5.1 specific workarounds + typedef checked_array_deleter deleter; + typedef shared_array this_type; + +public: + + typedef T element_type; + + explicit shared_array(T * p = 0): px(p), pn(p, deleter()) + { + } + + // + // Requirements: D's copy constructor must not throw + // + // shared_array will release p by calling d(p) + // + + template shared_array(T * p, D d): px(p), pn(p, d) + { + } + +// generated copy constructor, assignment, destructor are fine + + void reset(T * p = 0) + { + BOOST_ASSERT(p == 0 || p != px); + this_type(p).swap(*this); + } + + template void reset(T * p, D d) + { + this_type(p, d).swap(*this); + } + + T & operator[] (std::ptrdiff_t i) const // never throws + { + BOOST_ASSERT(px != 0); + BOOST_ASSERT(i >= 0); + return px[i]; + } + + T * get() const // never throws + { + return px; + } + + // implicit conversion to "bool" + +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return px != 0; + } + +#elif defined( _MANAGED ) + + static void unspecified_bool( this_type*** ) + { + } + + typedef void (*unspecified_bool_type)( this_type*** ); + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: unspecified_bool; + } + +#elif \ + ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ + ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) + + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::get; + } + +#else + + typedef T * this_type::*unspecified_bool_type; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::px; + } + +#endif + + bool operator! () const // never throws + { + return px == 0; + } + + bool unique() const // never throws + { + return pn.unique(); + } + + long use_count() const // never throws + { + return pn.use_count(); + } + + void swap(shared_array & other) // never throws + { + std::swap(px, other.px); + pn.swap(other.pn); + } + +private: + + T * px; // contained pointer + detail::shared_count pn; // reference counter + +}; // shared_array + +template inline bool operator==(shared_array const & a, shared_array const & b) // never throws +{ + return a.get() == b.get(); +} + +template inline bool operator!=(shared_array const & a, shared_array const & b) // never throws +{ + return a.get() != b.get(); +} + +template inline bool operator<(shared_array const & a, shared_array const & b) // never throws +{ + return std::less()(a.get(), b.get()); +} + +template void swap(shared_array & a, shared_array & b) // never throws +{ + a.swap(b); +} + +} // namespace boost + +#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) + +#endif // #ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp new file mode 100644 index 0000000..78711ed --- /dev/null +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -0,0 +1,751 @@ +#ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED +#define BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED + +// +// shared_ptr.hpp +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001-2008 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) +// +// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. +// + +#include // for broken compiler workarounds + +#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#include +#else + +// In order to avoid circular dependencies with Boost.TR1 +// we make sure that our include of doesn't try to +// pull in the TR1 headers: that's why we use this header +// rather than including directly: +#include // std::auto_ptr + +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) +#include +#include +#endif + +#include // for std::swap +#include // for std::less +#include // for std::bad_cast + +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) +#include // for std::basic_ostream +#else +#include +#endif +#endif + +#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash +# pragma warning(push) +# pragma warning(disable:4284) // odd return type for operator-> +#endif + +namespace boost +{ + +template class weak_ptr; +template class enable_shared_from_this; + +namespace detail +{ + +struct static_cast_tag {}; +struct const_cast_tag {}; +struct dynamic_cast_tag {}; +struct polymorphic_cast_tag {}; + +template struct shared_ptr_traits +{ + typedef T & reference; +}; + +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + +#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) + +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + +#endif + +// enable_shared_from_this support + +template void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this const * pe, Y const * px ) +{ + if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); +} + +#ifdef _MANAGED + +// Avoid C4793, ... causes native code generation + +struct sp_any_pointer +{ + template sp_any_pointer( T* ) {} +}; + +inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer ) +{ +} + +#else // _MANAGED + +#ifdef sgi +// Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed +# pragma set woff 3506 +#endif + +inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) +{ +} + +#ifdef sgi +# pragma reset woff 3506 +#endif + +#endif // _MANAGED + +#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) + +// rvalue auto_ptr support based on a technique by Dave Abrahams + +template< class T, class R > struct sp_enable_if_auto_ptr +{ +}; + +template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R > +{ + typedef R type; +}; + +#endif + +} // namespace detail + + +// +// shared_ptr +// +// An enhanced relative of scoped_ptr with reference counted copy semantics. +// The object pointed to is deleted when the last shared_ptr pointing to it +// is destroyed or reset. +// + +template class shared_ptr +{ +private: + + // Borland 5.5.1 specific workaround + typedef shared_ptr this_type; + +public: + + typedef T element_type; + typedef T value_type; + typedef T * pointer; + typedef typename boost::detail::shared_ptr_traits::reference reference; + + shared_ptr(): px(0), pn() // never throws in 1.30+ + { + } + + template + explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete + { + boost::detail::sp_enable_shared_from_this( pn, p, p ); + } + + // + // Requirements: D's copy constructor must not throw + // + // shared_ptr will release p by calling d(p) + // + + template shared_ptr(Y * p, D d): px(p), pn(p, d) + { + boost::detail::sp_enable_shared_from_this( pn, p, p ); + } + + // As above, but with allocator. A's copy constructor shall not throw. + + template shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) + { + boost::detail::sp_enable_shared_from_this( pn, p, p ); + } + +// generated copy constructor, assignment, destructor are fine... + +// except that Borland C++ has a bug, and g++ with -Wsynth warns +#if defined(__BORLANDC__) || defined(__GNUC__) + + shared_ptr & operator=(shared_ptr const & r) // never throws + { + px = r.px; + pn = r.pn; // shared_count::op= doesn't throw + return *this; + } + +#endif + + template + explicit shared_ptr(weak_ptr const & r): pn(r.pn) // may throw + { + // it is now safe to copy r.px, as pn(r.pn) did not throw + px = r.px; + } + + template + shared_ptr( weak_ptr const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws + { + if( !pn.empty() ) + { + px = r.px; + } + } + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + shared_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + shared_ptr( shared_ptr const & r ) + +#endif + : px( r.px ), pn( r.pn ) // never throws + { + } + + // aliasing + template< class Y > + shared_ptr( shared_ptr const & r, T * p ): px( p ), pn( r.pn ) // never throws + { + } + + template + shared_ptr(shared_ptr const & r, boost::detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) + { + } + + template + shared_ptr(shared_ptr const & r, boost::detail::const_cast_tag): px(const_cast(r.px)), pn(r.pn) + { + } + + template + shared_ptr(shared_ptr const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) + { + if(px == 0) // need to allocate new counter -- the cast failed + { + pn = boost::detail::shared_count(); + } + } + + template + shared_ptr(shared_ptr const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) + { + if(px == 0) + { + boost::throw_exception(std::bad_cast()); + } + } + +#ifndef BOOST_NO_AUTO_PTR + + template + explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn() + { + Y * tmp = r.get(); + pn = boost::detail::shared_count(r); + boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); + } + +#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + + template + shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() + { + typename Ap::element_type * tmp = r.get(); + pn = boost::detail::shared_count( r ); + boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); + } + + +#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_NO_AUTO_PTR + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + + template + shared_ptr & operator=(shared_ptr const & r) // never throws + { + px = r.px; + pn = r.pn; // shared_count::op= doesn't throw + return *this; + } + +#endif + +#ifndef BOOST_NO_AUTO_PTR + + template + shared_ptr & operator=( std::auto_ptr & r ) + { + this_type(r).swap(*this); + return *this; + } + +#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + + template + typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r ) + { + this_type( r ).swap( *this ); + return *this; + } + + +#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_NO_AUTO_PTR + +// Move support + +#if defined( BOOST_HAS_RVALUE_REFS ) + + shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws + { + pn.swap( r.pn ); + r.px = 0; + } + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + shared_ptr( shared_ptr && r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + shared_ptr( shared_ptr && r ) + +#endif + : px( r.px ), pn() // never throws + { + pn.swap( r.pn ); + r.px = 0; + } + + shared_ptr & operator=( shared_ptr && r ) // never throws + { + this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); + return *this; + } + + template + shared_ptr & operator=( shared_ptr && r ) // never throws + { + this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); + return *this; + } + +#endif + + void reset() // never throws in 1.30+ + { + this_type().swap(*this); + } + + template void reset(Y * p) // Y must be complete + { + BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors + this_type(p).swap(*this); + } + + template void reset( Y * p, D d ) + { + this_type( p, d ).swap( *this ); + } + + template void reset( Y * p, D d, A a ) + { + this_type( p, d, a ).swap( *this ); + } + + template void reset( shared_ptr const & r, T * p ) + { + this_type( r, p ).swap( *this ); + } + + reference operator* () const // never throws + { + BOOST_ASSERT(px != 0); + return *px; + } + + T * operator-> () const // never throws + { + BOOST_ASSERT(px != 0); + return px; + } + + T * get() const // never throws + { + return px; + } + + // implicit conversion to "bool" + +#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) + + operator bool () const + { + return px != 0; + } + +#elif defined( _MANAGED ) + + static void unspecified_bool( this_type*** ) + { + } + + typedef void (*unspecified_bool_type)( this_type*** ); + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: unspecified_bool; + } + +#elif \ + ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ + ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \ + ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) ) + + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::get; + } + +#else + + typedef T * this_type::*unspecified_bool_type; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::px; + } + +#endif + + // operator! is redundant, but some compilers need it + + bool operator! () const // never throws + { + return px == 0; + } + + bool unique() const // never throws + { + return pn.unique(); + } + + long use_count() const // never throws + { + return pn.use_count(); + } + + void swap(shared_ptr & other) // never throws + { + std::swap(px, other.px); + pn.swap(other.pn); + } + + template bool _internal_less(shared_ptr const & rhs) const + { + return pn < rhs.pn; + } + + void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const + { + return pn.get_deleter( ti ); + } + + bool _internal_equiv( shared_ptr const & r ) const + { + return px == r.px && pn == r.pn; + } + +// Tasteless as this may seem, making all members public allows member templates +// to work in the absence of member template friends. (Matthew Langston) + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + +private: + + template friend class shared_ptr; + template friend class weak_ptr; + + +#endif + + T * px; // contained pointer + boost::detail::shared_count pn; // reference counter + +}; // shared_ptr + +template inline bool operator==(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() != b.get(); +} + +#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 + +// Resolve the ambiguity between our op!= and the one in rel_ops + +template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() != b.get(); +} + +#endif + +template inline bool operator<(shared_ptr const & a, shared_ptr const & b) +{ + return a._internal_less(b); +} + +template inline void swap(shared_ptr & a, shared_ptr & b) +{ + a.swap(b); +} + +template shared_ptr static_pointer_cast(shared_ptr const & r) +{ + return shared_ptr(r, boost::detail::static_cast_tag()); +} + +template shared_ptr const_pointer_cast(shared_ptr const & r) +{ + return shared_ptr(r, boost::detail::const_cast_tag()); +} + +template shared_ptr dynamic_pointer_cast(shared_ptr const & r) +{ + return shared_ptr(r, boost::detail::dynamic_cast_tag()); +} + +// shared_*_cast names are deprecated. Use *_pointer_cast instead. + +template shared_ptr shared_static_cast(shared_ptr const & r) +{ + return shared_ptr(r, boost::detail::static_cast_tag()); +} + +template shared_ptr shared_dynamic_cast(shared_ptr const & r) +{ + return shared_ptr(r, boost::detail::dynamic_cast_tag()); +} + +template shared_ptr shared_polymorphic_cast(shared_ptr const & r) +{ + return shared_ptr(r, boost::detail::polymorphic_cast_tag()); +} + +template shared_ptr shared_polymorphic_downcast(shared_ptr const & r) +{ + BOOST_ASSERT(dynamic_cast(r.get()) == r.get()); + return shared_static_cast(r); +} + +// get_pointer() enables boost::mem_fn to recognize shared_ptr + +template inline T * get_pointer(shared_ptr const & p) +{ + return p.get(); +} + +// operator<< + +#if !defined(BOOST_NO_IOSTREAM) + +#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) + +template std::ostream & operator<< (std::ostream & os, shared_ptr const & p) +{ + os << p.get(); + return os; +} + +#else + +// in STLport's no-iostreams mode no iostream symbols can be used +#ifndef _STLP_NO_IOSTREAMS + +# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) +// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL +using std::basic_ostream; +template basic_ostream & operator<< (basic_ostream & os, shared_ptr const & p) +# else +template std::basic_ostream & operator<< (std::basic_ostream & os, shared_ptr const & p) +# endif +{ + os << p.get(); + return os; +} + +#endif // _STLP_NO_IOSTREAMS + +#endif // __GNUC__ < 3 + +#endif // !defined(BOOST_NO_IOSTREAM) + +// get_deleter + +#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ + ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ + ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) ) + +// g++ 2.9x doesn't allow static_cast(void *) +// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it + +template D * get_deleter(shared_ptr const & p) +{ + void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D)); + return const_cast(static_cast(q)); +} + +#else + +template D * get_deleter(shared_ptr const & p) +{ + return static_cast(p._internal_get_deleter(BOOST_SP_TYPEID(D))); +} + +#endif + +// atomic access + +#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) + +template inline bool atomic_is_lock_free( shared_ptr const * /*p*/ ) +{ + return false; +} + +template shared_ptr atomic_load( shared_ptr const * p ) +{ + boost::detail::spinlock_pool<2>::scoped_lock lock( p ); + return *p; +} + +template inline shared_ptr atomic_load_explicit( shared_ptr const * p, memory_order /*mo*/ ) +{ + return atomic_load( p ); +} + +template void atomic_store( shared_ptr * p, shared_ptr r ) +{ + boost::detail::spinlock_pool<2>::scoped_lock lock( p ); + p->swap( r ); +} + +template inline void atomic_store_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) +{ + atomic_store( p, r ); // std::move( r ) +} + +template shared_ptr atomic_exchange( shared_ptr * p, shared_ptr r ) +{ + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); + + sp.lock(); + p->swap( r ); + sp.unlock(); + + return r; // return std::move( r ) +} + +template shared_ptr atomic_exchange_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) +{ + return atomic_exchange( p, r ); // std::move( r ) +} + +template bool atomic_compare_exchange( shared_ptr * p, shared_ptr * v, shared_ptr w ) +{ + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); + + sp.lock(); + + if( p->_internal_equiv( *v ) ) + { + p->swap( w ); + + sp.unlock(); + + return true; + } + else + { + shared_ptr tmp( *p ); + + sp.unlock(); + + tmp.swap( *v ); + return false; + } +} + +template inline bool atomic_compare_exchange_explicit( shared_ptr * p, shared_ptr * v, shared_ptr w, memory_order /*success*/, memory_order /*failure*/ ) +{ + return atomic_compare_exchange( p, v, w ); // std::move( w ) +} + +#endif + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) + +#endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp new file mode 100644 index 0000000..bf5296a --- /dev/null +++ b/include/boost/smart_ptr/weak_ptr.hpp @@ -0,0 +1,182 @@ +#ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED +#define BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED + +// +// weak_ptr.hpp +// +// Copyright (c) 2001, 2002, 2003 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) +// +// See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation. +// + +#include // boost.TR1 include order fix +#include +#include + +#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash +# pragma warning(push) +# pragma warning(disable:4284) // odd return type for operator-> +#endif + +namespace boost +{ + +template class weak_ptr +{ +private: + + // Borland 5.5.1 specific workarounds + typedef weak_ptr this_type; + +public: + + typedef T element_type; + + weak_ptr(): px(0), pn() // never throws in 1.30+ + { + } + +// generated copy constructor, assignment, destructor are fine + + +// +// The "obvious" converting constructor implementation: +// +// template +// weak_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // never throws +// { +// } +// +// has a serious problem. +// +// r.px may already have been invalidated. The px(r.px) +// conversion may require access to *r.px (virtual inheritance). +// +// It is not possible to avoid spurious access violations since +// in multithreaded programs r.px may be invalidated at any point. +// + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + weak_ptr( weak_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + weak_ptr( weak_ptr const & r ) + +#endif + : pn(r.pn) // never throws + { + px = r.lock().get(); + } + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + weak_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + weak_ptr( shared_ptr const & r ) + +#endif + : px( r.px ), pn( r.pn ) // never throws + { + } + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + + template + weak_ptr & operator=(weak_ptr const & r) // never throws + { + px = r.lock().get(); + pn = r.pn; + return *this; + } + + template + weak_ptr & operator=(shared_ptr const & r) // never throws + { + px = r.px; + pn = r.pn; + return *this; + } + +#endif + + shared_ptr lock() const // never throws + { + return shared_ptr( *this, boost::detail::sp_nothrow_tag() ); + } + + long use_count() const // never throws + { + return pn.use_count(); + } + + bool expired() const // never throws + { + return pn.use_count() == 0; + } + + void reset() // never throws in 1.30+ + { + this_type().swap(*this); + } + + void swap(this_type & other) // never throws + { + std::swap(px, other.px); + pn.swap(other.pn); + } + + void _internal_assign(T * px2, boost::detail::shared_count const & pn2) + { + px = px2; + pn = pn2; + } + + template bool _internal_less(weak_ptr const & rhs) const + { + return pn < rhs.pn; + } + +// Tasteless as this may seem, making all members public allows member templates +// to work in the absence of member template friends. (Matthew Langston) + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + +private: + + template friend class weak_ptr; + template friend class shared_ptr; + +#endif + + T * px; // contained pointer + boost::detail::weak_count pn; // reference counter + +}; // weak_ptr + +template inline bool operator<(weak_ptr const & a, weak_ptr const & b) +{ + return a._internal_less(b); +} + +template void swap(weak_ptr & a, weak_ptr & b) +{ + a.swap(b); +} + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index b300813..dd26869 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -6,177 +6,13 @@ // // Copyright (c) 2001, 2002, 2003 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) +// 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 // // See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation. // -#include // boost.TR1 include order fix -#include -#include - -#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash -# pragma warning(push) -# pragma warning(disable:4284) // odd return type for operator-> -#endif - -namespace boost -{ - -template class weak_ptr -{ -private: - - // Borland 5.5.1 specific workarounds - typedef weak_ptr this_type; - -public: - - typedef T element_type; - - weak_ptr(): px(0), pn() // never throws in 1.30+ - { - } - -// generated copy constructor, assignment, destructor are fine - - -// -// The "obvious" converting constructor implementation: -// -// template -// weak_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // never throws -// { -// } -// -// has a serious problem. -// -// r.px may already have been invalidated. The px(r.px) -// conversion may require access to *r.px (virtual inheritance). -// -// It is not possible to avoid spurious access violations since -// in multithreaded programs r.px may be invalidated at any point. -// - - template -#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) - - weak_ptr( weak_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) - -#else - - weak_ptr( weak_ptr const & r ) - -#endif - : pn(r.pn) // never throws - { - px = r.lock().get(); - } - - template -#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) - - weak_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) - -#else - - weak_ptr( shared_ptr const & r ) - -#endif - : px( r.px ), pn( r.pn ) // never throws - { - } - -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) - - template - weak_ptr & operator=(weak_ptr const & r) // never throws - { - px = r.lock().get(); - pn = r.pn; - return *this; - } - - template - weak_ptr & operator=(shared_ptr const & r) // never throws - { - px = r.px; - pn = r.pn; - return *this; - } - -#endif - - shared_ptr lock() const // never throws - { - return shared_ptr( *this, boost::detail::sp_nothrow_tag() ); - } - - long use_count() const // never throws - { - return pn.use_count(); - } - - bool expired() const // never throws - { - return pn.use_count() == 0; - } - - void reset() // never throws in 1.30+ - { - this_type().swap(*this); - } - - void swap(this_type & other) // never throws - { - std::swap(px, other.px); - pn.swap(other.pn); - } - - void _internal_assign(T * px2, boost::detail::shared_count const & pn2) - { - px = px2; - pn = pn2; - } - - template bool _internal_less(weak_ptr const & rhs) const - { - return pn < rhs.pn; - } - -// Tasteless as this may seem, making all members public allows member templates -// to work in the absence of member template friends. (Matthew Langston) - -#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS - -private: - - template friend class weak_ptr; - template friend class shared_ptr; - -#endif - - T * px; // contained pointer - boost::detail::weak_count pn; // reference counter - -}; // weak_ptr - -template inline bool operator<(weak_ptr const & a, weak_ptr const & b) -{ - return a._internal_less(b); -} - -template void swap(weak_ptr & a, weak_ptr & b) -{ - a.swap(b); -} - -} // namespace boost - -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif +#include #endif // #ifndef BOOST_WEAK_PTR_HPP_INCLUDED diff --git a/test/spinlock_pool_test.cpp b/test/spinlock_pool_test.cpp index c1ce2b3..53f61ca 100644 --- a/test/spinlock_pool_test.cpp +++ b/test/spinlock_pool_test.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include // Sanity check only