From 7ce5b55f5ca1a7a55d00d02ab0ccd9559fee09ba Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 24 Mar 2006 00:38:22 +0000 Subject: [PATCH 001/140] Fix issues on HP-UX (ILP32 model) [SVN r33464] --- .../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 6e120f4bf177c62634c96b9d6506a9c5ca27e45a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 19 Apr 2006 21:03:18 +0000 Subject: [PATCH 002/140] 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 75cd88112c2d976282bcbf0694a6b90b1b148839 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 15 May 2006 13:56:27 +0000 Subject: [PATCH 003/140] Workaround for MSVC 8.0 managed/unmanaged mismatch (reported by Loic Joly) [SVN r33968] --- include/boost/shared_ptr.hpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index bab848d..b1868fe 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -330,6 +330,19 @@ 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) ) From 7e5d7011e6b8770b2e7402cc4b9ff5877285b0be Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 6 Jul 2006 12:13:25 +0000 Subject: [PATCH 004/140] Attempt to fix sun-5.8 shared_ptr_delete_fail regression [SVN r34466] --- 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 b1868fe..0aaa48d 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -330,7 +330,7 @@ public: return px != 0; } -#elif defined( _MANAGED ) +#elif defined( _MANAGED ) || defined( __SUNPRO_CC ) static void unspecified_bool( this_type*** ) { From 7c477960d3ebf526fa6c9dea13470127337b25c8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 7 Jul 2006 22:48:20 +0000 Subject: [PATCH 005/140] Second try, revert to old Sun behavior for 5.8 and below [SVN r34479] --- include/boost/shared_ptr.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 0aaa48d..1924c9f 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -323,14 +323,14 @@ public: // implicit conversion to "bool" -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) operator bool () const { return px != 0; } -#elif defined( _MANAGED ) || defined( __SUNPRO_CC ) +#elif defined( _MANAGED ) static void unspecified_bool( this_type*** ) { From db0969d97b78015a4a95ee80a6f5cc77316fce09 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 12 Jul 2006 12:31:28 +0000 Subject: [PATCH 006/140] TR1 cyclic inclusion fix [SVN r34512] --- 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 ebc0af9147d440cc86af764a4705961868b6d622 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Mon, 6 Nov 2006 17:10:46 +0000 Subject: [PATCH 007/140] Remove obsolete Boost.Build v1 files. [SVN r35880] --- test/Jamfile | 48 ------------------------------------------------ 1 file changed, 48 deletions(-) delete mode 100644 test/Jamfile diff --git a/test/Jamfile b/test/Jamfile deleted file mode 100644 index 2bd285c..0000000 --- a/test/Jamfile +++ /dev/null @@ -1,48 +0,0 @@ -# Boost.SmartPtr Library test Jamfile -# -# 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. - -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 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 ] - [ run shared_ptr_alloc2_test.cpp ] - [ run pointer_cast_test.cpp ] - [ compile pointer_to_other_test.cpp ] - [ run auto_ptr_rv_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 4a98c2931c0e10d63abfab65c04a70845a648216 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 6 Nov 2006 17:25:59 +0000 Subject: [PATCH 008/140] 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 1924c9f..9edc86f 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -504,6 +504,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; @@ -516,7 +519,9 @@ template std::basic_ostream & operator<< (std:: return os; } -#endif +#endif // _STLP_NO_IOSTREAMS + +#endif // __GNUC__ < 3 // get_deleter (experimental) From c464a07ab103006a40227ef1f57869a8db02bed1 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Tue, 7 Nov 2006 19:27:00 +0000 Subject: [PATCH 009/140] Merged copyright and license addition [SVN r35907] --- 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 2f70e81b73499db37ce6c8736d1aec34419436a6 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 9 Nov 2006 12:21:28 +0000 Subject: [PATCH 010/140] TR1 conformance fix [SVN r35949] --- 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 d889751bc0c8c36e774fd065770e739d5e792dcf Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 9 Nov 2006 20:24:23 +0000 Subject: [PATCH 011/140] License/copyright edits [SVN r35957] --- enable_shared_from_this.html | 7 +++---- index.html | 15 ++++++++------- intrusive_ptr.html | 7 +++---- sp_techniques.html | 7 +++---- test/Jamfile.v2 | 7 +++---- 5 files changed, 20 insertions(+), 23 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/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 + + 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.v2 b/test/Jamfile.v2 index 0dd4e11..fbb1657 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 94db73543872e9c3e398b9c5b05b7b954f31a6a6 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Mon, 21 May 2007 01:34:43 +0000 Subject: [PATCH 012/140] gcc-4.2+ moved atomicity.hpp from bits/ to ext/ [SVN r37728] --- include/boost/detail/atomic_count_gcc.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/boost/detail/atomic_count_gcc.hpp b/include/boost/detail/atomic_count_gcc.hpp index 1160e44..9a1820d 100644 --- a/include/boost/detail/atomic_count_gcc.hpp +++ b/include/boost/detail/atomic_count_gcc.hpp @@ -17,7 +17,11 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) +# include +#else +# include +#endif namespace boost { From 5ab6b2485639fdabbd230cd93c3cbd648d32f061 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 23 Nov 2007 17:03:14 +0000 Subject: [PATCH 013/140] config, detail, filesystem, system, tools, at 41278. [SVN r41316] --- include/boost/detail/atomic_count.hpp | 16 ++ include/boost/detail/atomic_count_gcc.hpp | 6 +- include/boost/detail/atomic_count_gcc_x86.hpp | 84 +++++++++ include/boost/detail/atomic_count_solaris.hpp | 59 +++++++ include/boost/detail/atomic_count_sync.hpp | 57 ++++++ include/boost/detail/lightweight_mutex.hpp | 4 +- include/boost/detail/shared_count.hpp | 3 +- include/boost/detail/sp_counted_base.hpp | 16 +- .../boost/detail/sp_counted_base_acc_ia64.hpp | 150 ++++++++++++++++ .../boost/detail/sp_counted_base_cw_ppc.hpp | 4 +- .../boost/detail/sp_counted_base_cw_x86.hpp | 4 +- .../boost/detail/sp_counted_base_gcc_ia64.hpp | 4 +- .../boost/detail/sp_counted_base_gcc_ppc.hpp | 4 +- .../detail/sp_counted_base_gcc_sparc.hpp | 166 ++++++++++++++++++ .../boost/detail/sp_counted_base_gcc_x86.hpp | 4 +- include/boost/detail/sp_counted_base_nt.hpp | 4 +- include/boost/detail/sp_counted_base_pt.hpp | 4 +- .../boost/detail/sp_counted_base_solaris.hpp | 113 ++++++++++++ include/boost/detail/sp_counted_base_sync.hpp | 151 ++++++++++++++++ include/boost/detail/sp_counted_base_w32.hpp | 4 +- include/boost/detail/sp_counted_impl.hpp | 11 +- include/boost/detail/sp_typeinfo.hpp | 83 +++++++++ 22 files changed, 918 insertions(+), 33 deletions(-) create mode 100644 include/boost/detail/atomic_count_gcc_x86.hpp create mode 100644 include/boost/detail/atomic_count_solaris.hpp create mode 100644 include/boost/detail/atomic_count_sync.hpp create mode 100644 include/boost/detail/sp_counted_base_acc_ia64.hpp create mode 100644 include/boost/detail/sp_counted_base_gcc_sparc.hpp create mode 100644 include/boost/detail/sp_counted_base_solaris.hpp create mode 100644 include/boost/detail/sp_counted_base_sync.hpp create mode 100644 include/boost/detail/sp_typeinfo.hpp diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 9985b2c..804fd1a 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -90,14 +90,30 @@ typedef long atomic_count; } #elif defined(BOOST_AC_USE_PTHREADS) + # include + +#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) + +# include + #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) + # include + +#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + +# include + #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) + # include + #elif defined(BOOST_HAS_PTHREADS) + # define BOOST_AC_USE_PTHREADS # include + #else // Use #define BOOST_DISABLE_THREADS to avoid the error diff --git a/include/boost/detail/atomic_count_gcc.hpp b/include/boost/detail/atomic_count_gcc.hpp index 9a1820d..1160e44 100644 --- a/include/boost/detail/atomic_count_gcc.hpp +++ b/include/boost/detail/atomic_count_gcc.hpp @@ -17,11 +17,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) -# include -#else -# include -#endif +#include namespace boost { diff --git a/include/boost/detail/atomic_count_gcc_x86.hpp b/include/boost/detail/atomic_count_gcc_x86.hpp new file mode 100644 index 0000000..1312e8c --- /dev/null +++ b/include/boost/detail/atomic_count_gcc_x86.hpp @@ -0,0 +1,84 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED + +// +// boost/detail/atomic_count_gcc_x86.hpp +// +// atomic_count for g++ on 486+/AMD64 +// +// Copyright 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( long v ) : value_( static_cast< int >( v ) ) {} + + void operator++() + { + __asm__ + ( + "lock\n\t" + "incl %0": + "+m"( value_ ): // output (%0) + : // inputs + "cc" // clobbers + ); + } + + long operator--() + { + return atomic_exchange_and_add( &value_, -1 ) - 1; + } + + operator long() const + { + return atomic_exchange_and_add( &value_, 0 ); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + mutable int value_; + +private: + + static int atomic_exchange_and_add( int * pw, int dv ) + { + // int r = *pw; + // *pw += dv; + // return r; + + int r; + + __asm__ __volatile__ + ( + "lock\n\t" + "xadd %1, %0": + "+m"( *pw ), "=r"( r ): // outputs (%0, %1) + "1"( dv ): // inputs (%2 == %1) + "memory", "cc" // clobbers + ); + + return r; + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_solaris.hpp b/include/boost/detail/atomic_count_solaris.hpp new file mode 100644 index 0000000..8e2907f --- /dev/null +++ b/include/boost/detail/atomic_count_solaris.hpp @@ -0,0 +1,59 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED + +// +// boost/detail/atomic_count_solaris.hpp +// based on: boost/detail/atomic_count_win32.hpp +// +// Copyright (c) 2001-2005 Peter Dimov +// Copyright (c) 2006 Michael van der Westhuizen +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( uint32_t v ): value_( v ) + { + } + + long operator++() + { + return atomic_inc_32_nv( &value_ ); + } + + long operator--() + { + return atomic_dec_32_nv( &value_ ); + } + + operator uint32_t() const + { + return static_cast( value_ ); + } + +private: + + atomic_count( atomic_count const & ); + atomic_count & operator=( atomic_count const & ); + + uint32_t value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_sync.hpp b/include/boost/detail/atomic_count_sync.hpp new file mode 100644 index 0000000..e973fb7 --- /dev/null +++ b/include/boost/detail/atomic_count_sync.hpp @@ -0,0 +1,57 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED + +// +// boost/detail/atomic_count_sync.hpp +// +// atomic_count for g++ 4.1+ +// +// http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html +// +// Copyright 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( long v ) : value_( v ) {} + + void operator++() + { + __sync_add_and_fetch( &value_, 1 ); + } + + long operator--() + { + return __sync_add_and_fetch( &value_, -1 ); + } + + operator long() const + { + return __sync_fetch_and_add( &value_, 0 ); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + mutable long value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index a0936cb..e740d7f 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -30,10 +30,10 @@ #if !defined(BOOST_HAS_THREADS) # include -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -# include #elif defined(BOOST_HAS_PTHREADS) # include +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# include #else // Use #define BOOST_DISABLE_THREADS to avoid the error # error Unrecognized threading platform diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index e139a7d..085b12f 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -32,7 +32,6 @@ #include // std::auto_ptr #include // std::less #include // std::bad_alloc -#include // std::type_info in get_deleter namespace boost { @@ -259,7 +258,7 @@ public: return std::less()( a.pi_, b.pi_ ); } - void * get_deleter(std::type_info const & ti) const + void * get_deleter( sp_typeinfo const & ti ) const { return pi_? pi_->get_deleter( ti ): 0; } diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index bc170ca..f925a5d 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -10,7 +10,7 @@ // // detail/sp_counted_base.hpp // -// Copyright 2005 Peter Dimov +// Copyright 2005, 2006 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -39,14 +39,26 @@ # include +#elif defined(__HP_aCC) && defined(__ia64) + +# include + #elif defined( __MWERKS__ ) && defined( __POWERPC__ ) # include -#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) ) +#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) # include +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + +# include + +#elif defined(__GNUC__) && ( defined( __sparcv8 ) || defined( __sparcv9 ) ) + +# include + #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) # include diff --git a/include/boost/detail/sp_counted_base_acc_ia64.hpp b/include/boost/detail/sp_counted_base_acc_ia64.hpp new file mode 100644 index 0000000..94c015d --- /dev/null +++ b/include/boost/detail/sp_counted_base_acc_ia64.hpp @@ -0,0 +1,150 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED + +// +// detail/sp_counted_base_acc_ia64.hpp - aC++ on HP-UX IA64 +// +// Copyright 2007 Baruch Zilber +// Copyright 2007 Boris Gubenko +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// +// Lock-free algorithm by Alexander Terekhov +// + +#include "sp_typeinfo.hpp" +#include + +namespace boost +{ + +namespace detail +{ + +inline void atomic_increment( int * pw ) +{ + // ++*pw; + + _Asm_fetchadd(_FASZ_W, _SEM_REL, pw, +1, _LDHINT_NONE); +} + +inline int atomic_decrement( int * pw ) +{ + // return --*pw; + + int r = static_cast(_Asm_fetchadd(_FASZ_W, _SEM_REL, pw, -1, _LDHINT_NONE)); + if (1 == r) + { + _Asm_mf(); + } + + return r - 1; +} + +inline int atomic_conditional_increment( int * pw ) +{ + // if( *pw != 0 ) ++*pw; + // return *pw; + + int v = *pw; + + for (;;) + { + if (0 == v) + { + return 0; + } + + _Asm_mov_to_ar(_AREG_CCV, + v, + (_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE)); + int r = static_cast(_Asm_cmpxchg(_SZ_W, _SEM_ACQ, pw, v + 1, _LDHINT_NONE)); + if (r == v) + { + return r + 1; + } + + v = r; + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); // TODO use ld.acq here + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_cw_ppc.hpp b/include/boost/detail/sp_counted_base_cw_ppc.hpp index c56a562..17fb736 100644 --- a/include/boost/detail/sp_counted_base_cw_ppc.hpp +++ b/include/boost/detail/sp_counted_base_cw_ppc.hpp @@ -24,7 +24,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -123,7 +123,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_cw_x86.hpp b/include/boost/detail/sp_counted_base_cw_x86.hpp index 63c9fa2..32dd02c 100644 --- a/include/boost/detail/sp_counted_base_cw_x86.hpp +++ b/include/boost/detail/sp_counted_base_cw_x86.hpp @@ -25,7 +25,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -111,7 +111,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/detail/sp_counted_base_gcc_ia64.hpp index 7f4bd25..70b2a26 100644 --- a/include/boost/detail/sp_counted_base_gcc_ia64.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ia64.hpp @@ -16,7 +16,7 @@ // Lock-free algorithm by Alexander Terekhov // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -110,7 +110,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/detail/sp_counted_base_gcc_ppc.hpp index ca5cf2b..5a488f5 100644 --- a/include/boost/detail/sp_counted_base_gcc_ppc.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ppc.hpp @@ -24,7 +24,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -134,7 +134,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_gcc_sparc.hpp b/include/boost/detail/sp_counted_base_gcc_sparc.hpp new file mode 100644 index 0000000..c6624cf --- /dev/null +++ b/include/boost/detail/sp_counted_base_gcc_sparc.hpp @@ -0,0 +1,166 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_counted_base_gcc_sparc.hpp - g++ on Sparc V8+ +// +// Copyright (c) 2006 Piotr Wyderski +// Copyright (c) 2006 Tomas Puverle +// Copyright (c) 2006 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// Thanks to Michael van der Westhuizen + +#include "sp_typeinfo.hpp" +#include // int32_t + +namespace boost +{ + +namespace detail +{ + +inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ ) +{ + __asm__ __volatile__( "cas %0, %2, %1" + : "+m" (*dest_), "+r" (swap_) + : "r" (compare_) + : "memory" ); + + return swap_; +} + +inline int32_t atomic_fetch_and_add( int32_t * pw, int32_t dv ) +{ + // long r = *pw; + // *pw += dv; + // return r; + + for( ;; ) + { + int32_t r = *pw; + + if( __builtin_expect((compare_and_swap(pw, r, r + dv) == r), 1) ) + { + return r; + } + } +} + +inline void atomic_increment( int32_t * pw ) +{ + atomic_fetch_and_add( pw, 1 ); +} + +inline int32_t atomic_decrement( int32_t * pw ) +{ + return atomic_fetch_and_add( pw, -1 ); +} + +inline int32_t atomic_conditional_increment( int32_t * pw ) +{ + // long r = *pw; + // if( r != 0 ) ++*pw; + // return r; + + for( ;; ) + { + int32_t r = *pw; + + if( r == 0 ) + { + return r; + } + + if( __builtin_expect( ( compare_and_swap( pw, r, r + 1 ) == r ), 1 ) ) + { + return r; + } + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int32_t use_count_; // #shared + int32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return const_cast< int32_t const volatile & >( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/detail/sp_counted_base_gcc_x86.hpp index 0a8e189..7d243de 100644 --- a/include/boost/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/detail/sp_counted_base_gcc_x86.hpp @@ -24,7 +24,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -126,7 +126,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_nt.hpp b/include/boost/detail/sp_counted_base_nt.hpp index 4a4401d..626e06f 100644 --- a/include/boost/detail/sp_counted_base_nt.hpp +++ b/include/boost/detail/sp_counted_base_nt.hpp @@ -18,7 +18,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -58,7 +58,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_pt.hpp b/include/boost/detail/sp_counted_base_pt.hpp index 191064f..6e0835f 100644 --- a/include/boost/detail/sp_counted_base_pt.hpp +++ b/include/boost/detail/sp_counted_base_pt.hpp @@ -18,7 +18,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#include "sp_typeinfo.hpp" #include namespace boost @@ -69,7 +69,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_solaris.hpp b/include/boost/detail/sp_counted_base_solaris.hpp new file mode 100644 index 0000000..58119db --- /dev/null +++ b/include/boost/detail/sp_counted_base_solaris.hpp @@ -0,0 +1,113 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED + +// +// detail/sp_counted_base_solaris.hpp +// based on: detail/sp_counted_base_w32.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// Copyright 2006 Michael van der Westhuizen +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include "sp_typeinfo.hpp" +#include + +namespace boost +{ + +namespace detail +{ + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + uint32_t use_count_; // #shared + uint32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_inc_32( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + for( ;; ) + { + uint32_t tmp = static_cast< uint32_t const volatile& >( use_count_ ); + if( tmp == 0 ) return false; + if( atomic_cas_32( &use_count_, tmp, tmp + 1 ) == tmp ) return true; + } + } + + void release() // nothrow + { + if( atomic_dec_32_nv( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_inc_32( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_dec_32_nv( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_sync.hpp b/include/boost/detail/sp_counted_base_sync.hpp new file mode 100644 index 0000000..bf2a0fb --- /dev/null +++ b/include/boost/detail/sp_counted_base_sync.hpp @@ -0,0 +1,151 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_counted_base_sync.hpp - g++ 4.1+ __sync intrinsics +// +// Copyright (c) 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include "sp_typeinfo.hpp" +#include + +namespace boost +{ + +namespace detail +{ + +#if INT_MAX >= 2147483647 + +typedef int sp_int32_t; + +#else + +typedef long sp_int32_t; + +#endif + +inline void atomic_increment( sp_int32_t * pw ) +{ + __sync_fetch_and_add( pw, 1 ); +} + +inline sp_int32_t atomic_decrement( sp_int32_t * pw ) +{ + return __sync_fetch_and_add( pw, -1 ); +} + +inline sp_int32_t atomic_conditional_increment( sp_int32_t * pw ) +{ + // long r = *pw; + // if( r != 0 ) ++*pw; + // return r; + + sp_int32_t r = *pw; + + for( ;; ) + { + if( r == 0 ) + { + return r; + } + + sp_int32_t r2 = __sync_val_compare_and_swap( pw, r, r + 1 ); + + if( r2 == r ) + { + return r; + } + else + { + r = r2; + } + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + sp_int32_t use_count_; // #shared + sp_int32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return const_cast< sp_int32_t const volatile & >( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_w32.hpp b/include/boost/detail/sp_counted_base_w32.hpp index fb42c4e..4328962 100644 --- a/include/boost/detail/sp_counted_base_w32.hpp +++ b/include/boost/detail/sp_counted_base_w32.hpp @@ -26,7 +26,7 @@ #include #include -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -66,7 +66,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_impl.hpp b/include/boost/detail/sp_counted_impl.hpp index 6963f59..81f92da 100644 --- a/include/boost/detail/sp_counted_impl.hpp +++ b/include/boost/detail/sp_counted_impl.hpp @@ -35,7 +35,6 @@ #include // std::allocator #endif -#include // std::type_info in get_deleter #include // std::size_t namespace boost @@ -79,7 +78,7 @@ public: boost::checked_delete( px_ ); } - virtual void * get_deleter( std::type_info const & ) + virtual void * get_deleter( detail::sp_typeinfo const & ) { return 0; } @@ -145,9 +144,9 @@ public: del( ptr ); } - virtual void * get_deleter( std::type_info const & ti ) + virtual void * get_deleter( detail::sp_typeinfo const & ti ) { - return ti == typeid(D)? &del: 0; + return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast( del ): 0; } #if defined(BOOST_SP_USE_STD_ALLOCATOR) @@ -215,9 +214,9 @@ public: a2.deallocate( this, 1 ); } - virtual void * get_deleter( std::type_info const & ti ) + virtual void * get_deleter( detail::sp_typeinfo const & ti ) { - return ti == typeid( D )? &d_: 0; + return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast( d_ ): 0; } }; diff --git a/include/boost/detail/sp_typeinfo.hpp b/include/boost/detail/sp_typeinfo.hpp new file mode 100644 index 0000000..e78c943 --- /dev/null +++ b/include/boost/detail/sp_typeinfo.hpp @@ -0,0 +1,83 @@ +#ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED +#define BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_typeinfo.hpp +// +// Copyright 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#if defined( BOOST_NO_TYPEID ) + +namespace boost +{ + +namespace detail +{ + +typedef void* sp_typeinfo; + +template struct sp_typeid_ +{ + static char v_; +}; + +template char sp_typeid_< T >::v_; + +template struct sp_typeid_< T const >: sp_typeid_< T > +{ +}; + +template struct sp_typeid_< T volatile >: sp_typeid_< T > +{ +}; + +template struct sp_typeid_< T const volatile >: sp_typeid_< T > +{ +}; + +} // namespace detail + +} // namespace boost + +#define BOOST_SP_TYPEID(T) (&boost::detail::sp_typeid_::v_) + +#else + +#include + +namespace boost +{ + +namespace detail +{ + +#if defined( BOOST_NO_STD_TYPEINFO ) + +typedef ::type_info sp_typeinfo; + +#else + +typedef std::type_info sp_typeinfo; + +#endif + +} // namespace detail + +} // namespace boost + +#define BOOST_SP_TYPEID(T) typeid(T) + +#endif + +#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED From d2194e3b243c73bd4bcfcc2d1a2e742387a1fd3c Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sun, 25 Nov 2007 18:07:19 +0000 Subject: [PATCH 014/140] Full merge from trunk at revision 41356 of entire boost-root tree. [SVN r41369] --- include/boost/intrusive_ptr.hpp | 7 +++ include/boost/shared_array.hpp | 18 +++++++- include/boost/shared_ptr.hpp | 79 +++++++++++++++++++++++++++++---- include/boost/weak_ptr.hpp | 6 --- 4 files changed, 94 insertions(+), 16 deletions(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index cd1ac11..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_; @@ -112,11 +117,13 @@ public: T & operator*() const { + BOOST_ASSERT( p_ != 0 ); return *p_; } T * operator->() const { + BOOST_ASSERT( p_ != 0 ); return p_; } 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 diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 9edc86f..5e1abd8 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 @@ -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 @@ -195,6 +212,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) { @@ -236,7 +259,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 ); @@ -283,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 ); + 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 + { + 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); @@ -304,6 +359,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); @@ -323,7 +383,7 @@ public: // implicit conversion to "bool" -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) +#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) operator bool () const { @@ -345,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; @@ -393,9 +454,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 @@ -523,7 +584,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) ) || \ @@ -534,7 +595,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)); } @@ -542,7 +603,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 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 dba6ebbb01b82171be97da909ebcc06d6b5f0ad5 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sun, 25 Nov 2007 18:38:02 +0000 Subject: [PATCH 015/140] Full merge from trunk at revision 41356 of entire boost-root tree. [SVN r41370] --- compatibility.htm | 7 +++-- intrusive_ptr.html | 8 +++++- scoped_array.htm | 9 +++---- scoped_ptr.htm | 9 +++---- shared_array.htm | 9 +++---- shared_ptr.htm | 20 +++++++++++--- smart_ptr.htm | 9 +++---- test/Jamfile.v2 | 8 +++++- test/smart_ptr_test.cpp | 58 ++++++++++++++++++----------------------- weak_ptr.htm | 8 +++--- 10 files changed, 78 insertions(+), 67 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/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
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 71cb9c9..e108278 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
@@ -696,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/test/Jamfile.v2 b/test/Jamfile.v2 index fbb1657..e6b49d7 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 @@ -23,9 +23,15 @@ 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 ] [ 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 ] ; } diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp index 27cba2b..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; @@ -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 } 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 60ae24f4ae5d4b40a1506a0c6936ba293381da89 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sun, 25 Nov 2007 22:34:55 +0000 Subject: [PATCH 016/140] Pick up missing smart_ptr, utility, and type_traits files from full merge from trunk at revision 41356 of entire boost-root tree. [SVN r41386] --- test/shared_ptr_alias_test.cpp | 146 +++++++++++++++++++++++++++++++ test/shared_ptr_compare_fail.cpp | 27 ++++++ test/shared_ptr_move_test.cpp | 95 ++++++++++++++++++++ test/shared_ptr_pv_fail.cpp | 31 +++++++ test/shared_ptr_rv_test.cpp | 110 +++++++++++++++++++++++ test/sp_unary_addr_test.cpp | 62 +++++++++++++ 6 files changed, 471 insertions(+) create mode 100644 test/shared_ptr_alias_test.cpp create mode 100644 test/shared_ptr_compare_fail.cpp create mode 100644 test/shared_ptr_move_test.cpp create mode 100644 test/shared_ptr_pv_fail.cpp create mode 100644 test/shared_ptr_rv_test.cpp create mode 100644 test/sp_unary_addr_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(); +} 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; +} 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_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; +} 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(); +} 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 4ba016d29e9bd48b3bd2f5a8a66ecc0d852d7d56 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 10 Feb 2008 16:39:38 +0000 Subject: [PATCH 017/140] Merged revisions 43206,43208-43213 via svnmerge from https://svn.boost.org/svn/boost/trunk ........ r43206 | danieljames | 2008-02-10 09:55:03 +0000 (Sun, 10 Feb 2008) | 1 line Fix some broken links. ........ r43209 | danieljames | 2008-02-10 14:56:22 +0000 (Sun, 10 Feb 2008) | 1 line Link to people pages on the website, as they've been removed from the download. ........ r43210 | danieljames | 2008-02-10 15:02:17 +0000 (Sun, 10 Feb 2008) | 1 line Point links to the pages that used to be in 'more' to the site. ........ r43212 | danieljames | 2008-02-10 16:10:16 +0000 (Sun, 10 Feb 2008) | 1 line Fix links on the home page as well. ........ r43213 | danieljames | 2008-02-10 16:21:22 +0000 (Sun, 10 Feb 2008) | 1 line Generated documentation which is no longer generated. ........ [SVN r43214] --- smart_ptr.htm | 2 +- smarttests.htm | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) 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 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 316d00c3fcf2e9e6e8057377c644d7c6a9223734 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 2 Apr 2008 21:52:08 +0000 Subject: [PATCH 018/140] Fix #1759 in release. [SVN r44005] --- 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 2fe899cdfea54354ab62175053ec9885bc0f6ffd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 15 Apr 2008 18:57:46 +0000 Subject: [PATCH 019/140] Disable sync use for arm and hppa. [SVN r44440] --- 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 f925a5d..f2e59b9 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -51,7 +51,7 @@ # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined(__arm__) && !defined(__hppa) # include From a9cd84f43d5d1d5d03e169e42b09a5c82cc3de54 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 23 May 2008 20:30:15 +0000 Subject: [PATCH 020/140] Fix #1938 in release [SVN r45691] --- 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 866590ee97966451b1c0e9bc38a4bcdb30c7225a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 09:55:08 +0000 Subject: [PATCH 021/140] Merged 43316, 43317, 43318, 43733, 43782, 43873, 43888, 43916, 43950, 44055, 44056, 44058, 44073, 44074, 44132, 44137, 44138, 44140, 44344 from trunk to release [SVN r47339] --- include/boost/detail/shared_count.hpp | 19 +++ include/boost/detail/sp_counted_base.hpp | 4 + include/boost/detail/sp_counted_base_spin.hpp | 131 ++++++++++++++++ include/boost/detail/spinlock.hpp | 47 ++++++ include/boost/detail/spinlock_gcc_arm.hpp | 85 ++++++++++ include/boost/detail/spinlock_nt.hpp | 89 +++++++++++ include/boost/detail/spinlock_pool.hpp | 85 ++++++++++ include/boost/detail/spinlock_pt.hpp | 79 ++++++++++ include/boost/detail/spinlock_sync.hpp | 83 ++++++++++ include/boost/detail/spinlock_w32.hpp | 113 ++++++++++++++ include/boost/detail/yield_k.hpp | 145 ++++++++++++++++++ include/boost/scoped_array.hpp | 3 + include/boost/scoped_ptr.hpp | 3 + include/boost/shared_ptr.hpp | 20 +++ include/boost/weak_ptr.hpp | 26 +--- shared_ptr.htm | 11 +- test/Jamfile.v2 | 9 ++ test/esft_regtest.cpp | 136 ++++++++++++++++ test/scoped_array_eq_fail.cpp | 27 ++++ test/scoped_ptr_eq_fail.cpp | 27 ++++ test/shared_from_this_test.cpp | 3 +- test/shared_ptr_test.cpp | 12 ++ test/spinlock_pool_test.cpp | 30 ++++ test/spinlock_test.cpp | 31 ++++ test/spinlock_try_test.cpp | 46 ++++++ test/yield_k_test.cpp | 23 +++ 26 files changed, 1256 insertions(+), 31 deletions(-) create mode 100644 include/boost/detail/sp_counted_base_spin.hpp create mode 100644 include/boost/detail/spinlock.hpp create mode 100644 include/boost/detail/spinlock_gcc_arm.hpp create mode 100644 include/boost/detail/spinlock_nt.hpp create mode 100644 include/boost/detail/spinlock_pool.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 include/boost/detail/yield_k.hpp create mode 100644 test/esft_regtest.cpp create mode 100644 test/scoped_array_eq_fail.cpp create mode 100644 test/scoped_ptr_eq_fail.cpp create mode 100644 test/spinlock_pool_test.cpp create mode 100644 test/spinlock_test.cpp create mode 100644 test/spinlock_try_test.cpp create mode 100644 test/yield_k_test.cpp 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/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index f2e59b9..312893d 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.hpp b/include/boost/detail/spinlock.hpp new file mode 100644 index 0000000..e273647 --- /dev/null +++ b/include/boost/detail/spinlock.hpp @@ -0,0 +1,47 @@ +#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__) && defined( __arm__ ) +# include +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) +# include +#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 + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_gcc_arm.hpp b/include/boost/detail/spinlock_gcc_arm.hpp new file mode 100644 index 0000000..c21163b --- /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 diff --git a/include/boost/detail/spinlock_nt.hpp b/include/boost/detail/spinlock_nt.hpp new file mode 100644 index 0000000..f03ba08 --- /dev/null +++ b/include/boost/detail/spinlock_nt.hpp @@ -0,0 +1,89 @@ +#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) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + bool locked_; + +public: + + inline bool try_lock() + { + 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: + + 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 { false } + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_pool.hpp b/include/boost/detail/spinlock_pool.hpp new file mode 100644 index 0000000..92d26cb --- /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 const * 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 const * 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/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..76cfe8f --- /dev/null +++ b/include/boost/detail/spinlock_w32.hpp @@ -0,0 +1,113 @@ +#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 + +// 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 +{ + +namespace detail +{ + +class spinlock +{ +public: + + long v_; + +public: + + bool try_lock() + { + long r = BOOST_INTERLOCKED_EXCHANGE( &v_, 1 ); + + BOOST_COMPILER_FENCE + + return r == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + BOOST_COMPILER_FENCE + *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/include/boost/detail/yield_k.hpp b/include/boost/detail/yield_k.hpp new file mode 100644 index 0000000..d856d57 --- /dev/null +++ b/include/boost/detail/yield_k.hpp @@ -0,0 +1,145 @@ +#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 + +// 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 + +namespace boost +{ + +namespace detail +{ + +#if !defined( BOOST_USE_WINDOWS_H ) + extern "C" void __stdcall Sleep( unsigned ms ); +#endif + +inline void yield( unsigned k ) +{ + if( k < 4 ) + { + } +#if defined( BOOST_SMT_PAUSE ) + else if( k < 16 ) + { + BOOST_SMT_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 +{ + +inline void yield( unsigned k ) +{ + if( k < 4 ) + { + } +#if defined( BOOST_SMT_PAUSE ) + else if( k < 16 ) + { + BOOST_SMT_PAUSE + } +#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/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/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 5e1abd8..6f4d49a 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) @@ -207,6 +214,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 { @@ -555,6 +571,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 +602,8 @@ template std::basic_ostream & operator<< (std:: #endif // __GNUC__ < 3 +#endif // !defined(BOOST_NO_IOSTREAM) + // get_deleter #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ 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 diff --git a/shared_ptr.htm b/shared_ptr.htm index e108278..5b4444f 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.

@@ -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 @@ -709,8 +710,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/Jamfile.v2 b/test/Jamfile.v2 index e6b49d7..7abcb6e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -33,5 +33,14 @@ 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 ] + [ run esft_regtest.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 ] ; } 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(); +} 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; +} 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 &) { 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); } } 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; +} diff --git a/test/spinlock_test.cpp b/test/spinlock_test.cpp new file mode 100644 index 0000000..0820b96 --- /dev/null +++ b/test/spinlock_test.cpp @@ -0,0 +1,31 @@ +// +// 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 + +// Sanity check only + +static boost::detail::spinlock sp = BOOST_DETAIL_SPINLOCK_INIT; +static boost::detail::spinlock sp2 = BOOST_DETAIL_SPINLOCK_INIT; + +int main() +{ + sp.lock(); + sp2.lock(); + sp.unlock(); + sp2.unlock(); + + { + boost::detail::spinlock::scoped_lock lock( sp ); + boost::detail::spinlock::scoped_lock lock2( sp2 ); + } + + 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(); +} 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 0fd94d6d5649aa3f990ed7e303f9fba43934545b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 10:17:08 +0000 Subject: [PATCH 022/140] Updated sp_counted_base.hpp to trunk version; takes care of 44369, 44441. [SVN r47340] --- include/boost/detail/sp_counted_base.hpp | 29 ++++-------------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index 312893d..6d733d0 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -20,65 +20,46 @@ #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 ) && !defined(__arm__) && !defined(__hppa) - +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) # 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 774a8d330cc4ccf0000c30e28216a9318a82f6e0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 10:41:24 +0000 Subject: [PATCH 023/140] Merged 44595, 44638, 44707, 44711, 44728 from trunk to release [SVN r47341] --- include/boost/detail/shared_count.hpp | 27 +++-- include/boost/detail/yield_k.hpp | 6 +- include/boost/shared_ptr.hpp | 8 +- test/shared_ptr_mt_test.cpp | 143 +++++--------------------- test/weak_ptr_mt_test.cpp | 132 ++++-------------------- 5 files changed, 76 insertions(+), 240 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 1eae671..2745649 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 @@ -321,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; } @@ -331,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; } 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; diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 6f4d49a..b6af46d 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 @@ -573,7 +577,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) { 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 1bc4f16ff8d2985472103a661e0f0af0c9cc30ce Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 10:45:56 +0000 Subject: [PATCH 024/140] Update esft_regtest.cpp to trunk HEAD; takes care of 43829, 43856, 44775. [SVN r47342] --- test/esft_regtest.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/test/esft_regtest.cpp b/test/esft_regtest.cpp index 0e3036c..cc180a2 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,90 @@ 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 ); + BOOST_TEST( pv.use_count() == 1 ); +} + +struct null_deleter +{ + void operator()( void const* ) const {} +}; + +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() +{ + test(); + test2(); + test3(); + test4(); + test5(); return boost::report_errors(); } From 07b4c179801682648aefdbbf10d546d999c7197e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 11:37:16 +0000 Subject: [PATCH 025/140] Merged 44979, 45068, 45085, 45089, 45177, 45194, 45346, 45422, 45545, 46055 from trunk to release [SVN r47345] --- include/boost/detail/lwm_win32_cs.hpp | 16 +- include/boost/detail/shared_count.hpp | 9 +- include/boost/detail/sp_convertible.hpp | 76 +++++ include/boost/detail/spinlock_sync.hpp | 4 + include/boost/detail/spinlock_w32.hpp | 2 +- include/boost/detail/yield_k.hpp | 2 +- include/boost/intrusive_ptr.hpp | 35 +- include/boost/make_shared.hpp | 433 ++++++++++++++++++++++++ include/boost/shared_ptr.hpp | 23 +- include/boost/weak_ptr.hpp | 22 +- intrusive_ptr.html | 6 + test/Jamfile.v2 | 5 + test/allocate_shared_test.cpp | 189 +++++++++++ test/ip_convertible_test.cpp | 54 +++ test/make_shared_test.cpp | 189 +++++++++++ test/smart_ptr_test.cpp | 4 + test/sp_convertible_test.cpp | 71 ++++ test/sp_unary_addr_test.cpp | 5 + test/wp_convertible_test.cpp | 68 ++++ 19 files changed, 1196 insertions(+), 17 deletions(-) create mode 100644 include/boost/detail/sp_convertible.hpp create mode 100644 include/boost/make_shared.hpp create mode 100644 test/allocate_shared_test.cpp create mode 100644 test/ip_convertible_test.cpp create mode 100644 test/make_shared_test.cpp create mode 100644 test/sp_convertible_test.cpp create mode 100644 test/wp_convertible_test.cpp 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 &); diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 2745649..8f13777 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/sp_convertible.hpp b/include/boost/detail/sp_convertible.hpp new file mode 100644 index 0000000..017217b --- /dev/null +++ b/include/boost/detail/sp_convertible.hpp @@ -0,0 +1,76 @@ +#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 + +#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 ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x600 ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + +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 // !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + +#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED 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 { 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/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index c4ec407..338e672 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -22,9 +22,17 @@ #include #include +#include -#include // for std::less +#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 +74,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_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_); + if( p_ != 0 ) intrusive_ptr_add_ref( p_ ); } #endif @@ -105,6 +123,11 @@ public: return *this; } + void reset() + { + this_type().swap( *this ); + } + void reset( T * rhs ) { this_type( rhs ).swap( *this ); @@ -246,7 +269,9 @@ template intrusive_ptr dynamic_pointer_cast(intrusive_ptr std::ostream & operator<< (std::ostream & os, intrusive_ptr const & p) { @@ -275,6 +300,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/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/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index b6af46d..5a172b9 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include // for std::swap #include // for std::less @@ -228,7 +229,16 @@ public: } template - shared_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws +#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 { } @@ -337,7 +347,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; diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 4335738..b300813 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_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 - weak_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws +#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 { } 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).

diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7abcb6e..955b282 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -42,5 +42,10 @@ import testing ; [ run spinlock_try_test.cpp ] [ run spinlock_try_test.cpp : : : multi : spinlock_try_test.mt ] [ run spinlock_pool_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 ] ; } 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/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/make_shared_test.cpp b/test/make_shared_test.cpp new file mode 100644 index 0000000..9930e31 --- /dev/null +++ b/test/make_shared_test.cpp @@ -0,0 +1,189 @@ +// 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::make_shared< int >( 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::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::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::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::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::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::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::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::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::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 ); + } + + 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_convertible_test.cpp b/test/sp_convertible_test.cpp new file mode 100644 index 0000000..7f49e1f --- /dev/null +++ b/test/sp_convertible_test.cpp @@ -0,0 +1,71 @@ +#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::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(); +} 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(); } 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 f884c53bd685682aeaf31b4bc51525b0055bc7b4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 11:41:20 +0000 Subject: [PATCH 026/140] Updated spinlock_pool.hpp from trunk HEAD; takes care of 45069. [SVN r47346] --- include/boost/detail/spinlock_pool.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 ]; } From 034c12d2442389d6d89bccf81b0319e4ef683e63 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 11:57:45 +0000 Subject: [PATCH 027/140] Merged 44636, 44640, 45094 (atomic access) from trunk to release. [SVN r47349] --- include/boost/memory_order.hpp | 35 +++++ include/boost/shared_ptr.hpp | 64 +++++++++ test/Jamfile.v2 | 1 + test/sp_atomic_mt2_test.cpp | 247 +++++++++++++++++++++++++++++++++ test/sp_atomic_mt_test.cpp | 191 +++++++++++++++++++++++++ test/sp_atomic_test.cpp | 87 ++++++++++++ 6 files changed, 625 insertions(+) create mode 100644 include/boost/memory_order.hpp create mode 100644 test/sp_atomic_mt2_test.cpp create mode 100644 test/sp_atomic_mt_test.cpp 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 5a172b9..394e30c 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -33,6 +33,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 @@ -498,6 +503,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 955b282..5f68e20 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -47,5 +47,6 @@ import testing ; [ run wp_convertible_test.cpp ] [ run ip_convertible_test.cpp ] [ run allocate_shared_test.cpp ] + [ run sp_atomic_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 new file mode 100644 index 0000000..143df98 --- /dev/null +++ b/test/sp_atomic_mt_test.cpp @@ -0,0 +1,191 @@ + +// 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 + +#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(); +} 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 1b49f08cb8e8b80933ead2ade5ae95daf67a40b9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 12:21:19 +0000 Subject: [PATCH 028/140] Merged 44686 from trunk to release. [SVN r47350] --- 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 31d0c48f1810dfecb1e7af5199c658118c8bc879 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 14:47:13 +0000 Subject: [PATCH 029/140] Merged 45224, 45225 from trunk to release. [SVN r47355] --- include/boost/pointer_cast.hpp | 2 +- include/boost/pointer_to_other.hpp | 2 +- test/pointer_cast_test.cpp | 2 +- 3 files changed, 3 insertions(+), 3 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. 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 991b02b03e97ac8e29b076e280fb50056fbab6fa Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 15:16:31 +0000 Subject: [PATCH 030/140] Whitespace fix. [SVN r47356] --- include/boost/shared_ptr.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 394e30c..ef0d398 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -419,7 +419,7 @@ public: BOOST_ASSERT(px != 0); return px; } - + T * get() const // never throws { return px; @@ -453,13 +453,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; @@ -679,7 +679,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; @@ -719,7 +719,7 @@ template D * get_deleter(shared_ptr const & p) #ifdef BOOST_MSVC # pragma warning(pop) -#endif +#endif #endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) From 556b9fe563a73e0f710c5992bada5eef7cd5c921 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 16:18:05 +0000 Subject: [PATCH 031/140] Merge 47357 (atomic access N2674 edits) from trunk to release. [SVN r47358] --- 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 ef0d398..ad2bc17 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 @@ -503,65 +503,11 @@ 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 + 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) @@ -715,6 +661,85 @@ template D * get_deleter(shared_ptr const & p) #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 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 6ba78f76f609fddace8882b20cfc8b4f5036f052 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 23 Jul 2008 20:47:47 +0000 Subject: [PATCH 032/140] Merge 47736 from trunk (untabify). [SVN r47739] --- 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 6e804e64b82b371ece78cfc297b1d0fa39aa51b4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 28 Sep 2008 15:05:17 +0000 Subject: [PATCH 033/140] Merge 48832-48840 from trunk. [SVN r48989] --- include/boost/detail/atomic_count.hpp | 7 +------ include/boost/detail/atomic_count_sync.hpp | 4 ++++ include/boost/detail/sp_counted_base.hpp | 4 ++-- include/boost/detail/spinlock.hpp | 4 ++-- shared_array.htm | 2 +- src/sp_collector.cpp | 4 +++- 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 804fd1a..c53a63b 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 ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # 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 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 { diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index 6d733d0..c25a57f 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -46,10 +46,10 @@ #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 ) ) +#elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) ) # include #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) diff --git a/include/boost/detail/spinlock.hpp b/include/boost/detail/spinlock.hpp index e273647..346fb3c 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__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include 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 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 6f91ea87c34add9108acfebe2e349d15f90596a5 Mon Sep 17 00:00:00 2001 From: Nicola Musatti Date: Mon, 13 Oct 2008 19:22:17 +0000 Subject: [PATCH 034/140] CodeGear patch. Fixes #2342 [SVN r49320] --- 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 55583ac7490bcbfcf9f33d7fd7a23787adda2e4c Mon Sep 17 00:00:00 2001 From: "Troy D. Straszheim" Date: Sat, 24 Jan 2009 18:57:20 +0000 Subject: [PATCH 035/140] merge of cmake build files from trunk per beman [SVN r50756] --- CMakeLists.txt | 30 ++++++++++++++++++++++++++++++ module.cmake | 1 + test/CMakeLists.txt | 18 ++++++++++++++++++ 3 files changed, 49 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..7ddae31 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,18 @@ +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) +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 a2c5208b8ec20988759bc2505e0cf2e62e61fdfd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 28 Feb 2009 19:59:56 +0000 Subject: [PATCH 036/140] Sync shared_count.hpp with trunk. [SVN r51484] --- include/boost/detail/shared_count.hpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 8f13777..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 @@ -227,6 +228,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 @@ -368,6 +381,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_; From 6be1e3fceb0fb13efb9a4ee0c23575c95c79a4f3 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 2 Mar 2009 16:35:06 +0000 Subject: [PATCH 037/140] Merge [51514] to release. Closes #2394. [SVN r51535] --- include/boost/smart_ptr/detail/shared_count.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp index 3384faa..b968bba 100644 --- a/include/boost/smart_ptr/detail/shared_count.hpp +++ b/include/boost/smart_ptr/detail/shared_count.hpp @@ -319,7 +319,7 @@ public: weak_count(shared_count const & r): pi_(r.pi_) // nothrow #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - , id_(shared_count_id) + , id_(weak_count_id) #endif { if(pi_ != 0) pi_->weak_add_ref(); @@ -327,7 +327,7 @@ public: weak_count(weak_count const & r): pi_(r.pi_) // nothrow #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - , id_(shared_count_id) + , id_(weak_count_id) #endif { if(pi_ != 0) pi_->weak_add_ref(); From f93110620af5ccfcbbe879c5a04646a9a5b80a11 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 2 Mar 2009 16:37:31 +0000 Subject: [PATCH 038/140] Merge [51515] to release. Closes #2675. [SVN r51536] --- include/boost/smart_ptr/detail/lightweight_mutex.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/smart_ptr/detail/lightweight_mutex.hpp b/include/boost/smart_ptr/detail/lightweight_mutex.hpp index a2fc281..d46b193 100644 --- a/include/boost/smart_ptr/detail/lightweight_mutex.hpp +++ b/include/boost/smart_ptr/detail/lightweight_mutex.hpp @@ -32,7 +32,7 @@ # include #elif defined(BOOST_HAS_PTHREADS) # include -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +#elif defined(BOOST_HAS_WINTHREADS) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include #else // Use #define BOOST_DISABLE_THREADS to avoid the error From bad394b1e969eb4ae2a2bf262726d6bf359bbfdb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 2 Mar 2009 16:39:53 +0000 Subject: [PATCH 039/140] Merge [51516] to release. Closes #2662. [SVN r51537] --- include/boost/smart_ptr/make_shared.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/boost/smart_ptr/make_shared.hpp b/include/boost/smart_ptr/make_shared.hpp index 58e38d2..25b9cf0 100644 --- a/include/boost/smart_ptr/make_shared.hpp +++ b/include/boost/smart_ptr/make_shared.hpp @@ -60,6 +60,11 @@ public: { } + // optimization: do not copy storage_ + sp_ms_deleter( sp_ms_deleter const & ): initialized_( false ) + { + } + ~sp_ms_deleter() { destroy(); From dad59f3325a8f17fe4fb2020139d8c14688efb9c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 2 Mar 2009 16:42:28 +0000 Subject: [PATCH 040/140] Merge [51517] to release. Closes #2525. [SVN r51538] --- .../boost/smart_ptr/detail/atomic_count.hpp | 5 +- .../smart_ptr/detail/atomic_count_gcc.hpp | 6 ++- .../smart_ptr/detail/sp_counted_base.hpp | 5 +- .../boost/smart_ptr/detail/sp_has_sync.hpp | 49 +++++++++++++++++++ include/boost/smart_ptr/detail/spinlock.hpp | 8 ++- 5 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 include/boost/smart_ptr/detail/sp_has_sync.hpp diff --git a/include/boost/smart_ptr/detail/atomic_count.hpp b/include/boost/smart_ptr/detail/atomic_count.hpp index 91236e4..a6ddea3 100644 --- a/include/boost/smart_ptr/detail/atomic_count.hpp +++ b/include/boost/smart_ptr/detail/atomic_count.hpp @@ -74,6 +74,7 @@ // #include +#include #ifndef BOOST_HAS_THREADS @@ -95,10 +96,10 @@ typedef long atomic_count; #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) # include -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include -#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) +#elif defined( BOOST_SP_HAS_SYNC ) # include #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) diff --git a/include/boost/smart_ptr/detail/atomic_count_gcc.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp index 6abfdf2..1305632 100644 --- a/include/boost/smart_ptr/detail/atomic_count_gcc.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp @@ -17,7 +17,11 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#if __GNUC__ * 100 + __GNUC_MINOR__ >= 402 +# include +#else +# include +#endif namespace boost { diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp index 1352346..df8be5b 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp @@ -18,6 +18,7 @@ // #include +#include #if defined( BOOST_SP_DISABLE_THREADS ) # include @@ -46,13 +47,13 @@ #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) +#elif defined( BOOST_SP_HAS_SYNC ) # include #elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) ) # include -#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) +#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined(__CYGWIN__) # include #elif !defined( BOOST_HAS_THREADS ) diff --git a/include/boost/smart_ptr/detail/sp_has_sync.hpp b/include/boost/smart_ptr/detail/sp_has_sync.hpp new file mode 100644 index 0000000..cb0282d --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_has_sync.hpp @@ -0,0 +1,49 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/smart_ptr/detail/sp_has_sync.hpp +// +// Copyright (c) 2008, 2009 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) +// +// Defines the BOOST_SP_HAS_SYNC macro if the __sync_* intrinsics +// are available. +// + +#if defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + +#define BOOST_SP_HAS_SYNC + +#if defined( __arm__ ) || defined( __armel__ ) +#undef BOOST_SP_HAS_SYNC +#endif + +#if defined( __hppa ) || defined( __hppa__ ) +#undef BOOST_SP_HAS_SYNC +#endif + +#if defined( __m68k__ ) +#undef BOOST_SP_HAS_SYNC +#endif + +#if defined( __sparc__ ) +#undef BOOST_SP_HAS_SYNC +#endif + +#if defined( __INTEL_COMPILER ) && !defined( __ia64__ ) +#undef BOOST_SP_HAS_SYNC +#endif + +#endif // __GNUC__ * 100 + __GNUC_MINOR__ >= 401 + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/spinlock.hpp b/include/boost/smart_ptr/detail/spinlock.hpp index 9c6cb9f..1640a38 100644 --- a/include/boost/smart_ptr/detail/spinlock.hpp +++ b/include/boost/smart_ptr/detail/spinlock.hpp @@ -29,17 +29,23 @@ // #include +#include #if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ ) # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) + +#elif defined( BOOST_SP_HAS_SYNC ) # include + #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 From 5a2771e58590a8f82b78a5258dddc247f8a2e003 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 2 Mar 2009 16:45:22 +0000 Subject: [PATCH 041/140] Merge [51518] to release. Closes #2814. [SVN r51539] --- .../boost/smart_ptr/detail/operator_bool.hpp | 56 ++++++++++++++++ include/boost/smart_ptr/intrusive_ptr.hpp | 67 ++++++------------- include/boost/smart_ptr/scoped_array.hpp | 61 +++++------------ include/boost/smart_ptr/scoped_ptr.hpp | 65 +++++------------- include/boost/smart_ptr/shared_array.hpp | 50 +------------- include/boost/smart_ptr/shared_ptr.hpp | 53 +-------------- 6 files changed, 112 insertions(+), 240 deletions(-) create mode 100644 include/boost/smart_ptr/detail/operator_bool.hpp diff --git a/include/boost/smart_ptr/detail/operator_bool.hpp b/include/boost/smart_ptr/detail/operator_bool.hpp new file mode 100644 index 0000000..842a05d --- /dev/null +++ b/include/boost/smart_ptr/detail/operator_bool.hpp @@ -0,0 +1,56 @@ +// This header intentionally has no include guards. +// +// Copyright (c) 2001-2009 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 + +#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; + } diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp index f5acae3..d3bd02b 100644 --- a/include/boost/smart_ptr/intrusive_ptr.hpp +++ b/include/boost/smart_ptr/intrusive_ptr.hpp @@ -63,13 +63,13 @@ public: typedef T element_type; - intrusive_ptr(): p_(0) + intrusive_ptr(): px( 0 ) { } - intrusive_ptr(T * p, bool add_ref = true): p_(p) + intrusive_ptr( T * p, bool add_ref = true ): px( p ) { - if(p_ != 0 && add_ref) intrusive_ptr_add_ref(p_); + if( px != 0 && add_ref ) intrusive_ptr_add_ref( px ); } #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) @@ -84,21 +84,21 @@ public: intrusive_ptr( intrusive_ptr const & rhs ) #endif - : p_( rhs.get() ) + : px( rhs.get() ) { - if( p_ != 0 ) intrusive_ptr_add_ref( p_ ); + if( px != 0 ) intrusive_ptr_add_ref( px ); } #endif - intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_) + intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px ) { - if(p_ != 0) intrusive_ptr_add_ref(p_); + if( px != 0 ) intrusive_ptr_add_ref( px ); } ~intrusive_ptr() { - if(p_ != 0) intrusive_ptr_release(p_); + if( px != 0 ) intrusive_ptr_release( px ); } #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) @@ -135,63 +135,34 @@ public: T * get() const { - return p_; + return px; } T & operator*() const { - BOOST_ASSERT( p_ != 0 ); - return *p_; + BOOST_ASSERT( px != 0 ); + return *px; } T * operator->() const { - BOOST_ASSERT( p_ != 0 ); - return p_; + BOOST_ASSERT( px != 0 ); + return px; } -#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; - } +// implicit conversion to "bool" +#include void swap(intrusive_ptr & rhs) { - T * tmp = p_; - p_ = rhs.p_; - rhs.p_ = tmp; + T * tmp = px; + px = rhs.px; + rhs.px = tmp; } private: - T * p_; + T * px; }; template inline bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) diff --git a/include/boost/smart_ptr/scoped_array.hpp b/include/boost/smart_ptr/scoped_array.hpp index 23c2f87..483460f 100644 --- a/include/boost/smart_ptr/scoped_array.hpp +++ b/include/boost/smart_ptr/scoped_array.hpp @@ -39,7 +39,7 @@ template class scoped_array // noncopyable { private: - T * ptr; + T * px; scoped_array(scoped_array const &); scoped_array & operator=(scoped_array const &); @@ -53,79 +53,48 @@ public: typedef T element_type; - explicit scoped_array(T * p = 0) : ptr(p) // never throws + explicit scoped_array( T * p = 0 ) : px( p ) // never throws { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_array_constructor_hook(ptr); + boost::sp_array_constructor_hook( px ); #endif } ~scoped_array() // never throws { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_array_destructor_hook(ptr); + boost::sp_array_destructor_hook( px ); #endif - boost::checked_array_delete(ptr); + boost::checked_array_delete( px ); } void reset(T * p = 0) // never throws { - BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors + BOOST_ASSERT( p == 0 || p != px ); // 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]; + BOOST_ASSERT( px != 0 ); + BOOST_ASSERT( i >= 0 ); + return px[i]; } T * get() const // never throws { - return ptr; + return px; } - // 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; - } +// implicit conversion to "bool" +#include void swap(scoped_array & b) // never throws { - T * tmp = b.ptr; - b.ptr = ptr; - ptr = tmp; + T * tmp = b.px; + b.px = px; + px = tmp; } - }; template inline void swap(scoped_array & a, scoped_array & b) // never throws diff --git a/include/boost/smart_ptr/scoped_ptr.hpp b/include/boost/smart_ptr/scoped_ptr.hpp index 518a254..df479e5 100644 --- a/include/boost/smart_ptr/scoped_ptr.hpp +++ b/include/boost/smart_ptr/scoped_ptr.hpp @@ -40,7 +40,7 @@ template class scoped_ptr // noncopyable { private: - T * ptr; + T * px; scoped_ptr(scoped_ptr const &); scoped_ptr & operator=(scoped_ptr const &); @@ -54,19 +54,19 @@ public: typedef T element_type; - explicit scoped_ptr(T * p = 0): ptr(p) // never throws + explicit scoped_ptr( T * p = 0 ): px( p ) // never throws { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_scalar_constructor_hook(ptr); + boost::sp_scalar_constructor_hook( px ); #endif } #ifndef BOOST_NO_AUTO_PTR - explicit scoped_ptr(std::auto_ptr p): ptr(p.release()) // never throws + explicit scoped_ptr( std::auto_ptr p ): px( p.release() ) // never throws { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_scalar_constructor_hook(ptr); + boost::sp_scalar_constructor_hook( px ); #endif } @@ -75,71 +75,42 @@ public: ~scoped_ptr() // never throws { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_scalar_destructor_hook(ptr); + boost::sp_scalar_destructor_hook( px ); #endif - boost::checked_delete(ptr); + boost::checked_delete( px ); } void reset(T * p = 0) // never throws { - BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors + BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors this_type(p).swap(*this); } T & operator*() const // never throws { - BOOST_ASSERT(ptr != 0); - return *ptr; + BOOST_ASSERT( px != 0 ); + return *px; } T * operator->() const // never throws { - BOOST_ASSERT(ptr != 0); - return ptr; + BOOST_ASSERT( px != 0 ); + return px; } T * get() const // never throws { - return ptr; + return px; } - // 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; - } +// implicit conversion to "bool" +#include void swap(scoped_ptr & b) // never throws { - T * tmp = b.ptr; - b.ptr = ptr; - ptr = tmp; + T * tmp = b.px; + b.px = px; + px = tmp; } }; diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp index 7d68aa2..1f50403 100644 --- a/include/boost/smart_ptr/shared_array.hpp +++ b/include/boost/smart_ptr/shared_array.hpp @@ -94,54 +94,8 @@ public: 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; - } +// implicit conversion to "bool" +#include bool unique() const // never throws { diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 78711ed..c7cdaf7 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -425,57 +425,8 @@ public: 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; - } +// implicit conversion to "bool" +#include bool unique() const // never throws { From 22f1b092c90efe89f19636c90b84c23b60a66fdd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 5 Mar 2009 23:06:17 +0000 Subject: [PATCH 042/140] Merge [51581] to release. Fixes #2126. Fixes #2584. [SVN r51632] --- .../smart_ptr/enable_shared_from_this.hpp | 36 ++- include/boost/smart_ptr/make_shared.hpp | 154 +++++++--- include/boost/smart_ptr/shared_ptr.hpp | 31 +- test/Jamfile.v2 | 4 + test/allocate_shared_esft_test.cpp | 264 ++++++++++++++++++ test/allocate_shared_test.cpp | 9 + test/esft_second_ptr_test.cpp | 51 ++++ test/esft_void_test.cpp | 41 +++ test/make_shared_esft_test.cpp | 263 +++++++++++++++++ test/make_shared_test.cpp | 9 + test/shared_from_this_test.cpp | 43 ++- test/shared_ptr_move_test.cpp | 11 + 12 files changed, 824 insertions(+), 92 deletions(-) create mode 100644 test/allocate_shared_esft_test.cpp create mode 100644 test/esft_second_ptr_test.cpp create mode 100644 test/esft_void_test.cpp create mode 100644 test/make_shared_esft_test.cpp diff --git a/include/boost/smart_ptr/enable_shared_from_this.hpp b/include/boost/smart_ptr/enable_shared_from_this.hpp index ed9aadd..f7b1445 100644 --- a/include/boost/smart_ptr/enable_shared_from_this.hpp +++ b/include/boost/smart_ptr/enable_shared_from_this.hpp @@ -4,11 +4,11 @@ // // enable_shared_from_this.hpp // -// Copyright (c) 2002 Peter Dimov +// Copyright 2002, 2009 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 // @@ -46,26 +46,32 @@ public: shared_ptr shared_from_this() { - shared_ptr p(_internal_weak_this); - BOOST_ASSERT(p.get() == this); + shared_ptr p( 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); + shared_ptr p( 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 +public: // actually private, but avoids compiler template friendship issues - typedef T _internal_element_type; // for bcc 5.5.1 - mutable weak_ptr<_internal_element_type> _internal_weak_this; + // Note: invoked automatically by shared_ptr; do not call + template void _internal_accept_owner( shared_ptr const * ppx, Y * py ) const + { + if( weak_this_.expired() ) + { + weak_this_ = shared_ptr( *ppx, py ); + } + } + +private: + + mutable weak_ptr weak_this_; }; } // namespace boost diff --git a/include/boost/smart_ptr/make_shared.hpp b/include/boost/smart_ptr/make_shared.hpp index 25b9cf0..7e1e793 100644 --- a/include/boost/smart_ptr/make_shared.hpp +++ b/include/boost/smart_ptr/make_shared.hpp @@ -105,10 +105,13 @@ template< class T > boost::shared_ptr< T > make_shared() void * pv = pd->address(); - new( pv ) T(); + ::new( pv ) T(); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a ) @@ -119,10 +122,13 @@ template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a void * pv = pd->address(); - new( pv ) T(); + ::new( pv ) T(); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } #if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) @@ -137,10 +143,13 @@ template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && . void * pv = pd->address(); - new( pv ) T( detail::forward( args )... ); + ::new( pv ) T( detail::forward( args )... ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Args && ... args ) @@ -151,10 +160,13 @@ template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shar void * pv = pd->address(); - new( pv ) T( detail::forward( args )... ); + ::new( pv ) T( detail::forward( args )... ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } #else @@ -170,10 +182,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1 ) void * pv = pd->address(); - new( pv ) T( a1 ); + ::new( pv ) T( a1 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1 > @@ -185,10 +200,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 ) void * pv = pd->address(); - new( pv ) T( a1 ); + ::new( pv ) T( a1 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2 > @@ -200,10 +218,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 ) void * pv = pd->address(); - new( pv ) T( a1, a2 ); + ::new( pv ) T( a1, a2 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2 > @@ -215,10 +236,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2 ); + ::new( pv ) T( a1, a2 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2, class A3 > @@ -230,10 +254,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3 void * pv = pd->address(); - new( pv ) T( a1, a2, a3 ); + ::new( pv ) T( a1, a2, a3 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2, class A3 > @@ -245,10 +272,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2, a3 ); + ::new( pv ) T( a1, a2, a3 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2, class A3, class A4 > @@ -260,10 +290,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4 ); + ::new( pv ) T( a1, a2, a3, a4 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2, class A3, class A4 > @@ -275,10 +308,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4 ); + ::new( pv ) T( a1, a2, a3, a4 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2, class A3, class A4, class A5 > @@ -290,10 +326,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5 ); + ::new( pv ) T( a1, a2, a3, a4, a5 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2, class A3, class A4, class A5 > @@ -305,10 +344,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5 ); + ::new( pv ) T( a1, a2, a3, a4, a5 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2, class A3, class A4, class A5, class A6 > @@ -320,10 +362,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6 ); + ::new( pv ) T( a1, a2, a3, a4, a5, a6 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 > @@ -335,10 +380,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6 ); + ::new( pv ) T( a1, a2, a3, a4, a5, a6 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > @@ -350,10 +398,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); + ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > @@ -365,10 +416,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); + ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > @@ -380,10 +434,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); + ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > @@ -395,10 +452,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); + ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > @@ -410,10 +470,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + ::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 ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > @@ -425,10 +488,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + ::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 ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } #endif diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index c7cdaf7..0812c04 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -58,6 +58,7 @@ namespace boost { +template class shared_ptr; template class weak_ptr; template class enable_shared_from_this; @@ -100,9 +101,12 @@ 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 ) +template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr const * ppx, Y const * py, boost::enable_shared_from_this< T > const * pe ) { - if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); + if( pe != 0 ) + { + pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) ); + } } #ifdef _MANAGED @@ -114,25 +118,16 @@ 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, 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*/, ... ) +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 ) @@ -182,7 +177,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, p ); } // @@ -193,14 +188,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, 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, p ); } // generated copy constructor, assignment, destructor are fine... @@ -288,7 +283,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, tmp ); } #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) @@ -298,7 +293,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, tmp ); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5f68e20..34cd5f1 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -48,5 +48,9 @@ import testing ; [ run ip_convertible_test.cpp ] [ run allocate_shared_test.cpp ] [ run sp_atomic_test.cpp ] + [ run esft_void_test.cpp ] + [ run esft_second_ptr_test.cpp ] + [ run make_shared_esft_test.cpp ] + [ run allocate_shared_esft_test.cpp ] ; } diff --git a/test/allocate_shared_esft_test.cpp b/test/allocate_shared_esft_test.cpp new file mode 100644 index 0000000..2bb8ccc --- /dev/null +++ b/test/allocate_shared_esft_test.cpp @@ -0,0 +1,264 @@ +// allocate_shared_esft_test.cpp +// +// Copyright 2007-2009 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 +{ +private: + + X( X const & ); + X & operator=( X const & ); + +public: + + static int instances; + + explicit X( int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0 ) + { + ++instances; + } + + ~X() + { + --instances; + } +}; + +int X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator() ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2, 3 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7, 8 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +} diff --git a/test/allocate_shared_test.cpp b/test/allocate_shared_test.cpp index 71ee948..97808c2 100644 --- a/test/allocate_shared_test.cpp +++ b/test/allocate_shared_test.cpp @@ -10,6 +10,7 @@ #include #include #include +#include class X { @@ -18,6 +19,14 @@ private: X( X const & ); X & operator=( X const & ); + void * operator new( std::size_t ); + + void operator delete( void * p ) + { + // lack of this definition causes link errors on MSVC + ::operator delete( p ); + } + public: static int instances; diff --git a/test/esft_second_ptr_test.cpp b/test/esft_second_ptr_test.cpp new file mode 100644 index 0000000..0600667 --- /dev/null +++ b/test/esft_second_ptr_test.cpp @@ -0,0 +1,51 @@ +// +// esft_second_ptr_test.cpp +// +// This test has been extracted from a real +// scenario that occurs in Boost.Python +// +// Copyright 2009 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 + +// + +class X: public boost::enable_shared_from_this +{ +}; + +void null_deleter( void const* ) +{ +} + +int main() +{ + boost::shared_ptr px( new X ); + + { + boost::shared_ptr px2( px.get(), null_deleter ); + BOOST_TEST( px == px2 ); + } + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + + return boost::report_errors(); +} diff --git a/test/esft_void_test.cpp b/test/esft_void_test.cpp new file mode 100644 index 0000000..b28c669 --- /dev/null +++ b/test/esft_void_test.cpp @@ -0,0 +1,41 @@ +// +// esft_void_test.cpp +// +// Copyright 2009 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 + +// + +class X: public boost::enable_shared_from_this +{ +}; + +int main() +{ + boost::shared_ptr< void const volatile > pv( new X ); + boost::shared_ptr< void > pv2 = boost::const_pointer_cast< void >( pv ); + boost::shared_ptr< X > px = boost::static_pointer_cast< X >( pv2 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + + return boost::report_errors(); +} diff --git a/test/make_shared_esft_test.cpp b/test/make_shared_esft_test.cpp new file mode 100644 index 0000000..1956cba --- /dev/null +++ b/test/make_shared_esft_test.cpp @@ -0,0 +1,263 @@ +// make_shared_esft_test.cpp +// +// Copyright 2007-2009 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: public boost::enable_shared_from_this +{ +private: + + X( X const & ); + X & operator=( X const & ); + +public: + + static int instances; + + explicit X( int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0 ) + { + ++instances; + } + + ~X() + { + --instances; + } +}; + +int X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >(); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +} diff --git a/test/make_shared_test.cpp b/test/make_shared_test.cpp index 9930e31..474d1c5 100644 --- a/test/make_shared_test.cpp +++ b/test/make_shared_test.cpp @@ -10,6 +10,7 @@ #include #include #include +#include class X { @@ -18,6 +19,14 @@ private: X( X const & ); X & operator=( X const & ); + void * operator new( std::size_t ); + + void operator delete( void * p ) + { + // lack of this definition causes link errors on MSVC + ::operator delete( p ); + } + public: static int instances; diff --git a/test/shared_from_this_test.cpp b/test/shared_from_this_test.cpp index 61515bd..68d6098 100644 --- a/test/shared_from_this_test.cpp +++ b/test/shared_from_this_test.cpp @@ -55,16 +55,23 @@ void test() BOOST_TEST(py.get() != 0); BOOST_TEST(py.use_count() == 1); - boost::shared_ptr px = py->getX(); - BOOST_TEST(px.get() != 0); - BOOST_TEST(py.use_count() == 2); + try + { + boost::shared_ptr px = py->getX(); + BOOST_TEST(px.get() != 0); + BOOST_TEST(py.use_count() == 2); - px->f(); + px->f(); - boost::shared_ptr py2 = boost::dynamic_pointer_cast(px); - BOOST_TEST(py.get() == py2.get()); - BOOST_TEST(!(py < py2 || py2 < py)); - BOOST_TEST(py.use_count() == 3); + boost::shared_ptr py2 = boost::dynamic_pointer_cast(px); + BOOST_TEST(py.get() == py2.get()); + BOOST_TEST(!(py < py2 || py2 < py)); + BOOST_TEST(py.use_count() == 3); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "py->getX() failed" ); + } } void test2(); @@ -124,19 +131,25 @@ void test3() { boost::shared_ptr p(new V); - boost::shared_ptr q = p->shared_from_this(); - BOOST_TEST(p == q); - BOOST_TEST(!(p < q) && !(q < p)); + try + { + boost::shared_ptr q = p->shared_from_this(); + BOOST_TEST(p == q); + BOOST_TEST(!(p < q) && !(q < p)); + } + catch( boost::bad_weak_ptr const & ) + { + BOOST_ERROR( "p->shared_from_this() failed" ); + } V v2(*p); try { boost::shared_ptr r = v2.shared_from_this(); - BOOST_TEST( p < r || r < p ); - BOOST_TEST( r.get() == &v2 ); + BOOST_ERROR("v2.shared_from_this() failed to throw"); } - catch(boost::bad_weak_ptr const &) + catch( boost::bad_weak_ptr const & ) { } @@ -147,7 +160,7 @@ void test3() BOOST_TEST(p == r); BOOST_TEST(!(p < r) && !(r < p)); } - catch(boost::bad_weak_ptr const &) + catch( boost::bad_weak_ptr const & ) { BOOST_ERROR("p->shared_from_this() threw bad_weak_ptr after *p = V()"); } diff --git a/test/shared_ptr_move_test.cpp b/test/shared_ptr_move_test.cpp index 8814d3d..bd785e4 100644 --- a/test/shared_ptr_move_test.cpp +++ b/test/shared_ptr_move_test.cpp @@ -8,6 +8,8 @@ // http://www.boost.org/LICENSE_1_0.txt // +#if defined( BOOST_HAS_RVALUE_REFS ) + #include #include @@ -93,3 +95,12 @@ int main() return boost::report_errors(); } + +#else // !defined( BOOST_HAS_RVALUE_REFS ) + +int main() +{ + return 0; +} + +#endif From 31e06b4a1d2bb84af98d6a9bd643016ac5831299 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 10 Mar 2009 18:26:57 +0000 Subject: [PATCH 043/140] Merge [51643] to release. Fixes #2813. [SVN r51688] --- include/boost/smart_ptr/shared_ptr.hpp | 27 +++--- test/Jamfile.v2 | 4 + test/sp_recursive_assign2_rv_test.cpp | 114 +++++++++++++++++++++++ test/sp_recursive_assign2_test.cpp | 122 +++++++++++++++++++++++++ test/sp_recursive_assign_rv_test.cpp | 114 +++++++++++++++++++++++ test/sp_recursive_assign_test.cpp | 122 +++++++++++++++++++++++++ 6 files changed, 487 insertions(+), 16 deletions(-) create mode 100644 test/sp_recursive_assign2_rv_test.cpp create mode 100644 test/sp_recursive_assign2_test.cpp create mode 100644 test/sp_recursive_assign_rv_test.cpp create mode 100644 test/sp_recursive_assign_test.cpp diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 0812c04..0ce3b97 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -198,19 +198,7 @@ public: boost::detail::sp_enable_shared_from_this( this, 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 +// generated copy constructor, destructor are fine template explicit shared_ptr(weak_ptr const & r): pn(r.pn) // may throw @@ -301,13 +289,20 @@ public: #endif // BOOST_NO_AUTO_PTR -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + // assignment + + shared_ptr & operator=( shared_ptr const & r ) // never throws + { + this_type(r).swap(*this); + return *this; + } + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400) template shared_ptr & operator=(shared_ptr const & r) // never throws { - px = r.px; - pn = r.pn; // shared_count::op= doesn't throw + this_type(r).swap(*this); return *this; } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 34cd5f1..c862197 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -52,5 +52,9 @@ import testing ; [ run esft_second_ptr_test.cpp ] [ run make_shared_esft_test.cpp ] [ run allocate_shared_esft_test.cpp ] + [ run sp_recursive_assign_test.cpp ] + [ run sp_recursive_assign2_test.cpp ] + [ run sp_recursive_assign_rv_test.cpp ] + [ run sp_recursive_assign2_rv_test.cpp ] ; } diff --git a/test/sp_recursive_assign2_rv_test.cpp b/test/sp_recursive_assign2_rv_test.cpp new file mode 100644 index 0000000..e450c72 --- /dev/null +++ b/test/sp_recursive_assign2_rv_test.cpp @@ -0,0 +1,114 @@ +// +// sp_recursive_assign2_rv_test.cpp +// +// Copyright 2009 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 X +{ +public: + + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const& ); +}; + +int X::instances = 0; + +class Y +{ +public: + + static int instances; + + Y() + { + ++instances; + } + + ~Y() + { + --instances; + } + +private: + + Y( Y const& ); +}; + +int Y::instances = 0; + +static boost::shared_ptr s_pv; + +class Z +{ +public: + + static int instances; + + Z() + { + ++instances; + } + + ~Z() + { + --instances; + s_pv = boost::shared_ptr( new Y ); + } + +private: + + Z( Z const& ); +}; + +int Z::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + s_pv = boost::shared_ptr( new Z ); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 1 ); + + s_pv = boost::shared_ptr( new X ); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 1 ); + BOOST_TEST( Z::instances == 0 ); + + s_pv = boost::shared_ptr(); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + return boost::report_errors(); +} diff --git a/test/sp_recursive_assign2_test.cpp b/test/sp_recursive_assign2_test.cpp new file mode 100644 index 0000000..ef6fa52 --- /dev/null +++ b/test/sp_recursive_assign2_test.cpp @@ -0,0 +1,122 @@ +// +// sp_recursive_assign2_test.cpp +// +// Copyright 2009 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 X +{ +public: + + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const& ); +}; + +int X::instances = 0; + +class Y +{ +public: + + static int instances; + + Y() + { + ++instances; + } + + ~Y() + { + --instances; + } + +private: + + Y( Y const& ); +}; + +int Y::instances = 0; + +static boost::shared_ptr s_pv; + +class Z +{ +public: + + static int instances; + + Z() + { + ++instances; + } + + ~Z() + { + --instances; + + boost::shared_ptr pv( new Y ); + s_pv = pv; + } + +private: + + Z( Z const& ); +}; + +int Z::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + { + boost::shared_ptr pv( new Z ); + s_pv = pv; + } + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 1 ); + + { + boost::shared_ptr pv( new X ); + s_pv = pv; + } + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 1 ); + BOOST_TEST( Z::instances == 0 ); + + s_pv.reset(); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + return boost::report_errors(); +} diff --git a/test/sp_recursive_assign_rv_test.cpp b/test/sp_recursive_assign_rv_test.cpp new file mode 100644 index 0000000..8d80e72 --- /dev/null +++ b/test/sp_recursive_assign_rv_test.cpp @@ -0,0 +1,114 @@ +// +// sp_recursive_assign_rv_test.cpp +// +// Copyright 2009 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 X +{ +public: + + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const& ); +}; + +int X::instances = 0; + +class Y +{ +public: + + static int instances; + + Y() + { + ++instances; + } + + ~Y() + { + --instances; + } + +private: + + Y( Y const& ); +}; + +int Y::instances = 0; + +static boost::shared_ptr s_pv; + +class Z +{ +public: + + static int instances; + + Z() + { + ++instances; + } + + ~Z() + { + --instances; + s_pv = boost::shared_ptr( new Y ); + } + +private: + + Z( Z const& ); +}; + +int Z::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + s_pv = boost::shared_ptr( new Z ); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 1 ); + + s_pv = boost::shared_ptr( new X ); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 1 ); + BOOST_TEST( Z::instances == 0 ); + + s_pv = boost::shared_ptr(); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + return boost::report_errors(); +} diff --git a/test/sp_recursive_assign_test.cpp b/test/sp_recursive_assign_test.cpp new file mode 100644 index 0000000..0f36891 --- /dev/null +++ b/test/sp_recursive_assign_test.cpp @@ -0,0 +1,122 @@ +// +// sp_recursive_assign_test.cpp +// +// Copyright 2009 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 X +{ +public: + + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const& ); +}; + +int X::instances = 0; + +class Y +{ +public: + + static int instances; + + Y() + { + ++instances; + } + + ~Y() + { + --instances; + } + +private: + + Y( Y const& ); +}; + +int Y::instances = 0; + +static boost::shared_ptr s_pv; + +class Z +{ +public: + + static int instances; + + Z() + { + ++instances; + } + + ~Z() + { + --instances; + + boost::shared_ptr pv( new Y ); + s_pv = pv; + } + +private: + + Z( Z const& ); +}; + +int Z::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + { + boost::shared_ptr pv( new Z ); + s_pv = pv; + } + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 1 ); + + { + boost::shared_ptr pv( new X ); + s_pv = pv; + } + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 1 ); + BOOST_TEST( Z::instances == 0 ); + + s_pv.reset(); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + return boost::report_errors(); +} From 1742c37942455c617cf74dd48e41621ef3f2594e Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Wed, 11 Mar 2009 15:08:14 +0000 Subject: [PATCH 044/140] Merged [51699] and [51700] from trunk to release. Closes #1897 [SVN r51703] --- make_shared.html | 119 ++++++++++++++++++ shared_ptr.htm | 309 ++++++++++++++++++++++++----------------------- smart_ptr.htm | 159 ++++++++++++------------ 3 files changed, 361 insertions(+), 226 deletions(-) create mode 100644 make_shared.html diff --git a/make_shared.html b/make_shared.html new file mode 100644 index 0000000..e47fe2a --- /dev/null +++ b/make_shared.html @@ -0,0 +1,119 @@ + + + + make_shared and allocate_shared + + + +

boost.png (6897 bytes)make_shared and allocate_shared function templates

+

Introduction
+ Synopsis
+ Free Functions
+ Example
+

Introduction

+

Consistent use of shared_ptr + can eliminate the need to use an explicit delete, + but alone it provides no support in avoiding explicit new. + There have been repeated requests from users for a factory function that creates + an object of a given type and returns a shared_ptr to it. + Besides convenience and style, such a function is also exception safe and + considerably faster because it can use a single allocation for both the object + and its corresponding control block, eliminating a significant portion of + shared_ptr's construction overhead. + This eliminates one of the major efficiency complaints about shared_ptr. +

+

The header file <boost/make_shared.hpp> provides a family of overloaded function templates, + make_shared and allocate_shared, to address this need. + make_shared uses the global operator new to allocate memory, + whereas allocate_shared uses an user-supplied allocator, allowing finer control.

+

+ The rationale for choosing the name make_shared is that the expression + make_shared<Widget>() can be read aloud and conveys the intended meaning.

+

Synopsis

+
namespace boost {
+
+  template<typename T> class shared_ptr;
+
+  template<typename T>
+    shared_ptr<T> make_shared();
+
+  template<typename T, typename A>
+    shared_ptr<T> allocate_shared( A const & );
+
+#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )	// C++0x prototypes
+
+  template<typename T, typename... Args>
+    shared_ptr<T> make_shared( Args && ... args );
+
+  template<typename T, typename A, typename... Args>
+    shared_ptr<T> allocate_shared( A const & a, Args && ... args );
+
+#else // no C++0X support
+
+  template<typename T, typename Arg1 >
+    shared_ptr<T> make_shared( Arg1 const & arg1 );
+  template<typename T, typename Arg1, typename Arg2 >
+    shared_ptr<T> make_shared( Arg1 const & arg1, Arg2 const & arg2 );
+// ...
+  template<typename T, typename Arg1, typename Arg2, ..., typename ArgN >
+    shared_ptr<T> make_shared( Arg1 const & arg1, Arg2 const & arg2, ..., ArgN const & argN );
+
+  template<typename T, typename A, typename Arg1 >
+    shared_ptr<T> allocate_shared( A const & a, Arg1 const & arg1 );
+  template<typename T, typename A, typename Arg1, typename Arg2 >
+    shared_ptr<T> allocate_shared( Arg1 const & arg1, Arg2 const & arg2 );
+// ...
+  template<typename T, typename A, typename Arg1, typename Arg2, ..., typename ArgN >
+    shared_ptr<T> allocate_shared( A const & a, Arg1 const & arg1, Arg2 const & arg2, ..., ArgN const & argN );
+
+#endif
+}
+

Free Functions

+
template<class T, class... Args>
+    shared_ptr<T> make_shared( Args && ... args );
+template<class T, class A, class... Args>
+    shared_ptr<T> allocate_shared( A const & a, Args && ... args );
+
+

Requires: The expression new( pv ) T( std::forward<Args>(args)... ), + where pv is a void* pointing to storage suitable + to hold an object of type T, + shall be well-formed. A shall be an Allocator, + as described in section 20.1.5 (Allocator requirements) of the C++ Standard. + The copy constructor and destructor of A shall not throw.

+

Effects: Allocates memory suitable for an object of type T + and constructs an object in it via the placement new expression new( pv ) T() + or new( pv ) T( std::forward<Args>(args)... ). + allocate_shared uses a copy of a to allocate memory. + If an exception is thrown, has no effect.

+

Returns: A shared_ptr instance that stores and owns the address + of the newly constructed object of type T.

+

Postconditions: get() != 0 && use_count() == 1.

+

Throws: bad_alloc, or an exception thrown from A::allocate + or the constructor of T.

+

Notes: This implementation allocates the memory required for the + returned shared_ptr and an object of type T in a single + allocation. This provides efficiency equivalent to an intrusive smart pointer.

+

The prototypes shown above are used if your compiler supports rvalue references + and variadic templates. They perfectly forward the args parameters to + the constructors of T.

+

Otherwise, the implementation will fall back on + forwarding the arguments to the constructors of T as const references. + If you need to pass a non-const reference to a constructor of T, + you may do so by wrapping the parameter in a call to boost::ref. + In addition, you will be + limited to a maximum of 9 arguments (not counting the allocator argument of + allocate_shared).

+
+

Example

+
boost::shared_ptr<std::string> x = boost::make_shared<std::string>("hello, world!");
+std::cout << *x;
+
+

+ $Date: 2008-05-19 15:42:39 -0400 (Mon, 19 May 2008) $

+

Copyright 2008 Peter Dimov. Copyright 2008 Frank Mori Hess. + 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 5b4444f..77e1fa8 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -19,54 +19,54 @@ Smart Pointer Timings
Programming Techniques

Introduction

-

The shared_ptr class template stores a pointer to a dynamically allocated - object, typically with a C++ new-expression. The object pointed to is - guaranteed to be deleted when the last shared_ptr pointing to it is +

The shared_ptr class template stores a pointer to a dynamically allocated + object, typically with a C++ new-expression. The object pointed to is + guaranteed to be deleted when the last shared_ptr pointing to it is destroyed or reset. See the example.

-

Every shared_ptr meets the CopyConstructible and Assignable - requirements of the C++ Standard Library, and so can be used in standard - library containers. Comparison operators are supplied so that shared_ptr +

Every shared_ptr meets the CopyConstructible and Assignable + requirements of the C++ Standard Library, and so can be used in standard + library containers. Comparison operators are supplied so that shared_ptr works with the standard library's associative containers.

-

Normally, a shared_ptr cannot correctly hold a pointer to a dynamically - allocated array. See shared_array for +

Normally, a shared_ptr cannot correctly hold a pointer to a dynamically + allocated array. See shared_array for that usage.

-

Because the implementation uses reference counting, cycles of shared_ptr instances +

Because the implementation uses reference counting, cycles of shared_ptr instances will not be reclaimed. For example, if main() holds a shared_ptr to A, which directly or indirectly holds a shared_ptr back to A, - A's use count will be 2. Destruction of the original shared_ptr will + A's use count will be 2. Destruction of the original shared_ptr will leave A dangling with a use count of 1. Use weak_ptr to "break cycles."

-

The class template is parameterized on T, the type of the object pointed - to. shared_ptr and most of its member functions place no +

The class template is parameterized on T, the type of the object pointed + to. shared_ptr and most of its member functions place no requirements on T; it is allowed to be an incomplete type, or void. Member functions that do place additional requirements (constructors, reset) are explicitly documented below.

shared_ptr<T> can be implicitly converted to shared_ptr<U> - whenever T* can be implicitly converted to U*. - In particular, shared_ptr<T> is implicitly convertible + whenever T* can be implicitly converted to U*. + In particular, shared_ptr<T> is implicitly convertible to shared_ptr<T const>, to shared_ptr<U> where U is an accessible base of T, and to shared_ptr<void>.

-

shared_ptr is now part of TR1, the first C++ - Library Technical Report. The latest draft of TR1 is available +

shared_ptr is now part of TR1, the first C++ + Library Technical Report. The latest draft of TR1 is available at the following location:

http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf (1.36Mb PDF)

-

This implementation conforms to the TR1 specification, with the only exception +

This implementation conforms to the TR1 specification, with the only exception that it resides in namespace boost instead of std::tr1.

Best Practices

-

A simple guideline that nearly eliminates the possibility of memory leaks is: +

A simple guideline that nearly eliminates the possibility of memory leaks is: always use a named smart pointer variable to hold the result of new. - Every occurence of the new keyword in the code should have the + Every occurence of the new keyword in the code should have the form:

shared_ptr<T> p(new Y);

It is, of course, acceptable to use another smart pointer in place of shared_ptr - above; having T and Y be the same type, or + above; having T and Y be the same type, or passing arguments to Y's constructor is also OK.

-

If you observe this guideline, it naturally follows that you will have no - explicit deletes; try/catch constructs will +

If you observe this guideline, it naturally follows that you will have no + explicit deletes; try/catch constructs will be rare.

-

Avoid using unnamed shared_ptr temporaries to save typing; to +

Avoid using unnamed shared_ptr temporaries to save typing; to see why this is dangerous, consider this example:

void f(shared_ptr<int>, int);
 int g();
@@ -83,13 +83,18 @@ void bad()
 }
 

The function ok follows the guideline to the letter, whereas - bad constructs the temporary shared_ptr in place, - admitting the possibility of a memory leak. Since function arguments are - evaluated in unspecified order, it is possible for new int(2) to + bad constructs the temporary shared_ptr in place, + admitting the possibility of a memory leak. Since function arguments are + evaluated in unspecified order, it is possible for new int(2) to be evaluated first, g() second, and we may never get to the - shared_ptr constructor if g throws an exception. + shared_ptr constructor if g throws an exception. See Herb Sutter's treatment (also here) of the issue for more information.

+

The exception safety problem described above may also be eliminated by using + the make_shared + or allocate_shared + factory functions defined in boost/make_shared.hpp. These factory functions also provide + an efficiency benefit by consolidating allocations.

Synopsis

namespace boost {
 
@@ -115,7 +120,7 @@ void bad()
       template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
       template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
 
-      shared_ptr & operator=(shared_ptr const & r); // never throws  
+      shared_ptr & operator=(shared_ptr const & r); // never throws
       template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
       template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
 
@@ -178,32 +183,32 @@ void bad()
 			

Postconditions: use_count() == 0 && get() == 0.

Throws: nothing.

-

[The nothrow guarantee is important, since reset() is specified - in terms of the default constructor; this implies that the constructor must not +

[The nothrow guarantee is important, since reset() is specified + in terms of the default constructor; this implies that the constructor must not allocate memory.]

template<class Y> explicit shared_ptr(Y * p);

Requirements: p must be convertible to T *. Y - must be a complete type. The expression delete p must be + must be a complete type. The expression delete p must be well-formed, must not invoke undefined behavior, and must not throw exceptions.

Effects: Constructs a shared_ptr that owns the pointer p.

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

-

Throws: std::bad_alloc, or an implementation-defined +

Throws: std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

-

Exception safety: If an exception is thrown, delete p is +

Exception safety: If an exception is thrown, delete p is called.

-

Notes: p must be a pointer to an object that was +

Notes: p must be a pointer to an object that was allocated via a C++ new expression or be 0. The postcondition that use count is 1 holds even if p is 0; invoking delete on a pointer that has a value of 0 is harmless.

-

[This constructor has been changed to a template in order to remember the actual - pointer type passed. The destructor will call delete with the - same pointer, complete with its original type, even when T does +

[This constructor has been changed to a template in order to remember the actual + pointer type passed. The destructor will call delete with the + same pointer, complete with its original type, even when T does not have a virtual destructor, or is void.

-

The optional intrusive counting support has been dropped as it exposes too much - implementation details and doesn't interact well with weak_ptr. +

The optional intrusive counting support has been dropped as it exposes too much + implementation details and doesn't interact well with weak_ptr. The current implementation uses a different mechanism, enable_shared_from_this, to solve the "shared_ptr from this" problem.]

@@ -212,46 +217,46 @@ void bad() template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);

Requirements: p must be convertible to T *. D - must be CopyConstructible. The copy constructor and destructor - of D must not throw. The expression d(p) must be + must be CopyConstructible. The copy constructor and destructor + of D must not throw. The expression d(p) must be well-formed, must not invoke undefined behavior, and must not throw exceptions. - A must be an Allocator, as described in section 20.1.5 (Allocator + A must be an Allocator, as described in section 20.1.5 (Allocator requirements) of the C++ Standard.

Effects: Constructs a shared_ptr that owns the pointer - p and the deleter d. The second constructor allocates + p and the deleter d. The second constructor allocates memory using a copy of a.

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

-

Throws: std::bad_alloc, or an implementation-defined +

Throws: std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

Exception safety: If an exception is thrown, d(p) is called.

-

Notes: When the the time comes to delete the object pointed to by p, +

Notes: When the the time comes to delete the object pointed to by p, the stored copy of d is invoked with the stored copy of p as an argument.

[Custom deallocators allow a factory function returning a shared_ptr - to insulate the user from its memory allocation strategy. Since the deallocator - is not part of the type, changing the allocation strategy does not break source - or binary compatibility, and does not require a client recompilation. For + to insulate the user from its memory allocation strategy. Since the deallocator + is not part of the type, changing the allocation strategy does not break source + or binary compatibility, and does not require a client recompilation. For example, a "no-op" deallocator is useful when returning a shared_ptr to a statically allocated object, and other variations allow a shared_ptr to be used as a wrapper for another smart pointer, easing interoperability.

The support for custom deallocators does not impose significant overhead. Other shared_ptr features still require a deallocator to be kept.

-

The requirement that the copy constructor of D does not throw comes from - the pass by value. If the copy constructor throws, the pointer is leaked. +

The requirement that the copy constructor of D does not throw comes from + the pass by value. If the copy constructor throws, the pointer is leaked. Removing the requirement requires a pass by (const) reference.

-

The main problem with pass by reference lies in its interaction with rvalues. A - const reference may still cause a copy, and will require a const operator(). A - non-const reference won't bind to an rvalue at all. A good solution to this +

The main problem with pass by reference lies in its interaction with rvalues. A + const reference may still cause a copy, and will require a const operator(). A + non-const reference won't bind to an rvalue at all. A good solution to this problem is the rvalue reference proposed in N1377/N1385.]

shared_ptr(shared_ptr const & r); // never throws
 template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
-

Effects: If r is empty, constructs an empty shared_ptr; +

Effects: If r is empty, constructs an empty shared_ptr; otherwise, constructs a shared_ptr that shares ownership with r.

-

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

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

Throws: nothing.

@@ -268,21 +273,21 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r); // never r and stores a copy of the pointer stored in r.

Postconditions: use_count() == r.use_count().

Throws: bad_weak_ptr when r.use_count() == 0.

-

Exception safety: If an exception is thrown, the constructor has no +

Exception safety: If an exception is thrown, the constructor has no effect.

template<class Y> shared_ptr(std::auto_ptr<Y> & r);

Effects: Constructs a shared_ptr, as if by storing a copy of r.release().

Postconditions: use_count() == 1.

-

Throws: std::bad_alloc, or an implementation-defined +

Throws: std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

-

Exception safety: If an exception is thrown, the constructor has no +

Exception safety: If an exception is thrown, the constructor has no effect.

-

[This constructor takes a the source auto_ptr by reference and - not by value, and cannot accept auto_ptr temporaries. This is - by design, as the constructor offers the strong guarantee; an rvalue reference +

[This constructor takes a the source auto_ptr by reference and + not by value, and cannot accept auto_ptr temporaries. This is + by design, as the constructor offers the strong guarantee; an rvalue reference would solve this problem, too.]

destructor

~shared_ptr(); // never throws
@@ -290,15 +295,15 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r); // never

Effects:

  • - If *this is empty, or shares ownership with - another shared_ptr instance (use_count() > 1), + If *this is empty, or shares ownership with + another shared_ptr instance (use_count() > 1), there are no side effects.
  • - Otherwise, if *this owns a pointer p + Otherwise, if *this owns a pointer p and a deleter d, d(p) is called.
  • - Otherwise, *this owns a pointer p, + Otherwise, *this owns a pointer p, and delete p is called.

Throws: nothing.

@@ -309,9 +314,9 @@ template<class Y> shared_ptr & operator=(std::auto_ptr<Y> &

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

Returns: *this.

-

Notes: The use count updates caused by the temporary object construction - and destruction are not considered observable side effects, and the - implementation is free to meet the effects (and the implied guarantees) via +

Notes: The use count updates caused by the temporary object construction + and destruction are not considered observable side effects, and the + implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary. In particular, in the example:

shared_ptr<int> p(new int);
 shared_ptr<void> q(p);
@@ -365,32 +370,32 @@ q = p;
 		

Returns: use_count() == 1.

Throws: nothing.

-

Notes: unique() may be faster than use_count(). - If you are using unique() to implement copy on write, do not rely +

Notes: unique() may be faster than use_count(). + If you are using unique() to implement copy on write, do not rely on a specific value when the stored pointer is zero.

use_count

long use_count() const; // never throws
-

Returns: the number of shared_ptr objects, *this included, +

Returns: the number of shared_ptr objects, *this included, that share ownership with *this, or 0 when *this is empty.

Throws: nothing.

-

Notes: use_count() is not necessarily efficient. Use only +

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

conversions

operator unspecified-bool-type () const; // never throws
-

Returns: an unspecified value that, when used in boolean contexts, is +

Returns: an unspecified value that, when used in boolean contexts, is equivalent to get() != 0.

Throws: nothing.

-

Notes: This conversion operator allows shared_ptr objects to be - used in boolean contexts, like if (p && p->valid()) {}. - The actual target type is typically a pointer to a member function, avoiding +

Notes: This conversion operator allows shared_ptr objects to be + used in boolean contexts, like if (p && p->valid()) {}. + The actual target type is typically a pointer to a member function, avoiding many of the implicit conversion pitfalls.

-

[The conversion to bool is not merely syntactic sugar. It allows shared_ptrs +

[The conversion to bool is not merely syntactic sugar. It allows shared_ptrs to be declared in conditions when using dynamic_pointer_cast or weak_ptr::lock.]

swap

@@ -422,19 +427,19 @@ q = p; operator< is a strict weak ordering as described in section 25.3 [lib.alg.sorting] of the C++ standard;
  • - under the equivalence relation defined by operator<, !(a - < b) && !(b < a), two shared_ptr instances + under the equivalence relation defined by operator<, !(a + < b) && !(b < a), two shared_ptr instances are equivalent if and only if they share ownership or are both empty.
  • Throws: nothing.

    -

    Notes: Allows shared_ptr objects to be used as keys in +

    Notes: Allows shared_ptr objects to be used as keys in associative containers.

    [Operator< has been preferred over a std::less specialization for consistency and legality reasons, as std::less - is required to return the results of operator<, and many + is required to return the results of operator<, and many standard algorithms use operator< instead of std::less - for comparisons when a predicate is not supplied. Composite objects, like std::pair, - also implement their operator< in terms of their contained + for comparisons when a predicate is not supplied. Composite objects, like std::pair, + also implement their operator< in terms of their contained subobjects' operator<.

    The rest of the comparison operators are omitted by design.]

    swap

    @@ -443,11 +448,11 @@ q = p;

    Effects: Equivalent to a.swap(b).

    Throws: nothing.

    -

    Notes: Matches the interface of std::swap. Provided as an aid to +

    Notes: Matches the interface of std::swap. Provided as an aid to generic programming.

    [swap is defined in the same namespace as shared_ptr - as this is currently the only legal way to supply a swap function + as this is currently the only legal way to supply a swap function that has a chance to be used by the standard library.]

    get_pointer

    template<class T>
    @@ -464,13 +469,13 @@ q = p;
     		

    Requires: The expression static_cast<T*>(r.get()) must be well-formed.

    -

    Returns: If r is empty, an empty shared_ptr<T>; +

    Returns: If r is empty, an empty shared_ptr<T>; otherwise, a shared_ptr<T> object that stores a copy of static_cast<T*>(r.get()) and shares ownership with r.

    Throws: nothing.

    Notes: the seemingly equivalent expression

    shared_ptr<T>(static_cast<T*>(r.get()))

    -

    will eventually result in undefined behavior, attempting to delete the same +

    will eventually result in undefined behavior, attempting to delete the same object twice.

    const_pointer_cast

    @@ -479,13 +484,13 @@ q = p;

    Requires: The expression const_cast<T*>(r.get()) must be well-formed.

    -

    Returns: If r is empty, an empty shared_ptr<T>; +

    Returns: If r is empty, an empty shared_ptr<T>; otherwise, a shared_ptr<T> object that stores a copy of const_cast<T*>(r.get()) and shares ownership with r.

    Throws: nothing.

    Notes: the seemingly equivalent expression

    shared_ptr<T>(const_cast<T*>(r.get()))

    -

    will eventually result in undefined behavior, attempting to delete the same +

    will eventually result in undefined behavior, attempting to delete the same object twice.

    dynamic_pointer_cast

    @@ -498,14 +503,14 @@ q = p;
    • When dynamic_cast<T*>(r.get()) returns a nonzero value, a - shared_ptr<T> object that stores a copy of it and shares + shared_ptr<T> object that stores a copy of it and shares ownership with r;
    • Otherwise, an empty shared_ptr<T> object.

    Throws: nothing.

    Notes: the seemingly equivalent expression

    shared_ptr<T>(dynamic_cast<T*>(r.get()))

    -

    will eventually result in undefined behavior, attempting to delete the same +

    will eventually result in undefined behavior, attempting to delete the same object twice.

    operator<<

    @@ -520,41 +525,41 @@ q = p; D * get_deleter(shared_ptr<T> const & p);

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

    Throws: nothing.

    Example

    -

    See shared_ptr_example.cpp for a +

    See shared_ptr_example.cpp for a complete example program. The program builds a std::vector and std::set of shared_ptr objects.

    Note that after the containers have been populated, some of the shared_ptr - objects will have a use count of 1 rather than a use count of 2, since the set - is a std::set rather than a std::multiset, and thus does not - contain duplicate entries. Furthermore, the use count may be even higher at - various times while push_back and insert container operations are - performed. More complicated yet, the container operations may throw exceptions - under a variety of circumstances. Getting the memory management and exception + objects will have a use count of 1 rather than a use count of 2, since the set + is a std::set rather than a std::multiset, and thus does not + contain duplicate entries. Furthermore, the use count may be even higher at + various times while push_back and insert container operations are + performed. More complicated yet, the container operations may throw exceptions + under a variety of circumstances. Getting the memory management and exception handling in this example right without a smart pointer would be a nightmare.

    Handle/Body Idiom

    -

    One common usage of shared_ptr is to implement a handle/body (also called - pimpl) idiom which avoids exposing the body (implementation) in the header +

    One common usage of shared_ptr is to implement a handle/body (also called + pimpl) idiom which avoids exposing the body (implementation) in the header file.

    The shared_ptr_example2_test.cpp - sample program includes a header file, shared_ptr_example2.hpp, - which uses a shared_ptr<> to an incomplete type to hide the - implementation. The instantiation of member functions which require a complete + sample program includes a header file, shared_ptr_example2.hpp, + which uses a shared_ptr<> to an incomplete type to hide the + implementation. The instantiation of member functions which require a complete type occurs in the shared_ptr_example2.cpp - implementation file. Note that there is no need for an explicit destructor. - Unlike ~scoped_ptr, ~shared_ptr does not require that T be a complete + implementation file. Note that there is no need for an explicit destructor. + Unlike ~scoped_ptr, ~shared_ptr does not require that T be a complete type.

    Thread Safety

    -

    shared_ptr objects offer the same level of thread safety as - built-in types. A shared_ptr instance can be "read" (accessed +

    shared_ptr objects offer the same level of thread safety as + built-in types. A shared_ptr instance can be "read" (accessed using only const operations) simultaneously by multiple threads. Different shared_ptr instances can be "written to" (accessed using mutable operations such as operator= - or reset) simultaneosly by multiple threads (even - when these instances are copies, and share the same reference count + or reset) simultaneosly by multiple threads (even + when these instances are copies, and share the same reference count underneath.)

    Any other simultaneous accesses result in undefined behavior.

    Examples:

    @@ -601,7 +606,7 @@ p3.reset(new int(1)); p3.reset(new int(2)); // undefined, multiple writes

     

    -

    Starting with Boost release 1.33.0, shared_ptr uses a lock-free +

    Starting with Boost release 1.33.0, shared_ptr uses a lock-free implementation on the following platforms:

    • @@ -614,75 +619,75 @@ p3.reset(new int(2)); // undefined, multiple writes GNU GCC on PowerPC;
    • Windows.
    -

    If your program is single-threaded and does not link to any libraries that might +

    If your program is single-threaded and does not link to any libraries that might have used shared_ptr in its default configuration, you can - #define the macro BOOST_SP_DISABLE_THREADS on a + #define the macro BOOST_SP_DISABLE_THREADS on a project-wide basis to switch to ordinary non-atomic reference count updates.

    -

    (Defining BOOST_SP_DISABLE_THREADS in some, but not all, - translation units is technically a violation of the One Definition Rule and - undefined behavior. Nevertheless, the implementation attempts to do its best to - accommodate the request to use non-atomic updates in those translation units. +

    (Defining BOOST_SP_DISABLE_THREADS in some, but not all, + translation units is technically a violation of the One Definition Rule and + undefined behavior. Nevertheless, the implementation attempts to do its best to + accommodate the request to use non-atomic updates in those translation units. No guarantees, though.)

    -

    You can define the macro BOOST_SP_USE_PTHREADS to turn off the - lock-free platform-specific implementation and fall back to the generic pthread_mutex_t-based +

    You can define the macro BOOST_SP_USE_PTHREADS to turn off the + lock-free platform-specific implementation and fall back to the generic pthread_mutex_t-based code.

    Frequently Asked Questions

    -

    Q. There are several variations of shared pointers, with different - tradeoffs; why does the smart pointer library supply only a single - implementation? It would be useful to be able to experiment with each type so +

    Q. There are several variations of shared pointers, with different + tradeoffs; why does the smart pointer library supply only a single + implementation? It would be useful to be able to experiment with each type so as to find the most suitable for the job at hand?

    - A. An important goal of shared_ptr is to provide a - standard shared-ownership pointer. Having a single pointer type is important - for stable library interfaces, since different shared pointers typically cannot - interoperate, i.e. a reference counted pointer (used by library A) cannot share + A. An important goal of shared_ptr is to provide a + standard shared-ownership pointer. Having a single pointer type is important + for stable library interfaces, since different shared pointers typically cannot + interoperate, i.e. a reference counted pointer (used by library A) cannot share ownership with a linked pointer (used by library B.)

    -

    Q. Why doesn't shared_ptr have template parameters supplying +

    Q. Why doesn't shared_ptr have template parameters supplying traits or policies to allow extensive user customization?

    - A. Parameterization discourages users. The shared_ptr template is - carefully crafted to meet common needs without extensive parameterization. Some - day a highly configurable smart pointer may be invented that is also very easy - to use and very hard to misuse. Until then, shared_ptr is the smart - pointer of choice for a wide range of applications. (Those interested in policy + A. Parameterization discourages users. The shared_ptr template is + carefully crafted to meet common needs without extensive parameterization. Some + day a highly configurable smart pointer may be invented that is also very easy + to use and very hard to misuse. Until then, shared_ptr is the smart + pointer of choice for a wide range of applications. (Those interested in policy based smart pointers should read Modern C++ Design by Andrei Alexandrescu.)

    -

    Q. I am not convinced. Default parameters can be used where appropriate +

    Q. I am not convinced. Default parameters can be used where appropriate to hide the complexity. Again, why not policies?

    - A. Template parameters affect the type. See the answer to the first + A. Template parameters affect the type. See the answer to the first question above.

    Q. Why doesn't shared_ptr use a linked list implementation?

    - A. A linked list implementation does not offer enough advantages to + A. A linked list implementation does not offer enough advantages to offset the added cost of an extra pointer. See timings - page. In addition, it is expensive to make a linked list implementation thread + page. In addition, it is expensive to make a linked list implementation thread safe.

    -

    Q. Why doesn't shared_ptr (or any of the other Boost smart +

    Q. Why doesn't shared_ptr (or any of the other Boost smart pointers) supply an automatic conversion to T*?

    A. Automatic conversion is believed to be too error prone.

    Q. Why does shared_ptr supply use_count()?

    - A. As an aid to writing test cases and debugging displays. One of the - progenitors had use_count(), and it was useful in tracking down bugs in a + A. As an aid to writing test cases and debugging displays. One of the + progenitors had use_count(), and it was useful in tracking down bugs in a complex project that turned out to have cyclic-dependencies.

    Q. Why doesn't shared_ptr specify complexity requirements?

    - A. Because complexity requirements limit implementors and complicate the - specification without apparent benefit to shared_ptr users. For example, - error-checking implementations might become non-conforming if they had to meet + A. Because complexity requirements limit implementors and complicate the + specification without apparent benefit to shared_ptr users. For example, + error-checking implementations might become non-conforming if they had to meet stringent complexity requirements.

    Q. Why doesn't shared_ptr provide a release() function?

    - A. shared_ptr cannot give away ownership unless it's unique() + A. shared_ptr cannot give away ownership unless it's unique() because the other copy will still destroy the object.

    Consider:

    shared_ptr<int> a(new int);
    @@ -692,25 +697,25 @@ int * p = a.release();
     
     // Who owns p now? b will still call delete on it in its destructor.
    -

    Furthermore, the pointer returned by release() would be difficult - to deallocate reliably, as the source shared_ptr could have been created +

    Furthermore, the pointer returned by release() would be difficult + to deallocate reliably, as the source shared_ptr could have been created with a custom deleter.

    -

    Q. Why is operator->() const, but its return value is a +

    Q. Why is operator->() const, but its return value is a non-const pointer to the element type?

    - A. Shallow copy pointers, including raw pointers, typically don't - propagate constness. It makes little sense for them to do so, as you can always - obtain a non-const pointer from a const one and then proceed to modify the - object through it.shared_ptr is "as close to raw pointers as possible + A. Shallow copy pointers, including raw pointers, typically don't + propagate constness. It makes little sense for them to do so, as you can always + obtain a non-const pointer from a const one and then proceed to modify the + object through it.shared_ptr is "as close to raw pointers as possible but no closer".


    $Date$

    -

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, +

    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/smart_ptr.htm b/smart_ptr.htm index 497c63f..92ad2be 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -14,15 +14,15 @@ History and Acknowledgements
    References

    Introduction

    -

    Smart pointers are objects which store pointers to dynamically allocated (heap) - objects. They behave much like built-in C++ pointers except that they - automatically delete the object pointed to at the appropriate time. Smart - pointers are particularly useful in the face of exceptions as they ensure - proper destruction of dynamically allocated objects. They can also be used to +

    Smart pointers are objects which store pointers to dynamically allocated (heap) + objects. They behave much like built-in C++ pointers except that they + automatically delete the object pointed to at the appropriate time. Smart + pointers are particularly useful in the face of exceptions as they ensure + proper destruction of dynamically allocated objects. They can also be used to keep track of dynamically allocated objects shared by multiple owners.

    -

    Conceptually, smart pointers are seen as owning the object pointed to, and thus +

    Conceptually, smart pointers are seen as owning the object pointed to, and thus responsible for deletion of the object when it is no longer needed.

    -

    The smart pointer library provides five smart pointer class templates:

    +

    The smart pointer library provides six smart pointer class templates:

    @@ -38,7 +38,7 @@ - + @@ -58,126 +58,137 @@
    shared_ptr <boost/shared_ptr.hpp>Object ownership shared among multiple pointersObject ownership shared among multiple pointers.
    shared_array

    These templates are designed to complement the std::auto_ptr template.

    -

    They are examples of the "resource acquisition is initialization" idiom - described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition, +

    They are examples of the "resource acquisition is initialization" idiom + described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition, Section 14.4, Resource Management.

    -

    A test program, smart_ptr_test.cpp, is +

    Additionally, the smart pointer library provides efficient factory functions + for creating shared_ptr objects:

    +
    + + + + + + +
    make_shared and allocate_shared<boost/make_shared.hpp>Efficient creation of shared_ptr objects.
    +
    +

    A test program, smart_ptr_test.cpp, is provided to verify correct operation.

    -

    A page on compatibility with older versions of - the Boost smart pointer library describes some of the changes since earlier +

    A page on compatibility with older versions of + the Boost smart pointer library describes some of the changes since earlier versions of the smart pointer implementation.

    -

    A page on smart pointer timings will be of interest +

    A page on smart pointer timings will be of interest to those curious about performance issues.

    -

    A page on smart pointer programming techniques lists +

    A page on smart pointer programming techniques lists some advanced applications of shared_ptr and weak_ptr.

    Common Requirements

    -

    These smart pointer class templates have a template parameter, T, which - specifies the type of the object pointed to by the smart pointer. The behavior +

    These smart pointer class templates have a template parameter, T, which + specifies the type of the object pointed to by the smart pointer. The behavior of the smart pointer templates is undefined if the destructor or operator delete for objects of type T throw exceptions.

    -

    T may be an incomplete type at the point of smart pointer declaration. - Unless otherwise specified, it is required that T be a complete type at - points of smart pointer instantiation. Implementations are required to diagnose - (treat as an error) all violations of this requirement, including deletion of +

    T may be an incomplete type at the point of smart pointer declaration. + Unless otherwise specified, it is required that T be a complete type at + points of smart pointer instantiation. Implementations are required to diagnose + (treat as an error) all violations of this requirement, including deletion of an incomplete type. See the description of the checked_delete function template.

    -

    Note that shared_ptr does not have this restriction, as most of +

    Note that shared_ptr does not have this restriction, as most of its member functions do not require T to be a complete type.

    Rationale

    -

    The requirements on T are carefully crafted to maximize safety yet allow - handle-body (also called pimpl) and similar idioms. In these idioms a smart - pointer may appear in translation units where T is an incomplete type. - This separates interface from implementation and hides implementation from - translation units which merely use the interface. Examples described in the - documentation for specific smart pointers illustrate use of smart pointers in +

    The requirements on T are carefully crafted to maximize safety yet allow + handle-body (also called pimpl) and similar idioms. In these idioms a smart + pointer may appear in translation units where T is an incomplete type. + This separates interface from implementation and hides implementation from + translation units which merely use the interface. Examples described in the + documentation for specific smart pointers illustrate use of smart pointers in these idioms.

    -

    Note that scoped_ptr requires that T be a complete type at +

    Note that scoped_ptr requires that T be a complete type at destruction time, but shared_ptr does not.

    Exception Safety

    -

    Several functions in these smart pointer classes are specified as having "no - effect" or "no effect except such-and-such" if an exception is thrown. This - means that when an exception is thrown by an object of one of these classes, - the entire program state remains the same as it was prior to the function call - which resulted in the exception being thrown. This amounts to a guarantee that - there are no detectable side effects. Other functions never throw exceptions. - The only exception ever thrown by functions which do throw (assuming T meets - the common requirements) is std::bad_alloc, - and that is thrown only by functions which are explicitly documented as +

    Several functions in these smart pointer classes are specified as having "no + effect" or "no effect except such-and-such" if an exception is thrown. This + means that when an exception is thrown by an object of one of these classes, + the entire program state remains the same as it was prior to the function call + which resulted in the exception being thrown. This amounts to a guarantee that + there are no detectable side effects. Other functions never throw exceptions. + The only exception ever thrown by functions which do throw (assuming T meets + the common requirements) is std::bad_alloc, + 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-specification rationale.

    -

    All the smart pointer templates contain member functions which can never throw - exceptions, because they neither throw exceptions themselves nor call other +

    All the smart pointer templates contain member functions which can never throw + exceptions, because they neither throw exceptions themselves nor call other functions which may throw exceptions. These members are indicated by a comment: // never throws.

    -

    Functions which destroy objects of the pointed to type are prohibited from +

    Functions which destroy objects of the pointed to type are prohibited from throwing exceptions by the common requirements.

    History and Acknowledgements

    -

    January 2002. Peter Dimov reworked all four classes, adding features, fixing - bugs, and splitting them into four separate headers, and added weak_ptr. - See the compatibility page for a summary of the +

    January 2002. Peter Dimov reworked all four classes, adding features, fixing + bugs, and splitting them into four separate headers, and added weak_ptr. + See the compatibility page for a summary of the changes.

    -

    May 2001. Vladimir Prus suggested requiring a complete type on destruction. - Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman - Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and +

    May 2001. Vladimir Prus suggested requiring a complete type on destruction. + Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman + Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and others.

    November 1999. Darin Adler provided operator ==, operator !=, and std::swap and std::less specializations for shared types.

    September 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap

    -

    May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a +

    May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a number of suggestions resulting in numerous improvements.

    -

    October 1998. Beman Dawes proposed reviving the original semantics under the - names safe_ptr and counted_ptr, meeting of Per Andersson, Matt - Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar Kühl, - Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new - class names were finalized, it was decided that there was no need to exactly - follow the std::auto_ptr interface, and various function signatures and +

    October 1998. Beman Dawes proposed reviving the original semantics under the + names safe_ptr and counted_ptr, meeting of Per Andersson, Matt + Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar Kühl, + Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new + class names were finalized, it was decided that there was no need to exactly + follow the std::auto_ptr interface, and various function signatures and semantics were finalized.

    -

    Over the next three months, several implementations were considered for shared_ptr, - and discussed on the boost.org mailing list. - The implementation questions revolved around the reference count which must be - kept, either attached to the pointed to object, or detached elsewhere. Each of +

    Over the next three months, several implementations were considered for shared_ptr, + and discussed on the boost.org mailing list. + The implementation questions revolved around the reference count which must be + kept, either attached to the pointed to object, or detached elsewhere. Each of those variants have themselves two major variants:

    • - Direct detached: the shared_ptr contains a pointer to the object, and a pointer + Direct detached: the shared_ptr contains a pointer to the object, and a pointer to the count.
    • - Indirect detached: the shared_ptr contains a pointer to a helper object, which + Indirect detached: the shared_ptr contains a pointer to a helper object, which in turn contains a pointer to the object and the count.
    • Embedded attached: the count is a member of the object pointed to.
    • Placement attached: the count is attached via operator new manipulations.
    -

    Each implementation technique has advantages and disadvantages. We went so far - as to run various timings of the direct and indirect approaches, and found that - at least on Intel Pentium chips there was very little measurable difference. - Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar - Kühl suggested an elegant partial template specialization technique to allow - users to choose which implementation they preferred, and that was also +

    Each implementation technique has advantages and disadvantages. We went so far + as to run various timings of the direct and indirect approaches, and found that + at least on Intel Pentium chips there was very little measurable difference. + Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar + Kühl suggested an elegant partial template specialization technique to allow + users to choose which implementation they preferred, and that was also experimented with.

    -

    But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage +

    But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage users", and in the end we choose to supply only the direct implementation.

    Summer, 1994. Greg Colvin proposed to the C++ Standards Committee classes named auto_ptr and counted_ptr which were very similar to what we now call scoped_ptr - and shared_ptr. [Col-94] In one of the very few - cases where the Library Working Group's recommendations were not followed by - the full committee, counted_ptr was rejected and surprising + and shared_ptr. [Col-94] In one of the very few + cases where the Library Working Group's recommendations were not followed by + the full committee, counted_ptr was rejected and surprising transfer-of-ownership semantics were added to auto_ptr.

    References

    [Col-94] Gregory Colvin, - Exception Safe Smart Pointers, C++ committee document 94-168/N0555, + Exception Safe Smart Pointers, C++ committee document 94-168/N0555, July, 1994.

    [E&D-94] John R. Ellis & David L. Detlefs, - Safe, Efficient Garbage Collection for C++, Usenix Proceedings, - February, 1994. This paper includes an extensive discussion of weak pointers + Safe, Efficient Garbage Collection for C++, Usenix Proceedings, + February, 1994. This paper includes an extensive discussion of weak pointers and an extensive bibliography.


    $Date$

    -

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. +

    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.

    From 77971c6ff5f90fbe515f94ac0fa2c289477340de Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 18 Mar 2009 23:02:27 +0000 Subject: [PATCH 045/140] Merge [51686] to release. [SVN r51847] --- test/allocate_shared_test.cpp | 12 +++++++++--- test/make_shared_test.cpp | 12 +++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/test/allocate_shared_test.cpp b/test/allocate_shared_test.cpp index 97808c2..bdae793 100644 --- a/test/allocate_shared_test.cpp +++ b/test/allocate_shared_test.cpp @@ -1,6 +1,6 @@ -// allocate_shared_test.cpp +// allocate_shared_test.cpp // -// Copyright (c) 2007, 2008 Peter Dimov +// Copyright 2007-2009 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt or copy at @@ -19,11 +19,17 @@ private: X( X const & ); X & operator=( X const & ); - void * operator new( std::size_t ); + void * operator new( std::size_t n ) + { + // lack of this definition causes link errors on Comeau C++ + BOOST_ERROR( "private X::new called" ); + return ::operator new( n ); + } void operator delete( void * p ) { // lack of this definition causes link errors on MSVC + BOOST_ERROR( "private X::delete called" ); ::operator delete( p ); } diff --git a/test/make_shared_test.cpp b/test/make_shared_test.cpp index 474d1c5..9ebc3fa 100644 --- a/test/make_shared_test.cpp +++ b/test/make_shared_test.cpp @@ -1,6 +1,6 @@ -// make_shared_test.cpp +// make_shared_test.cpp // -// Copyright (c) 2007, 2008 Peter Dimov +// Copyright 2007-2009 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt or copy at @@ -19,11 +19,17 @@ private: X( X const & ); X & operator=( X const & ); - void * operator new( std::size_t ); + void * operator new( std::size_t n ) + { + // lack of this definition causes link errors on Comeau C++ + BOOST_ERROR( "private X::new called" ); + return ::operator new( n ); + } void operator delete( void * p ) { // lack of this definition causes link errors on MSVC + BOOST_ERROR( "private X::delete called" ); ::operator delete( p ); } From a1b4fc8d95eebb62a20eb3b2436fafd5190ef576 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 27 Mar 2009 13:10:46 +0000 Subject: [PATCH 046/140] Merge [51978], [51985] to release. Closes #2885. [SVN r52016] --- .../smart_ptr/detail/sp_counted_base.hpp | 3 + .../detail/sp_counted_base_gcc_mips.hpp | 172 ++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp index df8be5b..cab45cc 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp @@ -47,6 +47,9 @@ #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) # include +#elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) ) +# include + #elif defined( BOOST_SP_HAS_SYNC ) # include diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp new file mode 100644 index 0000000..0c69b0b --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp @@ -0,0 +1,172 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_gcc_mips.hpp - g++ on MIPS +// +// Copyright (c) 2009, Spirent Communications, Inc. +// +// 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 + +namespace boost +{ + +namespace detail +{ + +inline void atomic_increment( int * pw ) +{ + // ++*pw; + + int tmp; + + __asm__ __volatile__ + ( + "0:\n\t" + "ll %0, %1\n\t" + "addiu %0, 1\n\t" + "sc %0, %1\n\t" + "beqz %0, 0b": + "=&r"( tmp ), "=m"( *pw ): + "m"( *pw ) + ); +} + +inline int atomic_decrement( int * pw ) +{ + // return --*pw; + + int rv, tmp; + + __asm__ __volatile__ + ( + "0:\n\t" + "ll %1, %2\n\t" + "addiu %0, %1, -1\n\t" + "sc %0, %2\n\t" + "beqz %0, 0b\n\t" + "addiu %0, %1, -1": + "=&r"( rv ), "=&r"( tmp ), "=m"( *pw ): + "m"( *pw ): + "memory" + ); + + return rv; +} + +inline int atomic_conditional_increment( int * pw ) +{ + // if( *pw != 0 ) ++*pw; + // return *pw; + + int rv, tmp; + + __asm__ __volatile__ + ( + "0:\n\t" + "ll %0, %2\n\t" + "beqz %0, 1f\n\t" + "addiu %1, %0, 1\n\t" + "sc %1, %2\n\t" + "beqz %1, 0b\n\t" + "addiu %0, %0, 1\n\t" + "1:": + "=&r"( rv ), "=&r"( tmp ), "=m"( *pw ): + "m"( *pw ): + "memory" + ); + + 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_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_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED From 28de0cb1e3981756a8383b8352ec34c8ea1714ea Mon Sep 17 00:00:00 2001 From: David Deakins Date: Mon, 6 Apr 2009 21:25:18 +0000 Subject: [PATCH 047/140] Have config/select_stdlib_config.hpp and config/stdlib/stlport.hpp use instead of to determine which standard library is in use. For std lib implementations that rely on Boost components like TypeTraits, Bind, Function, or SmartPtr, this helps to avoid circular header dependency issues, since is much less likely to pull in Boost libraries than . In get_pointer.hpp, switched to using instead of using directly. As above, this helps avoid circular header dependency issues in Boost-supplemented std libs (specifically it avoids issues when pulls in pieces of Boost.SmartPtr). These two changes were made in response to testing done with STLport 5.2.1 using the _STLP_USE_BOOST_SUPPORT option. [SVN r52221] --- include/boost/get_pointer.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/boost/get_pointer.hpp b/include/boost/get_pointer.hpp index 17d11b8..a0cd5c0 100644 --- a/include/boost/get_pointer.hpp +++ b/include/boost/get_pointer.hpp @@ -5,7 +5,11 @@ #ifndef GET_POINTER_DWA20021219_HPP # define GET_POINTER_DWA20021219_HPP -# 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 +// rather than including directly: +# include // std::auto_ptr namespace boost { From a4293f9dfaf78dabe08c5c6554a299c110bda240 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Apr 2009 21:32:43 +0000 Subject: [PATCH 048/140] Merge [52454] to release. Fixes #2951. [SVN r52472] --- include/boost/smart_ptr/shared_ptr.hpp | 2 +- test/Jamfile.v2 | 1 + test/auto_ptr_lv_fail.cpp | 32 ++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 test/auto_ptr_lv_fail.cpp diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 0ce3b97..7f46c35 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -277,7 +277,7 @@ public: #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() + explicit 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 ); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c862197..0c760b2 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -56,5 +56,6 @@ import testing ; [ run sp_recursive_assign2_test.cpp ] [ run sp_recursive_assign_rv_test.cpp ] [ run sp_recursive_assign2_rv_test.cpp ] + [ compile-fail auto_ptr_lv_fail.cpp ] ; } diff --git a/test/auto_ptr_lv_fail.cpp b/test/auto_ptr_lv_fail.cpp new file mode 100644 index 0000000..b86832e --- /dev/null +++ b/test/auto_ptr_lv_fail.cpp @@ -0,0 +1,32 @@ +#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 + +// +// auto_ptr_lv_fail.cpp - a negative test for converting an auto_ptr to shared_ptr +// +// Copyright 2009 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 + +void f( boost::shared_ptr ) +{ +} + +int main() +{ + std::auto_ptr p; + f( p ); // must fail + return 0; +} From 9f30442d1e696ec26ed1c46faebb35ec6f19731f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20M=20L=C3=B3pez=20Mu=C3=B1oz?= Date: Sun, 19 Apr 2009 10:17:50 +0000 Subject: [PATCH 049/140] merged [52456], [52457] and [52464] from trunk [SVN r52486] --- .../boost/smart_ptr/detail/atomic_count.hpp | 5 +- .../smart_ptr/detail/atomic_count_gcc.hpp | 10 ++-- .../smart_ptr/detail/atomic_count_gcc_x86.hpp | 11 +--- .../detail/atomic_count_pthreads.hpp | 4 +- .../smart_ptr/detail/atomic_count_sync.hpp | 4 +- test/Jamfile.v2 | 1 + test/atomic_count_test2.cpp | 55 +++++++++++++++++++ 7 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 test/atomic_count_test2.cpp diff --git a/include/boost/smart_ptr/detail/atomic_count.hpp b/include/boost/smart_ptr/detail/atomic_count.hpp index a6ddea3..cc44ac2 100644 --- a/include/boost/smart_ptr/detail/atomic_count.hpp +++ b/include/boost/smart_ptr/detail/atomic_count.hpp @@ -31,13 +31,12 @@ // ++a; // // Effects: Atomically increments the value of a -// Returns: nothing +// Returns: (long) the new value of a // // --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) +// Returns: (long) the new value of a // // Important note: when --a returns zero, it must act as a // read memory barrier (RMB); i.e. the calling thread must diff --git a/include/boost/smart_ptr/detail/atomic_count_gcc.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp index 1305632..54807e9 100644 --- a/include/boost/smart_ptr/detail/atomic_count_gcc.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp @@ -40,21 +40,21 @@ class atomic_count { public: - explicit atomic_count(long v) : value_(v) {} + explicit atomic_count( long v ) : value_( v ) {} - void operator++() + long operator++() { - __atomic_add(&value_, 1); + return __exchange_and_add( &value_, +1 ) + 1; } long operator--() { - return __exchange_and_add(&value_, -1) - 1; + return __exchange_and_add( &value_, -1 ) - 1; } operator long() const { - return __exchange_and_add(&value_, 0); + return __exchange_and_add( &value_, 0 ); } private: diff --git a/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp index 4fd1c57..5c44d7c 100644 --- a/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp @@ -25,16 +25,9 @@ public: explicit atomic_count( long v ) : value_( static_cast< int >( v ) ) {} - void operator++() + long operator++() { - __asm__ - ( - "lock\n\t" - "incl %0": - "+m"( value_ ): // output (%0) - : // inputs - "cc" // clobbers - ); + return atomic_exchange_and_add( &value_, +1 ) + 1; } long operator--() diff --git a/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp b/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp index d8118f0..05f7867 100644 --- a/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp @@ -62,10 +62,10 @@ public: pthread_mutex_destroy(&mutex_); } - void operator++() + long operator++() { scoped_lock lock(mutex_); - ++value_; + return ++value_; } long operator--() diff --git a/include/boost/smart_ptr/detail/atomic_count_sync.hpp b/include/boost/smart_ptr/detail/atomic_count_sync.hpp index f2d22fb..b6359b5 100644 --- a/include/boost/smart_ptr/detail/atomic_count_sync.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_sync.hpp @@ -31,9 +31,9 @@ public: explicit atomic_count( long v ) : value_( v ) {} - void operator++() + long operator++() { - __sync_add_and_fetch( &value_, 1 ); + return __sync_add_and_fetch( &value_, 1 ); } long operator--() diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0c760b2..5c05f42 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -57,5 +57,6 @@ import testing ; [ run sp_recursive_assign_rv_test.cpp ] [ run sp_recursive_assign2_rv_test.cpp ] [ compile-fail auto_ptr_lv_fail.cpp ] + [ run atomic_count_test2.cpp ] ; } diff --git a/test/atomic_count_test2.cpp b/test/atomic_count_test2.cpp new file mode 100644 index 0000000..7e6dd97 --- /dev/null +++ b/test/atomic_count_test2.cpp @@ -0,0 +1,55 @@ +// +// atomic_count_test2.cpp +// +// Copyright 2009 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 + +int main() +{ + boost::detail::atomic_count n( 4 ); + + BOOST_TEST( n == 4 ); + + BOOST_TEST( ++n == 5 ); + BOOST_TEST( ++n == 6 ); + + BOOST_TEST( n == 6 ); + + BOOST_TEST( --n == 5 ); + BOOST_TEST( --n == 4 ); + + BOOST_TEST( n == 4 ); + + boost::detail::atomic_count m( 0 ); + + BOOST_TEST( m == 0 ); + + BOOST_TEST( ++m == 1 ); + BOOST_TEST( ++m == 2 ); + + BOOST_TEST( m == 2 ); + + BOOST_TEST( --m == 1 ); + BOOST_TEST( --m == 0 ); + + BOOST_TEST( m == 0 ); + + BOOST_TEST( --m == -1 ); + BOOST_TEST( --m == -2 ); + + BOOST_TEST( m == -2 ); + + BOOST_TEST( ++m == -1 ); + BOOST_TEST( ++m == 0 ); + + BOOST_TEST( m == 0 ); + + return boost::report_errors(); +} From 5fa1cbf6e1da8b533cb2be37fb0a180b146057eb Mon Sep 17 00:00:00 2001 From: "Troy D. Straszheim" Date: Thu, 14 May 2009 20:20:34 +0000 Subject: [PATCH 050/140] shared_ptr and bind cmake tweaks [SVN r53001] --- test/CMakeLists.txt | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7ddae31..b3f1c3f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -12,7 +12,39 @@ 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_compile_fail(shared_ptr_compare_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) +boost_test_run(shared_ptr_alias_test) +boost_test_run(shared_ptr_rv_test) +boost_test_run(shared_ptr_move_test) +boost_test_compile_fail(shared_ptr_pv_fail) +boost_test_run(sp_unary_addr_test) +boost_test_compile_fail(scoped_ptr_eq_fail) +boost_test_compile_fail(scoped_array_eq_fail) +boost_test_run(esft_regtest) +boost_test_run(yield_k_test) +message(STATUS "!!!> yield_k_test multhreaded") +boost_test_run(spinlock_test) +boost_test_run(spinlock_try_test) +message(STATUS "!!!> spinlock_try_test multithreaded") +boost_test_run(spinlock_pool_test) +boost_test_run(make_shared_test) +boost_test_run(sp_convertible_test) +boost_test_run(wp_convertible_test) +boost_test_run(ip_convertible_test) +boost_test_run(allocate_shared_test) +boost_test_run(sp_atomic_test) +boost_test_run(esft_void_test) +boost_test_run(esft_second_ptr_test) +boost_test_run(make_shared_esft_test) +boost_test_run(allocate_shared_esft_test) +boost_test_run(sp_recursive_assign_test) +boost_test_run(sp_recursive_assign2_test) +boost_test_run(sp_recursive_assign_rv_test) +boost_test_run(sp_recursive_assign2_rv_test) +boost_test_compile_fail(auto_ptr_lv_fail) +boost_test_run(atomic_count_test2) + From 8a421c2098ef23ef0304ea08663bfe15e8573a60 Mon Sep 17 00:00:00 2001 From: "Troy D. Straszheim" Date: Wed, 22 Jul 2009 21:51:01 +0000 Subject: [PATCH 051/140] Add basic copyright/license to keep cmake out of the inspection report [SVN r55095] --- CMakeLists.txt | 6 ++++++ test/CMakeLists.txt | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index abe2fc7..1c039fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,9 @@ +# +# Copyright Troy D. Straszheim +# +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt +# #---------------------------------------------------------------------------- # This file was automatically generated from the original CMakeLists.txt file # Add a variable to hold the headers for the library diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b3f1c3f..b89394e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,3 +1,9 @@ +# +# Copyright Troy D. Straszheim +# +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt +# boost_additional_test_dependencies(tokenizer BOOST_DEPENDS test intrusive) From 63b17c24eabb2f180ab0ea5ee03979ce2c9d930f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 8 Aug 2009 23:21:15 +0000 Subject: [PATCH 052/140] Merge [51909], [51912], [52937], [53672] to release. [SVN r55479] --- .../boost/smart_ptr/detail/shared_count.hpp | 14 ++ .../boost/smart_ptr/detail/sp_convertible.hpp | 2 +- .../smart_ptr/enable_shared_from_this2.hpp | 132 +++++++++++++ include/boost/smart_ptr/intrusive_ptr.hpp | 17 ++ include/boost/smart_ptr/shared_ptr.hpp | 13 +- include/boost/smart_ptr/weak_ptr.hpp | 52 ++++- test/Jamfile.v2 | 3 + test/esft_constructor_test.cpp | 169 ++++++++++++++++ test/intrusive_ptr_move_test.cpp | 184 ++++++++++++++++++ test/shared_ptr_move_test.cpp | 16 +- test/weak_ptr_move_test.cpp | 121 ++++++++++++ 11 files changed, 710 insertions(+), 13 deletions(-) create mode 100644 include/boost/smart_ptr/enable_shared_from_this2.hpp create mode 100644 test/esft_constructor_test.cpp create mode 100644 test/intrusive_ptr_move_test.cpp create mode 100644 test/weak_ptr_move_test.cpp diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp index b968bba..4943e37 100644 --- a/include/boost/smart_ptr/detail/shared_count.hpp +++ b/include/boost/smart_ptr/detail/shared_count.hpp @@ -333,6 +333,20 @@ public: if(pi_ != 0) pi_->weak_add_ref(); } +// Move support + +#if defined( BOOST_HAS_RVALUE_REFS ) + + weak_count(weak_count && r): pi_(r.pi_) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(weak_count_id) +#endif + { + r.pi_ = 0; + } + +#endif + ~weak_count() // nothrow { if(pi_ != 0) pi_->weak_release(); diff --git a/include/boost/smart_ptr/detail/sp_convertible.hpp b/include/boost/smart_ptr/detail/sp_convertible.hpp index 7d9502d..66e5ec7 100644 --- a/include/boost/smart_ptr/detail/sp_convertible.hpp +++ b/include/boost/smart_ptr/detail/sp_convertible.hpp @@ -45,7 +45,7 @@ template< class Y, class T > struct sp_convertible static yes f( T* ); static no f( ... ); - enum _vt { value = sizeof( f( (Y*)0 ) ) == sizeof(yes) }; + enum _vt { value = sizeof( f( static_cast(0) ) ) == sizeof(yes) }; }; struct sp_empty diff --git a/include/boost/smart_ptr/enable_shared_from_this2.hpp b/include/boost/smart_ptr/enable_shared_from_this2.hpp new file mode 100644 index 0000000..a5bfcff --- /dev/null +++ b/include/boost/smart_ptr/enable_shared_from_this2.hpp @@ -0,0 +1,132 @@ +#ifndef BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED +#define BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED + +// +// enable_shared_from_this2.hpp +// +// Copyright 2002, 2009 Peter Dimov +// Copyright 2008 Frank Mori Hess +// +// 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 + +namespace boost +{ + +namespace detail +{ + +class esft2_deleter_wrapper +{ +private: + + shared_ptr deleter_; + +public: + + esft2_deleter_wrapper() + { + } + + template< class T > void set_deleter( shared_ptr const & deleter ) + { + deleter_ = deleter; + } + + template< class T> void operator()( T* ) + { + BOOST_ASSERT( deleter_.use_count() <= 1 ); + deleter_.reset(); + } +}; + +} // namespace detail + +template< class T > class enable_shared_from_this2 +{ +protected: + + enable_shared_from_this2() + { + } + + enable_shared_from_this2( enable_shared_from_this2 const & ) + { + } + + enable_shared_from_this2 & operator=( enable_shared_from_this2 const & ) + { + return *this; + } + + ~enable_shared_from_this2() + { + BOOST_ASSERT( shared_this_.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist + } + +private: + + mutable weak_ptr weak_this_; + mutable shared_ptr shared_this_; + +public: + + shared_ptr shared_from_this() + { + init_weak_once(); + return shared_ptr( weak_this_ ); + } + + shared_ptr shared_from_this() const + { + init_weak_once(); + return shared_ptr( weak_this_ ); + } + +private: + + void init_weak_once() const + { + if( weak_this_._empty() ) + { + shared_this_.reset( static_cast< T* >( 0 ), detail::esft2_deleter_wrapper() ); + weak_this_ = shared_this_; + } + } + +public: // actually private, but avoids compiler template friendship issues + + // Note: invoked automatically by shared_ptr; do not call + template void _internal_accept_owner( shared_ptr * ppx, Y * py ) const + { + BOOST_ASSERT( ppx != 0 ); + + if( weak_this_.use_count() == 0 ) + { + weak_this_ = shared_ptr( *ppx, py ); + } + else if( shared_this_.use_count() != 0 ) + { + BOOST_ASSERT( ppx->unique() ); // no weak_ptrs should exist either, but there's no way to check that + + detail::esft2_deleter_wrapper * pd = boost::get_deleter( shared_this_ ); + BOOST_ASSERT( pd != 0 ); + + pd->set_deleter( *ppx ); + + ppx->reset( shared_this_, ppx->get() ); + shared_this_.reset(); + } + } +}; + +} // namespace boost + +#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp index d3bd02b..6927a59 100644 --- a/include/boost/smart_ptr/intrusive_ptr.hpp +++ b/include/boost/smart_ptr/intrusive_ptr.hpp @@ -109,6 +109,23 @@ public: return *this; } +#endif + +// Move support + +#if defined( BOOST_HAS_RVALUE_REFS ) + + intrusive_ptr(intrusive_ptr && rhs): px( rhs.px ) + { + rhs.px = 0; + } + + intrusive_ptr & operator=(intrusive_ptr && rhs) + { + this_type(std::move(rhs)).swap(*this); + return *this; + } + #endif intrusive_ptr & operator=(intrusive_ptr const & rhs) diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 7f46c35..1b367f0 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -61,6 +61,7 @@ namespace boost template class shared_ptr; template class weak_ptr; template class enable_shared_from_this; +template class enable_shared_from_this2; namespace detail { @@ -109,6 +110,14 @@ template< class X, class Y, class T > inline void sp_enable_shared_from_this( bo } } +template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr * ppx, Y const * py, boost::enable_shared_from_this2< T > const * pe ) +{ + if( pe != 0 ) + { + pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) ); + } +} + #ifdef _MANAGED // Avoid C4793, ... causes native code generation @@ -359,14 +368,14 @@ public: shared_ptr & operator=( shared_ptr && r ) // never throws { - this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); + this_type( std::move( r ) ).swap( *this ); return *this; } template shared_ptr & operator=( shared_ptr && r ) // never throws { - this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); + this_type( std::move( r ) ).swap( *this ); return *this; } diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp index bf5296a..621c433 100644 --- a/include/boost/smart_ptr/weak_ptr.hpp +++ b/include/boost/smart_ptr/weak_ptr.hpp @@ -70,11 +70,43 @@ public: weak_ptr( weak_ptr const & r ) #endif - : pn(r.pn) // never throws + : px(r.lock().get()), pn(r.pn) // never throws { - px = r.lock().get(); } +#if defined( BOOST_HAS_RVALUE_REFS ) + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + weak_ptr( weak_ptr && r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + weak_ptr( weak_ptr && r ) + +#endif + : px(r.lock().get()), pn(std::move(r.pn)) // never throws + { + r.px = 0; + } + + // for better efficiency in the T == Y case + weak_ptr( weak_ptr && r ): px( r.px ), pn(std::move(r.pn)) // never throws + { + r.px = 0; + } + + // for better efficiency in the T == Y case + weak_ptr & operator=( weak_ptr && r ) // never throws + { + this_type( std::move( r ) ).swap( *this ); + return *this; + } + + +#endif + template #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) @@ -99,6 +131,17 @@ public: return *this; } +#if defined( BOOST_HAS_RVALUE_REFS ) + + template + weak_ptr & operator=(weak_ptr && r) + { + this_type( std::move( r ) ).swap( *this ); + return *this; + } + +#endif + template weak_ptr & operator=(shared_ptr const & r) // never throws { @@ -124,6 +167,11 @@ public: return pn.use_count() == 0; } + bool _empty() const // extension, not in std::weak_ptr + { + return pn.empty(); + } + void reset() // never throws in 1.30+ { this_type().swap(*this); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5c05f42..db4bfb1 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -16,9 +16,11 @@ import testing ; [ run shared_ptr_basic_test.cpp : : : gcc:-Wno-non-virtual-dtor ] [ run shared_ptr_test.cpp : : : gcc:-Wno-non-virtual-dtor ] [ run weak_ptr_test.cpp ] + [ run weak_ptr_move_test.cpp ] [ run shared_from_this_test.cpp : : : gcc:-Wno-non-virtual-dtor ] [ run get_deleter_test.cpp ] [ run intrusive_ptr_test.cpp ] + [ run intrusive_ptr_move_test.cpp ] [ run atomic_count_test.cpp ] [ run lw_mutex_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] @@ -56,6 +58,7 @@ import testing ; [ run sp_recursive_assign2_test.cpp ] [ run sp_recursive_assign_rv_test.cpp ] [ run sp_recursive_assign2_rv_test.cpp ] + [ run esft_constructor_test.cpp ] [ compile-fail auto_ptr_lv_fail.cpp ] [ run atomic_count_test2.cpp ] ; diff --git a/test/esft_constructor_test.cpp b/test/esft_constructor_test.cpp new file mode 100644 index 0000000..ced24e2 --- /dev/null +++ b/test/esft_constructor_test.cpp @@ -0,0 +1,169 @@ +// +// 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_this2< 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 < b) && !(b < a); +} + +struct Y: public boost::enable_shared_from_this2 +{}; + +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 ); + px.reset(); + try + { + x.shared_from_this(); + BOOST_ERROR("x did not throw bad_weak_ptr"); + } + catch( const boost::bad_weak_ptr & ) + {} + } + + 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 ); + + { + boost::shared_ptr px(new Y()); + Y y(*px); + px.reset(); + try + { + y.shared_from_this(); + } + catch( const boost::bad_weak_ptr & ) + { + BOOST_ERROR("y threw bad_weak_ptr"); + } + } + + return boost::report_errors(); +} diff --git a/test/intrusive_ptr_move_test.cpp b/test/intrusive_ptr_move_test.cpp new file mode 100644 index 0000000..b5f0e65 --- /dev/null +++ b/test/intrusive_ptr_move_test.cpp @@ -0,0 +1,184 @@ +#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 +#pragma warning(disable: 4355) // 'this' : used in base member initializer list +#pragma warning(disable: 4511) // copy constructor could not be generated +#pragma warning(disable: 4512) // assignment operator could not be generated + +#if (BOOST_MSVC >= 1310) +#pragma warning(disable: 4675) // resolved overload found with Koenig lookup +#endif + +#endif + +// +// intrusive_ptr_move_test.cpp +// +// Copyright (c) 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) +// + +#include +#include +#include +#include +#include +#include + +#if defined( BOOST_HAS_RVALUE_REFS ) + +namespace N +{ + +class base +{ +private: + + boost::detail::atomic_count use_count_; + + base(base const &); + base & operator=(base const &); + +protected: + + base(): use_count_(0) + { + ++instances; + } + + virtual ~base() + { + --instances; + } + +public: + + static long instances; + + long use_count() const + { + return use_count_; + } + +#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + + inline friend void intrusive_ptr_add_ref(base * p) + { + ++p->use_count_; + } + + inline friend void intrusive_ptr_release(base * p) + { + if(--p->use_count_ == 0) delete p; + } + +#else + + void add_ref() + { + ++use_count_; + } + + void release() + { + if(--use_count_ == 0) delete this; + } + +#endif +}; + +long base::instances = 0; + +} // namespace N + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + +namespace boost +{ + +inline void intrusive_ptr_add_ref(N::base * p) +{ + p->add_ref(); +} + +inline void intrusive_ptr_release(N::base * p) +{ + p->release(); +} + +} // namespace boost + +#endif + +// + +struct X: public virtual N::base +{ +}; + +struct Y: public X +{ +}; + +int main() +{ + BOOST_TEST( N::base::instances == 0 ); + + { + boost::intrusive_ptr p( new X ); + BOOST_TEST( N::base::instances == 1 ); + + boost::intrusive_ptr p2( std::move( p ) ); + BOOST_TEST( N::base::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + p2.reset(); + BOOST_TEST( N::base::instances == 0 ); + } + + { + boost::intrusive_ptr p( new X ); + BOOST_TEST( N::base::instances == 1 ); + + boost::intrusive_ptr p2; + p2 = std::move( p ); + BOOST_TEST( N::base::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + p2.reset(); + BOOST_TEST( N::base::instances == 0 ); + } + + { + boost::intrusive_ptr p( new X ); + BOOST_TEST( N::base::instances == 1 ); + + boost::intrusive_ptr p2( new X ); + BOOST_TEST( N::base::instances == 2 ); + p2 = std::move( p ); + BOOST_TEST( N::base::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + p2.reset(); + BOOST_TEST( N::base::instances == 0 ); + } + + return boost::report_errors(); +} + +#else // !defined( BOOST_HAS_RVALUE_REFS ) + +int main() +{ + return 0; +} + +#endif diff --git a/test/shared_ptr_move_test.cpp b/test/shared_ptr_move_test.cpp index bd785e4..c02ffa9 100644 --- a/test/shared_ptr_move_test.cpp +++ b/test/shared_ptr_move_test.cpp @@ -8,11 +8,11 @@ // http://www.boost.org/LICENSE_1_0.txt // -#if defined( BOOST_HAS_RVALUE_REFS ) - #include #include +#if defined( BOOST_HAS_RVALUE_REFS ) + struct X { static long instances; @@ -43,11 +43,11 @@ int main() boost::shared_ptr p( new X ); BOOST_TEST( X::instances == 1 ); - boost::shared_ptr p2( static_cast< boost::shared_ptr && >( p ) ); + boost::shared_ptr p2( std::move( p ) ); BOOST_TEST( X::instances == 1 ); BOOST_TEST( p.get() == 0 ); - boost::shared_ptr p3( static_cast< boost::shared_ptr && >( p2 ) ); + boost::shared_ptr p3( std::move( p2 ) ); BOOST_TEST( X::instances == 1 ); BOOST_TEST( p2.get() == 0 ); @@ -60,12 +60,12 @@ int main() BOOST_TEST( X::instances == 1 ); boost::shared_ptr p2; - p2 = static_cast< boost::shared_ptr && >( p ); + p2 = std::move( p ); BOOST_TEST( X::instances == 1 ); BOOST_TEST( p.get() == 0 ); boost::shared_ptr p3; - p3 = static_cast< boost::shared_ptr && >( p2 ); + p3 = std::move( p2 ); BOOST_TEST( X::instances == 1 ); BOOST_TEST( p2.get() == 0 ); @@ -79,13 +79,13 @@ int main() boost::shared_ptr p2( new X ); BOOST_TEST( X::instances == 2 ); - p2 = static_cast< boost::shared_ptr && >( p ); + p2 = std::move( 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 ); + p3 = std::move( p2 ); BOOST_TEST( X::instances == 1 ); BOOST_TEST( p2.get() == 0 ); diff --git a/test/weak_ptr_move_test.cpp b/test/weak_ptr_move_test.cpp new file mode 100644 index 0000000..572b13d --- /dev/null +++ b/test/weak_ptr_move_test.cpp @@ -0,0 +1,121 @@ +// +// weak_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 + +#if defined( BOOST_HAS_RVALUE_REFS ) + +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::weak_ptr p( p_ ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.use_count() == 1 ); + + boost::weak_ptr p2( std::move( p ) ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p2.use_count() == 1 ); + BOOST_TEST( p.expired() ); + + boost::weak_ptr p3( std::move( p2 ) ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p3.use_count() == 1 ); + BOOST_TEST( p2.expired() ); + + p_.reset(); + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( p3.expired() ); + } + + { + boost::shared_ptr p_( new X ); + boost::weak_ptr p( p_ ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.use_count() == 1 ); + + boost::weak_ptr p2; + p2 = static_cast< boost::weak_ptr && >( p ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p2.use_count() == 1 ); + BOOST_TEST( p.expired() ); + + boost::weak_ptr p3; + p3 = std::move( p2 ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p3.use_count() == 1 ); + BOOST_TEST( p2.expired() ); + + p_.reset(); + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( p3.expired() ); + } + + { + boost::shared_ptr p_( new X ); + boost::weak_ptr p( p_ ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.use_count() == 1 ); + + boost::shared_ptr p_2( new X ); + boost::weak_ptr p2( p_2 ); + BOOST_TEST( X::instances == 2 ); + p2 = std::move( p ); + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( p2.use_count() == 1 ); + BOOST_TEST( p.expired() ); + BOOST_TEST( p2.lock() != p_2 ); + + boost::shared_ptr p_3( new X ); + boost::weak_ptr p3( p_3 ); + BOOST_TEST( X::instances == 3 ); + p3 = std::move( p2 ); + BOOST_TEST( X::instances == 3 ); + BOOST_TEST( p3.use_count() == 1 ); + BOOST_TEST( p2.expired() ); + BOOST_TEST( p3.lock() != p_3 ); + } + + return boost::report_errors(); +} + +#else // !defined( BOOST_HAS_RVALUE_REFS ) + +int main() +{ + return 0; +} + +#endif From e94f64039d6f540d1bada3bd422f592bd8733b8c Mon Sep 17 00:00:00 2001 From: "Troy D. Straszheim" Date: Sat, 17 Oct 2009 01:10:45 +0000 Subject: [PATCH 053/140] rm cmake from the release branch before it goes out broken. Policy dictates that you never commit to release, you commit to trunk and merge to release. [SVN r56941] --- CMakeLists.txt | 36 ----------------------------- module.cmake | 1 - test/CMakeLists.txt | 56 --------------------------------------------- 3 files changed, 93 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 module.cmake delete mode 100644 test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 1c039fc..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright Troy D. Straszheim -# -# Distributed under the Boost Software License, Version 1.0. -# See http://www.boost.org/LICENSE_1_0.txt -# -#---------------------------------------------------------------------------- -# 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 deleted file mode 100644 index d83266c..0000000 --- a/module.cmake +++ /dev/null @@ -1 +0,0 @@ -boost_module(smart_ptr DEPENDS utility) \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt deleted file mode 100644 index b89394e..0000000 --- a/test/CMakeLists.txt +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright Troy D. Straszheim -# -# Distributed under the Boost Software License, Version 1.0. -# See http://www.boost.org/LICENSE_1_0.txt -# -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) -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_compile_fail(shared_ptr_compare_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) -boost_test_run(shared_ptr_alias_test) -boost_test_run(shared_ptr_rv_test) -boost_test_run(shared_ptr_move_test) -boost_test_compile_fail(shared_ptr_pv_fail) -boost_test_run(sp_unary_addr_test) -boost_test_compile_fail(scoped_ptr_eq_fail) -boost_test_compile_fail(scoped_array_eq_fail) -boost_test_run(esft_regtest) -boost_test_run(yield_k_test) -message(STATUS "!!!> yield_k_test multhreaded") -boost_test_run(spinlock_test) -boost_test_run(spinlock_try_test) -message(STATUS "!!!> spinlock_try_test multithreaded") -boost_test_run(spinlock_pool_test) -boost_test_run(make_shared_test) -boost_test_run(sp_convertible_test) -boost_test_run(wp_convertible_test) -boost_test_run(ip_convertible_test) -boost_test_run(allocate_shared_test) -boost_test_run(sp_atomic_test) -boost_test_run(esft_void_test) -boost_test_run(esft_second_ptr_test) -boost_test_run(make_shared_esft_test) -boost_test_run(allocate_shared_esft_test) -boost_test_run(sp_recursive_assign_test) -boost_test_run(sp_recursive_assign2_test) -boost_test_run(sp_recursive_assign_rv_test) -boost_test_run(sp_recursive_assign2_rv_test) -boost_test_compile_fail(auto_ptr_lv_fail) -boost_test_run(atomic_count_test2) - From 754fd941ee0c30c347eaaf77706c8a797b8fdf18 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 26 Nov 2009 21:58:16 +0000 Subject: [PATCH 054/140] Merge [57950], [57952] to release. Fixes #3404. Fixes #3456. [SVN r57959] --- enable_shared_from_this.html | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/enable_shared_from_this.html b/enable_shared_from_this.html index 3f35665..c4caa25 100644 --- a/enable_shared_from_this.html +++ b/enable_shared_from_this.html @@ -29,20 +29,24 @@ and shared_ptr<T const>, depending on constness, to this.

    Example

    -class Y: public enable_shared_from_this<Y>
    +#include <boost/enable_shared_from_this.hpp>
    +#include <boost/shared_ptr.hpp>
    +#include <cassert>
    +
    +class Y: public boost::enable_shared_from_this<Y>
     {
     public:
     
    -    shared_ptr<Y> f()
    +    boost::shared_ptr<Y> f()
         {
             return shared_from_this();
         }
    -}
    +};
     
     int main()
     {
    -    shared_ptr<Y> p(new Y);
    -    shared_ptr<Y> q = p->f();
    +    boost::shared_ptr<Y> p(new Y);
    +    boost::shared_ptr<Y> q = p->f();
         assert(p == q);
         assert(!(p < q || q < p)); // p and q must share ownership
     }
    
    From eec640bfd7742716212b6b594bb8117b47a7ea63 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Thu, 26 Nov 2009 22:10:30 +0000
    Subject: [PATCH 055/140] Merge [57520] to release. Fixes #2962.
    
    [SVN r57960]
    ---
     include/boost/smart_ptr/make_shared.hpp      |  4 +-
     test/Jamfile.v2                              |  1 +
     test/make_shared_perfect_forwarding_test.cpp | 98 ++++++++++++++++++++
     3 files changed, 102 insertions(+), 1 deletion(-)
     create mode 100644 test/make_shared_perfect_forwarding_test.cpp
    
    diff --git a/include/boost/smart_ptr/make_shared.hpp b/include/boost/smart_ptr/make_shared.hpp
    index 7e1e793..d477188 100644
    --- a/include/boost/smart_ptr/make_shared.hpp
    +++ b/include/boost/smart_ptr/make_shared.hpp
    @@ -86,10 +86,12 @@ public:
         }
     };
     
    -template< class T > T forward( T t )
    +#if defined( BOOST_HAS_RVALUE_REFS )
    +template< class T > T&& forward( T &&t )
     {
         return t;
     }
    +#endif
     
     } // namespace detail
     
    diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
    index db4bfb1..d30f1ab 100644
    --- a/test/Jamfile.v2
    +++ b/test/Jamfile.v2
    @@ -45,6 +45,7 @@ import testing ;
               [ run spinlock_try_test.cpp : : : multi : spinlock_try_test.mt ]
               [ run spinlock_pool_test.cpp ]
               [ run make_shared_test.cpp ]
    +          [ run make_shared_perfect_forwarding_test.cpp ]
               [ run sp_convertible_test.cpp ]
               [ run wp_convertible_test.cpp ]
               [ run ip_convertible_test.cpp ]
    diff --git a/test/make_shared_perfect_forwarding_test.cpp b/test/make_shared_perfect_forwarding_test.cpp
    new file mode 100644
    index 0000000..45a111c
    --- /dev/null
    +++ b/test/make_shared_perfect_forwarding_test.cpp
    @@ -0,0 +1,98 @@
    +// make_shared_perfect_forwarding_test.cpp - a test of make_shared
    +//   perfect forwarding of constructor arguments when using a C++0x
    +//   compiler.
    +//
    +// Copyright 2009 Frank Mori Hess
    +//
    +// 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 
    +
    +#ifndef BOOST_HAS_RVALUE_REFS
    +
    +int main()
    +{
    +    return 0;
    +}
    +
    +#else // BOOST_HAS_RVALUE_REFS
    +
    +class myarg
    +{
    +public:
    +    myarg()
    +    {}
    +private:
    +    myarg(myarg && other)
    +    {}
    +    myarg& operator=(myarg && other)
    +    {
    +        return *this;
    +    }
    +    myarg(const myarg & other)
    +    {}
    +    myarg& operator=(const myarg & other)
    +    {
    +        return *this;
    +    }
    +};
    +
    +class X
    +{
    +public:
    +    enum constructor_id
    +    {
    +        move_constructor,
    +        const_ref_constructor,
    +        ref_constructor
    +    };
    +
    +    X(myarg &&arg): constructed_by_(move_constructor)
    +    {}
    +    X(const myarg &arg): constructed_by_(const_ref_constructor)
    +    {}
    +    X(myarg &arg): constructed_by_(ref_constructor)
    +    {}
    +
    +    constructor_id constructed_by_;
    +};
    +
    +struct Y
    +{
    +    Y(int &value): ref(value)
    +    {}
    +    int &ref;
    +};
    +
    +int main()
    +{
    +    {
    +        myarg a;
    +        boost::shared_ptr< X > x = boost::make_shared< X >(a);
    +        BOOST_TEST( x->constructed_by_ == X::ref_constructor);
    +    }
    +    {
    +        const myarg ca;
    +        boost::shared_ptr< X > x = boost::make_shared< X >(ca);
    +        BOOST_TEST( x->constructed_by_ == X::const_ref_constructor);
    +    }
    +    {
    +        boost::shared_ptr< X > x = boost::make_shared< X >(myarg());
    +        BOOST_TEST( x->constructed_by_ == X::move_constructor);
    +    }
    +    {
    +        int value = 1;
    +        boost::shared_ptr< Y > y = boost::make_shared< Y >(value);
    +        BOOST_TEST( y->ref == 1 && value == y->ref );
    +        ++y->ref;
    +        BOOST_TEST( value == y->ref );
    +    }
    +
    +    return boost::report_errors();
    +}
    +
    +#endif // BOOST_HAS_RVALUE_REFS
    
    From 2bd077877872ea9be019f7191693ce8b41823698 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Mon, 30 Nov 2009 20:17:14 +0000
    Subject: [PATCH 056/140] Merge [57949] to release. Fixes #3678. Fixes #3341.
    
    [SVN r58063]
    ---
     .../boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp    | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
    index 8af6f0a..21fa59d 100644
    --- a/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
    +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
    @@ -30,9 +30,9 @@ 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_)
    +    __asm__ __volatile__( "cas [%1], %2, %0"
    +                        : "+r" (swap_)
    +                        : "r" (dest_), "r" (compare_)
                             : "memory" );
     
         return swap_;
    
    From 2f8945a885269aa6616f3f101b0b679c0637234f Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Mon, 30 Nov 2009 20:20:52 +0000
    Subject: [PATCH 057/140] Merge [57951] to release. Fixes #3351.
    
    [SVN r58064]
    ---
     include/boost/smart_ptr/detail/sp_has_sync.hpp | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/include/boost/smart_ptr/detail/sp_has_sync.hpp b/include/boost/smart_ptr/detail/sp_has_sync.hpp
    index cb0282d..7fcd09e 100644
    --- a/include/boost/smart_ptr/detail/sp_has_sync.hpp
    +++ b/include/boost/smart_ptr/detail/sp_has_sync.hpp
    @@ -40,7 +40,7 @@
     #undef BOOST_SP_HAS_SYNC
     #endif
     
    -#if defined( __INTEL_COMPILER ) && !defined( __ia64__ )
    +#if defined( __INTEL_COMPILER ) && !defined( __ia64__ ) && ( __INTEL_COMPILER < 1100 )
     #undef BOOST_SP_HAS_SYNC
     #endif
     
    
    From f040bed751df50ee59f2b9e30739a29a68f3cb6a Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Mon, 30 Nov 2009 20:25:01 +0000
    Subject: [PATCH 058/140] Merge [57953] to release. Fixes #2681.
    
    [SVN r58065]
    ---
     include/boost/smart_ptr/detail/lwm_pthreads.hpp | 11 ++++++-----
     1 file changed, 6 insertions(+), 5 deletions(-)
    
    diff --git a/include/boost/smart_ptr/detail/lwm_pthreads.hpp b/include/boost/smart_ptr/detail/lwm_pthreads.hpp
    index fc20dbb..8eda518 100644
    --- a/include/boost/smart_ptr/detail/lwm_pthreads.hpp
    +++ b/include/boost/smart_ptr/detail/lwm_pthreads.hpp
    @@ -17,6 +17,7 @@
     // http://www.boost.org/LICENSE_1_0.txt)
     //
     
    +#include 
     #include 
     
     namespace boost
    @@ -42,15 +43,15 @@ public:
     // HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
     
     #if defined(__hpux) && defined(_DECTHREADS_)
    -        pthread_mutex_init(&m_, pthread_mutexattr_default);
    +        BOOST_VERIFY( pthread_mutex_init( &m_, pthread_mutexattr_default ) == 0 );
     #else
    -        pthread_mutex_init(&m_, 0);
    +        BOOST_VERIFY( pthread_mutex_init( &m_, 0 ) == 0 );
     #endif
         }
     
         ~lightweight_mutex()
         {
    -        pthread_mutex_destroy(&m_);
    +        BOOST_VERIFY( pthread_mutex_destroy( &m_ ) == 0 );
         }
     
         class scoped_lock;
    @@ -69,12 +70,12 @@ public:
     
             scoped_lock(lightweight_mutex & m): m_(m.m_)
             {
    -            pthread_mutex_lock(&m_);
    +            BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
             }
     
             ~scoped_lock()
             {
    -            pthread_mutex_unlock(&m_);
    +            BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
             }
         };
     };
    
    From 4f5062004a28254618e7568283c52a4ea8e757e7 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Mon, 30 Nov 2009 20:30:22 +0000
    Subject: [PATCH 059/140] Merge [57954], [57955] to release.
    
    [SVN r58066]
    ---
     include/boost/smart_ptr/detail/sp_convertible.hpp | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/include/boost/smart_ptr/detail/sp_convertible.hpp b/include/boost/smart_ptr/detail/sp_convertible.hpp
    index 66e5ec7..b7f0ea8 100644
    --- a/include/boost/smart_ptr/detail/sp_convertible.hpp
    +++ b/include/boost/smart_ptr/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__ <= 0x610 )
    +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ <= 0x620 )
     # define BOOST_SP_NO_SP_CONVERTIBLE
     #endif
     
    
    From b0fd8a6b080602bbceb3bcec1e2967141cb7ba99 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Mon, 30 Nov 2009 20:34:39 +0000
    Subject: [PATCH 060/140] Merge [57957] to release. Fixes #3570.
    
    [SVN r58067]
    ---
     include/boost/smart_ptr/intrusive_ptr.hpp |  2 +-
     include/boost/smart_ptr/shared_ptr.hpp    |  4 ++--
     include/boost/smart_ptr/weak_ptr.hpp      | 10 +++++-----
     3 files changed, 8 insertions(+), 8 deletions(-)
    
    diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp
    index 6927a59..0e30ece 100644
    --- a/include/boost/smart_ptr/intrusive_ptr.hpp
    +++ b/include/boost/smart_ptr/intrusive_ptr.hpp
    @@ -122,7 +122,7 @@ public:
     
         intrusive_ptr & operator=(intrusive_ptr && rhs)
         {
    -        this_type(std::move(rhs)).swap(*this);
    +        this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);
             return *this;
         }
     
    diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp
    index 1b367f0..8256d00 100644
    --- a/include/boost/smart_ptr/shared_ptr.hpp
    +++ b/include/boost/smart_ptr/shared_ptr.hpp
    @@ -368,14 +368,14 @@ public:
     
         shared_ptr & operator=( shared_ptr && r ) // never throws
         {
    -        this_type( std::move( r ) ).swap( *this );
    +        this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
             return *this;
         }
     
         template
         shared_ptr & operator=( shared_ptr && r ) // never throws
         {
    -        this_type( std::move( r ) ).swap( *this );
    +        this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
             return *this;
         }
     
    diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp
    index 621c433..8690cca 100644
    --- a/include/boost/smart_ptr/weak_ptr.hpp
    +++ b/include/boost/smart_ptr/weak_ptr.hpp
    @@ -86,13 +86,13 @@ public:
         weak_ptr( weak_ptr && r )
     
     #endif
    -    : px(r.lock().get()), pn(std::move(r.pn)) // never throws
    +    : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) // never throws
         {
             r.px = 0;
         }
     
         // for better efficiency in the T == Y case
    -    weak_ptr( weak_ptr && r ): px( r.px ), pn(std::move(r.pn)) // never throws
    +    weak_ptr( weak_ptr && r ): px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) // never throws
         {
             r.px = 0;
         }
    @@ -100,7 +100,7 @@ public:
         // for better efficiency in the T == Y case
         weak_ptr & operator=( weak_ptr && r ) // never throws
         {
    -        this_type( std::move( r ) ).swap( *this );
    +        this_type( static_cast< weak_ptr && >( r ) ).swap( *this );
             return *this;
         }
     
    @@ -134,9 +134,9 @@ public:
     #if defined( BOOST_HAS_RVALUE_REFS )
     
         template
    -    weak_ptr & operator=(weak_ptr && r)
    +    weak_ptr & operator=( weak_ptr && r )
         {
    -        this_type( std::move( r ) ).swap( *this );
    +        this_type( static_cast< weak_ptr && >( r ) ).swap( *this );
             return *this;
         }
     
    
    From a3b84f858605da7a3d300c1a8d5f9fa13d6ea483 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Thu, 3 Dec 2009 17:50:37 +0000
    Subject: [PATCH 061/140] Merge [58094] to release.
    
    [SVN r58122]
    ---
     include/boost/memory_order.hpp | 22 ++++++++++++++++++++--
     1 file changed, 20 insertions(+), 2 deletions(-)
    
    diff --git a/include/boost/memory_order.hpp b/include/boost/memory_order.hpp
    index 2524e8a..4945af6 100644
    --- a/include/boost/memory_order.hpp
    +++ b/include/boost/memory_order.hpp
    @@ -11,7 +11,7 @@
     //
     //  Defines enum boost::memory_order per the C++0x working draft
     //
    -//  Copyright (c) 2008 Peter Dimov
    +//  Copyright (c) 2008, 2009 Peter Dimov
     //
     //  Distributed under the Boost Software License, Version 1.0.
     //  See accompanying file LICENSE_1_0.txt or copy at
    @@ -21,13 +21,31 @@
     namespace boost
     {
     
    +//
    +// Enum values are chosen so that code that needs to insert
    +// a trailing fence for acquire semantics can use a single
    +// test such as:
    +//
    +// if( mo & memory_order_acquire ) { ...fence... }
    +//
    +// For leading fences one can use:
    +//
    +// if( mo & memory_order_release ) { ...fence... }
    +//
    +// Architectures such as Alpha that need a fence on consume
    +// can use:
    +//
    +// if( mo & ( memory_order_acquire | memory_order_consume ) ) { ...fence... }
    +//
    +
     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
    +    memory_order_seq_cst = 7, // acq_rel | 4
    +    memory_order_consume = 8
     };
     
     } // namespace boost
    
    From ba349679f3957511d5188af9bf63cdf15bdf3f60 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Sun, 6 Dec 2009 17:50:28 +0000
    Subject: [PATCH 062/140] Merge [58123], [58127], [58128] to release. Fixes
     #3666.
    
    [SVN r58195]
    ---
     include/boost/detail/sp_typeinfo.hpp | 54 +++++++++++++++++++++++++---
     test/Jamfile.v2                      |  1 +
     test/pointer_cast_test.cpp           | 10 ++++++
     test/shared_from_this_test.cpp       |  2 ++
     test/shared_ptr_basic_test.cpp       | 12 +++++++
     test/shared_ptr_test.cpp             |  8 +++++
     test/sp_typeinfo_test.cpp            | 51 ++++++++++++++++++++++++++
     7 files changed, 134 insertions(+), 4 deletions(-)
     create mode 100644 test/sp_typeinfo_test.cpp
    
    diff --git a/include/boost/detail/sp_typeinfo.hpp b/include/boost/detail/sp_typeinfo.hpp
    index e78c943..636fe27 100644
    --- a/include/boost/detail/sp_typeinfo.hpp
    +++ b/include/boost/detail/sp_typeinfo.hpp
    @@ -19,20 +19,66 @@
     
     #if defined( BOOST_NO_TYPEID )
     
    +#include 
    +#include 
    +
     namespace boost
     {
     
     namespace detail
     {
     
    -typedef void* sp_typeinfo;
    +class sp_typeinfo
    +{
    +private:
    +
    +    sp_typeinfo( sp_typeinfo const& );
    +    sp_typeinfo& operator=( sp_typeinfo const& );
    +
    +    char const * name_;
    +
    +public:
    +
    +    explicit sp_typeinfo( char const * name ): name_( name )
    +    {
    +    }
    +
    +    bool operator==( sp_typeinfo const& rhs ) const
    +    {
    +        return this == &rhs;
    +    }
    +
    +    bool operator!=( sp_typeinfo const& rhs ) const
    +    {
    +        return this != &rhs;
    +    }
    +
    +    bool before( sp_typeinfo const& rhs ) const
    +    {
    +        return std::less< sp_typeinfo const* >()( this, &rhs );
    +    }
    +
    +    char const* name() const
    +    {
    +        return name_;
    +    }
    +};
     
     template struct sp_typeid_
     {
    -    static char v_;
    +    static sp_typeinfo ti_;
    +
    +    static char const * name()
    +    {
    +        return BOOST_CURRENT_FUNCTION;
    +    }
     };
     
    -template char sp_typeid_< T >::v_;
    +template sp_typeinfo sp_typeid_< T >::ti_( sp_typeid_< T >::name() );
    +
    +template struct sp_typeid_< T & >: sp_typeid_< T >
    +{
    +};
     
     template struct sp_typeid_< T const >: sp_typeid_< T >
     {
    @@ -50,7 +96,7 @@ template struct sp_typeid_< T const volatile >: sp_typeid_< T >
     
     } // namespace boost
     
    -#define BOOST_SP_TYPEID(T) (&boost::detail::sp_typeid_::v_)
    +#define BOOST_SP_TYPEID(T) (boost::detail::sp_typeid_::ti_)
     
     #else
     
    diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
    index d30f1ab..056b011 100644
    --- a/test/Jamfile.v2
    +++ b/test/Jamfile.v2
    @@ -62,5 +62,6 @@ import testing ;
               [ run esft_constructor_test.cpp ]
               [ compile-fail auto_ptr_lv_fail.cpp ]
               [ run atomic_count_test2.cpp ]
    +          [ run sp_typeinfo_test.cpp ]
             ;
     }
    diff --git a/test/pointer_cast_test.cpp b/test/pointer_cast_test.cpp
    index 6e4620c..bd25dd1 100644
    --- a/test/pointer_cast_test.cpp
    +++ b/test/pointer_cast_test.cpp
    @@ -9,6 +9,8 @@
     // http://www.boost.org/LICENSE_1_0.txt)
     //
     
    +#include 
    +
     #include 
     
     #include 
    @@ -58,6 +60,8 @@ class derived_derived
     
     // And now some simple check functions
     
    +#if !defined( BOOST_NO_RTTI )
    +
     template 
     bool check_dynamic_pointer_cast(const BasePtr &ptr)
     {
    @@ -74,6 +78,8 @@ bool check_dynamic_pointer_cast(const BasePtr &ptr)
           dynamic_cast(boost::get_pointer(ptr));
     }
     
    +#endif
    +
     template 
     bool check_static_pointer_cast(const BasePtr &ptr)
     {
    @@ -107,7 +113,9 @@ int main()
     
             boost::shared_ptr ptr(new derived);
     
    +#if !defined( BOOST_NO_RTTI )
             BOOST_TEST( check_dynamic_pointer_cast( ptr ) );
    +#endif
             BOOST_TEST( check_static_pointer_cast( ptr ) );
             BOOST_TEST( check_const_pointer_cast( ptr ) );
         }
    @@ -117,7 +125,9 @@ int main()
     
             boost::scoped_ptr ptr(new derived);
     
    +#if !defined( BOOST_NO_RTTI )
             BOOST_TEST( check_dynamic_pointer_cast( ptr.get() ) );
    +#endif
             BOOST_TEST( check_static_pointer_cast( ptr.get() ) );
             BOOST_TEST( check_const_pointer_cast( ptr.get() ) );
         }
    diff --git a/test/shared_from_this_test.cpp b/test/shared_from_this_test.cpp
    index 68d6098..b3d7838 100644
    --- a/test/shared_from_this_test.cpp
    +++ b/test/shared_from_this_test.cpp
    @@ -63,10 +63,12 @@ void test()
     
             px->f();
     
    +#if !defined( BOOST_NO_RTTI )
             boost::shared_ptr py2 = boost::dynamic_pointer_cast(px);
             BOOST_TEST(py.get() == py2.get());
             BOOST_TEST(!(py < py2 || py2 < py));
             BOOST_TEST(py.use_count() == 3);
    +#endif
         }
         catch( boost::bad_weak_ptr const& )
         {
    diff --git a/test/shared_ptr_basic_test.cpp b/test/shared_ptr_basic_test.cpp
    index f699848..4d4179e 100644
    --- a/test/shared_ptr_basic_test.cpp
    +++ b/test/shared_ptr_basic_test.cpp
    @@ -188,6 +188,7 @@ int main()
                 test_eq(p, q);
             }
     
    +#if !defined( BOOST_NO_RTTI )
             shared_ptr p3 = dynamic_pointer_cast(p);
             shared_ptr p4 = dynamic_pointer_cast(p2);
     
    @@ -201,6 +202,7 @@ int main()
             test_is_Y(p3);
             test_eq2(p, p3);
             test_ne2(p2, p4);
    +#endif
     
             shared_ptr p5(p);
     
    @@ -214,13 +216,17 @@ int main()
     
             p.reset();
             p2.reset();
    +#if !defined( BOOST_NO_RTTI )
             p3.reset();
             p4.reset();
    +#endif
     
             test_is_zero(p);
             test_is_zero(p2);
    +#if !defined( BOOST_NO_RTTI )
             test_is_zero(p3);
             test_is_zero(p4);
    +#endif
     
             BOOST_TEST(p5.use_count() == 1);
     
    @@ -250,6 +256,7 @@ int main()
                 test_is_nonzero(wp2.lock());
             }
     
    +#if !defined( BOOST_NO_RTTI )
             weak_ptr wp3 = dynamic_pointer_cast(wp2.lock());
     
             BOOST_TEST(wp3.use_count() == 1);
    @@ -259,12 +266,15 @@ int main()
     
             BOOST_TEST(wp4.use_count() == 1);
             test_shared(wp2, wp4);
    +#endif
     
             wp1 = p2;
             test_is_zero(wp1.lock());
     
    +#if !defined( BOOST_NO_RTTI )
             wp1 = p4;
             wp1 = wp3;
    +#endif
             wp1 = wp2;
     
             BOOST_TEST(wp1.use_count() == 1);
    @@ -279,7 +289,9 @@ int main()
     
             BOOST_TEST(wp1.use_count() == 0);
             BOOST_TEST(wp2.use_count() == 0);
    +#if !defined( BOOST_NO_RTTI )
             BOOST_TEST(wp3.use_count() == 0);
    +#endif
     
             // Test operator< stability for std::set< weak_ptr<> >
             // Thanks to Joe Gottman for pointing this out
    diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp
    index f697192..60ed906 100644
    --- a/test/shared_ptr_test.cpp
    +++ b/test/shared_ptr_test.cpp
    @@ -2462,6 +2462,8 @@ void test()
     
     } // namespace n_const_cast
     
    +#if !defined( BOOST_NO_RTTI )
    +
     namespace n_dynamic_cast
     {
     
    @@ -2527,6 +2529,8 @@ void test()
     
     } // namespace n_dynamic_cast
     
    +#endif
    +
     namespace n_map
     {
     
    @@ -3200,10 +3204,12 @@ void test()
         BOOST_TEST(px.get() != 0);
         BOOST_TEST(py.use_count() == 2);
     
    +#if !defined( BOOST_NO_RTTI )
         boost::shared_ptr py2 = boost::dynamic_pointer_cast(px);
         BOOST_TEST(py.get() == py2.get());
         BOOST_TEST(!(py < py2 || py2 < py));
         BOOST_TEST(py.use_count() == 3);
    +#endif
     }
     
     } // namespace n_spt_shared_from_this
    @@ -3229,7 +3235,9 @@ int main()
         n_comparison::test();
         n_static_cast::test();
         n_const_cast::test();
    +#if !defined( BOOST_NO_RTTI )
         n_dynamic_cast::test();
    +#endif
     
         n_map::test();
     
    diff --git a/test/sp_typeinfo_test.cpp b/test/sp_typeinfo_test.cpp
    new file mode 100644
    index 0000000..c47d04e
    --- /dev/null
    +++ b/test/sp_typeinfo_test.cpp
    @@ -0,0 +1,51 @@
    +//
    +// sp_typeinfo_test.cpp
    +//
    +// Copyright (c) 2009 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 
    +
    +int main()
    +{
    +    BOOST_TEST( BOOST_SP_TYPEID( int ) == BOOST_SP_TYPEID( int ) );
    +    BOOST_TEST( BOOST_SP_TYPEID( int ) != BOOST_SP_TYPEID( long ) );
    +    BOOST_TEST( BOOST_SP_TYPEID( int ) != BOOST_SP_TYPEID( void ) );
    +
    +    boost::detail::sp_typeinfo const & ti = BOOST_SP_TYPEID( int );
    +
    +    boost::detail::sp_typeinfo const * pti = &BOOST_SP_TYPEID( int );
    +    BOOST_TEST( *pti == ti );
    +
    +    BOOST_TEST( ti == ti );
    +    BOOST_TEST( !( ti != ti ) );
    +    BOOST_TEST( !ti.before( ti ) );
    +
    +    char const * nti = ti.name();
    +	std::cout << nti << std::endl;
    +
    +    boost::detail::sp_typeinfo const & tv = BOOST_SP_TYPEID( void );
    +
    +    boost::detail::sp_typeinfo const * ptv = &BOOST_SP_TYPEID( void );
    +    BOOST_TEST( *ptv == tv );
    +
    +    BOOST_TEST( tv == tv );
    +    BOOST_TEST( !( tv != tv ) );
    +    BOOST_TEST( !tv.before( tv ) );
    +
    +    char const * ntv = tv.name();
    +	std::cout << ntv << std::endl;
    +
    +    BOOST_TEST( ti != tv );
    +    BOOST_TEST( !( ti == tv ) );
    +
    +    BOOST_TEST( ti.before( tv ) != tv.before( ti ) );
    +
    +    return boost::report_errors();
    +}
    
    From f4386409d9bb52573d42ffbd05f12c445fdf7bfd Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Mon, 14 Dec 2009 17:44:19 +0000
    Subject: [PATCH 063/140] Merge [58275], [58306] to release.
    
    [SVN r58380]
    ---
     include/boost/smart_ptr/detail/quick_allocator.hpp | 5 +++--
     include/boost/smart_ptr/intrusive_ptr.hpp          | 2 +-
     include/boost/smart_ptr/shared_ptr.hpp             | 6 +++---
     include/boost/smart_ptr/weak_ptr.hpp               | 6 +++---
     test/sp_typeinfo_test.cpp                          | 4 ++--
     5 files changed, 12 insertions(+), 11 deletions(-)
    
    diff --git a/include/boost/smart_ptr/detail/quick_allocator.hpp b/include/boost/smart_ptr/detail/quick_allocator.hpp
    index 6d136f8..159bd5e 100644
    --- a/include/boost/smart_ptr/detail/quick_allocator.hpp
    +++ b/include/boost/smart_ptr/detail/quick_allocator.hpp
    @@ -74,8 +74,9 @@ template struct allocator_impl
     
         static lightweight_mutex & mutex()
         {
    -        static lightweight_mutex m;
    -        return m;
    +        static freeblock< sizeof( lightweight_mutex ), boost::alignment_of< lightweight_mutex >::value > fbm;
    +        static lightweight_mutex * pm = new( &fbm ) lightweight_mutex;
    +        return *pm;
         }
     
         static lightweight_mutex * mutex_init;
    diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp
    index 0e30ece..e72eb21 100644
    --- a/include/boost/smart_ptr/intrusive_ptr.hpp
    +++ b/include/boost/smart_ptr/intrusive_ptr.hpp
    @@ -77,7 +77,7 @@ public:
         template
     #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
     
    -    intrusive_ptr( intrusive_ptr const & rhs, typename detail::sp_enable_if_convertible::type = detail::sp_empty() )
    +    intrusive_ptr( intrusive_ptr const & rhs, typename boost::detail::sp_enable_if_convertible::type = boost::detail::sp_empty() )
     
     #else
     
    diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp
    index 8256d00..609cce9 100644
    --- a/include/boost/smart_ptr/shared_ptr.hpp
    +++ b/include/boost/smart_ptr/shared_ptr.hpp
    @@ -228,7 +228,7 @@ public:
         template
     #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
     
    -    shared_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() )
    +    shared_ptr( shared_ptr const & r, typename boost::detail::sp_enable_if_convertible::type = boost::detail::sp_empty() )
     
     #else
     
    @@ -353,7 +353,7 @@ public:
         template
     #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
     
    -    shared_ptr( shared_ptr && r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() )
    +    shared_ptr( shared_ptr && r, typename boost::detail::sp_enable_if_convertible::type = boost::detail::sp_empty() )
     
     #else
     
    @@ -448,7 +448,7 @@ public:
             return pn < rhs.pn;
         }
     
    -    void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const
    +    void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const
         {
             return pn.get_deleter( ti );
         }
    diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp
    index 8690cca..d314b0d 100644
    --- a/include/boost/smart_ptr/weak_ptr.hpp
    +++ b/include/boost/smart_ptr/weak_ptr.hpp
    @@ -63,7 +63,7 @@ public:
         template
     #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
     
    -    weak_ptr( weak_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() )
    +    weak_ptr( weak_ptr const & r, typename boost::detail::sp_enable_if_convertible::type = boost::detail::sp_empty() )
     
     #else
     
    @@ -79,7 +79,7 @@ public:
         template
     #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
     
    -    weak_ptr( weak_ptr && r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() )
    +    weak_ptr( weak_ptr && r, typename boost::detail::sp_enable_if_convertible::type = boost::detail::sp_empty() )
     
     #else
     
    @@ -110,7 +110,7 @@ public:
         template
     #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
     
    -    weak_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() )
    +    weak_ptr( shared_ptr const & r, typename boost::detail::sp_enable_if_convertible::type = boost::detail::sp_empty() )
     
     #else
     
    diff --git a/test/sp_typeinfo_test.cpp b/test/sp_typeinfo_test.cpp
    index c47d04e..e29e576 100644
    --- a/test/sp_typeinfo_test.cpp
    +++ b/test/sp_typeinfo_test.cpp
    @@ -28,7 +28,7 @@ int main()
         BOOST_TEST( !ti.before( ti ) );
     
         char const * nti = ti.name();
    -	std::cout << nti << std::endl;
    +    std::cout << nti << std::endl;
     
         boost::detail::sp_typeinfo const & tv = BOOST_SP_TYPEID( void );
     
    @@ -40,7 +40,7 @@ int main()
         BOOST_TEST( !tv.before( tv ) );
     
         char const * ntv = tv.name();
    -	std::cout << ntv << std::endl;
    +    std::cout << ntv << std::endl;
     
         BOOST_TEST( ti != tv );
         BOOST_TEST( !( ti == tv ) );
    
    From 697f33851002c5994cf0909481ca8104a8ba380b Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Mon, 5 Apr 2010 19:37:32 +0000
    Subject: [PATCH 064/140] Merge [61074]. Fixes #4067.
    
    [SVN r61078]
    ---
     include/boost/smart_ptr/detail/sp_convertible.hpp | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/include/boost/smart_ptr/detail/sp_convertible.hpp b/include/boost/smart_ptr/detail/sp_convertible.hpp
    index b7f0ea8..fe44069 100644
    --- a/include/boost/smart_ptr/detail/sp_convertible.hpp
    +++ b/include/boost/smart_ptr/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__ <= 0x620 )
    +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x630 )
     # define BOOST_SP_NO_SP_CONVERTIBLE
     #endif
     
    
    From 1f50e3abe4df6350c4cf405da62c8d3d490a1b4c Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 26 May 2010 17:25:06 +0000
    Subject: [PATCH 065/140] Merge [61574], [61575], [61579] to release.
    
    [SVN r62243]
    ---
     include/boost/smart_ptr/make_shared.hpp      | 98 ++++++++++----------
     test/make_shared_perfect_forwarding_test.cpp |  4 +-
     test/weak_ptr_test.cpp                       |  3 -
     3 files changed, 52 insertions(+), 53 deletions(-)
    
    diff --git a/include/boost/smart_ptr/make_shared.hpp b/include/boost/smart_ptr/make_shared.hpp
    index d477188..a01cec6 100644
    --- a/include/boost/smart_ptr/make_shared.hpp
    +++ b/include/boost/smart_ptr/make_shared.hpp
    @@ -87,10 +87,12 @@ public:
     };
     
     #if defined( BOOST_HAS_RVALUE_REFS )
    -template< class T > T&& forward( T &&t )
    +
    +template< class T > T&& sp_forward( T & t )
     {
    -    return t;
    +    return static_cast< T&& >( t );
     }
    +
     #endif
     
     } // namespace detail
    @@ -101,9 +103,9 @@ template< class T > T&& forward( T &&t )
     
     template< class T > boost::shared_ptr< T > make_shared()
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -118,9 +120,9 @@ template< class T > boost::shared_ptr< T > make_shared()
     
     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 );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -139,13 +141,13 @@ template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a
     
     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 >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    -    ::new( pv ) T( detail::forward( args )... );
    +    ::new( pv ) T( boost::detail::sp_forward( args )... );
         pd->set_initialized();
     
         T * pt2 = static_cast< T* >( pv );
    @@ -156,13 +158,13 @@ template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && .
     
     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 );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    -    ::new( pv ) T( detail::forward( args )... );
    +    ::new( pv ) T( boost::detail::sp_forward( args )... );
         pd->set_initialized();
     
         T * pt2 = static_cast< T* >( pv );
    @@ -178,9 +180,9 @@ template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shar
     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 >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -196,9 +198,9 @@ boost::shared_ptr< T > make_shared( A1 const & a1 )
     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 );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -214,9 +216,9 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 )
     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 >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -232,9 +234,9 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 )
     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 );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -250,9 +252,9 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     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 >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -268,9 +270,9 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3
     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 );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -286,9 +288,9 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     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 >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -304,9 +306,9 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
     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 );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -322,9 +324,9 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     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 >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -340,9 +342,9 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
     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 );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -358,9 +360,9 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     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 >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -376,9 +378,9 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
     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 );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -394,9 +396,9 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     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 >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -412,9 +414,9 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
     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 );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -430,9 +432,9 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     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 >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -448,9 +450,9 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
     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 );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -466,9 +468,9 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     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 >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    @@ -484,9 +486,9 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
     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 );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
     
    -    detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
         void * pv = pd->address();
     
    diff --git a/test/make_shared_perfect_forwarding_test.cpp b/test/make_shared_perfect_forwarding_test.cpp
    index 45a111c..ed7ee3b 100644
    --- a/test/make_shared_perfect_forwarding_test.cpp
    +++ b/test/make_shared_perfect_forwarding_test.cpp
    @@ -12,14 +12,14 @@
     #include 
     #include 
     
    -#ifndef BOOST_HAS_RVALUE_REFS
    +#if !defined( BOOST_HAS_RVALUE_REFS ) || !defined( BOOST_HAS_VARIADIC_TMPL )
     
     int main()
     {
         return 0;
     }
     
    -#else // BOOST_HAS_RVALUE_REFS
    +#else // BOOST_HAS_RVALUE_REFS, BOOST_HAS_VARIADIC_TMPL
     
     class myarg
     {
    diff --git a/test/weak_ptr_test.cpp b/test/weak_ptr_test.cpp
    index 7213794..a4ad766 100644
    --- a/test/weak_ptr_test.cpp
    +++ b/test/weak_ptr_test.cpp
    @@ -914,7 +914,6 @@ void test()
             BOOST_TEST(wp2.use_count() == 0);
             BOOST_TEST(!(wp < wp3 || wp3 < wp));
     
    -        using std::swap;
             swap(wp, wp2);
     
             BOOST_TEST(wp.use_count() == 0);
    @@ -950,7 +949,6 @@ void test()
             BOOST_TEST(wp2.use_count() == 0);
             BOOST_TEST(!(wp < wp3 || wp3 < wp));
     
    -        using std::swap;
             swap(wp, wp2);
     
             BOOST_TEST(wp.use_count() == 0);
    @@ -965,7 +963,6 @@ void test()
             BOOST_TEST(wp2.use_count() == 0);
             BOOST_TEST(!(wp < wp3 || wp3 < wp));
     
    -        using std::swap;
             swap(wp, wp2);
     
             BOOST_TEST(wp.use_count() == 0);
    
    From b9d77d877e9c06a5f53c7c4ec2d7c156e2bf5077 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 26 May 2010 17:34:01 +0000
    Subject: [PATCH 066/140] Merge [61344] to release. Fixes #4108.
    
    [SVN r62244]
    ---
     include/boost/smart_ptr/detail/sp_convertible.hpp | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/include/boost/smart_ptr/detail/sp_convertible.hpp b/include/boost/smart_ptr/detail/sp_convertible.hpp
    index fe44069..eb39797 100644
    --- a/include/boost/smart_ptr/detail/sp_convertible.hpp
    +++ b/include/boost/smart_ptr/detail/sp_convertible.hpp
    @@ -45,7 +45,7 @@ template< class Y, class T > struct sp_convertible
         static yes f( T* );
         static no  f( ... );
     
    -    enum _vt { value = sizeof( f( static_cast(0) ) ) == sizeof(yes) };
    +    enum _vt { value = sizeof( (f)( static_cast(0) ) ) == sizeof(yes) };
     };
     
     struct sp_empty
    
    From cfc82854d3e8c08c2da0c67788c21f7703a99383 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Sat, 10 Jul 2010 20:46:53 +0000
    Subject: [PATCH 067/140] Merge [62245] to release. Fixes #4199.
    
    [SVN r63825]
    ---
     include/boost/detail/sp_typeinfo.hpp | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/include/boost/detail/sp_typeinfo.hpp b/include/boost/detail/sp_typeinfo.hpp
    index 636fe27..3ee934f 100644
    --- a/include/boost/detail/sp_typeinfo.hpp
    +++ b/include/boost/detail/sp_typeinfo.hpp
    @@ -74,7 +74,7 @@ template struct sp_typeid_
         }
     };
     
    -template sp_typeinfo sp_typeid_< T >::ti_( sp_typeid_< T >::name() );
    +template sp_typeinfo sp_typeid_< T >::ti_ = sp_typeid_< T >::name();
     
     template struct sp_typeid_< T & >: sp_typeid_< T >
     {
    
    From 6ca6d3ce6f83d09547d8ab4063b42882027ed7e2 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Sat, 10 Jul 2010 21:07:05 +0000
    Subject: [PATCH 068/140] Merge [62246] to release. Fixes #4217.
    
    [SVN r63826]
    ---
     include/boost/smart_ptr/detail/yield_k.hpp | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/include/boost/smart_ptr/detail/yield_k.hpp b/include/boost/smart_ptr/detail/yield_k.hpp
    index a956cc0..23eadd8 100644
    --- a/include/boost/smart_ptr/detail/yield_k.hpp
    +++ b/include/boost/smart_ptr/detail/yield_k.hpp
    @@ -55,7 +55,7 @@ namespace detail
     {
     
     #if !defined( BOOST_USE_WINDOWS_H )
    -  extern "C" void __stdcall Sleep( unsigned ms );
    +  extern "C" void __stdcall Sleep( unsigned long ms );
     #endif
     
     inline void yield( unsigned k )
    
    From 0d77fd06785a924e8dd022a1f8b3661c5de8e12f Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Sat, 10 Jul 2010 21:17:40 +0000
    Subject: [PATCH 069/140] Merge [62248] to release. Fixes #3856.
    
    [SVN r63827]
    ---
     include/boost/smart_ptr/make_shared.hpp |  8 ++++----
     test/Jamfile.v2                         |  1 +
     test/make_shared_fp_test.cpp            | 19 +++++++++++++++++++
     3 files changed, 24 insertions(+), 4 deletions(-)
     create mode 100644 test/make_shared_fp_test.cpp
    
    diff --git a/include/boost/smart_ptr/make_shared.hpp b/include/boost/smart_ptr/make_shared.hpp
    index a01cec6..c4ed28a 100644
    --- a/include/boost/smart_ptr/make_shared.hpp
    +++ b/include/boost/smart_ptr/make_shared.hpp
    @@ -139,7 +139,7 @@ template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a
     
     // Variadic templates, rvalue reference
     
    -template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && ... args )
    +template< class T, class Arg1, class... Args > boost::shared_ptr< T > make_shared( Arg1 && arg1, Args && ... args )
     {
         boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
     
    @@ -147,7 +147,7 @@ template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && .
     
         void * pv = pd->address();
     
    -    ::new( pv ) T( boost::detail::sp_forward( args )... );
    +    ::new( pv ) T( boost::detail::sp_forward( arg1 ), boost::detail::sp_forward( args )... );
         pd->set_initialized();
     
         T * pt2 = static_cast< T* >( pv );
    @@ -156,7 +156,7 @@ template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && .
         return boost::shared_ptr< T >( pt, pt2 );
     }
     
    -template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Args && ... args )
    +template< class T, class A, class Arg1, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Arg1 && arg1, Args && ... args )
     {
         boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
     
    @@ -164,7 +164,7 @@ template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shar
     
         void * pv = pd->address();
     
    -    ::new( pv ) T( boost::detail::sp_forward( args )... );
    +    ::new( pv ) T( boost::detail::sp_forward( arg1 ), boost::detail::sp_forward( args )... );
         pd->set_initialized();
     
         T * pt2 = static_cast< T* >( pv );
    diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
    index 056b011..9b80ab8 100644
    --- a/test/Jamfile.v2
    +++ b/test/Jamfile.v2
    @@ -63,5 +63,6 @@ import testing ;
               [ compile-fail auto_ptr_lv_fail.cpp ]
               [ run atomic_count_test2.cpp ]
               [ run sp_typeinfo_test.cpp ]
    +          [ compile make_shared_fp_test.cpp ]
             ;
     }
    diff --git a/test/make_shared_fp_test.cpp b/test/make_shared_fp_test.cpp
    new file mode 100644
    index 0000000..f443d34
    --- /dev/null
    +++ b/test/make_shared_fp_test.cpp
    @@ -0,0 +1,19 @@
    +//
    +//  make_shared_fp_test.cpp
    +//
    +//  Copyright 2010 Georg Fritzsche
    +//
    +//  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 
    +
    +int main()
    +{
    +    typedef boost::shared_ptr(*FP)(); 
    +    FP fp = boost::make_shared;
    +}
    
    From d71cc6ab081434ba77feeecd75b4199ec90ac18a Mon Sep 17 00:00:00 2001
    From: Hartmut Kaiser 
    Date: Sun, 24 Oct 2010 22:24:54 +0000
    Subject: [PATCH 070/140] Merging from trunk
    
    [SVN r66166]
    ---
     include/boost/detail/sp_typeinfo.hpp | 6 ++++++
     1 file changed, 6 insertions(+)
    
    diff --git a/include/boost/detail/sp_typeinfo.hpp b/include/boost/detail/sp_typeinfo.hpp
    index 3ee934f..43fae78 100644
    --- a/include/boost/detail/sp_typeinfo.hpp
    +++ b/include/boost/detail/sp_typeinfo.hpp
    @@ -74,7 +74,13 @@ template struct sp_typeid_
         }
     };
     
    +#if defined(__SUNPRO_CC)
    +// see #4199, the Sun Studio compiler gets confused about static initialization 
    +// constructor arguments. But an assignment works just fine. 
     template sp_typeinfo sp_typeid_< T >::ti_ = sp_typeid_< T >::name();
    +#else
    +template sp_typeinfo sp_typeid_< T >::ti_(sp_typeid_< T >::name());
    +#endif
     
     template struct sp_typeid_< T & >: sp_typeid_< T >
     {
    
    From 545745d649d99e28466018f6edaee245efc67f49 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Tue, 22 Mar 2011 23:05:48 +0000
    Subject: [PATCH 071/140] Merge [69242] to release. Fixes #4288. Fixes #5189.
    
    [SVN r70432]
    ---
     include/boost/smart_ptr.hpp | 6 ++++++
     test/smart_ptr_test.cpp     | 5 +----
     2 files changed, 7 insertions(+), 4 deletions(-)
    
    diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp
    index 98e0894..b5e569d 100644
    --- a/include/boost/smart_ptr.hpp
    +++ b/include/boost/smart_ptr.hpp
    @@ -1,3 +1,6 @@
    +#ifndef BOOST_SMART_PTR_HPP_INCLUDED
    +#define BOOST_SMART_PTR_HPP_INCLUDED
    +
     //
     //  smart_ptr.hpp
     //
    @@ -22,4 +25,7 @@
     # include 
     # include 
     # include 
    +# include 
     #endif
    +
    +#endif // #ifndef BOOST_SMART_PTR_HPP_INCLUDED
    diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp
    index 8832deb..7b4de34 100644
    --- a/test/smart_ptr_test.cpp
    +++ b/test/smart_ptr_test.cpp
    @@ -33,10 +33,7 @@
     # pragma warn -8092 // template argument passed to 'find' is not an iterator
     #endif
     
    -#include 
    -#include 
    -#include 
    -#include 
    +#include 
     
     #include 
     
    
    From 445e8d1728e1e443cd8335c313edb53626804d98 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Tue, 22 Mar 2011 23:17:51 +0000
    Subject: [PATCH 072/140] Merge [69244] to release. Fixes #4892.
    
    [SVN r70433]
    ---
     include/boost/smart_ptr/make_shared.hpp      | 454 +++++++++++++++++++
     test/make_shared_perfect_forwarding_test.cpp |   4 +-
     2 files changed, 456 insertions(+), 2 deletions(-)
    
    diff --git a/include/boost/smart_ptr/make_shared.hpp b/include/boost/smart_ptr/make_shared.hpp
    index c4ed28a..3d12bbe 100644
    --- a/include/boost/smart_ptr/make_shared.hpp
    +++ b/include/boost/smart_ptr/make_shared.hpp
    @@ -173,6 +173,460 @@ template< class T, class A, class Arg1, class... Args > boost::shared_ptr< T > a
         return boost::shared_ptr< T >( pt, pt2 );
     }
     
    +#elif defined( BOOST_HAS_RVALUE_REFS )
    +
    +// For example MSVC 10.0
    +
    +template< class T, class A1 >
    +boost::shared_ptr< T > make_shared( A1 && a1 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1 >
    +boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2 >
    +boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2 >
    +boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3 >
    +boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3 >
    +boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4 >
    +boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3, class A4 >
    +boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4, class A5 >
    +boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
    +boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
    +boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 ), 
    +        boost::detail::sp_forward( a7 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 ), 
    +        boost::detail::sp_forward( a7 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 ), 
    +        boost::detail::sp_forward( a7 ), 
    +        boost::detail::sp_forward( a8 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 ), 
    +        boost::detail::sp_forward( a7 ), 
    +        boost::detail::sp_forward( a8 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 ), 
    +        boost::detail::sp_forward( a7 ), 
    +        boost::detail::sp_forward( a8 ), 
    +        boost::detail::sp_forward( a9 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 ), 
    +        boost::detail::sp_forward( a7 ), 
    +        boost::detail::sp_forward( a8 ), 
    +        boost::detail::sp_forward( a9 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
     #else
     
     // C++03 version
    diff --git a/test/make_shared_perfect_forwarding_test.cpp b/test/make_shared_perfect_forwarding_test.cpp
    index ed7ee3b..bd5f5c5 100644
    --- a/test/make_shared_perfect_forwarding_test.cpp
    +++ b/test/make_shared_perfect_forwarding_test.cpp
    @@ -12,14 +12,14 @@
     #include 
     #include 
     
    -#if !defined( BOOST_HAS_RVALUE_REFS ) || !defined( BOOST_HAS_VARIADIC_TMPL )
    +#if !defined( BOOST_HAS_RVALUE_REFS )
     
     int main()
     {
         return 0;
     }
     
    -#else // BOOST_HAS_RVALUE_REFS, BOOST_HAS_VARIADIC_TMPL
    +#else // BOOST_HAS_RVALUE_REFS
     
     class myarg
     {
    
    From 1086aff971f977d1eacdfcb1698fb448e63970b0 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Tue, 22 Mar 2011 23:23:44 +0000
    Subject: [PATCH 073/140] Merge [69245] to release. Fixes #4433.
    
    [SVN r70434]
    ---
     include/boost/smart_ptr/intrusive_ptr.hpp | 9 ---------
     include/boost/smart_ptr/shared_ptr.hpp    | 9 ---------
     2 files changed, 18 deletions(-)
    
    diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp
    index e72eb21..2fa4670 100644
    --- a/include/boost/smart_ptr/intrusive_ptr.hpp
    +++ b/include/boost/smart_ptr/intrusive_ptr.hpp
    @@ -15,11 +15,6 @@
     
     #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 
    @@ -292,8 +287,4 @@ template std::basic_ostream & operator<< (std::
     
     } // 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/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp
    index 609cce9..27e6ee4 100644
    --- a/include/boost/smart_ptr/shared_ptr.hpp
    +++ b/include/boost/smart_ptr/shared_ptr.hpp
    @@ -50,11 +50,6 @@
     #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
     {
     
    @@ -692,10 +687,6 @@ template inline bool atomic_compare_exchange_explicit( shared_ptr *
     
     } // 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
    
    From b978919dd16da11f982c6b1a2134309c895ab382 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Tue, 22 Mar 2011 23:29:35 +0000
    Subject: [PATCH 074/140] Merge [69246] to release. Fixes #4478.
    
    [SVN r70435]
    ---
     include/boost/smart_ptr/detail/spinlock_pool.hpp | 4 ++++
     1 file changed, 4 insertions(+)
    
    diff --git a/include/boost/smart_ptr/detail/spinlock_pool.hpp b/include/boost/smart_ptr/detail/spinlock_pool.hpp
    index 0e2e08a..f09d5c6 100644
    --- a/include/boost/smart_ptr/detail/spinlock_pool.hpp
    +++ b/include/boost/smart_ptr/detail/spinlock_pool.hpp
    @@ -41,7 +41,11 @@ public:
     
         static spinlock & spinlock_for( void const * pv )
         {
    +#if defined(__VMS) && __INITIAL_POINTER_SIZE == 64  
    +        std::size_t i = reinterpret_cast< unsigned long long >( pv ) % 41;
    +#else  
             std::size_t i = reinterpret_cast< std::size_t >( pv ) % 41;
    +#endif  
             return pool_[ i ];
         }
     
    
    From cf7b6904e87e1a07f8b707aa214a508109ae0df5 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Tue, 22 Mar 2011 23:38:12 +0000
    Subject: [PATCH 075/140] Merge [69250] to release. Fixes #4256. Fixes #3875.
    
    [SVN r70436]
    ---
     .../boost/smart_ptr/detail/shared_count.hpp   | 88 +++++++++++++++++++
     .../smart_ptr/detail/sp_counted_impl.hpp      | 12 ++-
     include/boost/smart_ptr/make_shared.hpp       | 88 ++++++++++---------
     3 files changed, 146 insertions(+), 42 deletions(-)
    
    diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp
    index 4943e37..f96a220 100644
    --- a/include/boost/smart_ptr/detail/shared_count.hpp
    +++ b/include/boost/smart_ptr/detail/shared_count.hpp
    @@ -52,6 +52,10 @@ int const   weak_count_id = 0x298C38A4;
     
     struct sp_nothrow_tag {};
     
    +template< class D > struct sp_inplace_tag
    +{
    +};
    +
     class weak_count;
     
     class shared_count
    @@ -142,6 +146,40 @@ public:
     #endif
         }
     
    +#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
    +
    +    template< class P, class D > shared_count( P p, sp_inplace_tag ): pi_( 0 )
    +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
    +        , id_(shared_count_id)
    +#endif
    +    {
    +#ifndef BOOST_NO_EXCEPTIONS
    +
    +        try
    +        {
    +            pi_ = new sp_counted_impl_pd< P, D >( p );
    +        }
    +        catch( ... )
    +        {
    +            D()( p ); // delete p
    +            throw;
    +        }
    +
    +#else
    +
    +        pi_ = new sp_counted_impl_pd< P, D >( p );
    +
    +        if( pi_ == 0 )
    +        {
    +            D()( p ); // delete p
    +            boost::throw_exception( std::bad_alloc() );
    +        }
    +
    +#endif // #ifndef BOOST_NO_EXCEPTIONS
    +    }
    +
    +#endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
    +
         template shared_count( P p, D d, A a ): pi_( 0 )
     #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
             , id_(shared_count_id)
    @@ -188,6 +226,56 @@ public:
     #endif
         }
     
    +#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
    +
    +    template< class P, class D, class A > shared_count( P p, sp_inplace_tag< D >, A a ): pi_( 0 )
    +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
    +        , id_(shared_count_id)
    +#endif
    +    {
    +        typedef sp_counted_impl_pda< P, D, A > impl_type;
    +        typedef typename A::template rebind< impl_type >::other A2;
    +
    +        A2 a2( a );
    +
    +#ifndef BOOST_NO_EXCEPTIONS
    +
    +        try
    +        {
    +            pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
    +            new( static_cast< void* >( pi_ ) ) impl_type( p, a );
    +        }
    +        catch(...)
    +        {
    +            D()( p );
    +
    +            if( pi_ != 0 )
    +            {
    +                a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
    +            }
    +
    +            throw;
    +        }
    +
    +#else
    +
    +        pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
    +
    +        if( pi_ != 0 )
    +        {
    +            new( static_cast< void* >( pi_ ) ) impl_type( p, a );
    +        }
    +        else
    +        {
    +            D()( p );
    +            boost::throw_exception( std::bad_alloc() );
    +        }
    +
    +#endif // #ifndef BOOST_NO_EXCEPTIONS
    +    }
    +
    +#endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
    +
     #ifndef BOOST_NO_AUTO_PTR
     
         // auto_ptr is special cased to provide the strong guarantee
    diff --git a/include/boost/smart_ptr/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp
    index 397421a..aab39bd 100644
    --- a/include/boost/smart_ptr/detail/sp_counted_impl.hpp
    +++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp
    @@ -135,7 +135,11 @@ public:
     
         // pre: d(p) must not throw
     
    -    sp_counted_impl_pd( P p, D d ): ptr(p), del(d)
    +    sp_counted_impl_pd( P p, D & d ): ptr( p ), del( d )
    +    {
    +    }
    +
    +    sp_counted_impl_pd( P p ): ptr( p ), del()
         {
         }
     
    @@ -195,7 +199,11 @@ public:
     
         // pre: d( p ) must not throw
     
    -    sp_counted_impl_pda( P p, D d, A a ): p_( p ), d_( d ), a_( a )
    +    sp_counted_impl_pda( P p, D & d, A a ): p_( p ), d_( d ), a_( a )
    +    {
    +    }
    +
    +    sp_counted_impl_pda( P p, A a ): p_( p ), d_(), a_( a )
         {
         }
     
    diff --git a/include/boost/smart_ptr/make_shared.hpp b/include/boost/smart_ptr/make_shared.hpp
    index 3d12bbe..3d40aa2 100644
    --- a/include/boost/smart_ptr/make_shared.hpp
    +++ b/include/boost/smart_ptr/make_shared.hpp
    @@ -97,13 +97,19 @@ template< class T > T&& sp_forward( T & t )
     
     } // namespace detail
     
    +#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
    +# define BOOST_SP_MSD( T ) boost::detail::sp_inplace_tag< boost::detail::sp_ms_deleter< T > >()
    +#else
    +# define BOOST_SP_MSD( T ) boost::detail::sp_ms_deleter< T >()
    +#endif
    +
     // 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 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -120,7 +126,7 @@ template< class T > boost::shared_ptr< T > make_shared()
     
     template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -141,7 +147,7 @@ template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a
     
     template< class T, class Arg1, class... Args > boost::shared_ptr< T > make_shared( Arg1 && arg1, Args && ... args )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -158,7 +164,7 @@ template< class T, class Arg1, class... Args > boost::shared_ptr< T > make_share
     
     template< class T, class A, class Arg1, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Arg1 && arg1, Args && ... args )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -180,7 +186,7 @@ template< class T, class A, class Arg1, class... Args > boost::shared_ptr< T > a
     template< class T, class A1 >
     boost::shared_ptr< T > make_shared( A1 && a1 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -201,7 +207,7 @@ boost::shared_ptr< T > make_shared( A1 && a1 )
     template< class T, class A, class A1 >
     boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -222,7 +228,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1 )
     template< class T, class A1, class A2 >
     boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -244,7 +250,7 @@ boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2 )
     template< class T, class A, class A1, class A2 >
     boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -266,7 +272,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2 )
     template< class T, class A1, class A2, class A3 >
     boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -289,7 +295,7 @@ boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3 )
     template< class T, class A, class A1, class A2, class A3 >
     boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -312,7 +318,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a
     template< class T, class A1, class A2, class A3, class A4 >
     boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -336,7 +342,7 @@ boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4 )
     template< class T, class A, class A1, class A2, class A3, class A4 >
     boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -360,7 +366,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a
     template< class T, class A1, class A2, class A3, class A4, class A5 >
     boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -385,7 +391,7 @@ boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 &
     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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -410,7 +416,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a
     template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
     boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -436,7 +442,7 @@ boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 &
     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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -462,7 +468,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a
     template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
     boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -489,7 +495,7 @@ boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 &
     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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -516,7 +522,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a
     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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -544,7 +550,7 @@ boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 &
     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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -572,7 +578,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a
     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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -601,7 +607,7 @@ boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 &
     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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -634,7 +640,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a
     template< class T, class A1 >
     boost::shared_ptr< T > make_shared( A1 const & a1 )
     {
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -652,7 +658,7 @@ boost::shared_ptr< T > make_shared( A1 const & a1 )
     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 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -670,7 +676,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 )
     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 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -688,7 +694,7 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 )
     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 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -706,7 +712,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     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 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -724,7 +730,7 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3
     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 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -742,7 +748,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     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 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -760,7 +766,7 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
     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 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -778,7 +784,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     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 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -796,7 +802,7 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
     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 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -814,7 +820,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     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 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -832,7 +838,7 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
     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 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -850,7 +856,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     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 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -868,7 +874,7 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
     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 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -886,7 +892,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     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 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -904,7 +910,7 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
     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 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -922,7 +928,7 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     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 ), boost::detail::sp_ms_deleter< T >() );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -940,7 +946,7 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
     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 ), boost::detail::sp_ms_deleter< T >(), a );
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
     
         boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
     
    @@ -957,6 +963,8 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
     
     #endif
     
    +#undef BOOST_SP_MSD
    +
     } // namespace boost
     
     #endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED
    
    From 210288f02e41390210aa7f6be9ef085c08a456c7 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Tue, 22 Mar 2011 23:45:59 +0000
    Subject: [PATCH 076/140] Merge [69251] to release. Fixes #4127.
    
    [SVN r70439]
    ---
     include/boost/smart_ptr/make_shared.hpp | 11 +++++++++++
     1 file changed, 11 insertions(+)
    
    diff --git a/include/boost/smart_ptr/make_shared.hpp b/include/boost/smart_ptr/make_shared.hpp
    index 3d40aa2..7b605e2 100644
    --- a/include/boost/smart_ptr/make_shared.hpp
    +++ b/include/boost/smart_ptr/make_shared.hpp
    @@ -49,7 +49,18 @@ private:
         {
             if( initialized_ )
             {
    +#if defined( __GNUC__ )
    +
    +            // fixes incorrect aliasing warning
    +            T * p = reinterpret_cast< T* >( storage_.data_ );
    +            p->~T();
    +
    +#else
    +
                 reinterpret_cast< T* >( storage_.data_ )->~T();
    +
    +#endif
    +
                 initialized_ = false;
             }
         }
    
    From 7c0815c567a5c800b2412d5ca97125babd00b4df Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Tue, 22 Mar 2011 23:51:10 +0000
    Subject: [PATCH 077/140] Merge [69260] to release. Fixes #5216.
    
    [SVN r70440]
    ---
     include/boost/smart_ptr/shared_ptr.hpp | 12 ++++++++-
     test/Jamfile.v2                        |  1 +
     test/sp_hash_test.cpp                  | 34 ++++++++++++++++++++++++++
     3 files changed, 46 insertions(+), 1 deletion(-)
     create mode 100644 test/sp_hash_test.cpp
    
    diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp
    index 27e6ee4..100f1a8 100644
    --- a/include/boost/smart_ptr/shared_ptr.hpp
    +++ b/include/boost/smart_ptr/shared_ptr.hpp
    @@ -41,6 +41,7 @@
     #include             // for std::swap
     #include            // for std::less
     #include              // for std::bad_cast
    +#include               // for std::size_t
     
     #if !defined(BOOST_NO_IOSTREAM)
     #if !defined(BOOST_NO_IOSFWD)
    @@ -683,7 +684,16 @@ template inline bool atomic_compare_exchange_explicit( shared_ptr *
         return atomic_compare_exchange( p, v, w ); // std::move( w )
     }
     
    -#endif
    +#endif // !defined(BOOST_SP_NO_ATOMIC_ACCESS)
    +
    +// hash_value
    +
    +template< class T > struct hash;
    +
    +template< class T > std::size_t hash_value( boost::shared_ptr const & p )
    +{
    +    return boost::hash< T* >()( p.get() );
    +}
     
     } // namespace boost
     
    diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
    index 9b80ab8..811aa41 100644
    --- a/test/Jamfile.v2
    +++ b/test/Jamfile.v2
    @@ -64,5 +64,6 @@ import testing ;
               [ run atomic_count_test2.cpp ]
               [ run sp_typeinfo_test.cpp ]
               [ compile make_shared_fp_test.cpp ]
    +          [ run sp_hash_test.cpp ]
             ;
     }
    diff --git a/test/sp_hash_test.cpp b/test/sp_hash_test.cpp
    new file mode 100644
    index 0000000..b67f547
    --- /dev/null
    +++ b/test/sp_hash_test.cpp
    @@ -0,0 +1,34 @@
    +//
    +// sp_hash_test.cpp
    +//
    +// Copyright 2011 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 
    +
    +int main()
    +{
    +    boost::hash< boost::shared_ptr > hasher;
    +
    +    boost::shared_ptr< int > p1, p2( p1 ), p3( new int ), p4( p3 ), p5( new int );
    +
    +    BOOST_TEST_EQ( p1, p2 );
    +    BOOST_TEST_EQ( hasher( p1 ), hasher( p2 ) );
    +
    +    BOOST_TEST_NE( p1, p3 );
    +    BOOST_TEST_NE( hasher( p1 ), hasher( p3 ) );
    +
    +    BOOST_TEST_EQ( p3, p4 );
    +    BOOST_TEST_EQ( hasher( p3 ), hasher( p4 ) );
    +
    +    BOOST_TEST_NE( p3, p5 );
    +    BOOST_TEST_NE( hasher( p3 ), hasher( p5 ) );
    +
    +    return boost::report_errors();
    +}
    
    From c5b47e21361b2065b113e53208ad1be259115b23 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Tue, 22 Mar 2011 23:55:05 +0000
    Subject: [PATCH 078/140] Merge [69261] to release. Fixes #5019.
    
    [SVN r70441]
    ---
     include/boost/smart_ptr/detail/sp_has_sync.hpp | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/include/boost/smart_ptr/detail/sp_has_sync.hpp b/include/boost/smart_ptr/detail/sp_has_sync.hpp
    index 7fcd09e..31cedbc 100644
    --- a/include/boost/smart_ptr/detail/sp_has_sync.hpp
    +++ b/include/boost/smart_ptr/detail/sp_has_sync.hpp
    @@ -20,7 +20,7 @@
     //  are available.
     //
     
    -#if defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
    +#if defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( BOOST_SP_NO_SYNC )
     
     #define BOOST_SP_HAS_SYNC
     
    
    From 8abc8889d11ab46076795aa7d6d34ca8b80e663a Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 23 Mar 2011 00:13:54 +0000
    Subject: [PATCH 079/140] Merge [69262] to release. Fixes #5018.
    
    [SVN r70447]
    ---
     include/boost/smart_ptr/detail/spinlock.hpp | 5 ++++-
     1 file changed, 4 insertions(+), 1 deletion(-)
    
    diff --git a/include/boost/smart_ptr/detail/spinlock.hpp b/include/boost/smart_ptr/detail/spinlock.hpp
    index 1640a38..88d7ad6 100644
    --- a/include/boost/smart_ptr/detail/spinlock.hpp
    +++ b/include/boost/smart_ptr/detail/spinlock.hpp
    @@ -31,7 +31,10 @@
     #include 
     #include 
     
    -#if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ )
    +#if defined( BOOST_SP_USE_PTHREADS )
    +#  include 
    +
    +#elif defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ )
     #  include 
     
     #elif defined( BOOST_SP_HAS_SYNC )
    
    From d6ac116b71ba710849e35f0881a3d94000dee200 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Fri, 5 Aug 2011 08:58:31 +0000
    Subject: [PATCH 080/140] Merge [73202] to release.
    
    [SVN r73542]
    ---
     include/boost/smart_ptr/shared_array.hpp | 20 +++++++++++++++++++-
     include/boost/smart_ptr/shared_ptr.hpp   | 12 +++++++++++-
     include/boost/smart_ptr/weak_ptr.hpp     | 18 +++++++++++++++++-
     3 files changed, 47 insertions(+), 3 deletions(-)
    
    diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp
    index 1f50403..0acdff7 100644
    --- a/include/boost/smart_ptr/shared_array.hpp
    +++ b/include/boost/smart_ptr/shared_array.hpp
    @@ -69,7 +69,25 @@ public:
         {
         }
     
    -//  generated copy constructor, assignment, destructor are fine
    +//  generated copy constructor, destructor are fine...
    +
    +#if defined( BOOST_HAS_RVALUE_REFS )
    +
    +// ... except in C++0x, move disables the implicit copy
    +
    +    shared_array( shared_array const & r ): px( r.px ), pn( r.pn ) // never throws
    +    {
    +    }
    +
    +#endif
    +
    +    // assignment
    +
    +    shared_array & operator=( shared_array const & r ) // never throws
    +    {
    +        this_type( r ).swap( *this );
    +        return *this;
    +    }
     
         void reset(T * p = 0)
         {
    diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp
    index 100f1a8..9ead1ba 100644
    --- a/include/boost/smart_ptr/shared_ptr.hpp
    +++ b/include/boost/smart_ptr/shared_ptr.hpp
    @@ -203,7 +203,17 @@ public:
             boost::detail::sp_enable_shared_from_this( this, p, p );
         }
     
    -//  generated copy constructor, destructor are fine
    +//  generated copy constructor, destructor are fine...
    +
    +#if defined( BOOST_HAS_RVALUE_REFS )
    +
    +// ... except in C++0x, move disables the implicit copy
    +
    +    shared_ptr( shared_ptr const & r ): px( r.px ), pn( r.pn ) // never throws
    +    {
    +    }
    +
    +#endif
     
         template
         explicit shared_ptr(weak_ptr const & r): pn(r.pn) // may throw
    diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp
    index d314b0d..34b0d1e 100644
    --- a/include/boost/smart_ptr/weak_ptr.hpp
    +++ b/include/boost/smart_ptr/weak_ptr.hpp
    @@ -40,8 +40,24 @@ public:
         {
         }
     
    -//  generated copy constructor, assignment, destructor are fine
    +//  generated copy constructor, assignment, destructor are fine...
     
    +#if defined( BOOST_HAS_RVALUE_REFS )
    +
    +// ... except in C++0x, move disables the implicit copy
    +
    +    weak_ptr( weak_ptr const & r ): px( r.px ), pn( r.pn ) // never throws
    +    {
    +    }
    +
    +    weak_ptr & operator=( weak_ptr const & r ) // never throws
    +    {
    +        px = r.px;
    +        pn = r.pn;
    +        return *this;
    +    }
    +
    +#endif
     
     //
     //  The "obvious" converting constructor implementation:
    
    From 7cb040edb0fd0557d34629447bb7e3750ddc3ae5 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Mon, 7 Nov 2011 14:25:23 +0000
    Subject: [PATCH 081/140] Merge [70452] to release. Fixes #5327.
    
    [SVN r75381]
    ---
     .../boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp  | 9 +++++++++
     1 file changed, 9 insertions(+)
    
    diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
    index 0c69b0b..3f1f449 100644
    --- a/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
    +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
    @@ -37,9 +37,12 @@ inline void atomic_increment( int * pw )
         __asm__ __volatile__
         (
             "0:\n\t"
    +        ".set push\n\t"
    +        ".set mips2\n\t"
             "ll %0, %1\n\t"
             "addiu %0, 1\n\t"
             "sc %0, %1\n\t"
    +        ".set pop\n\t"
             "beqz %0, 0b":
             "=&r"( tmp ), "=m"( *pw ):
             "m"( *pw )
    @@ -55,9 +58,12 @@ inline int atomic_decrement( int * pw )
         __asm__ __volatile__
         (
             "0:\n\t"
    +        ".set push\n\t"
    +        ".set mips2\n\t"
             "ll %1, %2\n\t"
             "addiu %0, %1, -1\n\t"
             "sc %0, %2\n\t"
    +        ".set pop\n\t"
             "beqz %0, 0b\n\t"
             "addiu %0, %1, -1":
             "=&r"( rv ), "=&r"( tmp ), "=m"( *pw ):
    @@ -78,10 +84,13 @@ inline int atomic_conditional_increment( int * pw )
         __asm__ __volatile__
         (
             "0:\n\t"
    +        ".set push\n\t"
    +        ".set mips2\n\t"
             "ll %0, %2\n\t"
             "beqz %0, 1f\n\t"
             "addiu %1, %0, 1\n\t"
             "sc %1, %2\n\t"
    +        ".set pop\n\t"
             "beqz %1, 0b\n\t"
             "addiu %0, %0, 1\n\t"
             "1:":
    
    From 7b097467d626a4813cda0b666bdcacf50fb4b32e Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Mon, 7 Nov 2011 15:05:43 +0000
    Subject: [PATCH 082/140] Merge [75385] to release. Fixes #6099.
    
    [SVN r75386]
    ---
     include/boost/smart_ptr/detail/sp_has_sync.hpp | 4 ++++
     1 file changed, 4 insertions(+)
    
    diff --git a/include/boost/smart_ptr/detail/sp_has_sync.hpp b/include/boost/smart_ptr/detail/sp_has_sync.hpp
    index 31cedbc..12acea8 100644
    --- a/include/boost/smart_ptr/detail/sp_has_sync.hpp
    +++ b/include/boost/smart_ptr/detail/sp_has_sync.hpp
    @@ -36,6 +36,10 @@
     #undef BOOST_SP_HAS_SYNC
     #endif
     
    +#if defined( __sh__ )
    +#undef BOOST_SP_HAS_SYNC
    +#endif
    +
     #if defined( __sparc__ )
     #undef BOOST_SP_HAS_SYNC
     #endif
    
    From c846d230f03aa915f44e636ca0b5d6b0e2bffe17 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 30 Nov 2011 17:49:43 +0000
    Subject: [PATCH 083/140] Merge [75389] to release. Fixes #5372.
    
    [SVN r75753]
    ---
     .../smart_ptr/detail/spinlock_gcc_arm.hpp     | 23 ++++++++++++++++---
     1 file changed, 20 insertions(+), 3 deletions(-)
    
    diff --git a/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp b/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp
    index ba6c511..f58ea44 100644
    --- a/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp
    +++ b/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp
    @@ -2,7 +2,7 @@
     #define BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED
     
     //
    -//  Copyright (c) 2008 Peter Dimov
    +//  Copyright (c) 2008, 2011 Peter Dimov
     //
     //  Distributed under the Boost Software License, Version 1.0.
     //  See accompanying file LICENSE_1_0.txt or copy at
    @@ -11,6 +11,20 @@
     
     #include 
     
    +#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
    +
    +# define BOOST_SP_ARM_BARRIER "dmb"
    +
    +#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__)
    +
    +# define BOOST_SP_ARM_BARRIER "mcr p15, 0, r0, c7, c10, 5"
    +
    +#else
    +
    +# define BOOST_SP_ARM_BARRIER ""
    +
    +#endif
    +
     namespace boost
     {
     
    @@ -30,7 +44,8 @@ public:
             int r;
     
             __asm__ __volatile__(
    -            "swp %0, %1, [%2]":
    +            "swp %0, %1, [%2]\n\t"
    +			BOOST_SP_ARM_BARRIER :
                 "=&r"( r ): // outputs
                 "r"( 1 ), "r"( &v_ ): // inputs
                 "memory", "cc" );
    @@ -48,7 +63,7 @@ public:
     
         void unlock()
         {
    -        __asm__ __volatile__( "" ::: "memory" );
    +        __asm__ __volatile__( BOOST_SP_ARM_BARRIER ::: "memory" );
             *const_cast< int volatile* >( &v_ ) = 0;
         }
     
    @@ -82,4 +97,6 @@ public:
     
     #define BOOST_DETAIL_SPINLOCK_INIT {0}
     
    +#undef BOOST_SP_ARM_BARRIER
    +
     #endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED
    
    From 5fc9bf5bc55a290857406bb0bca5b3d794cb79c6 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 30 Nov 2011 17:51:43 +0000
    Subject: [PATCH 084/140] Merge [75390] to release. Fixes #4493.
    
    [SVN r75754]
    ---
     include/boost/smart_ptr/shared_array.hpp | 10 +++
     test/Jamfile.v2                          |  1 +
     test/get_deleter_array_test.cpp          | 95 ++++++++++++++++++++++++
     3 files changed, 106 insertions(+)
     create mode 100644 test/get_deleter_array_test.cpp
    
    diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp
    index 0acdff7..36799e6 100644
    --- a/include/boost/smart_ptr/shared_array.hpp
    +++ b/include/boost/smart_ptr/shared_array.hpp
    @@ -131,6 +131,11 @@ public:
             pn.swap(other.pn);
         }
     
    +    void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const
    +    {
    +        return pn.get_deleter( ti );
    +    }
    +
     private:
     
         T * px;                     // contained pointer
    @@ -158,6 +163,11 @@ template void swap(shared_array & a, shared_array & b) // never t
         a.swap(b);
     }
     
    +template< class D, class T > D * get_deleter( shared_array const & p )
    +{
    +    return static_cast< D * >( p._internal_get_deleter( BOOST_SP_TYPEID(D) ) );
    +}
    +
     } // namespace boost
     
     #endif  // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
    diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
    index 811aa41..8dcb8ee 100644
    --- a/test/Jamfile.v2
    +++ b/test/Jamfile.v2
    @@ -65,5 +65,6 @@ import testing ;
               [ run sp_typeinfo_test.cpp ]
               [ compile make_shared_fp_test.cpp ]
               [ run sp_hash_test.cpp ]
    +          [ run get_deleter_array_test.cpp ]
             ;
     }
    diff --git a/test/get_deleter_array_test.cpp b/test/get_deleter_array_test.cpp
    new file mode 100644
    index 0000000..f6d2500
    --- /dev/null
    +++ b/test/get_deleter_array_test.cpp
    @@ -0,0 +1,95 @@
    +//
    +//  get_deleter_array_test.cpp
    +//
    +//  Copyright (c) 2002, 2011 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 deleter
    +{
    +    int data;
    +
    +    deleter(): data(0)
    +    {
    +    }
    +
    +    void operator()(void *)
    +    {
    +        BOOST_TEST(data == 17041);
    +    }
    +};
    +
    +struct deleter2
    +{
    +};
    +
    +struct X
    +{
    +};
    +
    +int main()
    +{
    +    {
    +        boost::shared_array p;
    +
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +    }
    +
    +    {
    +        boost::shared_array p(new X[1]);
    +
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +    }
    +
    +    {
    +        X x[1];
    +        boost::shared_array p(x, deleter());
    +
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +        BOOST_TEST(boost::get_deleter(p) == 0);
    +
    +        deleter * q = boost::get_deleter(p);
    +
    +        BOOST_TEST(q != 0);
    +        BOOST_TEST(q->data == 0);
    +
    +        q->data = 17041;
    +
    +        deleter const * r = boost::get_deleter(p);
    +
    +        BOOST_TEST(r == q);
    +        BOOST_TEST(r->data == 17041);
    +    }
    +
    +    return boost::report_errors();
    +}
    
    From 1c208ad3ea4d079dfe5a3ca7d41754af43cb6c40 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 30 Nov 2011 18:01:02 +0000
    Subject: [PATCH 085/140] Merge [75392] to release. Fixes #6087.
    
    [SVN r75756]
    ---
     include/boost/smart_ptr/intrusive_ptr.hpp |  9 +++
     test/Jamfile.v2                           |  1 +
     test/ip_hash_test.cpp                     | 75 +++++++++++++++++++++++
     3 files changed, 85 insertions(+)
     create mode 100644 test/ip_hash_test.cpp
    
    diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp
    index 2fa4670..a575223 100644
    --- a/include/boost/smart_ptr/intrusive_ptr.hpp
    +++ b/include/boost/smart_ptr/intrusive_ptr.hpp
    @@ -285,6 +285,15 @@ template std::basic_ostream & operator<< (std::
     
     #endif // !defined(BOOST_NO_IOSTREAM)
     
    +// hash_value
    +
    +template< class T > struct hash;
    +
    +template< class T > std::size_t hash_value( boost::intrusive_ptr const & p )
    +{
    +    return boost::hash< T* >()( p.get() );
    +}
    +
     } // namespace boost
     
     #endif  // #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
    diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
    index 8dcb8ee..a11b431 100644
    --- a/test/Jamfile.v2
    +++ b/test/Jamfile.v2
    @@ -66,5 +66,6 @@ import testing ;
               [ compile make_shared_fp_test.cpp ]
               [ run sp_hash_test.cpp ]
               [ run get_deleter_array_test.cpp ]
    +          [ run ip_hash_test.cpp ]
             ;
     }
    diff --git a/test/ip_hash_test.cpp b/test/ip_hash_test.cpp
    new file mode 100644
    index 0000000..be38b3d
    --- /dev/null
    +++ b/test/ip_hash_test.cpp
    @@ -0,0 +1,75 @@
    +//
    +// ip_hash_test.cpp
    +//
    +// Copyright 2011 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 
    +
    +class base
    +{
    +private:
    +
    +    int use_count_;
    +
    +    base(base const &);
    +    base & operator=(base const &);
    +
    +protected:
    +
    +    base(): use_count_(0)
    +    {
    +    }
    +
    +    virtual ~base()
    +    {
    +    }
    +
    +public:
    +
    +    long use_count() const
    +    {
    +        return use_count_;
    +    }
    +
    +    inline friend void intrusive_ptr_add_ref(base * p)
    +    {
    +        ++p->use_count_;
    +    }
    +
    +    inline friend void intrusive_ptr_release(base * p)
    +    {
    +        if(--p->use_count_ == 0) delete p;
    +    }
    +};
    +
    +struct X: public base
    +{
    +};
    +
    +int main()
    +{
    +    boost::hash< boost::intrusive_ptr > hasher;
    +
    +    boost::intrusive_ptr p1, p2( p1 ), p3( new X ), p4( p3 ), p5( new X );
    +
    +    BOOST_TEST_EQ( p1, p2 );
    +    BOOST_TEST_EQ( hasher( p1 ), hasher( p2 ) );
    +
    +    BOOST_TEST_NE( p1, p3 );
    +    BOOST_TEST_NE( hasher( p1 ), hasher( p3 ) );
    +
    +    BOOST_TEST_EQ( p3, p4 );
    +    BOOST_TEST_EQ( hasher( p3 ), hasher( p4 ) );
    +
    +    BOOST_TEST_NE( p3, p5 );
    +    BOOST_TEST_NE( hasher( p3 ), hasher( p5 ) );
    +
    +    return boost::report_errors();
    +}
    
    From 90db9a64357a3523cd0f8e4b9899a7dc75707f20 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 21 Dec 2011 00:43:56 +0000
    Subject: [PATCH 086/140] Merge [76086] to release. Fixes #6308.
    
    [SVN r76087]
    ---
     .../smart_ptr/detail/sp_counted_base.hpp      |   3 +
     .../smart_ptr/detail/sp_counted_base_aix.hpp  | 113 ++++++++++++++++++
     2 files changed, 116 insertions(+)
     create mode 100644 include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
    
    diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp
    index cab45cc..8401bfe 100644
    --- a/include/boost/smart_ptr/detail/sp_counted_base.hpp
    +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp
    @@ -59,6 +59,9 @@
     #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined(__CYGWIN__)
     # include 
     
    +#elif defined( _AIX )
    +# include 
    +
     #elif !defined( BOOST_HAS_THREADS )
     # include 
     
    diff --git a/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp b/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
    new file mode 100644
    index 0000000..9dc77c8
    --- /dev/null
    +++ b/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
    @@ -0,0 +1,113 @@
    +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_AIX_HPP_INCLUDED
    +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_AIX_HPP_INCLUDED
    +
    +//
    +//  detail/sp_counted_base_aix.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 & );
    +
    +    int32_t use_count_;        // #shared
    +    int32_t weak_count_;       // #weak + (#shared != 0)
    +
    +public:
    +
    +    sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
    +    {
    +    }
    +
    +    virtual ~sp_counted_base() // nothrow
    +    {
    +    }
    +
    +    // dispose() is called when use_count_ drops to zero, to release
    +    // the resources managed by *this.
    +
    +    virtual void dispose() = 0; // nothrow
    +
    +    // destroy() is called when weak_count_ drops to zero.
    +
    +    virtual void destroy() // nothrow
    +    {
    +        delete this;
    +    }
    +
    +    virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
    +
    +    void add_ref_copy()
    +    {
    +        fetch_and_add( &use_count_, 1 );
    +    }
    +
    +    bool add_ref_lock() // true on success
    +    {
    +        int32_t tmp = fetch_and_add( &use_count_, 0 );
    +        for( ;; )
    +        {
    +            if( tmp == 0 ) return false;
    +            if( compare_and_swap( &use_count_, &tmp, tmp + 1 ) ) return true;
    +        }
    +    }
    +
    +    void release() // nothrow
    +    {
    +        if( fetch_and_add( &use_count_, -1 ) == 1 )
    +        {
    +            dispose();
    +            weak_release();
    +        }
    +    }
    +
    +    void weak_add_ref() // nothrow
    +    {
    +        fetch_and_add( &weak_count_, 1 );
    +    }
    +
    +    void weak_release() // nothrow
    +    {
    +        if( fetch_and_add( &weak_count_, -1 ) == 1 )
    +        {
    +            destroy();
    +        }
    +    }
    +
    +    long use_count() const // nothrow
    +    {
    +        return fetch_and_add( const_cast(&use_count_), 0 );
    +    }
    +};
    +
    +} // namespace detail
    +
    +} // namespace boost
    +
    +#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_AIX_HPP_INCLUDED
    
    From d1348ea05e64a927e6f1a2d821cacf4d96e604f1 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Fri, 23 Dec 2011 15:10:51 +0000
    Subject: [PATCH 087/140] Merge [76119] to release. Refs #6308.
    
    [SVN r76120]
    ---
     .../smart_ptr/detail/sp_counted_base_aix.hpp  | 48 +++++++++++++++----
     1 file changed, 38 insertions(+), 10 deletions(-)
    
    diff --git a/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp b/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
    index 9dc77c8..a17e6cc 100644
    --- a/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
    +++ b/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
    @@ -26,6 +26,39 @@
     namespace boost
     {
     
    +inline void atomic_increment( int32_t* pw )
    +{
    +    // ++*pw;
    +
    +    fetch_and_add( pw, 1 );
    +}
    +
    +inline int32_t atomic_decrement( int32_t * pw )
    +{
    +    // return --*pw;
    +
    +    int32_t originalValue;
    +
    +    __asm__ __volatile__( "sync" );
    +    originalValue = fetch_and_add( pw, -1 );
    +    __asm__ __volatile__( "isync" );
    +
    +    return (originalValue - 1);
    +}
    +
    +inline int32_t atomic_conditional_increment( int32_t * pw )
    +{
    +    // if( *pw != 0 ) ++*pw;
    +    // return *pw;
    +
    +    int32_t tmp = fetch_and_add( pw, 0 );
    +    for( ;; )
    +    {
    +        if( tmp == 0 ) return 0;
    +        if( compare_and_swap( pw, &tmp, tmp + 1 ) ) return (tmp + 1);
    +    }
    +}
    +
     namespace detail
     {
     
    @@ -65,22 +98,17 @@ public:
     
         void add_ref_copy()
         {
    -        fetch_and_add( &use_count_, 1 );
    +        atomic_increment( &use_count_ );
         }
     
         bool add_ref_lock() // true on success
         {
    -        int32_t tmp = fetch_and_add( &use_count_, 0 );
    -        for( ;; )
    -        {
    -            if( tmp == 0 ) return false;
    -            if( compare_and_swap( &use_count_, &tmp, tmp + 1 ) ) return true;
    -        }
    +        return atomic_conditional_increment( &use_count_ ) != 0;
         }
     
         void release() // nothrow
         {
    -        if( fetch_and_add( &use_count_, -1 ) == 1 )
    +        if( atomic_decrement( &use_count_ ) == 0 )
             {
                 dispose();
                 weak_release();
    @@ -89,12 +117,12 @@ public:
     
         void weak_add_ref() // nothrow
         {
    -        fetch_and_add( &weak_count_, 1 );
    +        atomic_increment( &weak_count_ );
         }
     
         void weak_release() // nothrow
         {
    -        if( fetch_and_add( &weak_count_, -1 ) == 1 )
    +        if( atomic_decrement( &weak_count_ ) == 0 )
             {
                 destroy();
             }
    
    From 9147489b4c5c1f4c30681240d095d293a049f1a2 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Fri, 23 Dec 2011 23:12:50 +0000
    Subject: [PATCH 088/140] Merge [76123] to release. Refs #6308.
    
    [SVN r76124]
    ---
     .../boost/smart_ptr/detail/sp_counted_base_aix.hpp    | 11 ++++++-----
     1 file changed, 6 insertions(+), 5 deletions(-)
    
    diff --git a/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp b/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
    index a17e6cc..0208678 100644
    --- a/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
    +++ b/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
    @@ -21,11 +21,15 @@
     //
     
     #include 
    +#include 
     #include 
     
     namespace boost
     {
     
    +namespace detail
    +{
    +
     inline void atomic_increment( int32_t* pw )
     {
         // ++*pw;
    @@ -39,9 +43,9 @@ inline int32_t atomic_decrement( int32_t * pw )
     
         int32_t originalValue;
     
    -    __asm__ __volatile__( "sync" );
    +    __lwsync();
         originalValue = fetch_and_add( pw, -1 );
    -    __asm__ __volatile__( "isync" );
    +    __isync();
     
         return (originalValue - 1);
     }
    @@ -59,9 +63,6 @@ inline int32_t atomic_conditional_increment( int32_t * pw )
         }
     }
     
    -namespace detail
    -{
    -
     class sp_counted_base
     {
     private:
    
    From b9970eda456a633dd1e77a707505f6f3060b3944 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Mon, 26 Dec 2011 00:23:00 +0000
    Subject: [PATCH 089/140] Merge [76111] to release. Fixes #2603.
    
    [SVN r76163]
    ---
     include/boost/smart_ptr/owner_less.hpp | 57 ++++++++++++++++++++++
     include/boost/smart_ptr/shared_ptr.hpp |  9 +++-
     include/boost/smart_ptr/weak_ptr.hpp   |  9 +++-
     test/Jamfile.v2                        |  1 +
     test/owner_less_test.cpp               | 67 ++++++++++++++++++++++++++
     5 files changed, 139 insertions(+), 4 deletions(-)
     create mode 100644 include/boost/smart_ptr/owner_less.hpp
     create mode 100644 test/owner_less_test.cpp
    
    diff --git a/include/boost/smart_ptr/owner_less.hpp b/include/boost/smart_ptr/owner_less.hpp
    new file mode 100644
    index 0000000..6899325
    --- /dev/null
    +++ b/include/boost/smart_ptr/owner_less.hpp
    @@ -0,0 +1,57 @@
    +#ifndef BOOST_SMART_PTR_OWNER_LESS_HPP_INCLUDED
    +#define BOOST_SMART_PTR_OWNER_LESS_HPP_INCLUDED
    +
    +//
    +//  owner_less.hpp
    +//
    +//  Copyright (c) 2008 Frank Mori Hess
    +//
    +//  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/smart_ptr.htm for documentation.
    +//
    +
    +#include 
    +
    +namespace boost
    +{
    +  template class shared_ptr;
    +  template class weak_ptr;
    +
    +  namespace detail
    +  {
    +    template
    +      struct generic_owner_less : public std::binary_function
    +    {
    +      bool operator()(const T &lhs, const T &rhs) const
    +      {
    +        return lhs.owner_before(rhs);
    +      }
    +      bool operator()(const T &lhs, const U &rhs) const
    +      {
    +        return lhs.owner_before(rhs);
    +      }
    +      bool operator()(const U &lhs, const T &rhs) const
    +      {
    +        return lhs.owner_before(rhs);
    +      }
    +    };
    +  } // namespace detail
    +
    +  template struct owner_less;
    +
    +  template
    +    struct owner_less >:
    +    public detail::generic_owner_less, weak_ptr >
    +  {};
    +
    +  template
    +    struct owner_less >:
    +    public detail::generic_owner_less, shared_ptr >
    +  {};
    +
    +} // namespace boost
    +
    +#endif  // #ifndef BOOST_SMART_PTR_OWNER_LESS_HPP_INCLUDED
    diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp
    index 9ead1ba..1bfb75c 100644
    --- a/include/boost/smart_ptr/shared_ptr.hpp
    +++ b/include/boost/smart_ptr/shared_ptr.hpp
    @@ -449,7 +449,12 @@ public:
             pn.swap(other.pn);
         }
     
    -    template bool _internal_less(shared_ptr const & rhs) const
    +    template bool owner_before( shared_ptr const & rhs ) const
    +    {
    +        return pn < rhs.pn;
    +    }
    +
    +    template bool owner_before( weak_ptr const & rhs ) const
         {
             return pn < rhs.pn;
         }
    @@ -505,7 +510,7 @@ template inline bool operator!=(shared_ptr const & a, shared_ptr
     
     template inline bool operator<(shared_ptr const & a, shared_ptr const & b)
     {
    -    return a._internal_less(b);
    +    return a.owner_before( b );
     }
     
     template inline void swap(shared_ptr & a, shared_ptr & b)
    diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp
    index 34b0d1e..3dfae07 100644
    --- a/include/boost/smart_ptr/weak_ptr.hpp
    +++ b/include/boost/smart_ptr/weak_ptr.hpp
    @@ -205,7 +205,12 @@ public:
             pn = pn2;
         }
     
    -    template bool _internal_less(weak_ptr const & rhs) const
    +    template bool owner_before( weak_ptr const & rhs ) const
    +    {
    +        return pn < rhs.pn;
    +    }
    +
    +    template bool owner_before( shared_ptr const & rhs ) const
         {
             return pn < rhs.pn;
         }
    @@ -229,7 +234,7 @@ private:
     
     template inline bool operator<(weak_ptr const & a, weak_ptr const & b)
     {
    -    return a._internal_less(b);
    +    return a.owner_before( b );
     }
     
     template void swap(weak_ptr & a, weak_ptr & b)
    diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
    index a11b431..c5dfba3 100644
    --- a/test/Jamfile.v2
    +++ b/test/Jamfile.v2
    @@ -67,5 +67,6 @@ import testing ;
               [ run sp_hash_test.cpp ]
               [ run get_deleter_array_test.cpp ]
               [ run ip_hash_test.cpp ]
    +          [ run owner_less_test.cpp ]
             ;
     }
    diff --git a/test/owner_less_test.cpp b/test/owner_less_test.cpp
    new file mode 100644
    index 0000000..572b72b
    --- /dev/null
    +++ b/test/owner_less_test.cpp
    @@ -0,0 +1,67 @@
    +//
    +//  owner_less_test.cpp
    +//
    +//  A regression test for owner_less
    +//
    +//  Copyright (c) 2008 Frank Mori Hess
    +//
    +//  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 
    +
    +int main()
    +{
    +  boost::owner_less > comp;
    +  {
    +    boost::shared_ptr x;
    +    boost::shared_ptr y;
    +    boost::weak_ptr w;
    +    BOOST_TEST(!(comp(x, w) || comp(w, x)));
    +  }
    +  {
    +    boost::shared_ptr z((int*)0);
    +    boost::weak_ptr w;
    +    BOOST_TEST(comp(z, w) || comp(w, z));
    +    {
    +      boost::shared_ptr zz(z);
    +      w = boost::weak_ptr(zz);
    +      BOOST_TEST(!(comp(z, zz) || comp(z, zz)));
    +      BOOST_TEST(!(comp(z, w) || comp(z, w)));
    +    }
    +    BOOST_TEST(!(comp(z, w) || comp(w, z)));
    +  }
    +  {
    +    boost::shared_ptr x;
    +    boost::shared_ptr z((int*)0);
    +    BOOST_TEST(comp(x, z) || comp(z, x));
    +  }
    +  {
    +    boost::shared_ptr a((int*)0);
    +    boost::shared_ptr b((int*)0);
    +    BOOST_TEST(comp(a, b) || comp(b, a));
    +    boost::weak_ptr w(a);
    +    BOOST_TEST(!(comp(a, w) || comp(w, a)));
    +    BOOST_TEST(comp(b, w) || comp(w, b));
    +  }
    +
    +  boost::owner_less > weak_comp;
    +  {
    +    boost::shared_ptr a((int*)0);
    +    boost::weak_ptr wa(a);
    +    boost::shared_ptr b((int*)0);
    +    boost::weak_ptr wb(b);
    +    BOOST_TEST(!(weak_comp(a, wa) || weak_comp(wa, a)));
    +    BOOST_TEST(!(weak_comp(b, wb) || weak_comp(wb, b)));
    +    BOOST_TEST(weak_comp(wa, wb) || weak_comp(wb, wa));
    +    BOOST_TEST(weak_comp(wa, b) || weak_comp(b, wa));
    +  }
    +
    +  return boost::report_errors();
    +}
    
    From 40073ef64f82795fda76f48843bc568525f224cd Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Mon, 26 Dec 2011 00:25:42 +0000
    Subject: [PATCH 090/140] Merge [76125], [76126] to release.
    
    [SVN r76164]
    ---
     test/intrusive_ptr_move_test.cpp | 3 +--
     test/shared_ptr_move_test.cpp    | 1 +
     test/weak_ptr_move_test.cpp      | 1 +
     3 files changed, 3 insertions(+), 2 deletions(-)
    
    diff --git a/test/intrusive_ptr_move_test.cpp b/test/intrusive_ptr_move_test.cpp
    index b5f0e65..3faf16e 100644
    --- a/test/intrusive_ptr_move_test.cpp
    +++ b/test/intrusive_ptr_move_test.cpp
    @@ -30,8 +30,7 @@
     #include 
     #include 
     #include 
    -#include 
    -#include 
    +#include 
     
     #if defined( BOOST_HAS_RVALUE_REFS )
     
    diff --git a/test/shared_ptr_move_test.cpp b/test/shared_ptr_move_test.cpp
    index c02ffa9..82ba9d6 100644
    --- a/test/shared_ptr_move_test.cpp
    +++ b/test/shared_ptr_move_test.cpp
    @@ -10,6 +10,7 @@
     
     #include 
     #include 
    +#include 
     
     #if defined( BOOST_HAS_RVALUE_REFS )
     
    diff --git a/test/weak_ptr_move_test.cpp b/test/weak_ptr_move_test.cpp
    index 572b13d..4df3691 100644
    --- a/test/weak_ptr_move_test.cpp
    +++ b/test/weak_ptr_move_test.cpp
    @@ -10,6 +10,7 @@
     
     #include 
     #include 
    +#include 
     
     #if defined( BOOST_HAS_RVALUE_REFS )
     
    
    From 3090f6f4affb22ec8f5698e93ec8db9323667726 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Thu, 29 Dec 2011 22:43:02 +0000
    Subject: [PATCH 091/140] Merge [76219] to release. Fixes #6332.
    
    [SVN r76221]
    ---
     include/boost/smart_ptr/weak_ptr.hpp | 9 ---------
     1 file changed, 9 deletions(-)
    
    diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp
    index 3dfae07..2e35583 100644
    --- a/include/boost/smart_ptr/weak_ptr.hpp
    +++ b/include/boost/smart_ptr/weak_ptr.hpp
    @@ -17,11 +17,6 @@
     #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
     {
     
    @@ -244,8 +239,4 @@ template void swap(weak_ptr & a, weak_ptr & b)
     
     } // namespace boost
     
    -#ifdef BOOST_MSVC
    -# pragma warning(pop)
    -#endif    
    -
     #endif  // #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
    
    From 5979c1d4bdb6219cadd63e79a9d8f40eba942e15 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Mon, 12 Mar 2012 17:37:51 +0000
    Subject: [PATCH 092/140] Merge [77315] to release. Closes #5331.
    
    [SVN r77317]
    ---
     .../smart_ptr/detail/spinlock_gcc_arm.hpp     | 29 +++++++++++++++++--
     1 file changed, 27 insertions(+), 2 deletions(-)
    
    diff --git a/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp b/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp
    index f58ea44..f1bbaf6 100644
    --- a/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp
    +++ b/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp
    @@ -43,13 +43,38 @@ public:
         {
             int r;
     
    +#if defined(__ARM_ARCH_6__) \
    +    || defined(__ARM_ARCH_6J__) \
    +    || defined(__ARM_ARCH_6K__) \
    +    || defined(__ARM_ARCH_6Z__) \
    +    || defined(__ARM_ARCH_6ZK__) \
    +    || defined(__ARM_ARCH_6T2__) \
    +    || defined(__ARM_ARCH_7__) \
    +    || defined(__ARM_ARCH_7A__) \
    +    || defined(__ARM_ARCH_7R__) \
    +    || defined(__ARM_ARCH_7M__) \
    +    || defined(__ARM_ARCH_7EM__)
    +
             __asm__ __volatile__(
    -            "swp %0, %1, [%2]\n\t"
    -			BOOST_SP_ARM_BARRIER :
    +            "ldrex %0, [%2]; \n"
    +            "cmp %0, %1; \n"
    +            "strexne %0, %1, [%2]; \n"
    +            BOOST_SP_ARM_BARRIER :
                 "=&r"( r ): // outputs
                 "r"( 1 ), "r"( &v_ ): // inputs
                 "memory", "cc" );
     
    +#else
    +
    +        __asm__ __volatile__(
    +            "swp %0, %1, [%2];\n"
    +            BOOST_SP_ARM_BARRIER :
    +            "=&r"( r ): // outputs
    +            "r"( 1 ), "r"( &v_ ): // inputs
    +            "memory", "cc" );
    +
    +#endif
    +
             return r == 0;
         }
     
    
    From c2048732d8427946195165de63e58a004a471228 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Mon, 12 Mar 2012 17:40:02 +0000
    Subject: [PATCH 093/140] Merge [77316] to release. Closes #6667.
    
    [SVN r77318]
    ---
     .../smart_ptr/detail/sp_counted_base.hpp      |   6 +-
     .../detail/sp_counted_base_vacpp_ppc.hpp      | 150 ++++++++++++++++++
     2 files changed, 153 insertions(+), 3 deletions(-)
     create mode 100644 include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp
    
    diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp
    index 8401bfe..24adfcc 100644
    --- a/include/boost/smart_ptr/detail/sp_counted_base.hpp
    +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp
    @@ -41,6 +41,9 @@
     #elif defined(__HP_aCC) && defined(__ia64)
     # include 
     
    +#elif defined( __IBMCPP__ ) && defined( __powerpc )
    +# include 
    +
     #elif defined( __MWERKS__ ) && defined( __POWERPC__ )
     # include 
     
    @@ -59,9 +62,6 @@
     #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined(__CYGWIN__)
     # include 
     
    -#elif defined( _AIX )
    -# include 
    -
     #elif !defined( BOOST_HAS_THREADS )
     # include 
     
    diff --git a/include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp
    new file mode 100644
    index 0000000..842f58f
    --- /dev/null
    +++ b/include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp
    @@ -0,0 +1,150 @@
    +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_VACPP_PPC_HPP_INCLUDED
    +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_VACPP_PPC_HPP_INCLUDED
    +
    +//
    +//  detail/sp_counted_base_vacpp_ppc.hpp - xlC(vacpp) on POWER
    +//   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
    +//  Copyright 2012 IBM Corp.
    +//
    +//  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 
    +
    +extern "builtin" void __lwsync(void);
    +extern "builtin" void __isync(void);
    +extern "builtin" int __fetch_and_add(volatile int* addr, int val);
    +extern "builtin" int __compare_and_swap(volatile int*, int*, int);
    +
    +namespace boost
    +{
    +
    +namespace detail
    +{
    +
    +inline void atomic_increment( int *pw )
    +{
    +   // ++*pw;
    +   __lwsync();
    +   __fetch_and_add(pw, 1);
    +   __isync();
    +} 
    +
    +inline int atomic_decrement( int *pw )
    +{
    +   // return --*pw;
    +   __lwsync();
    +   int originalValue = __fetch_and_add(pw, -1);
    +   __isync();
    +
    +   return (originalValue - 1);
    +}
    +
    +inline int atomic_conditional_increment( int *pw )
    +{
    +   // if( *pw != 0 ) ++*pw;
    +   // return *pw;
    +
    +   __lwsync();
    +   int v = *const_cast(pw);
    +   for (;;)
    +   // loop until state is known
    +   {
    +      if (v == 0) return 0;
    +      if (__compare_and_swap(pw, &v, v + 1))
    +      {
    +         __isync(); return (v + 1);
    +      }
    +   }
    +}
    +
    +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)
    +    char pad[64] __attribute__((__aligned__(64)));
    +            // pad to prevent false sharing
    +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 *const_cast(&use_count_); 
    +    }
    +};
    +
    +} // namespace detail
    +
    +} // namespace boost
    +
    +#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_VACPP_PPC_HPP_INCLUDED
    
    From 5017da25146ce7161adf3f5fa14d9fbf3f7e1ed8 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 14 Nov 2012 11:17:48 +0000
    Subject: [PATCH 094/140] Merged [81119] from trunk. Fixes #7599.
    
    [SVN r81328]
    ---
     .../boost/smart_ptr/detail/spinlock_gcc_arm.hpp | 17 +++++------------
     1 file changed, 5 insertions(+), 12 deletions(-)
    
    diff --git a/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp b/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp
    index f1bbaf6..016796a 100644
    --- a/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp
    +++ b/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp
    @@ -11,13 +11,15 @@
     
     #include 
     
    -#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
    +#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7S__)
     
     # define BOOST_SP_ARM_BARRIER "dmb"
    +# define BOOST_SP_ARM_HAS_LDREX
     
     #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__)
     
     # define BOOST_SP_ARM_BARRIER "mcr p15, 0, r0, c7, c10, 5"
    +# define BOOST_SP_ARM_HAS_LDREX
     
     #else
     
    @@ -43,17 +45,7 @@ public:
         {
             int r;
     
    -#if defined(__ARM_ARCH_6__) \
    -    || defined(__ARM_ARCH_6J__) \
    -    || defined(__ARM_ARCH_6K__) \
    -    || defined(__ARM_ARCH_6Z__) \
    -    || defined(__ARM_ARCH_6ZK__) \
    -    || defined(__ARM_ARCH_6T2__) \
    -    || defined(__ARM_ARCH_7__) \
    -    || defined(__ARM_ARCH_7A__) \
    -    || defined(__ARM_ARCH_7R__) \
    -    || defined(__ARM_ARCH_7M__) \
    -    || defined(__ARM_ARCH_7EM__)
    +#ifdef BOOST_SP_ARM_HAS_LDREX
     
             __asm__ __volatile__(
                 "ldrex %0, [%2]; \n"
    @@ -123,5 +115,6 @@ public:
     #define BOOST_DETAIL_SPINLOCK_INIT {0}
     
     #undef BOOST_SP_ARM_BARRIER
    +#undef BOOST_SP_ARM_HAS_LDREX
     
     #endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED
    
    From 8bf183b37390424df28b4d631adde520ebca41ec Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 14 Nov 2012 11:20:29 +0000
    Subject: [PATCH 095/140] Merged [81125] from trunk. Fixes #4185.
    
    [SVN r81329]
    ---
     include/boost/get_pointer.hpp | 19 +++++++++++++++++--
     1 file changed, 17 insertions(+), 2 deletions(-)
    
    diff --git a/include/boost/get_pointer.hpp b/include/boost/get_pointer.hpp
    index a0cd5c0..b27b98a 100644
    --- a/include/boost/get_pointer.hpp
    +++ b/include/boost/get_pointer.hpp
    @@ -3,13 +3,15 @@
     // accompanying file LICENSE_1_0.txt or copy at
     // http://www.boost.org/LICENSE_1_0.txt)
     #ifndef GET_POINTER_DWA20021219_HPP
    -# define GET_POINTER_DWA20021219_HPP
    +#define GET_POINTER_DWA20021219_HPP
    +
    +#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 
     // rather than including  directly:
    -# include   // std::auto_ptr
    +#include   // std::auto_ptr
     
     namespace boost { 
     
    @@ -27,6 +29,19 @@ template T * get_pointer(std::auto_ptr const& p)
         return p.get();
     }
     
    +#if !defined( BOOST_NO_CXX11_SMART_PTR )
    +
    +template T * get_pointer( std::unique_ptr const& p )
    +{
    +    return p.get();
    +}
    +
    +template T * get_pointer( std::shared_ptr const& p )
    +{
    +    return p.get();
    +}
    +
    +#endif
     
     } // namespace boost
     
    
    From 227d2e3255adee372f3b7a9fc5acc500b9174653 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 14 Nov 2012 11:43:17 +0000
    Subject: [PATCH 096/140] Manually apply [69019] from trunk.
    
    [SVN r81330]
    ---
     include/boost/smart_ptr/detail/sp_has_sync.hpp | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/include/boost/smart_ptr/detail/sp_has_sync.hpp b/include/boost/smart_ptr/detail/sp_has_sync.hpp
    index 12acea8..6a2e65e 100644
    --- a/include/boost/smart_ptr/detail/sp_has_sync.hpp
    +++ b/include/boost/smart_ptr/detail/sp_has_sync.hpp
    @@ -44,7 +44,7 @@
     #undef BOOST_SP_HAS_SYNC
     #endif
     
    -#if defined( __INTEL_COMPILER ) && !defined( __ia64__ ) && ( __INTEL_COMPILER < 1100 )
    +#if defined( __INTEL_COMPILER ) && !defined( __ia64__ ) && ( __INTEL_COMPILER < 1110 )
     #undef BOOST_SP_HAS_SYNC
     #endif
     
    
    From aae5440854ba42a318bf4257e6f66d8d452f7bdb Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 14 Nov 2012 11:51:00 +0000
    Subject: [PATCH 097/140] Merged [80988] from trunk.
    
    [SVN r81331]
    ---
     include/boost/smart_ptr/detail/sp_counted_base.hpp | 8 ++++----
     include/boost/smart_ptr/detail/sp_has_sync.hpp     | 4 ++++
     2 files changed, 8 insertions(+), 4 deletions(-)
    
    diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp
    index 24adfcc..12038c6 100644
    --- a/include/boost/smart_ptr/detail/sp_counted_base.hpp
    +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp
    @@ -32,10 +32,10 @@
     #elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 )
     # include 
     
    -#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
    +#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined(__PATHSCALE__)
     # include 
     
    -#elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER )
    +#elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER ) && !defined(__PATHSCALE__)
     # include 
     
     #elif defined(__HP_aCC) && defined(__ia64)
    @@ -47,10 +47,10 @@
     #elif defined( __MWERKS__ ) && defined( __POWERPC__ )
     # include 
     
    -#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) )
    +#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) && !defined(__PATHSCALE__)
     # include 
     
    -#elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) )
    +#elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) ) && !defined(__PATHSCALE__)
     # include 
     
     #elif defined( BOOST_SP_HAS_SYNC )
    diff --git a/include/boost/smart_ptr/detail/sp_has_sync.hpp b/include/boost/smart_ptr/detail/sp_has_sync.hpp
    index 6a2e65e..c266e75 100644
    --- a/include/boost/smart_ptr/detail/sp_has_sync.hpp
    +++ b/include/boost/smart_ptr/detail/sp_has_sync.hpp
    @@ -48,6 +48,10 @@
     #undef BOOST_SP_HAS_SYNC
     #endif
     
    +#if defined(__PATHSCALE__) && ((__PATHCC__ == 4) && (__PATHCC_MINOR__ < 9)) 
    +#undef BOOST_SP_HAS_SYNC
    +#endif
    +
     #endif // __GNUC__ * 100 + __GNUC_MINOR__ >= 401
     
     #endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED
    
    From 777b86a6611a1158c5f32336db3097b458dce4d3 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 14 Nov 2012 11:53:05 +0000
    Subject: [PATCH 098/140] Merged [81126] from trunk. Fixes #6996.
    
    [SVN r81332]
    ---
     include/boost/smart_ptr/detail/sp_counted_base.hpp | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp
    index 12038c6..afe111d 100644
    --- a/include/boost/smart_ptr/detail/sp_counted_base.hpp
    +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp
    @@ -47,7 +47,7 @@
     #elif defined( __MWERKS__ ) && defined( __POWERPC__ )
     # include 
     
    -#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) && !defined(__PATHSCALE__)
    +#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) && !defined(__PATHSCALE__) && !defined( _AIX )
     # include 
     
     #elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) ) && !defined(__PATHSCALE__)
    
    From d065e4d971e5298416563035ca27cdecf8f9c804 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 14 Nov 2012 11:55:10 +0000
    Subject: [PATCH 099/140] Merged [81127] from trunk. Fixes #6901.
    
    [SVN r81333]
    ---
     include/boost/smart_ptr/detail/sp_has_sync.hpp | 12 ++++++++++--
     1 file changed, 10 insertions(+), 2 deletions(-)
    
    diff --git a/include/boost/smart_ptr/detail/sp_has_sync.hpp b/include/boost/smart_ptr/detail/sp_has_sync.hpp
    index c266e75..3a1d346 100644
    --- a/include/boost/smart_ptr/detail/sp_has_sync.hpp
    +++ b/include/boost/smart_ptr/detail/sp_has_sync.hpp
    @@ -20,7 +20,9 @@
     //  are available.
     //
     
    -#if defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( BOOST_SP_NO_SYNC )
    +#ifndef BOOST_SP_NO_SYNC
    +
    +#if defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
     
     #define BOOST_SP_HAS_SYNC
     
    @@ -52,6 +54,12 @@
     #undef BOOST_SP_HAS_SYNC
     #endif
     
    -#endif // __GNUC__ * 100 + __GNUC_MINOR__ >= 401
    +#elif defined( __IBMCPP__ ) && ( __IBMCPP__ >= 1210 )
    +
    +#define BOOST_SP_HAS_SYNC
    +
    +#endif
    +
    +#endif // #ifndef BOOST_SP_NO_SYNC
     
     #endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED
    
    From c19cbc189236d445ac5113ec8d4244ce4187e522 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 14 Nov 2012 11:57:58 +0000
    Subject: [PATCH 100/140] Merged [81128] from trunk. Fixes #7141.
    
    [SVN r81334]
    ---
     include/boost/smart_ptr/detail/sp_has_sync.hpp | 14 +++++++++-----
     1 file changed, 9 insertions(+), 5 deletions(-)
    
    diff --git a/include/boost/smart_ptr/detail/sp_has_sync.hpp b/include/boost/smart_ptr/detail/sp_has_sync.hpp
    index 3a1d346..16de21d 100644
    --- a/include/boost/smart_ptr/detail/sp_has_sync.hpp
    +++ b/include/boost/smart_ptr/detail/sp_has_sync.hpp
    @@ -22,7 +22,15 @@
     
     #ifndef BOOST_SP_NO_SYNC
     
    -#if defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
    +#if defined( __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 )
    +
    +# define BOOST_SP_HAS_SYNC
    +
    +#elif defined( __IBMCPP__ ) && ( __IBMCPP__ >= 1210 )
    +
    +# define BOOST_SP_HAS_SYNC
    +
    +#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
     
     #define BOOST_SP_HAS_SYNC
     
    @@ -54,10 +62,6 @@
     #undef BOOST_SP_HAS_SYNC
     #endif
     
    -#elif defined( __IBMCPP__ ) && ( __IBMCPP__ >= 1210 )
    -
    -#define BOOST_SP_HAS_SYNC
    -
     #endif
     
     #endif // #ifndef BOOST_SP_NO_SYNC
    
    From babc72757d3f50221dc18a7e1021014848f60a09 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 14 Nov 2012 12:04:48 +0000
    Subject: [PATCH 101/140] Merged [81131] from trunk. Fixes #6625.
    
    [SVN r81335]
    ---
     .../boost/smart_ptr/detail/shared_count.hpp   |  63 ++++++++
     include/boost/smart_ptr/shared_ptr.hpp        |  12 ++
     test/Jamfile.v2                               |   1 +
     test/sp_unique_ptr_test.cpp                   | 152 ++++++++++++++++++
     4 files changed, 228 insertions(+)
     create mode 100644 test/sp_unique_ptr_test.cpp
    
    diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp
    index f96a220..2c99f02 100644
    --- a/include/boost/smart_ptr/detail/shared_count.hpp
    +++ b/include/boost/smart_ptr/detail/shared_count.hpp
    @@ -37,6 +37,10 @@
     #include        // std::less
     #include               // std::bad_alloc
     
    +#if !defined( BOOST_NO_CXX11_SMART_PTR )
    +# include 
    +#endif
    +
     namespace boost
     {
     
    @@ -56,6 +60,38 @@ template< class D > struct sp_inplace_tag
     {
     };
     
    +#if !defined( BOOST_NO_CXX11_SMART_PTR )
    +
    +template< class T > class sp_reference_wrapper
    +{ 
    +public:
    +
    +    explicit sp_reference_wrapper( T & t): t_( boost::addressof( t ) )
    +    {
    +    }
    +
    +    template< class Y > void operator()( Y * p ) const
    +    {
    +        (*t_)( p );
    +    }
    +
    +private:
    +
    +    T * t_;
    +};
    +
    +template< class D > struct sp_convert_reference
    +{
    +    typedef D type;
    +};
    +
    +template< class D > struct sp_convert_reference< D& >
    +{
    +    typedef sp_reference_wrapper< D > type;
    +};
    +
    +#endif
    +
     class weak_count;
     
     class shared_count
    @@ -300,6 +336,33 @@ public:
     
     #endif 
     
    +#if !defined( BOOST_NO_CXX11_SMART_PTR )
    +
    +    template
    +    explicit shared_count( std::unique_ptr & r ): pi_( 0 )
    +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
    +        , id_(shared_count_id)
    +#endif
    +    {
    +        typedef typename sp_convert_reference::type D2;
    +
    +        D2 d2( r.get_deleter() );
    +        pi_ = new sp_counted_impl_pd< Y*, D2 >( r.get(), d2 );
    +
    +#ifdef BOOST_NO_EXCEPTIONS
    +
    +        if( pi_ == 0 )
    +        {
    +            boost::throw_exception( std::bad_alloc() );
    +        }
    +
    +#endif
    +
    +        r.release();
    +    }
    +
    +#endif
    +
         ~shared_count() // nothrow
         {
             if( pi_ != 0 ) pi_->release();
    diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp
    index 1bfb75c..12f42c5 100644
    --- a/include/boost/smart_ptr/shared_ptr.hpp
    +++ b/include/boost/smart_ptr/shared_ptr.hpp
    @@ -304,6 +304,18 @@ public:
     
     #endif // BOOST_NO_AUTO_PTR
     
    +#if !defined( BOOST_NO_CXX11_SMART_PTR )
    +
    +    template< class Y, class D >
    +    shared_ptr( std::unique_ptr< Y, D > && r): px( r.get() ), pn()
    +    {
    +        Y * tmp = r.get();
    +        pn = boost::detail::shared_count( r );
    +        boost::detail::sp_enable_shared_from_this( this, tmp, tmp );
    +    }
    +
    +#endif
    +
         // assignment
     
         shared_ptr & operator=( shared_ptr const & r ) // never throws
    diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
    index c5dfba3..90b3bef 100644
    --- a/test/Jamfile.v2
    +++ b/test/Jamfile.v2
    @@ -68,5 +68,6 @@ import testing ;
               [ run get_deleter_array_test.cpp ]
               [ run ip_hash_test.cpp ]
               [ run owner_less_test.cpp ]
    +          [ run sp_unique_ptr_test.cpp ]
             ;
     }
    diff --git a/test/sp_unique_ptr_test.cpp b/test/sp_unique_ptr_test.cpp
    new file mode 100644
    index 0000000..70c5aff
    --- /dev/null
    +++ b/test/sp_unique_ptr_test.cpp
    @@ -0,0 +1,152 @@
    +//
    +//  sp_unique_ptr_test.cpp
    +//
    +//  Copyright (c) 2012 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 
    +
    +#if !defined( BOOST_NO_CXX11_SMART_PTR )
    +
    +struct X: public boost::enable_shared_from_this< X >
    +{
    +    static int instances;
    +
    +    X()
    +    {
    +        ++instances;
    +    }
    +
    +    ~X()
    +    {
    +        --instances;
    +    }
    +
    +private:
    +
    +    X( X const & );
    +    X & operator=( X const & );
    +};
    +
    +int X::instances = 0;
    +
    +struct Y
    +{
    +    static int instances;
    +
    +    bool deleted_;
    +
    +    Y(): deleted_( false )
    +    {
    +        ++instances;
    +    }
    +
    +    ~Y()
    +    {
    +        BOOST_TEST( deleted_ );
    +        --instances;
    +    }
    +
    +private:
    +
    +    Y( Y const & );
    +    Y & operator=( Y const & );
    +};
    +
    +int Y::instances = 0;
    +
    +struct YD
    +{
    +    void operator()( Y* p ) const
    +    {
    +        p->deleted_ = true;
    +        delete p;
    +    }
    +};
    +
    +int main()
    +{
    +    {
    +        BOOST_TEST( X::instances == 0 );
    +
    +        std::unique_ptr p( new X );
    +        BOOST_TEST( X::instances == 1 );
    +
    +        boost::shared_ptr p2( std::move( p ) );
    +        BOOST_TEST( X::instances == 1 );
    +        BOOST_TEST( p.get() == 0 );
    +
    +        boost::shared_ptr p3 = p2->shared_from_this();
    +        BOOST_TEST( p2 == p3 );
    +        BOOST_TEST( !(p2 < p3) && !(p3 < p2) );
    +
    +        p2.reset();
    +        p3.reset();
    +        BOOST_TEST( X::instances == 0 );
    +    }
    +
    +    {
    +        BOOST_TEST( Y::instances == 0 );
    +
    +        std::unique_ptr p( new Y, YD() );
    +        BOOST_TEST( Y::instances == 1 );
    +
    +        boost::shared_ptr p2( std::move( p ) );
    +        BOOST_TEST( Y::instances == 1 );
    +        BOOST_TEST( p.get() == 0 );
    +
    +        p2.reset();
    +        BOOST_TEST( Y::instances == 0 );
    +    }
    +
    +    {
    +        BOOST_TEST( Y::instances == 0 );
    +
    +        YD yd;
    +
    +        std::unique_ptr p( new Y, yd );
    +        BOOST_TEST( Y::instances == 1 );
    +
    +        boost::shared_ptr p2( std::move( p ) );
    +        BOOST_TEST( Y::instances == 1 );
    +        BOOST_TEST( p.get() == 0 );
    +
    +        p2.reset();
    +        BOOST_TEST( Y::instances == 0 );
    +    }
    +
    +    {
    +        BOOST_TEST( Y::instances == 0 );
    +
    +        YD yd;
    +
    +        std::unique_ptr p( new Y, yd );
    +        BOOST_TEST( Y::instances == 1 );
    +
    +        boost::shared_ptr p2( std::move( p ) );
    +        BOOST_TEST( Y::instances == 1 );
    +        BOOST_TEST( p.get() == 0 );
    +
    +        p2.reset();
    +        BOOST_TEST( Y::instances == 0 );
    +    }
    +
    +    return boost::report_errors();
    +}
    +
    +#else // !defined( BOOST_NO_CXX11_SMART_PTR )
    +
    +int main()
    +{
    +    return 0;
    +}
    +
    +#endif
    
    From 4a2dad1574b06ce56aa6c7e7ede901ed7c38a044 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 14 Nov 2012 12:09:30 +0000
    Subject: [PATCH 102/140] Merged [81134] from trunk. Fixes #6308. Refs #6667.
    
    [SVN r81336]
    ---
     include/boost/smart_ptr/detail/sp_counted_base.hpp | 3 +++
     1 file changed, 3 insertions(+)
    
    diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp
    index afe111d..fd9eab4 100644
    --- a/include/boost/smart_ptr/detail/sp_counted_base.hpp
    +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp
    @@ -62,6 +62,9 @@
     #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined(__CYGWIN__)
     # include 
     
    +#elif defined( _AIX )
    +# include 
    +
     #elif !defined( BOOST_HAS_THREADS )
     # include 
     
    
    From 71eb4354122da5c575223f030296a3d3f6759311 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 14 Nov 2012 13:26:30 +0000
    Subject: [PATCH 103/140] Merged revision(s) 57197, 57206, 57423, 57518 from
     trunk: Renamed enable_shared_from_this2 to enable_shared_from_raw and added
     shared_from_raw free function.  These changes fix the pointer value in
     shared_ptr which were obtained before an external shared_ptr has taken
     ownership of the object (for example when a shared_ptr to this is obtained in
     an object's constructor).
    
    ........
    Brought back code which fixes get_deleter when it is called on a deleter
    which has been wrapped inside a deleter_wrapper by "shared_from_raw() in
    constructors" support.
    
    ........
    Added weak_from_raw(), for use in conjunction with
    enable_shared_from_raw base class.
    
    
    ........
    Fixed access to enable_shared_from_raw::weak_this_ when
    BOOST_NO_MEMBER_TEMPLATE_FRIENDS is defined.
    
    
    ........
    
    
    [SVN r81337]
    ---
     .../smart_ptr/enable_shared_from_raw.hpp      | 144 ++++++++++++++++++
     .../smart_ptr/enable_shared_from_this2.hpp    | 132 ----------------
     include/boost/smart_ptr/shared_ptr.hpp        |  59 +++++--
     include/boost/smart_ptr/weak_ptr.hpp          |   5 +-
     4 files changed, 196 insertions(+), 144 deletions(-)
     create mode 100644 include/boost/smart_ptr/enable_shared_from_raw.hpp
     delete mode 100644 include/boost/smart_ptr/enable_shared_from_this2.hpp
    
    diff --git a/include/boost/smart_ptr/enable_shared_from_raw.hpp b/include/boost/smart_ptr/enable_shared_from_raw.hpp
    new file mode 100644
    index 0000000..f659c04
    --- /dev/null
    +++ b/include/boost/smart_ptr/enable_shared_from_raw.hpp
    @@ -0,0 +1,144 @@
    +#ifndef BOOST_ENABLE_SHARED_FROM_RAW_HPP_INCLUDED
    +#define BOOST_ENABLE_SHARED_FROM_RAW_HPP_INCLUDED
    +
    +//
    +//  enable_shared_from_raw.hpp
    +//
    +//  Copyright 2002, 2009 Peter Dimov
    +//  Copyright 2008-2009 Frank Mori Hess
    +//
    +//  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 
    +
    +namespace boost
    +{
    +template boost::shared_ptr shared_from_raw(T *);
    +template boost::weak_ptr weak_from_raw(T *);
    +
    +namespace detail
    +{
    +template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr * ppx, Y const * py, boost::enable_shared_from_raw const * pe );
    +
    +} // namespace detail
    +
    +class enable_shared_from_raw
    +{
    +protected:
    +
    +    enable_shared_from_raw()
    +    {
    +    }
    +
    +    enable_shared_from_raw( enable_shared_from_raw const & )
    +    {
    +    }
    +
    +    enable_shared_from_raw & operator=( enable_shared_from_raw const & )
    +    {
    +        return *this;
    +    }
    +
    +    ~enable_shared_from_raw()
    +    {
    +        BOOST_ASSERT( shared_this_.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist
    +    }
    +
    +private:
    +
    +    void init_weak_once() const
    +    {
    +        if( weak_this_.expired() )
    +        {
    +            shared_this_.reset( static_cast(0), detail::esft2_deleter_wrapper() );
    +            weak_this_ = shared_this_;
    +        }
    +    }
    +
    +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
    +public:
    +#else
    +private:
    +    template friend class shared_ptr;
    +    template friend boost::shared_ptr shared_from_raw(T *);
    +    template friend boost::weak_ptr weak_from_raw(T *);
    +    template< class X, class Y > friend inline void detail::sp_enable_shared_from_this( boost::shared_ptr * ppx, Y const * py, boost::enable_shared_from_raw const * pe );
    +#endif
    +
    +    shared_ptr shared_from_this()
    +    {
    +        init_weak_once();
    +        return shared_ptr( weak_this_ );
    +    }
    +
    +    shared_ptr shared_from_this() const
    +    {
    +        init_weak_once();
    +        return shared_ptr( weak_this_ );
    +    }
    +
    +    // Note: invoked automatically by shared_ptr; do not call
    +    template void _internal_accept_owner( shared_ptr * ppx, Y * py ) const
    +    {
    +        BOOST_ASSERT( ppx != 0 );
    +
    +        if( weak_this_.expired() )
    +        {
    +            weak_this_ = *ppx;
    +        }
    +        else if( shared_this_.use_count() != 0 )
    +        {
    +            BOOST_ASSERT( ppx->unique() ); // no weak_ptrs should exist either, but there's no way to check that
    +
    +            detail::esft2_deleter_wrapper * pd = boost::get_deleter( shared_this_ );
    +            BOOST_ASSERT( pd != 0 );
    +
    +            pd->set_deleter( *ppx );
    +
    +            ppx->reset( shared_this_, ppx->get() );
    +            shared_this_.reset();
    +        }
    +    }
    +
    +    mutable weak_ptr weak_this_;
    +private:
    +    mutable shared_ptr shared_this_;
    +};
    +
    +template
    +boost::shared_ptr shared_from_raw(T *p)
    +{
    +    BOOST_ASSERT(p != 0);
    +    return boost::shared_ptr(p->enable_shared_from_raw::shared_from_this(), p);
    +}
    +
    +template
    +boost::weak_ptr weak_from_raw(T *p)
    +{
    +    BOOST_ASSERT(p != 0);
    +    boost::weak_ptr result;
    +    result._internal_aliasing_assign(p->enable_shared_from_raw::weak_this_, p);
    +    return result;
    +}
    +
    +namespace detail
    +{
    +    template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr * ppx, Y const * py, boost::enable_shared_from_raw const * pe )
    +    {
    +        if( pe != 0 )
    +        {
    +            pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
    +        }
    +    }
    +} // namepsace detail
    +
    +} // namespace boost
    +
    +#endif  // #ifndef BOOST_ENABLE_SHARED_FROM_RAW_HPP_INCLUDED
    diff --git a/include/boost/smart_ptr/enable_shared_from_this2.hpp b/include/boost/smart_ptr/enable_shared_from_this2.hpp
    deleted file mode 100644
    index a5bfcff..0000000
    --- a/include/boost/smart_ptr/enable_shared_from_this2.hpp
    +++ /dev/null
    @@ -1,132 +0,0 @@
    -#ifndef BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED
    -#define BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED
    -
    -//
    -//  enable_shared_from_this2.hpp
    -//
    -//  Copyright 2002, 2009 Peter Dimov
    -//  Copyright 2008 Frank Mori Hess
    -//
    -//  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 
    -
    -namespace boost
    -{
    -
    -namespace detail
    -{
    -
    -class esft2_deleter_wrapper
    -{
    -private:
    -
    -    shared_ptr deleter_;
    -
    -public:
    -
    -    esft2_deleter_wrapper()
    -    {
    -    }
    -
    -    template< class T > void set_deleter( shared_ptr const & deleter )
    -    {
    -        deleter_ = deleter;
    -    }
    -
    -    template< class T> void operator()( T* )
    -    {
    -        BOOST_ASSERT( deleter_.use_count() <= 1 );
    -        deleter_.reset();
    -    }
    -};
    -
    -} // namespace detail
    -
    -template< class T > class enable_shared_from_this2
    -{
    -protected:
    -
    -    enable_shared_from_this2()
    -    {
    -    }
    -
    -    enable_shared_from_this2( enable_shared_from_this2 const & )
    -    {
    -    }
    -
    -    enable_shared_from_this2 & operator=( enable_shared_from_this2 const & )
    -    {
    -        return *this;
    -    }
    -
    -    ~enable_shared_from_this2()
    -    {
    -        BOOST_ASSERT( shared_this_.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist
    -    }
    -
    -private:
    -
    -    mutable weak_ptr weak_this_;
    -    mutable shared_ptr shared_this_;
    -
    -public:
    -
    -    shared_ptr shared_from_this()
    -    {
    -        init_weak_once();
    -        return shared_ptr( weak_this_ );
    -    }
    -
    -    shared_ptr shared_from_this() const
    -    {
    -        init_weak_once();
    -        return shared_ptr( weak_this_ );
    -    }
    -
    -private:
    -
    -    void init_weak_once() const
    -    {
    -        if( weak_this_._empty() )
    -        {
    -            shared_this_.reset( static_cast< T* >( 0 ), detail::esft2_deleter_wrapper() );
    -            weak_this_ = shared_this_;
    -        }
    -    }
    -
    -public: // actually private, but avoids compiler template friendship issues
    -
    -    // Note: invoked automatically by shared_ptr; do not call
    -    template void _internal_accept_owner( shared_ptr * ppx, Y * py ) const
    -    {
    -        BOOST_ASSERT( ppx != 0 );
    -
    -        if( weak_this_.use_count() == 0 )
    -        {
    -            weak_this_ = shared_ptr( *ppx, py );
    -        }
    -        else if( shared_this_.use_count() != 0 )
    -        {
    -            BOOST_ASSERT( ppx->unique() ); // no weak_ptrs should exist either, but there's no way to check that
    -
    -            detail::esft2_deleter_wrapper * pd = boost::get_deleter( shared_this_ );
    -            BOOST_ASSERT( pd != 0 );
    -
    -            pd->set_deleter( *ppx );
    -
    -            ppx->reset( shared_this_, ppx->get() );
    -            shared_this_.reset();
    -        }
    -    }
    -};
    -
    -} // namespace boost
    -
    -#endif  // #ifndef BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED
    diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp
    index 12f42c5..08cf3fe 100644
    --- a/include/boost/smart_ptr/shared_ptr.hpp
    +++ b/include/boost/smart_ptr/shared_ptr.hpp
    @@ -57,7 +57,7 @@ namespace boost
     template class shared_ptr;
     template class weak_ptr;
     template class enable_shared_from_this;
    -template class enable_shared_from_this2;
    +class enable_shared_from_raw;
     
     namespace detail
     {
    @@ -106,13 +106,7 @@ template< class X, class Y, class T > inline void sp_enable_shared_from_this( bo
         }
     }
     
    -template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr * ppx, Y const * py, boost::enable_shared_from_this2< T > const * pe )
    -{
    -    if( pe != 0 )
    -    {
    -        pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
    -    }
    -}
    +template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr * ppx, Y const * py, boost::enable_shared_from_raw const * pe );
     
     #ifdef _MANAGED
     
    @@ -612,6 +606,9 @@ 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) )
    @@ -619,7 +616,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));
    @@ -627,13 +624,55 @@ 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 esft2_deleter_wrapper
    +{
    +private:
    +
    +    shared_ptr deleter_;
    +
    +public:
    +
    +    esft2_deleter_wrapper()
    +    {
    +    }
    +
    +    template< class T > void set_deleter( shared_ptr const & deleter )
    +    {
    +        deleter_ = deleter;
    +    }
    +    template D* get_deleter() const
    +    {
    +        return boost::detail::basic_get_deleter(deleter_);
    +    }
    +    template< class T> void operator()( T* )
    +    {
    +        BOOST_ASSERT( deleter_.use_count() <= 1 );
    +        deleter_.reset();
    +    }
    +};
    +
    +} // namespace detail
    +
    +template D * get_deleter(shared_ptr const & p)
    +{
    +    D *del = detail::basic_get_deleter(p);
    +    if(del == 0)
    +    {
    +        detail::esft2_deleter_wrapper *del_wrapper = detail::basic_get_deleter(p);
    +// 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::esft2_deleter_wrapper::get_deleter();
    +    }
    +    return del;
    +}
    +
     // atomic access
     
     #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
    diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp
    index 2e35583..5391910 100644
    --- a/include/boost/smart_ptr/weak_ptr.hpp
    +++ b/include/boost/smart_ptr/weak_ptr.hpp
    @@ -194,10 +194,11 @@ public:
             pn.swap(other.pn);
         }
     
    -    void _internal_assign(T * px2, boost::detail::shared_count const & pn2)
    +    template
    +    void _internal_aliasing_assign(weak_ptr const & r, T * px2)
         {
             px = px2;
    -        pn = pn2;
    +        pn = r.pn;
         }
     
         template bool owner_before( weak_ptr const & rhs ) const
    
    From e8103f9774e72ecf947197e42638c594f2e0a620 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 14 Nov 2012 13:36:44 +0000
    Subject: [PATCH 104/140] Merge from 57197, 57206, 57423, 57518 did not apply
     to 'libs' for some reason; update.
    
    [SVN r81338]
    ---
     test/Jamfile.v2                      |  1 +
     test/enable_shared_from_raw_test.cpp | 39 ++++++++++++++++++++++++++++
     test/esft_constructor_test.cpp       | 30 ++++++++++-----------
     3 files changed, 54 insertions(+), 16 deletions(-)
     create mode 100644 test/enable_shared_from_raw_test.cpp
    
    diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
    index 90b3bef..1df2a3e 100644
    --- a/test/Jamfile.v2
    +++ b/test/Jamfile.v2
    @@ -60,6 +60,7 @@ import testing ;
               [ run sp_recursive_assign_rv_test.cpp ]
               [ run sp_recursive_assign2_rv_test.cpp ]
               [ run esft_constructor_test.cpp ]
    +          [ run enable_shared_from_raw_test.cpp ]
               [ compile-fail auto_ptr_lv_fail.cpp ]
               [ run atomic_count_test2.cpp ]
               [ run sp_typeinfo_test.cpp ]
    diff --git a/test/enable_shared_from_raw_test.cpp b/test/enable_shared_from_raw_test.cpp
    new file mode 100644
    index 0000000..ba95ecc
    --- /dev/null
    +++ b/test/enable_shared_from_raw_test.cpp
    @@ -0,0 +1,39 @@
    +#include 
    +
    +//
    +//  weak_from_raw_test.cpp
    +//
    +//  Copyright (c) 2009 Frank Mori Hess
    +//
    +// 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: public boost::enable_shared_from_raw
    +{};
    +
    +void basic_weak_from_raw_test()
    +{
    +    X *p(new X);
    +    boost::weak_ptr weak = boost::weak_from_raw(p);
    +    BOOST_TEST(weak.expired());
    +    boost::shared_ptr shared(p);
    +    weak = boost::weak_from_raw(p);
    +    BOOST_TEST(weak.expired() == false);
    +    boost::shared_ptr shared2(weak);
    +    BOOST_TEST((shared < shared2 || shared2 < shared) == false);
    +    BOOST_TEST(shared.get() == p);
    +}
    +
    +int main()
    +{
    +    basic_weak_from_raw_test();
    +    return boost::report_errors();
    +}
    diff --git a/test/esft_constructor_test.cpp b/test/esft_constructor_test.cpp
    index ced24e2..32a25b5 100644
    --- a/test/esft_constructor_test.cpp
    +++ b/test/esft_constructor_test.cpp
    @@ -13,14 +13,13 @@
     //  See accompanying file LICENSE_1_0.txt or copy at
     //  http://www.boost.org/LICENSE_1_0.txt)
     //
    -
    -#include 
    +#include 
     #include 
     #include 
     #include 
     #include 
     
    -class X: public boost::enable_shared_from_this2< X >
    +class X: public boost::enable_shared_from_raw
     {
     private:
     
    @@ -42,7 +41,7 @@ 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();
    +        if( early_px ) *early_px = shared_from_raw(this);
         }
     
         ~X()
    @@ -75,7 +74,7 @@ bool are_shared_owners(const boost::shared_ptr &a, const boost::shared_ptr
         return !(a < b) && !(b < a);
     }
     
    -struct Y: public boost::enable_shared_from_this2
    +struct Y: public boost::enable_shared_from_raw
     {};
     
     int main()
    @@ -87,14 +86,15 @@ int main()
             X* x = new X( 1, &early_px );
             BOOST_TEST( early_px.use_count() > 0 );
             BOOST_TEST( boost::get_deleter(early_px) == 0 );
    +        BOOST_TEST( early_px.get() == x );
             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 );
    +        X::deleter_type *pd = boost::get_deleter(early_px);
    +        BOOST_TEST(pd && *pd == &X::deleter2 );
         }
     
         BOOST_TEST( X::instances == 0 );
    @@ -117,7 +117,7 @@ int main()
     
         {
             boost::shared_ptr early_px;
    -        X x( 1, &early_px );
    +        X x( 2, &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 );
    @@ -125,13 +125,11 @@ int main()
             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 & )
    -        {}
    +        // test reinitialization after all shared_ptr have expired
    +        early_px = shared_from_raw(&x);
    +        px.reset( &x, &X::deleter );
    +        BOOST_TEST(are_shared_owners(early_px, px));
    +        early_px.reset();
         }
     
         BOOST_TEST( X::instances == 0 );
    @@ -157,7 +155,7 @@ int main()
             px.reset();
             try
             {
    -            y.shared_from_this();
    +            shared_from_raw(&y);
             }
             catch( const boost::bad_weak_ptr & )
             {
    
    From cb0797acf0569bdd89736c69ea49a9415974924b Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 14 Nov 2012 13:52:11 +0000
    Subject: [PATCH 105/140] Merged revision(s) 81149, 81159, 81171, 81174,
     81219-81220, 81222-81224, 81226, 81229-81239, 81242, 81253, 81257-81262,
     81265-81268, 81271-81272, 81275-81277, 81299-81300 from trunk: Implement
     shared_ptr, weak_ptr. Refs #1113. ........ Fix shared_ptr EDG
     issues. ........ Disable make_shared overloads when T is Q[]. ........ Add
     catch(...) clauses to sp_array_test.cpp. ........ Add allocate_shared and
     make_shared for shared_ptr arrays of runtime size. Fulfills need for
     allocate_shared_array and make_shared_array. ........ Update Jamfile.v2 to
     run make_shared array tests and allocate_shared array tests. ........ Fix g++
     issues. ........ Add specialization of sp_if_not_array. ........ Rename
     make_shared.hpp to make_shared_object.hpp, include from make_shared.hpp.
     ........ Add make_shared_array_args_test.cpp. ........ Add support for
     make_shared of array of arrays. Correctly destroy elements and construct
     elements for the variadic template constructor variants. ........ Fix
     sp_convertible. ........ Update
     smart_ptr/detail/array_helper to have create and create_noinit for non-array
     case. ........ Rename sp_convertible_test.cpp to
     shared_ptr_convertible_test.cpp. ........ Don't treat array_helper create and
     create_noinit for array types as a special case. ........ Add
     sp_convertible_test.cpp. ........ Fix array_helper (create_noinit and use of
     args...). ........ Update allocate_shared and make_shared to treat
     multidimensional array as single dimension. Remove detail array_helper. Add
     detail array traits. Update tests. ........ Simplify array_deleter interface
     ........ Add missing semicolon. ........ Fix typo. ........ Add tests for
     variadic template constructors overload of array forms of make_shared and
     allocate_shared for multidimensional arrays and up to 9 constructor
     arguments. ........ Add support for shared_ptr. ........ Add C++11
     initializer list support for make_shared and allocate_shared array forms.
    
    ........
    Clean up code in allocate_shared_array.hpp and make_shared_array.hpp
    ........
    Change make_shared and allocate_shared array form semantics with initializer lists overload that takes no size.
    ........
    Disable make_shared for arrays when the compiler doesn't support partial specialization or SFINAE.
    ........
    For allocate_shared and make_shared: Separate test case that g++ does support yet. Remove macros testing for no partial specialization in traits. Add additional traits.
    ........
    Actually remove test cases from make_shared_array_create_test.cpp and allocate_shared_array_create_test.cpp that g++ does not handle.
    ........
    Add overloads to support fixed size arrays, T[N], to allocate_shared (variadic) and make_shared (variadic) and make_shared_noinit.
    ........
    Add additional overload for make_shared and allocate_shared for arrays for fixed size arrays and initializer lists.
    ........
    Add assertion to overload of make_shared and allocate_shared for T[N] with initializer lists. Rename detail type to be more intuitive.
    ........
    Add allocate_shared_array_args_test.cpp.
    ........
    Keep old definition of sp_assert_convertible when BOOST_SP_NO_SP_CONVERTIBLE is set.
    ........
    Updated shared_array to match shared_ptr. Refs #1113.
    ........
    Add final overload of make_shared and allocate_shared (array forms) for T[][N] with C++11 initializer lists.
    ........
    Change traits for initializer list for g++
    ........
    Tidy long line formatting in allocate_shared_array.hpp and make_shared_array.hpp
    ........
    Update tests for make_shared and allocate_shared array forms, for normal case, initializer lists, variadic template arguments, for arrays and fixed size arrays.
    ........
    Update Jamfile.v2 with two new smart_ptr tests for allocate_shared and make_shared
    ........
    
    
    [SVN r81339]
    ---
     .../boost/smart_ptr/allocate_shared_array.hpp | 144 +++
     .../detail/allocate_array_helper.hpp          |  98 ++
     .../boost/smart_ptr/detail/array_deleter.hpp  |  76 ++
     .../boost/smart_ptr/detail/array_traits.hpp   |  66 ++
     .../smart_ptr/detail/make_array_helper.hpp    |  91 ++
     .../boost/smart_ptr/detail/operator_bool.hpp  |   4 +-
     .../boost/smart_ptr/detail/shared_count.hpp   |   2 +-
     .../boost/smart_ptr/detail/sp_convertible.hpp |  15 +
     .../boost/smart_ptr/detail/sp_if_array.hpp    |  33 +
     include/boost/smart_ptr/make_shared.hpp       | 969 +----------------
     include/boost/smart_ptr/make_shared_array.hpp | 176 +++
     .../boost/smart_ptr/make_shared_object.hpp    | 998 ++++++++++++++++++
     include/boost/smart_ptr/shared_array.hpp      | 106 +-
     include/boost/smart_ptr/shared_ptr.hpp        | 263 ++++-
     include/boost/smart_ptr/weak_ptr.hpp          |  21 +-
     make_shared_array.html                        | 129 +++
     test/Jamfile.v2                               |  79 +-
     test/allocate_shared_array_args_test.cpp      | 173 +++
     test/allocate_shared_array_create_test.cpp    | 114 ++
     test/allocate_shared_array_esft_test.cpp      |  42 +
     test/allocate_shared_array_init_test.cpp      |  82 ++
     test/allocate_shared_array_test.cpp           | 125 +++
     test/allocate_shared_array_throws_test.cpp    |  47 +
     test/allocate_shared_arrays_create_test.cpp   |  44 +
     test/allocate_shared_arrays_test.cpp          | 104 ++
     test/array_fail_ap_spa_a.cpp                  |  20 +
     test/array_fail_ap_spa_c.cpp                  |  20 +
     test/array_fail_ap_spa_ma.cpp                 |  19 +
     test/array_fail_ap_spa_mc.cpp                 |  19 +
     test/array_fail_array_access.cpp              |  19 +
     test/array_fail_dereference.cpp               |  19 +
     test/array_fail_member_access.cpp             |  20 +
     test/array_fail_sp_spa_a.cpp                  |  19 +
     test/array_fail_sp_spa_c.cpp                  |  19 +
     test/array_fail_sp_spa_ma.cpp                 |  18 +
     test/array_fail_sp_spa_mc.cpp                 |  18 +
     test/array_fail_sp_wpa_a.cpp                  |  20 +
     test/array_fail_sp_wpa_c.cpp                  |  20 +
     test/array_fail_sp_wpa_ma.cpp                 |  19 +
     test/array_fail_sp_wpa_mc.cpp                 |  19 +
     test/array_fail_spa_sp_a.cpp                  |  19 +
     test/array_fail_spa_sp_c.cpp                  |  19 +
     test/array_fail_spa_sp_ma.cpp                 |  18 +
     test/array_fail_spa_sp_mc.cpp                 |  18 +
     test/array_fail_spa_spa_a.cpp                 |  23 +
     test/array_fail_spa_spa_c.cpp                 |  23 +
     test/array_fail_spa_spa_ma.cpp                |  22 +
     test/array_fail_spa_spa_mc.cpp                |  22 +
     test/array_fail_spa_wp_a.cpp                  |  20 +
     test/array_fail_spa_wp_c.cpp                  |  20 +
     test/array_fail_spa_wp_ma.cpp                 |  19 +
     test/array_fail_spa_wp_mc.cpp                 |  19 +
     test/array_fail_spa_wpa_a.cpp                 |  24 +
     test/array_fail_spa_wpa_c.cpp                 |  24 +
     test/array_fail_spa_wpa_ma.cpp                |  23 +
     test/array_fail_spa_wpa_mc.cpp                |  23 +
     test/array_fail_up_spa_a.cpp                  |  20 +
     test/array_fail_up_spa_c.cpp                  |  20 +
     test/array_fail_up_spa_ma.cpp                 |  19 +
     test/array_fail_up_spa_mc.cpp                 |  19 +
     test/array_fail_upa_sp_a.cpp                  |  20 +
     test/array_fail_upa_sp_c.cpp                  |  20 +
     test/array_fail_upa_sp_ma.cpp                 |  19 +
     test/array_fail_upa_sp_mc.cpp                 |  19 +
     test/array_fail_wp_wpa_a.cpp                  |  19 +
     test/array_fail_wp_wpa_c.cpp                  |  19 +
     test/array_fail_wp_wpa_ma.cpp                 |  18 +
     test/array_fail_wp_wpa_mc.cpp                 |  18 +
     test/array_fail_wpa_wp_a.cpp                  |  19 +
     test/array_fail_wpa_wp_c.cpp                  |  19 +
     test/array_fail_wpa_wp_ma.cpp                 |  18 +
     test/array_fail_wpa_wp_mc.cpp                 |  18 +
     test/array_fail_wpa_wpa_a.cpp                 |  23 +
     test/array_fail_wpa_wpa_c.cpp                 |  23 +
     test/array_fail_wpa_wpa_ma.cpp                |  22 +
     test/array_fail_wpa_wpa_mc.cpp                |  22 +
     test/make_shared_array_args_test.cpp          | 172 +++
     test/make_shared_array_create_test.cpp        | 114 ++
     test/make_shared_array_esft_test.cpp          |  52 +
     test/make_shared_array_init_test.cpp          |  82 ++
     test/make_shared_array_test.cpp               | 199 ++++
     test/make_shared_array_throws_test.cpp        |  61 ++
     test/make_shared_arrays_create_test.cpp       |  45 +
     test/make_shared_arrays_test.cpp              | 160 +++
     test/shared_ptr_convertible_test.cpp          |  71 ++
     test/smart_ptr_test.cpp                       |   4 +-
     test/sp_array_cv_test.cpp                     |  60 ++
     test/sp_array_n_test.cpp                      | 248 +++++
     test/sp_array_test.cpp                        | 311 ++++++
     test/sp_convertible_test.cpp                  | 108 +-
     90 files changed, 5636 insertions(+), 1070 deletions(-)
     create mode 100644 include/boost/smart_ptr/allocate_shared_array.hpp
     create mode 100644 include/boost/smart_ptr/detail/allocate_array_helper.hpp
     create mode 100644 include/boost/smart_ptr/detail/array_deleter.hpp
     create mode 100644 include/boost/smart_ptr/detail/array_traits.hpp
     create mode 100644 include/boost/smart_ptr/detail/make_array_helper.hpp
     create mode 100644 include/boost/smart_ptr/detail/sp_if_array.hpp
     create mode 100644 include/boost/smart_ptr/make_shared_array.hpp
     create mode 100644 include/boost/smart_ptr/make_shared_object.hpp
     create mode 100644 make_shared_array.html
     create mode 100644 test/allocate_shared_array_args_test.cpp
     create mode 100644 test/allocate_shared_array_create_test.cpp
     create mode 100644 test/allocate_shared_array_esft_test.cpp
     create mode 100644 test/allocate_shared_array_init_test.cpp
     create mode 100644 test/allocate_shared_array_test.cpp
     create mode 100644 test/allocate_shared_array_throws_test.cpp
     create mode 100644 test/allocate_shared_arrays_create_test.cpp
     create mode 100644 test/allocate_shared_arrays_test.cpp
     create mode 100644 test/array_fail_ap_spa_a.cpp
     create mode 100644 test/array_fail_ap_spa_c.cpp
     create mode 100644 test/array_fail_ap_spa_ma.cpp
     create mode 100644 test/array_fail_ap_spa_mc.cpp
     create mode 100644 test/array_fail_array_access.cpp
     create mode 100644 test/array_fail_dereference.cpp
     create mode 100644 test/array_fail_member_access.cpp
     create mode 100644 test/array_fail_sp_spa_a.cpp
     create mode 100644 test/array_fail_sp_spa_c.cpp
     create mode 100644 test/array_fail_sp_spa_ma.cpp
     create mode 100644 test/array_fail_sp_spa_mc.cpp
     create mode 100644 test/array_fail_sp_wpa_a.cpp
     create mode 100644 test/array_fail_sp_wpa_c.cpp
     create mode 100644 test/array_fail_sp_wpa_ma.cpp
     create mode 100644 test/array_fail_sp_wpa_mc.cpp
     create mode 100644 test/array_fail_spa_sp_a.cpp
     create mode 100644 test/array_fail_spa_sp_c.cpp
     create mode 100644 test/array_fail_spa_sp_ma.cpp
     create mode 100644 test/array_fail_spa_sp_mc.cpp
     create mode 100644 test/array_fail_spa_spa_a.cpp
     create mode 100644 test/array_fail_spa_spa_c.cpp
     create mode 100644 test/array_fail_spa_spa_ma.cpp
     create mode 100644 test/array_fail_spa_spa_mc.cpp
     create mode 100644 test/array_fail_spa_wp_a.cpp
     create mode 100644 test/array_fail_spa_wp_c.cpp
     create mode 100644 test/array_fail_spa_wp_ma.cpp
     create mode 100644 test/array_fail_spa_wp_mc.cpp
     create mode 100644 test/array_fail_spa_wpa_a.cpp
     create mode 100644 test/array_fail_spa_wpa_c.cpp
     create mode 100644 test/array_fail_spa_wpa_ma.cpp
     create mode 100644 test/array_fail_spa_wpa_mc.cpp
     create mode 100644 test/array_fail_up_spa_a.cpp
     create mode 100644 test/array_fail_up_spa_c.cpp
     create mode 100644 test/array_fail_up_spa_ma.cpp
     create mode 100644 test/array_fail_up_spa_mc.cpp
     create mode 100644 test/array_fail_upa_sp_a.cpp
     create mode 100644 test/array_fail_upa_sp_c.cpp
     create mode 100644 test/array_fail_upa_sp_ma.cpp
     create mode 100644 test/array_fail_upa_sp_mc.cpp
     create mode 100644 test/array_fail_wp_wpa_a.cpp
     create mode 100644 test/array_fail_wp_wpa_c.cpp
     create mode 100644 test/array_fail_wp_wpa_ma.cpp
     create mode 100644 test/array_fail_wp_wpa_mc.cpp
     create mode 100644 test/array_fail_wpa_wp_a.cpp
     create mode 100644 test/array_fail_wpa_wp_c.cpp
     create mode 100644 test/array_fail_wpa_wp_ma.cpp
     create mode 100644 test/array_fail_wpa_wp_mc.cpp
     create mode 100644 test/array_fail_wpa_wpa_a.cpp
     create mode 100644 test/array_fail_wpa_wpa_c.cpp
     create mode 100644 test/array_fail_wpa_wpa_ma.cpp
     create mode 100644 test/array_fail_wpa_wpa_mc.cpp
     create mode 100644 test/make_shared_array_args_test.cpp
     create mode 100644 test/make_shared_array_create_test.cpp
     create mode 100644 test/make_shared_array_esft_test.cpp
     create mode 100644 test/make_shared_array_init_test.cpp
     create mode 100644 test/make_shared_array_test.cpp
     create mode 100644 test/make_shared_array_throws_test.cpp
     create mode 100644 test/make_shared_arrays_create_test.cpp
     create mode 100644 test/make_shared_arrays_test.cpp
     create mode 100644 test/shared_ptr_convertible_test.cpp
     create mode 100644 test/sp_array_cv_test.cpp
     create mode 100644 test/sp_array_n_test.cpp
     create mode 100644 test/sp_array_test.cpp
    
    diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp
    new file mode 100644
    index 0000000..b2aa826
    --- /dev/null
    +++ b/include/boost/smart_ptr/allocate_shared_array.hpp
    @@ -0,0 +1,144 @@
    +/*
    + * Copyright (c) 2012 Glen Joseph Fernandes 
    + * glenfe at live dot com
    + *
    + * Distributed under the Boost Software License, 
    + * Version 1.0. (See accompanying file LICENSE_1_0.txt 
    + * or copy at http://boost.org/LICENSE_1_0.txt)
    + */
    +#ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
    +#define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
    +#include 
    +#endif
    +
    +namespace boost {
    +    template
    +    inline typename detail::sp_if_array::type 
    +    allocate_shared(const A& allocator, std::size_t size) {
    +        typedef typename detail::array_inner::type T1;
    +        typedef typename detail::array_base::type T2;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        std::size_t n1 = size * detail::array_total::size;
    +        detail::allocate_array_helper a1(allocator, n1, &p2);
    +        detail::array_deleter d1;
    +        shared_ptr s1(p1, d1, a1);
    +        detail::array_deleter* d2;
    +        p1 = reinterpret_cast(p2);
    +        d2 = get_deleter >(s1);
    +        d2->construct(p2, n1);
    +        return shared_ptr(s1, p1);
    +    }
    +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
    +    template
    +    inline typename detail::sp_if_array::type
    +    allocate_shared(const A& allocator, std::size_t size, Args&&... args) {
    +        typedef typename detail::array_inner::type T1;
    +        typedef typename detail::array_base::type T2;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        std::size_t n1 = size * detail::array_total::size;
    +        detail::allocate_array_helper a1(allocator, n1, &p2);
    +        detail::array_deleter d1;
    +        shared_ptr s1(p1, d1, a1);
    +        detail::array_deleter* d2;
    +        p1 = reinterpret_cast(p2);
    +        d2 = get_deleter >(s1);
    +        d2->construct(p2, n1, std::forward(args)...);
    +        return shared_ptr(s1, p1);
    +    }
    +    template
    +    inline typename detail::sp_if_size_array::type
    +    allocate_shared(const A& allocator, Args&&... args) {
    +        typedef typename detail::array_inner::type T1;
    +        typedef typename detail::array_base::type T2;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        std::size_t n1 = detail::array_total::size;
    +        detail::allocate_array_helper a1(allocator, n1, &p2);
    +        detail::array_deleter d1;
    +        shared_ptr s1(p1, d1, a1);
    +        detail::array_deleter* d2;
    +        p1 = reinterpret_cast(p2);
    +        d2 = get_deleter >(s1);
    +        d2->construct(p2, n1, std::forward(args)...);
    +        return shared_ptr(s1, p1);
    +    }
    +#endif
    +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
    +    template
    +    inline typename detail::sp_if_array::type
    +    allocate_shared(const A& allocator, 
    +        std::initializer_list::type> list) {
    +        typedef typename detail::array_inner::type T1;
    +        typedef typename detail::array_base::type T2;
    +        typedef const T2 T3;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        T3* p3 = 0;
    +        std::size_t n1 = list.size() * detail::array_total::size;
    +        detail::allocate_array_helper a1(allocator, n1, &p2);
    +        detail::array_deleter d1;
    +        shared_ptr s1(p1, d1, a1);
    +        detail::array_deleter* d2;
    +        p3 = reinterpret_cast(list.begin());
    +        p1 = reinterpret_cast(p2);
    +        d2 = get_deleter >(s1);
    +        d2->construct_list(p2, n1, p3);
    +        return shared_ptr(s1, p1);
    +    }
    +    template
    +    inline typename detail::sp_if_size_array::type
    +    allocate_shared(const A& allocator, 
    +        std::initializer_list::type> list) {
    +        BOOST_ASSERT(list.size() == detail::array_size::size);
    +        typedef typename detail::array_inner::type T1;
    +        typedef typename detail::array_base::type T2;
    +        typedef const T2 T3;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        T3* p3 = 0;
    +        std::size_t n1 = detail::array_total::size;
    +        detail::allocate_array_helper a1(allocator, n1, &p2);
    +        detail::array_deleter d1;
    +        shared_ptr s1(p1, d1, a1);
    +        detail::array_deleter* d2;
    +        p3 = reinterpret_cast(list.begin());
    +        p1 = reinterpret_cast(p2);
    +        d2 = get_deleter >(s1);
    +        d2->construct_list(p2, n1, p3);
    +        return shared_ptr(s1, p1);
    +    }
    +    template
    +    inline typename detail::sp_if_array::type
    +    allocate_shared(const A& allocator, std::size_t size, 
    +        std::initializer_list::type> list) {
    +        typedef typename detail::array_inner::type T1;
    +        typedef typename detail::array_base::type T2;
    +        typedef const T2 T3;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        T3* p3 = 0;
    +        std::size_t n0 = detail::array_total::size;
    +        std::size_t n1 = n0 * list.size();
    +        detail::allocate_array_helper a1(allocator, n1, &p2);
    +        detail::array_deleter d1;
    +        shared_ptr s1(p1, d1, a1);
    +        detail::array_deleter* d2;
    +        p3 = reinterpret_cast(list.begin());
    +        p1 = reinterpret_cast(p2);
    +        d2 = get_deleter >(s1);
    +        d2->construct_list(p2, n1, p3, n0);
    +        return shared_ptr(s1, p1);
    +    }
    +#endif
    +}
    +
    +#endif
    diff --git a/include/boost/smart_ptr/detail/allocate_array_helper.hpp b/include/boost/smart_ptr/detail/allocate_array_helper.hpp
    new file mode 100644
    index 0000000..bfb4dec
    --- /dev/null
    +++ b/include/boost/smart_ptr/detail/allocate_array_helper.hpp
    @@ -0,0 +1,98 @@
    +/*
    + * Copyright (c) 2012 Glen Joseph Fernandes 
    + * glenfe at live dot com
    + *
    + * Distributed under the Boost Software License, 
    + * Version 1.0. (See accompanying file LICENSE_1_0.txt 
    + * or copy at http://boost.org/LICENSE_1_0.txt)
    + */
    +#ifndef BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP
    +#define BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP
    +
    +#include 
    +
    +namespace boost {
    +    namespace detail {
    +        template
    +        class allocate_array_helper {
    +            template
    +            friend class allocate_array_helper;
    +            typedef typename A::template rebind   ::other A2;
    +            typedef typename A::template rebind::other A3;
    +        public:
    +            typedef typename A2::value_type      value_type;
    +            typedef typename A2::pointer         pointer;
    +            typedef typename A2::const_pointer   const_pointer;
    +            typedef typename A2::reference       reference;
    +            typedef typename A2::const_reference const_reference;
    +            typedef typename A2::size_type       size_type;
    +            typedef typename A2::difference_type difference_type;
    +            template
    +            struct rebind {
    +                typedef allocate_array_helper other;
    +            };
    +            allocate_array_helper(const A& allocator, std::size_t size, T** data)
    +                : allocator(allocator),
    +                  size(sizeof(T) * size),
    +                  data(data) {
    +            }
    +            allocate_array_helper(const allocate_array_helper& other)
    +                : allocator(other.allocator),
    +                  size(other.size),
    +                  data(other.data) {
    +            }
    +            template
    +            allocate_array_helper(const allocate_array_helper& other) 
    +                : allocator(other.allocator),
    +                  size(other.size),
    +                  data(other.data) {
    +            }
    +            pointer address(reference value) const {
    +                return allocator.address(value);
    +            }
    +            const_pointer address(const_reference value) const {
    +                return allocator.address(value);
    +            }
    +            size_type max_size() const {
    +                return allocator.max_size();
    +            }
    +            pointer allocate(size_type count, const void* value = 0) {
    +                std::size_t a1 = alignment_of::value;
    +                std::size_t n1 = count * sizeof(Y) + a1 - 1;
    +                char*  p1 = A3(allocator).allocate(n1 + size, value);
    +                char*  p2 = p1 + n1;
    +                while (std::size_t(p2) % a1 != 0) {
    +                    p2--;
    +                }
    +                *data = reinterpret_cast(p2);
    +                return  reinterpret_cast(p1);
    +            }
    +            void deallocate(pointer memory, size_type count) {
    +                std::size_t a1 = alignment_of::value;
    +                std::size_t n1 = count * sizeof(Y) + a1 - 1;
    +                char*  p1 = reinterpret_cast(memory);
    +                A3(allocator).deallocate(p1, n1 + size);
    +            }
    +            void construct(pointer memory, const Y& value) {
    +                allocator.construct(memory, value);
    +            }
    +            void destroy(pointer memory) {
    +                allocator.destroy(memory);
    +            }
    +            template
    +            bool operator==(const allocate_array_helper& other) const {
    +                return allocator == other.allocator;
    +            }
    +            template
    +            bool operator!=(const allocate_array_helper& other) const {
    +                return !(*this == other); 
    +            }
    +        private:
    +            A2 allocator;
    +            std::size_t size;
    +            T** data;
    +        };
    +    }
    +}
    +
    +#endif
    diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp
    new file mode 100644
    index 0000000..273dcac
    --- /dev/null
    +++ b/include/boost/smart_ptr/detail/array_deleter.hpp
    @@ -0,0 +1,76 @@
    +/*
    + * Copyright (c) 2012 Glen Joseph Fernandes 
    + * glenfe at live dot com
    + *
    + * Distributed under the Boost Software License, 
    + * Version 1.0. (See accompanying file LICENSE_1_0.txt 
    + * or copy at http://boost.org/LICENSE_1_0.txt)
    + */
    +#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP
    +#define BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP
    +
    +#include 
    +#include 
    +
    +namespace boost {
    +    namespace detail {
    +        template
    +        class array_deleter {
    +        public:
    +            array_deleter() 
    +                : size(0) {
    +            }
    +            ~array_deleter() {
    +                destroy();
    +            }
    +            void construct(T* memory, std::size_t count) {
    +                for (object = memory; size < count; size++) {
    +                    void* p1 = object + size;
    +                    ::new(p1) T();
    +                }
    +            }
    +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
    +            template
    +            void construct(T* memory, std::size_t count, Args&&... args) {
    +                for (object = memory; size < count; size++) {
    +                    void* p1 = object + size;
    +                    ::new(p1) T(args...);
    +                }
    +            }
    +#endif
    +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
    +            void construct_list(T* memory, std::size_t count, const T* list) {
    +                for (object = memory; size < count; size++) {
    +                    void* p1 = object + size;
    +                    ::new(p1) T(list[size]);
    +                }
    +            }
    +            void construct_list(T* memory, std::size_t count, const T* list, std::size_t n) {
    +                for (object = memory; size < count; size++) {
    +                    void* p1 = object + size;
    +                    ::new(p1) T(list[size % n]);
    +                }
    +            }
    +#endif
    +            void construct_noinit(T* memory, std::size_t count) {
    +                for (object = memory; size < count; size++) {
    +                    void* p1 = object + size;
    +                    ::new(p1) T;
    +                }
    +            }
    +            void operator()(const void*) {
    +                destroy();
    +            }
    +        private:
    +            void destroy() {
    +                while (size > 0) {
    +                    object[--size].~T();
    +                }
    +            }
    +            std::size_t size;
    +            T* object;
    +        };
    +    }
    +}
    +
    +#endif
    diff --git a/include/boost/smart_ptr/detail/array_traits.hpp b/include/boost/smart_ptr/detail/array_traits.hpp
    new file mode 100644
    index 0000000..068629a
    --- /dev/null
    +++ b/include/boost/smart_ptr/detail/array_traits.hpp
    @@ -0,0 +1,66 @@
    +/*
    + * Copyright (c) 2012 Glen Joseph Fernandes 
    + * glenfe at live dot com
    + *
    + * Distributed under the Boost Software License, 
    + * Version 1.0. (See accompanying file LICENSE_1_0.txt 
    + * or copy at http://boost.org/LICENSE_1_0.txt)
    + */
    +#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP
    +#define BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP
    +
    +#include 
    +
    +namespace boost {
    +    namespace detail {
    +        template
    +        struct array_base {
    +            typedef typename boost::remove_cv::type type;
    +        };
    +        template
    +        struct array_base {
    +            typedef typename array_base::type type;
    +        };
    +        template
    +        struct array_size {
    +        };
    +        template
    +        struct array_size {
    +            enum {
    +                size = N
    +            };
    +        };
    +        template
    +        struct array_total {
    +            enum {
    +                size = 1
    +            };
    +        };
    +        template
    +        struct array_total {
    +            enum {
    +                size = N * array_total::size
    +            };
    +        };
    +        template 
    +        struct array_inner {
    +        };
    +        template
    +        struct array_inner {
    +            typedef T type;
    +        };
    +        template
    +        struct array_inner {
    +            typedef T type;
    +        };
    +        template 
    +        struct arrays_inner {
    +        };
    +        template 
    +        struct arrays_inner {
    +            typedef T type;
    +        };
    +    }
    +}
    +
    +#endif
    diff --git a/include/boost/smart_ptr/detail/make_array_helper.hpp b/include/boost/smart_ptr/detail/make_array_helper.hpp
    new file mode 100644
    index 0000000..96fa3f9
    --- /dev/null
    +++ b/include/boost/smart_ptr/detail/make_array_helper.hpp
    @@ -0,0 +1,91 @@
    +/*
    + * Copyright (c) 2012 Glen Joseph Fernandes 
    + * glenfe at live dot com
    + *
    + * Distributed under the Boost Software License, 
    + * Version 1.0. (See accompanying file LICENSE_1_0.txt 
    + * or copy at http://boost.org/LICENSE_1_0.txt)
    + */
    +#ifndef BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP
    +#define BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP
    +
    +#include 
    +
    +namespace boost {
    +    namespace detail {
    +        template
    +        class make_array_helper {
    +            template
    +            friend class make_array_helper;
    +        public:
    +            typedef Y           value_type;
    +            typedef Y*          pointer;
    +            typedef const Y*    const_pointer;
    +            typedef Y&          reference;
    +            typedef const Y&    const_reference;
    +            typedef std::size_t size_type;
    +            typedef ptrdiff_t   difference_type;
    +            template
    +            struct rebind {
    +                typedef make_array_helper other;
    +            };
    +            make_array_helper(std::size_t size, T** data)
    +                : size(sizeof(T) * size),
    +                  data(data) {
    +            }
    +            make_array_helper(const make_array_helper& other)
    +                : size(other.size),
    +                  data(other.data) {
    +            }
    +            template
    +            make_array_helper(const make_array_helper& other) 
    +                : size(other.size),
    +                  data(other.data) {
    +            }
    +            pointer address(reference value) const {
    +                return &value;
    +            }
    +            const_pointer address(const_reference value) const {
    +                return &value;
    +            }
    +            size_type max_size() const {
    +                return static_cast(-1) / sizeof(Y);
    +            }
    +            pointer allocate(size_type count, const void* = 0) {
    +                std::size_t a1 = alignment_of::value;
    +                std::size_t n1 = count * sizeof(Y) + a1 - 1;
    +                void*  p1 = ::operator new(n1 + size);
    +                char*  p2 = static_cast(p1) + n1;
    +                while (std::size_t(p2) % a1 != 0) {
    +                    p2--;
    +                }
    +                *data = reinterpret_cast(p2);
    +                return  reinterpret_cast(p1);
    +            }
    +            void deallocate(pointer memory, size_type) {
    +                void* p1 = memory;
    +                ::operator delete(p1);
    +            }
    +            void construct(pointer memory, const Y& value) {
    +                void* p1 = memory;
    +                ::new(p1) Y(value);
    +            }
    +            void destroy(pointer memory) {
    +                memory->~Y();
    +            }
    +            template
    +            bool operator==(const make_array_helper& other) const {
    +                return true;
    +            }
    +            template
    +            bool operator!=(const make_array_helper& other) const {
    +                return !(*this == other); 
    +            }
    +        private:
    +            std::size_t size;
    +            T** data;
    +        };
    +    }
    +}
    +
    +#endif
    diff --git a/include/boost/smart_ptr/detail/operator_bool.hpp b/include/boost/smart_ptr/detail/operator_bool.hpp
    index 842a05d..1d5be11 100644
    --- a/include/boost/smart_ptr/detail/operator_bool.hpp
    +++ b/include/boost/smart_ptr/detail/operator_bool.hpp
    @@ -31,7 +31,7 @@
         ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \
         ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) )
     
    -    typedef T * (this_type::*unspecified_bool_type)() const;
    +    typedef element_type * (this_type::*unspecified_bool_type)() const;
     
         operator unspecified_bool_type() const // never throws
         {
    @@ -40,7 +40,7 @@
     
     #else
     
    -    typedef T * this_type::*unspecified_bool_type;
    +    typedef element_type * this_type::*unspecified_bool_type;
     
         operator unspecified_bool_type() const // never throws
         {
    diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp
    index 2c99f02..be4f65b 100644
    --- a/include/boost/smart_ptr/detail/shared_count.hpp
    +++ b/include/boost/smart_ptr/detail/shared_count.hpp
    @@ -347,7 +347,7 @@ public:
             typedef typename sp_convert_reference::type D2;
     
             D2 d2( r.get_deleter() );
    -        pi_ = new sp_counted_impl_pd< Y*, D2 >( r.get(), d2 );
    +        pi_ = new sp_counted_impl_pd< typename std::unique_ptr::pointer, D2 >( r.get(), d2 );
     
     #ifdef BOOST_NO_EXCEPTIONS
     
    diff --git a/include/boost/smart_ptr/detail/sp_convertible.hpp b/include/boost/smart_ptr/detail/sp_convertible.hpp
    index eb39797..31b2627 100644
    --- a/include/boost/smart_ptr/detail/sp_convertible.hpp
    +++ b/include/boost/smart_ptr/detail/sp_convertible.hpp
    @@ -48,6 +48,21 @@ template< class Y, class T > struct sp_convertible
         enum _vt { value = sizeof( (f)( static_cast(0) ) ) == sizeof(yes) };
     };
     
    +template< class Y, class T > struct sp_convertible< Y, T[] >
    +{
    +    enum _vt { value = false };
    +};
    +
    +template< class Y, class T > struct sp_convertible< Y[], T[] >
    +{
    +    enum _vt { value = sp_convertible< Y[1], T[1] >::value };
    +};
    +
    +template< class Y, std::size_t N, class T > struct sp_convertible< Y[N], T[] >
    +{
    +    enum _vt { value = sp_convertible< Y[1], T[1] >::value };
    +};
    +
     struct sp_empty
     {
     };
    diff --git a/include/boost/smart_ptr/detail/sp_if_array.hpp b/include/boost/smart_ptr/detail/sp_if_array.hpp
    new file mode 100644
    index 0000000..3ba3a0e
    --- /dev/null
    +++ b/include/boost/smart_ptr/detail/sp_if_array.hpp
    @@ -0,0 +1,33 @@
    +/*
    + * Copyright (c) 2012 Glen Joseph Fernandes 
    + * glenfe at live dot com
    + *
    + * Distributed under the Boost Software License, 
    + * Version 1.0. (See accompanying file LICENSE_1_0.txt 
    + * or copy at http://boost.org/LICENSE_1_0.txt)
    + */
    +#ifndef BOOST_SMART_PTR_DETAIL_SP_IF_ARRAY_HPP
    +#define BOOST_SMART_PTR_DETAIL_SP_IF_ARRAY_HPP
    +
    +#include 
    +
    +namespace boost {
    +    namespace detail {
    +        template 
    +        struct sp_if_array {
    +        };
    +        template
    +        struct sp_if_array {
    +            typedef boost::shared_ptr type;
    +        };
    +        template
    +        struct sp_if_size_array {
    +        };
    +        template
    +        struct sp_if_size_array {
    +            typedef boost::shared_ptr type;
    +        };
    +    }
    +}
    +
    +#endif
    diff --git a/include/boost/smart_ptr/make_shared.hpp b/include/boost/smart_ptr/make_shared.hpp
    index 7b605e2..8d0e3ea 100644
    --- a/include/boost/smart_ptr/make_shared.hpp
    +++ b/include/boost/smart_ptr/make_shared.hpp
    @@ -3,7 +3,7 @@
     
     //  make_shared.hpp
     //
    -//  Copyright (c) 2007, 2008 Peter Dimov
    +//  Copyright (c) 2007, 2008, 2012 Peter Dimov
     //
     //  Distributed under the Boost Software License, Version 1.0.
     //  See accompanying file LICENSE_1_0.txt or copy at
    @@ -12,970 +12,11 @@
     //  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_ )
    -        {
    -#if defined( __GNUC__ )
    -
    -            // fixes incorrect aliasing warning
    -            T * p = reinterpret_cast< T* >( storage_.data_ );
    -            p->~T();
    -
    -#else
    -
    -            reinterpret_cast< T* >( storage_.data_ )->~T();
    +#include 
     
    +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_SFINAE )
    +# include 
    +# include 
     #endif
     
    -            initialized_ = false;
    -        }
    -    }
    -
    -public:
    -
    -    sp_ms_deleter(): initialized_( false )
    -    {
    -    }
    -
    -    // optimization: do not copy storage_
    -    sp_ms_deleter( sp_ms_deleter const & ): initialized_( false )
    -    {
    -    }
    -
    -    ~sp_ms_deleter()
    -    {
    -        destroy();
    -    }
    -
    -    void operator()( T * )
    -    {
    -        destroy();
    -    }
    -
    -    void * address()
    -    {
    -        return storage_.data_;
    -    }
    -
    -    void set_initialized()
    -    {
    -        initialized_ = true;
    -    }
    -};
    -
    -#if defined( BOOST_HAS_RVALUE_REFS )
    -
    -template< class T > T&& sp_forward( T & t )
    -{
    -    return static_cast< T&& >( t );
    -}
    -
    -#endif
    -
    -} // namespace detail
    -
    -#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
    -# define BOOST_SP_MSD( T ) boost::detail::sp_inplace_tag< boost::detail::sp_ms_deleter< T > >()
    -#else
    -# define BOOST_SP_MSD( T ) boost::detail::sp_ms_deleter< T >()
    -#endif
    -
    -// 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 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T();
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T();
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )
    -
    -// Variadic templates, rvalue reference
    -
    -template< class T, class Arg1, class... Args > boost::shared_ptr< T > make_shared( Arg1 && arg1, Args && ... args )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( boost::detail::sp_forward( arg1 ), boost::detail::sp_forward( args )... );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -template< class T, class A, class Arg1, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Arg1 && arg1, Args && ... args )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( boost::detail::sp_forward( arg1 ), boost::detail::sp_forward( args )... );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -#elif defined( BOOST_HAS_RVALUE_REFS )
    -
    -// For example MSVC 10.0
    -
    -template< class T, class A1 >
    -boost::shared_ptr< T > make_shared( A1 && a1 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T(
    -        boost::detail::sp_forward( a1 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -template< class T, class A, class A1 >
    -boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( 
    -        boost::detail::sp_forward( a1 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -template< class T, class A1, class A2 >
    -boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T(
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -template< class T, class A, class A1, class A2 >
    -boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( 
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -template< class T, class A1, class A2, class A3 >
    -boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T(
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 ), 
    -        boost::detail::sp_forward( a3 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -template< class T, class A, class A1, class A2, class A3 >
    -boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( 
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 ), 
    -        boost::detail::sp_forward( a3 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -template< class T, class A1, class A2, class A3, class A4 >
    -boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T(
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 ), 
    -        boost::detail::sp_forward( a3 ), 
    -        boost::detail::sp_forward( a4 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -template< class T, class A, class A1, class A2, class A3, class A4 >
    -boost::shared_ptr< T > allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( 
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 ), 
    -        boost::detail::sp_forward( a3 ), 
    -        boost::detail::sp_forward( a4 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -template< class T, class A1, class A2, class A3, class A4, class A5 >
    -boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T(
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 ), 
    -        boost::detail::sp_forward( a3 ), 
    -        boost::detail::sp_forward( a4 ), 
    -        boost::detail::sp_forward( a5 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( 
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 ), 
    -        boost::detail::sp_forward( a3 ), 
    -        boost::detail::sp_forward( a4 ), 
    -        boost::detail::sp_forward( a5 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
    -boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T(
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 ), 
    -        boost::detail::sp_forward( a3 ), 
    -        boost::detail::sp_forward( a4 ), 
    -        boost::detail::sp_forward( a5 ), 
    -        boost::detail::sp_forward( a6 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( 
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 ), 
    -        boost::detail::sp_forward( a3 ), 
    -        boost::detail::sp_forward( a4 ), 
    -        boost::detail::sp_forward( a5 ), 
    -        boost::detail::sp_forward( a6 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
    -boost::shared_ptr< T > make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T(
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 ), 
    -        boost::detail::sp_forward( a3 ), 
    -        boost::detail::sp_forward( a4 ), 
    -        boost::detail::sp_forward( a5 ), 
    -        boost::detail::sp_forward( a6 ), 
    -        boost::detail::sp_forward( a7 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( 
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 ), 
    -        boost::detail::sp_forward( a3 ), 
    -        boost::detail::sp_forward( a4 ), 
    -        boost::detail::sp_forward( a5 ), 
    -        boost::detail::sp_forward( a6 ), 
    -        boost::detail::sp_forward( a7 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T(
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 ), 
    -        boost::detail::sp_forward( a3 ), 
    -        boost::detail::sp_forward( a4 ), 
    -        boost::detail::sp_forward( a5 ), 
    -        boost::detail::sp_forward( a6 ), 
    -        boost::detail::sp_forward( a7 ), 
    -        boost::detail::sp_forward( a8 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( 
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 ), 
    -        boost::detail::sp_forward( a3 ), 
    -        boost::detail::sp_forward( a4 ), 
    -        boost::detail::sp_forward( a5 ), 
    -        boost::detail::sp_forward( a6 ), 
    -        boost::detail::sp_forward( a7 ), 
    -        boost::detail::sp_forward( a8 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T(
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 ), 
    -        boost::detail::sp_forward( a3 ), 
    -        boost::detail::sp_forward( a4 ), 
    -        boost::detail::sp_forward( a5 ), 
    -        boost::detail::sp_forward( a6 ), 
    -        boost::detail::sp_forward( a7 ), 
    -        boost::detail::sp_forward( a8 ), 
    -        boost::detail::sp_forward( a9 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 )
    -{
    -    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( 
    -        boost::detail::sp_forward( a1 ), 
    -        boost::detail::sp_forward( a2 ), 
    -        boost::detail::sp_forward( a3 ), 
    -        boost::detail::sp_forward( a4 ), 
    -        boost::detail::sp_forward( a5 ), 
    -        boost::detail::sp_forward( a6 ), 
    -        boost::detail::sp_forward( a7 ), 
    -        boost::detail::sp_forward( a8 ), 
    -        boost::detail::sp_forward( a9 )
    -        );
    -
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -#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 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1, a2 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1, a2 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1, a2, a3 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1, a2, a3 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1, a2, a3, a4 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1, a2, a3, a4 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1, a2, a3, a4, a5 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1, a2, a3, a4, a5 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1, a2, a3, a4, a5, a6 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1, a2, a3, a4, a5, a6 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    -
    -    void * pv = pd->address();
    -
    -    ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
    -    pd->set_initialized();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ) );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::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();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -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 ), BOOST_SP_MSD( T ), a );
    -
    -    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::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();
    -
    -    T * pt2 = static_cast< T* >( pv );
    -
    -    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    -    return boost::shared_ptr< T >( pt, pt2 );
    -}
    -
    -#endif
    -
    -#undef BOOST_SP_MSD
    -
    -} // namespace boost
    -
     #endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED
    diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp
    new file mode 100644
    index 0000000..f9a39ff
    --- /dev/null
    +++ b/include/boost/smart_ptr/make_shared_array.hpp
    @@ -0,0 +1,176 @@
    +/*
    + * Copyright (c) 2012 Glen Joseph Fernandes 
    + * glenfe at live dot com
    + *
    + * Distributed under the Boost Software License, 
    + * Version 1.0. (See accompanying file LICENSE_1_0.txt 
    + * or copy at http://boost.org/LICENSE_1_0.txt)
    + */
    +#ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
    +#define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
    +#include 
    +#endif
    +
    +namespace boost {
    +    template
    +    inline typename detail::sp_if_array::type
    +    make_shared(std::size_t size) {
    +        typedef typename detail::array_inner::type T1;
    +        typedef typename detail::array_base::type T2;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        std::size_t n1 = size * detail::array_total::size;
    +        detail::make_array_helper a1(n1, &p2);
    +        detail::array_deleter d1;
    +        shared_ptr s1(p1, d1, a1);
    +        detail::array_deleter* d2;
    +        p1 = reinterpret_cast(p2);        
    +        d2 = get_deleter >(s1);
    +        d2->construct(p2, n1);
    +        return shared_ptr(s1, p1);
    +    }
    +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
    +    template
    +    inline typename detail::sp_if_array::type
    +    make_shared(std::size_t size, Args&&... args) {
    +        typedef typename detail::array_inner::type T1;
    +        typedef typename detail::array_base::type T2;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        std::size_t n1 = size * detail::array_total::size;
    +        detail::make_array_helper a1(n1, &p2);
    +        detail::array_deleter d1;
    +        shared_ptr s1(p1, d1, a1);
    +        detail::array_deleter* d2;
    +        p1 = reinterpret_cast(p2);        
    +        d2 = get_deleter >(s1);
    +        d2->construct(p2, n1, std::forward(args)...);
    +        return shared_ptr(s1, p1);
    +    }
    +    template
    +    inline typename detail::sp_if_size_array::type
    +    make_shared(Args&&... args) {
    +        typedef typename detail::array_inner::type T1;
    +        typedef typename detail::array_base::type T2;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        std::size_t n1 = detail::array_total::size;
    +        detail::make_array_helper a1(n1, &p2);
    +        detail::array_deleter d1;
    +        shared_ptr s1(p1, d1, a1);
    +        detail::array_deleter* d2;
    +        p1 = reinterpret_cast(p2);        
    +        d2 = get_deleter >(s1);
    +        d2->construct(p2, n1, std::forward(args)...);
    +        return shared_ptr(s1, p1);
    +    }
    +#endif
    +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
    +    template
    +    inline typename detail::sp_if_array::type
    +    make_shared(std::initializer_list::type> list) {
    +        typedef typename detail::array_inner::type T1;
    +        typedef typename detail::array_base::type T2;
    +        typedef const T2 T3;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        T3* p3 = 0;
    +        std::size_t n1 = list.size() * detail::array_total::size;
    +        detail::make_array_helper a1(n1, &p2);
    +        detail::array_deleter d1;
    +        shared_ptr s1(p1, d1, a1);
    +        detail::array_deleter* d2;        
    +        p3 = reinterpret_cast(list.begin());
    +        p1 = reinterpret_cast(p2);
    +        d2 = get_deleter >(s1);
    +        d2->construct_list(p2, n1, p3);
    +        return shared_ptr(s1, p1);
    +    }
    +    template
    +    inline typename detail::sp_if_size_array::type
    +    make_shared(std::initializer_list::type> list) {
    +        BOOST_ASSERT(list.size() == detail::array_size::size);
    +        typedef typename detail::array_inner::type T1;
    +        typedef typename detail::array_base::type T2;
    +        typedef const T2 T3;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        T3* p3 = 0;
    +        std::size_t n1 = detail::array_total::size;
    +        detail::make_array_helper a1(n1, &p2);
    +        detail::array_deleter d1;
    +        shared_ptr s1(p1, d1, a1);
    +        detail::array_deleter* d2;        
    +        p3 = reinterpret_cast(list.begin());
    +        p1 = reinterpret_cast(p2);
    +        d2 = get_deleter >(s1);
    +        d2->construct_list(p2, n1, p3);
    +        return shared_ptr(s1, p1);
    +    }
    +    template
    +    inline typename detail::sp_if_array::type
    +    make_shared(std::size_t size, 
    +        std::initializer_list::type> list) {
    +        typedef typename detail::array_inner::type T1;
    +        typedef typename detail::array_base::type T2;
    +        typedef const T2 T3;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        T3* p3 = 0;
    +        std::size_t n0 = detail::array_total::size;
    +        std::size_t n1 = n0 * size;
    +        detail::make_array_helper a1(n1, &p2);
    +        detail::array_deleter d1;
    +        shared_ptr s1(p1, d1, a1);
    +        detail::array_deleter* d2;        
    +        p3 = reinterpret_cast(list.begin());
    +        p1 = reinterpret_cast(p2);
    +        d2 = get_deleter >(s1);
    +        d2->construct_list(p2, n1, p3, n0);
    +        return shared_ptr(s1, p1);
    +    }
    +#endif
    +    template
    +    inline typename detail::sp_if_array::type
    +    make_shared_noinit(std::size_t size) {
    +        typedef typename detail::array_inner::type T1;
    +        typedef typename detail::array_base::type T2;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        std::size_t n1 = size * detail::array_total::size;
    +        detail::make_array_helper a1(n1, &p2);
    +        detail::array_deleter d1;
    +        shared_ptr s1(p1, d1, a1);
    +        detail::array_deleter* d2;
    +        p1 = reinterpret_cast(p2);        
    +        d2 = get_deleter >(s1);
    +        d2->construct_noinit(p2, n1);
    +        return shared_ptr(s1, p1);
    +    }
    +    template
    +    inline typename detail::sp_if_size_array::type
    +    make_shared_noinit() {
    +        typedef typename detail::array_inner::type T1;
    +        typedef typename detail::array_base::type T2;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        std::size_t n1 = detail::array_total::size;
    +        detail::make_array_helper a1(n1, &p2);
    +        detail::array_deleter d1;
    +        shared_ptr s1(p1, d1, a1);
    +        detail::array_deleter* d2;
    +        p1 = reinterpret_cast(p2);        
    +        d2 = get_deleter >(s1);
    +        d2->construct_noinit(p2, n1);
    +        return shared_ptr(s1, p1);
    +    }
    +}
    +
    +#endif
    diff --git a/include/boost/smart_ptr/make_shared_object.hpp b/include/boost/smart_ptr/make_shared_object.hpp
    new file mode 100644
    index 0000000..3872909
    --- /dev/null
    +++ b/include/boost/smart_ptr/make_shared_object.hpp
    @@ -0,0 +1,998 @@
    +#ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED
    +#define BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED
    +
    +//  make_shared_object.hpp
    +//
    +//  Copyright (c) 2007, 2008, 2012 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_ )
    +        {
    +#if defined( __GNUC__ )
    +
    +            // fixes incorrect aliasing warning
    +            T * p = reinterpret_cast< T* >( storage_.data_ );
    +            p->~T();
    +
    +#else
    +
    +            reinterpret_cast< T* >( storage_.data_ )->~T();
    +
    +#endif
    +
    +            initialized_ = false;
    +        }
    +    }
    +
    +public:
    +
    +    sp_ms_deleter(): initialized_( false )
    +    {
    +    }
    +
    +    // optimization: do not copy storage_
    +    sp_ms_deleter( sp_ms_deleter const & ): initialized_( false )
    +    {
    +    }
    +
    +    ~sp_ms_deleter()
    +    {
    +        destroy();
    +    }
    +
    +    void operator()( T * )
    +    {
    +        destroy();
    +    }
    +
    +    void * address()
    +    {
    +        return storage_.data_;
    +    }
    +
    +    void set_initialized()
    +    {
    +        initialized_ = true;
    +    }
    +};
    +
    +#if defined( BOOST_HAS_RVALUE_REFS )
    +
    +template< class T > T&& sp_forward( T & t )
    +{
    +    return static_cast< T&& >( t );
    +}
    +
    +#endif
    +
    +template< class T > struct sp_if_not_array
    +{
    +    typedef boost::shared_ptr< T > type;
    +};
    +
    +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    +
    +template< class T > struct sp_if_not_array< T[] >
    +{
    +};
    +
    +template< class T, std::size_t N > struct sp_if_not_array< T[N] >
    +{
    +};
    +
    +#endif
    +
    +} // namespace detail
    +
    +#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
    +# define BOOST_SP_MSD( T ) boost::detail::sp_inplace_tag< boost::detail::sp_ms_deleter< T > >()
    +#else
    +# define BOOST_SP_MSD( T ) boost::detail::sp_ms_deleter< T >()
    +#endif
    +
    +// Zero-argument versions
    +//
    +// Used even when variadic templates are available because of the new T() vs new T issue
    +
    +template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared()
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T();
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T();
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )
    +
    +// Variadic templates, rvalue reference
    +
    +template< class T, class Arg1, class... Args > typename boost::detail::sp_if_not_array< T >::type make_shared( Arg1 && arg1, Args && ... args )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( boost::detail::sp_forward( arg1 ), boost::detail::sp_forward( args )... );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class Arg1, class... Args > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, Arg1 && arg1, Args && ... args )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( boost::detail::sp_forward( arg1 ), boost::detail::sp_forward( args )... );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +#elif defined( BOOST_HAS_RVALUE_REFS )
    +
    +// For example MSVC 10.0
    +
    +template< class T, class A1 >
    +typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1 >
    +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2 >
    +typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2 >
    +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3 >
    +typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3 >
    +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4 >
    +typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3, class A4 >
    +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4, class A5 >
    +typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3, class A4, class A5 >
    +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
    +typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 >
    +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
    +typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 ), 
    +        boost::detail::sp_forward( a7 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
    +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 ), 
    +        boost::detail::sp_forward( a7 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
    +typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 ), 
    +        boost::detail::sp_forward( a7 ), 
    +        boost::detail::sp_forward( a8 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
    +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 ), 
    +        boost::detail::sp_forward( a7 ), 
    +        boost::detail::sp_forward( a8 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
    +typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T(
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 ), 
    +        boost::detail::sp_forward( a7 ), 
    +        boost::detail::sp_forward( a8 ), 
    +        boost::detail::sp_forward( a9 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
    +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( 
    +        boost::detail::sp_forward( a1 ), 
    +        boost::detail::sp_forward( a2 ), 
    +        boost::detail::sp_forward( a3 ), 
    +        boost::detail::sp_forward( a4 ), 
    +        boost::detail::sp_forward( a5 ), 
    +        boost::detail::sp_forward( a6 ), 
    +        boost::detail::sp_forward( a7 ), 
    +        boost::detail::sp_forward( a8 ), 
    +        boost::detail::sp_forward( a9 )
    +        );
    +
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +#else
    +
    +// C++03 version
    +
    +template< class T, class A1 >
    +typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1 >
    +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 const & a1 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2 >
    +typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A2 const & a2 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1, a2 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2 >
    +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 const & a1, A2 const & a2 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1, a2 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3 >
    +typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A2 const & a2, A3 const & a3 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1, a2, a3 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3 >
    +typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1, a2, a3 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4 >
    +typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
    +{
    +    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1, a2, a3, a4 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3, class A4 >
    +typename boost::detail::sp_if_not_array< T >::type 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 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1, a2, a3, a4 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4, class A5 >
    +typename boost::detail::sp_if_not_array< T >::type 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 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1, a2, a3, a4, a5 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3, class A4, class A5 >
    +typename boost::detail::sp_if_not_array< T >::type 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 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1, a2, a3, a4, a5 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
    +typename boost::detail::sp_if_not_array< T >::type 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 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1, a2, a3, a4, a5, a6 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 >
    +typename boost::detail::sp_if_not_array< T >::type 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 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1, a2, a3, a4, a5, a6 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
    +typename boost::detail::sp_if_not_array< T >::type 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 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
    +typename boost::detail::sp_if_not_array< T >::type 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 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
    +typename boost::detail::sp_if_not_array< T >::type 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 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
    +typename boost::detail::sp_if_not_array< T >::type 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 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt );
    +
    +    void * pv = pd->address();
    +
    +    ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
    +    pd->set_initialized();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
    +typename boost::detail::sp_if_not_array< T >::type 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 ), BOOST_SP_MSD( T ) );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::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();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
    +typename boost::detail::sp_if_not_array< T >::type 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 ), BOOST_SP_MSD( T ), a );
    +
    +    boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::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();
    +
    +    T * pt2 = static_cast< T* >( pv );
    +
    +    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    +    return boost::shared_ptr< T >( pt, pt2 );
    +}
    +
    +#endif
    +
    +#undef BOOST_SP_MSD
    +
    +} // namespace boost
    +
    +#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED
    diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp
    index 36799e6..3e79582 100644
    --- a/include/boost/smart_ptr/shared_array.hpp
    +++ b/include/boost/smart_ptr/shared_array.hpp
    @@ -5,7 +5,7 @@
     //  shared_array.hpp
     //
     //  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
    -//  Copyright (c) 2001, 2002 Peter Dimov
    +//  Copyright (c) 2001, 2002, 2012 Peter Dimov
     //
     //  Distributed under the Boost Software License, Version 1.0. (See
     //  accompanying file LICENSE_1_0.txt or copy at
    @@ -25,6 +25,7 @@
     #include 
     #include 
     
    +#include 
     #include 
     #include 
     
    @@ -55,18 +56,32 @@ public:
     
         typedef T element_type;
     
    -    explicit shared_array(T * p = 0): px(p), pn(p, deleter())
    +    shared_array(): px( 0 ), pn() // never throws
         {
         }
     
    +    template
    +    explicit shared_array( Y * p ): px( p ), pn( p, checked_array_deleter() )
    +    {
    +        boost::detail::sp_assert_convertible< Y[], T[] >();
    +    }
    +
         //
         // 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)
    +    template shared_array( Y * p, D d ): px( p ), pn( p, d )
         {
    +        boost::detail::sp_assert_convertible< Y[], T[] >();
    +    }
    +
    +    // As above, but with allocator. A's copy constructor shall not throw.
    +
    +    template shared_array( Y * p, D d, A a ): px( p ), pn( p, d, a )
    +    {
    +        boost::detail::sp_assert_convertible< Y[], T[] >();
         }
     
     //  generated copy constructor, destructor are fine...
    @@ -79,8 +94,38 @@ public:
         {
         }
     
    +    shared_array( shared_array && r ): px( r.px ), pn() // never throws
    +    {
    +        pn.swap( r.pn );
    +        r.px = 0;
    +    }
    +
     #endif
     
    +    // conversion
    +
    +    template
    +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
    +
    +    shared_array( shared_array const & r, typename boost::detail::sp_enable_if_convertible< Y[], T[] >::type = boost::detail::sp_empty() )
    +
    +#else
    +
    +    shared_array( shared_array const & r )
    +
    +#endif
    +    : px( r.px ), pn( r.pn ) // never throws
    +    {
    +        boost::detail::sp_assert_convertible< Y[], T[] >();
    +    }
    +
    +    // aliasing
    +
    +    template< class Y >
    +    shared_array( shared_array const & r, element_type * p ): px( p ), pn( r.pn ) // never throws
    +    {
    +    }
    +
         // assignment
     
         shared_array & operator=( shared_array const & r ) // never throws
    @@ -89,15 +134,58 @@ public:
             return *this;
         }
     
    -    void reset(T * p = 0)
    +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
    +
    +    template
    +    shared_array & operator=( shared_array const & r ) // never throws
         {
    -        BOOST_ASSERT(p == 0 || p != px);
    -        this_type(p).swap(*this);
    +        this_type( r ).swap( *this );
    +        return *this;
         }
     
    -    template  void reset(T * p, D d)
    +#endif
    +
    +#if defined( BOOST_HAS_RVALUE_REFS )
    +
    +    shared_array & operator=( shared_array && r ) // never throws
         {
    -        this_type(p, d).swap(*this);
    +        this_type( static_cast< shared_array && >( r ) ).swap( *this );
    +        return *this;
    +    }
    +
    +    template
    +    shared_array & operator=( shared_array && r ) // never throws
    +    {
    +        this_type( static_cast< shared_array && >( r ) ).swap( *this );
    +        return *this;
    +    }
    +
    +#endif
    +
    +    void reset() // never throws
    +    {
    +        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_array const & r, element_type * p )
    +    {
    +        this_type( r, p ).swap( *this );
         }
     
         T & operator[] (std::ptrdiff_t i) const // never throws
    @@ -138,6 +226,8 @@ public:
     
     private:
     
    +    template friend class shared_array;
    +
         T * px;                     // contained pointer
         detail::shared_count pn;    // reference counter
     
    diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp
    index 08cf3fe..f9fe0d3 100644
    --- a/include/boost/smart_ptr/shared_ptr.hpp
    +++ b/include/boost/smart_ptr/shared_ptr.hpp
    @@ -67,34 +67,129 @@ struct const_cast_tag {};
     struct dynamic_cast_tag {};
     struct polymorphic_cast_tag {};
     
    -template struct shared_ptr_traits
    +// sp_element, element_type
    +
    +template< class T > struct sp_element
     {
    -    typedef T & reference;
    +    typedef T type;
     };
     
    -template<> struct shared_ptr_traits
    +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    +
    +template< class T > struct sp_element< T[] >
     {
    -    typedef void reference;
    +    typedef T type;
    +};
    +
    +template< class T, std::size_t N > struct sp_element< T[N] >
    +{
    +    typedef T type;
    +};
    +
    +#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    +
    +// sp_dereference, return type of operator*
    +
    +template< class T > struct sp_dereference
    +{
    +    typedef T & type;
    +};
    +
    +template<> struct sp_dereference< void >
    +{
    +    typedef void type;
     };
     
     #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
     
    -template<> struct shared_ptr_traits
    +template<> struct sp_dereference< void const >
     {
    -    typedef void reference;
    +    typedef void type;
     };
     
    -template<> struct shared_ptr_traits
    +template<> struct sp_dereference< void volatile >
     {
    -    typedef void reference;
    +    typedef void type;
     };
     
    -template<> struct shared_ptr_traits
    +template<> struct sp_dereference< void const volatile >
     {
    -    typedef void reference;
    +    typedef void type;
     };
     
    -#endif
    +#endif // !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
    +
    +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    +
    +template< class T > struct sp_dereference< T[] >
    +{
    +    typedef void type;
    +};
    +
    +template< class T, std::size_t N > struct sp_dereference< T[N] >
    +{
    +    typedef void type;
    +};
    +
    +#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    +
    +// sp_member_access, return type of operator->
    +
    +template< class T > struct sp_member_access
    +{
    +    typedef T * type;
    +};
    +
    +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    +
    +template< class T > struct sp_member_access< T[] >
    +{
    +    typedef void type;
    +};
    +
    +template< class T, std::size_t N > struct sp_member_access< T[N] >
    +{
    +    typedef void type;
    +};
    +
    +#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    +
    +// sp_array_access, return type of operator[]
    +
    +template< class T > struct sp_array_access
    +{
    +    typedef void type;
    +};
    +
    +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    +
    +template< class T > struct sp_array_access< T[] >
    +{
    +    typedef T & type;
    +};
    +
    +template< class T, std::size_t N > struct sp_array_access< T[N] >
    +{
    +    typedef T & type;
    +};
    +
    +#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    +
    +// sp_extent, for operator[] index check
    +
    +template< class T > struct sp_extent
    +{
    +    enum _vt { value = 0 };
    +};
    +
    +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    +
    +template< class T, std::size_t N > struct sp_extent< T[N] >
    +{
    +    enum _vt { value = N };
    +};
    +
    +#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
     
     // enable_shared_from_this support
     
    @@ -144,6 +239,69 @@ template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R
     
     #endif
     
    +// sp_assert_convertible
    +
    +template< class Y, class T > inline void sp_assert_convertible()
    +{
    +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
    +
    +    // static_assert( sp_convertible< Y, T >::value );
    +    typedef char tmp[ sp_convertible< Y, T >::value? 1: -1 ];
    +    (void)sizeof( tmp );
    +
    +#else
    +
    +    T* p = static_cast< Y* >( 0 );
    +    (void)p;
    +
    +#endif
    +}
    +
    +// pointer constructor helper
    +
    +template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & pn )
    +{
    +    boost::detail::shared_count( p ).swap( pn );
    +    boost::detail::sp_enable_shared_from_this( ppx, p, p );
    +}
    +
    +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    +
    +template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
    +{
    +    sp_assert_convertible< Y[], T[] >();
    +    boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
    +}
    +
    +template< class T, std::size_t N, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
    +{
    +    sp_assert_convertible< Y[N], T[N] >();
    +    boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
    +}
    +
    +#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    +
    +// deleter constructor helper
    +
    +template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T > * ppx, Y * p )
    +{
    +    boost::detail::sp_enable_shared_from_this( ppx, p, p );
    +}
    +
    +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    +
    +template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * /*p*/ )
    +{
    +    sp_assert_convertible< Y[], T[] >();
    +}
    +
    +template< class T, std::size_t N, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * /*p*/ )
    +{
    +    sp_assert_convertible< Y[N], T[N] >();
    +}
    +
    +#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    +
     } // namespace detail
     
     
    @@ -164,19 +322,16 @@ private:
     
     public:
     
    -    typedef T element_type;
    -    typedef T value_type;
    -    typedef T * pointer;
    -    typedef typename boost::detail::shared_ptr_traits::reference reference;
    +    typedef typename boost::detail::sp_element< T >::type element_type;
     
    -    shared_ptr(): px(0), pn() // never throws in 1.30+
    +    shared_ptr(): px( 0 ), pn() // never throws in 1.30+
         {
         }
     
         template
    -    explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
    +    explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete
         {
    -        boost::detail::sp_enable_shared_from_this( this, p, p );
    +        boost::detail::sp_pointer_construct( this, p, pn );
         }
     
         //
    @@ -185,16 +340,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 )
         {
    -        boost::detail::sp_enable_shared_from_this( this, p, p );
    +        boost::detail::sp_deleter_construct( 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( this, p, p );
    +        boost::detail::sp_deleter_construct( this, p );
         }
     
     //  generated copy constructor, destructor are fine...
    @@ -210,8 +365,10 @@ public:
     #endif
     
         template
    -    explicit shared_ptr(weak_ptr const & r): pn(r.pn) // may throw
    +    explicit shared_ptr( weak_ptr const & r ): pn( r.pn ) // may throw
         {
    +        boost::detail::sp_assert_convertible< Y, T >();
    +
             // it is now safe to copy r.px, as pn(r.pn) did not throw
             px = r.px;
         }
    @@ -237,11 +394,12 @@ public:
     #endif
         : px( r.px ), pn( r.pn ) // never throws
         {
    +        boost::detail::sp_assert_convertible< Y, T >();
         }
     
         // aliasing
         template< class Y >
    -    shared_ptr( shared_ptr const & r, T * p ): px( p ), pn( r.pn ) // never throws
    +    shared_ptr( shared_ptr const & r, element_type * p ): px( p ), pn( r.pn ) // never throws
         {
         }
     
    @@ -278,9 +436,12 @@ public:
         template
         explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn()
         {
    +        boost::detail::sp_assert_convertible< Y, T >();
    +
             Y * tmp = r.get();
             pn = boost::detail::shared_count(r);
    -        boost::detail::sp_enable_shared_from_this( this, tmp, tmp );
    +
    +        boost::detail::sp_deleter_construct( this, tmp );
         }
     
     #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
    @@ -288,11 +449,15 @@ public:
         template
         explicit 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( this, tmp, tmp );
    -    }
    +        typedef typename Ap::element_type Y;
     
    +        boost::detail::sp_assert_convertible< Y, T >();
    +
    +        Y * tmp = r.get();
    +        pn = boost::detail::shared_count( r );
    +
    +        boost::detail::sp_deleter_construct( this, tmp );
    +    }
     
     #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
     
    @@ -301,11 +466,14 @@ public:
     #if !defined( BOOST_NO_CXX11_SMART_PTR )
     
         template< class Y, class D >
    -    shared_ptr( std::unique_ptr< Y, D > && r): px( r.get() ), pn()
    +    shared_ptr( std::unique_ptr< Y, D > && r ): px( r.get() ), pn()
         {
    -        Y * tmp = r.get();
    +        boost::detail::sp_assert_convertible< Y, T >();
    +
    +        typename std::unique_ptr< Y, D >::pointer tmp = r.get();
             pn = boost::detail::shared_count( r );
    -        boost::detail::sp_enable_shared_from_this( this, tmp, tmp );
    +
    +        boost::detail::sp_deleter_construct( this, tmp );
         }
     
     #endif
    @@ -347,7 +515,6 @@ public:
             return *this;
         }
     
    -
     #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
     
     #endif // BOOST_NO_AUTO_PTR
    @@ -374,6 +541,8 @@ public:
     #endif
         : px( r.px ), pn() // never throws
         {
    +        boost::detail::sp_assert_convertible< Y, T >();
    +
             pn.swap( r.pn );
             r.px = 0;
         }
    @@ -398,10 +567,10 @@ public:
             this_type().swap(*this);
         }
     
    -    template void reset(Y * p) // Y must be complete
    +    template void reset( Y * p ) // Y must be complete
         {
    -        BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
    -        this_type(p).swap(*this);
    +        BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
    +        this_type( p ).swap( *this );
         }
     
         template void reset( Y * p, D d )
    @@ -414,24 +583,32 @@ public:
             this_type( p, d, a ).swap( *this );
         }
     
    -    template void reset( shared_ptr const & r, T * p )
    +    template void reset( shared_ptr const & r, element_type * p )
         {
             this_type( r, p ).swap( *this );
         }
     
    -    reference operator* () const // never throws
    +    typename boost::detail::sp_dereference< T >::type operator* () const // never throws
         {
    -        BOOST_ASSERT(px != 0);
    +        BOOST_ASSERT( px != 0 );
             return *px;
         }
     
    -    T * operator-> () const // never throws
    +    typename boost::detail::sp_member_access< T >::type operator-> () const // never throws
         {
    -        BOOST_ASSERT(px != 0);
    +        BOOST_ASSERT( px != 0 );
             return px;
         }
     
    -    T * get() const // never throws
    +    typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const // never throws
    +    {
    +        BOOST_ASSERT( px != 0 );
    +        BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
    +
    +        return px[ i ];
    +    }
    +
    +    element_type * get() const // never throws
         {
             return px;
         }
    @@ -449,7 +626,7 @@ public:
             return pn.use_count();
         }
     
    -    void swap(shared_ptr & other) // never throws
    +    void swap( shared_ptr & other ) // never throws
         {
             std::swap(px, other.px);
             pn.swap(other.pn);
    @@ -488,7 +665,7 @@ private:
     
     #endif
     
    -    T * px;                     // contained pointer
    +    element_type * px;                 // contained pointer
         boost::detail::shared_count pn;    // reference counter
     
     };  // shared_ptr
    diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp
    index 5391910..62b6afe 100644
    --- a/include/boost/smart_ptr/weak_ptr.hpp
    +++ b/include/boost/smart_ptr/weak_ptr.hpp
    @@ -29,7 +29,7 @@ private:
     
     public:
     
    -    typedef T element_type;
    +    typedef typename boost::detail::sp_element< T >::type element_type;
     
         weak_ptr(): px(0), pn() // never throws in 1.30+
         {
    @@ -83,6 +83,7 @@ public:
     #endif
         : px(r.lock().get()), pn(r.pn) // never throws
         {
    +        boost::detail::sp_assert_convertible< Y, T >();
         }
     
     #if defined( BOOST_HAS_RVALUE_REFS )
    @@ -99,6 +100,7 @@ public:
     #endif
         : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) // never throws
         {
    +        boost::detail::sp_assert_convertible< Y, T >();
             r.px = 0;
         }
     
    @@ -130,15 +132,19 @@ public:
     #endif
         : px( r.px ), pn( r.pn ) // never throws
         {
    +        boost::detail::sp_assert_convertible< Y, T >();
         }
     
     #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
     
         template
    -    weak_ptr & operator=(weak_ptr const & r) // never throws
    +    weak_ptr & operator=( weak_ptr const & r ) // never throws
         {
    +        boost::detail::sp_assert_convertible< Y, T >();
    +
             px = r.lock().get();
             pn = r.pn;
    +
             return *this;
         }
     
    @@ -154,10 +160,13 @@ public:
     #endif
     
         template
    -    weak_ptr & operator=(shared_ptr const & r) // never throws
    +    weak_ptr & operator=( shared_ptr const & r ) // never throws
         {
    +        boost::detail::sp_assert_convertible< Y, T >();
    +
             px = r.px;
             pn = r.pn;
    +
             return *this;
         }
     
    @@ -165,7 +174,7 @@ public:
     
         shared_ptr lock() const // never throws
         {
    -        return shared_ptr( *this, boost::detail::sp_nothrow_tag() );
    +        return shared_ptr( *this, boost::detail::sp_nothrow_tag() );
         }
     
         long use_count() const // never throws
    @@ -195,7 +204,7 @@ public:
         }
     
         template
    -    void _internal_aliasing_assign(weak_ptr const & r, T * px2)
    +    void _internal_aliasing_assign(weak_ptr const & r, element_type * px2)
         {
             px = px2;
             pn = r.pn;
    @@ -223,7 +232,7 @@ private:
     
     #endif
     
    -    T * px;                       // contained pointer
    +    element_type * px;            // contained pointer
         boost::detail::weak_count pn; // reference counter
     
     };  // weak_ptr
    diff --git a/make_shared_array.html b/make_shared_array.html
    new file mode 100644
    index 0000000..4739b3a
    --- /dev/null
    +++ b/make_shared_array.html
    @@ -0,0 +1,129 @@
    +
    +
    +  
    +    make_shared and allocate_shared
    +    
    +  
    +  
    +    

    boost.png (6897 bytes)make_shared and allocate_shared + for arrays

    +

    Introduction
    + Synopsis
    + Free Functions
    + Example
    +

    Introduction

    +

    One criticism of Boost shared_array is + the lack of utility similar to make_shared + which ensures only a single allocation for an array. A second criticism + is Boost shared_array does not support custom allocators + and so also lacks an allocate_shared utility.

    +

    The header files <boost/smart_ptr/make_shared_array.hpp> and + <boost/smart_ptr/allocate_shared_array.hpp> provide new function + templates, make_shared and allocate_shared, + to address this need. make_shared uses the global + operator new to allocate memory, whereas + allocate_shared uses an user-supplied allocator, + allowing finer control.

    +

    Synopsis

    +
    namespace boost {
    +    template<typename T>
    +    shared_ptr<T[]> make_shared(size_t size);
    +
    +    template<typename T, typename A>
    +    shared_ptr<T[]> allocate_shared(const A& allocator, size_t size);
    +    
    +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
    +    template<typename T, typename... Args>
    +    shared_ptr<T[]> make_shared(size_t size, Args&&... args);
    +    
    +    template<typename T, typename... Args>
    +    shared_ptr<T[N]> make_shared(Args&&... args);
    +    
    +    template<typename T, typename A, typename... Args>
    +    shared_ptr<T> allocate_shared(const A& allocator, size_t size, Args&&... args);
    +    
    +    template<typename T, typename A, typename... Args>
    +    shared_ptr<T[N]> allocate_shared(const A& allocator, Args&&... args);
    +#endif
    +
    +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
    +    template<typename T, typename... Args>
    +    shared_ptr<T[]> make_shared(initializer_list<T> list);
    +    
    +    template<typename T, typename... Args>
    +    shared_ptr<T[N]> make_shared(initializer_list<T> list);
    +    
    +    template<typename T, typename... Args>
    +    shared_ptr<T[][N]> make_shared(size_t size, initializer_list<T> list);
    +        
    +    template<typename T, typename A, typename... Args>
    +    shared_ptr<T[]> allocate_shared(const A& allocator, initializer_list<T> list);
    +    
    +    template<typename T, typename A, typename... Args>
    +    shared_ptr<T[N]> allocate_shared(const A& allocator, initializer_list<T> list);
    +    
    +    template<typename T, typename A, typename... Args>
    +    shared_ptr<T[][N]> allocate_shared(const A& allocator, size_t size, initializer_list<T> list);
    +#endif
    +
    +    template<typename T>
    +    shared_ptr<T> make_shared_noinit(size_t size);
    +    
    +    template<typename T>
    +    shared_ptr<T[N]> make_shared_noinit();
    +}
    +

    Free Functions

    +
    template<typename T, typename... Args>
    +    shared_ptr<T> make_shared(size_t size, Args&&... args);
    +template<typename T, typename A, typename... Args>
    +    shared_ptr<T> allocate_shared(const A& allocator, size_t size, Args&&... args);
    +
    +

    Requires: The expression + new(pointer) T(forward<Args>(args)...), where + pointer is a void* pointing to storage + suitable to hold an object of type T, shall be + well-formed. A shall be an Allocator, as + described in section 20.1.5 (Allocator requirements) + of the C++ Standard. The copy constructor and destructor of + A shall not throw.

    +

    Effects: Allocates memory suitable for an array of type + T and size size and constructs an array + of objects in it via the placement new expression + new(pointer) T() or + new(pointer) T(forward<Args>(args)...). + allocate_shared uses a copy of + allocator to allocate memory. If an exception is thrown, + has no effect.

    +

    Returns: A shared_ptr instance that stores and + owns the address of the newly constructed array of type T + and size size.

    +

    Postconditions: + get() != 0 && use_count() == 1.

    +

    Throws: bad_alloc, or an exception thrown from + A::allocate or the constructor of T.

    +

    Notes: This implementation allocates the memory required for + the returned shared_ptr and an array of type + T of size size in a single allocation. This + provides efficiency to equivalent to an intrusive smart array + pointer.

    +

    The prototypes shown above are used if your compiler supports r-value + references and variadic templates. They perfectly forward the + args parameters to the constructors of + T for each array element.

    +

    Otherwise, you can use the overloads which take only the array size + (and the allocator in case of allocate_shared) and do not + take any constructor arguments. These overloads invoke the default + constructor of T for each array element.

    +
    +

    Example

    +
    boost::shared_ptr<int[]> array = boost::make_shared<int[]>(size);
    +
    +

    $Date: 2012-10-30 10:12:25 -0800 (Tue, 30 Oct 2012) $

    +

    Copyright 2012 Glen Fernandes. 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.v2 b/test/Jamfile.v2 index 1df2a3e..e3b41c0 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -46,7 +46,7 @@ import testing ; [ run spinlock_pool_test.cpp ] [ run make_shared_test.cpp ] [ run make_shared_perfect_forwarding_test.cpp ] - [ run sp_convertible_test.cpp ] + [ run shared_ptr_convertible_test.cpp ] [ run wp_convertible_test.cpp ] [ run ip_convertible_test.cpp ] [ run allocate_shared_test.cpp ] @@ -70,5 +70,82 @@ import testing ; [ run ip_hash_test.cpp ] [ run owner_less_test.cpp ] [ run sp_unique_ptr_test.cpp ] + [ run sp_array_test.cpp ] + [ compile sp_array_cv_test.cpp ] + [ run sp_convertible_test.cpp ] + [ run sp_array_n_test.cpp ] + + [ compile-fail array_fail_spa_sp_c.cpp ] + [ compile-fail array_fail_sp_spa_c.cpp ] + [ compile-fail array_fail_spa_spa_c.cpp ] + [ compile-fail array_fail_spa_wp_c.cpp ] + [ compile-fail array_fail_sp_wpa_c.cpp ] + [ compile-fail array_fail_spa_wpa_c.cpp ] + [ compile-fail array_fail_wpa_wp_c.cpp ] + [ compile-fail array_fail_wp_wpa_c.cpp ] + [ compile-fail array_fail_wpa_wpa_c.cpp ] + [ compile-fail array_fail_ap_spa_c.cpp ] + [ compile-fail array_fail_upa_sp_c.cpp ] + [ compile-fail array_fail_up_spa_c.cpp ] + + [ compile-fail array_fail_spa_sp_mc.cpp ] + [ compile-fail array_fail_sp_spa_mc.cpp ] + [ compile-fail array_fail_spa_spa_mc.cpp ] + [ compile-fail array_fail_spa_wp_mc.cpp ] + [ compile-fail array_fail_sp_wpa_mc.cpp ] + [ compile-fail array_fail_spa_wpa_mc.cpp ] + [ compile-fail array_fail_wpa_wp_mc.cpp ] + [ compile-fail array_fail_wp_wpa_mc.cpp ] + [ compile-fail array_fail_wpa_wpa_mc.cpp ] + [ compile-fail array_fail_ap_spa_mc.cpp ] + [ compile-fail array_fail_upa_sp_mc.cpp ] + [ compile-fail array_fail_up_spa_mc.cpp ] + + [ compile-fail array_fail_spa_sp_a.cpp ] + [ compile-fail array_fail_sp_spa_a.cpp ] + [ compile-fail array_fail_spa_spa_a.cpp ] + [ compile-fail array_fail_spa_wp_a.cpp ] + [ compile-fail array_fail_sp_wpa_a.cpp ] + [ compile-fail array_fail_spa_wpa_a.cpp ] + [ compile-fail array_fail_wpa_wp_a.cpp ] + [ compile-fail array_fail_wp_wpa_a.cpp ] + [ compile-fail array_fail_wpa_wpa_a.cpp ] + [ compile-fail array_fail_ap_spa_a.cpp ] + [ compile-fail array_fail_upa_sp_a.cpp ] + [ compile-fail array_fail_up_spa_a.cpp ] + + [ compile-fail array_fail_spa_sp_ma.cpp ] + [ compile-fail array_fail_sp_spa_ma.cpp ] + [ compile-fail array_fail_spa_spa_ma.cpp ] + [ compile-fail array_fail_spa_wp_ma.cpp ] + [ compile-fail array_fail_sp_wpa_ma.cpp ] + [ compile-fail array_fail_spa_wpa_ma.cpp ] + [ compile-fail array_fail_wpa_wp_ma.cpp ] + [ compile-fail array_fail_wp_wpa_ma.cpp ] + [ compile-fail array_fail_wpa_wpa_ma.cpp ] + [ compile-fail array_fail_ap_spa_ma.cpp ] + [ compile-fail array_fail_upa_sp_ma.cpp ] + [ compile-fail array_fail_up_spa_ma.cpp ] + + [ compile-fail array_fail_dereference.cpp ] + [ compile-fail array_fail_member_access.cpp ] + [ compile-fail array_fail_array_access.cpp ] + + [ run make_shared_array_test.cpp ] + [ run make_shared_arrays_test.cpp ] + [ run make_shared_array_create_test.cpp ] + [ run make_shared_array_init_test.cpp ] + [ run make_shared_arrays_create_test.cpp ] + [ run make_shared_array_throws_test.cpp ] + [ run make_shared_array_esft_test.cpp ] + [ run make_shared_array_args_test.cpp ] + [ run allocate_shared_array_test.cpp ] + [ run allocate_shared_arrays_test.cpp ] + [ run allocate_shared_array_create_test.cpp ] + [ run allocate_shared_array_init_test.cpp ] + [ run allocate_shared_arrays_create_test.cpp ] + [ run allocate_shared_array_throws_test.cpp ] + [ run allocate_shared_array_esft_test.cpp ] + [ run allocate_shared_array_args_test.cpp ] ; } diff --git a/test/allocate_shared_array_args_test.cpp b/test/allocate_shared_array_args_test.cpp new file mode 100644 index 0000000..1226b94 --- /dev/null +++ b/test/allocate_shared_array_args_test.cpp @@ -0,0 +1,173 @@ +// allocate_shared_array_args_test.cpp +// +// Copyright 2007-2009, 2012 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 +{ +private: + + X( X const & ); + X & operator=( X const & ); + + void * operator new[]( std::size_t n ); + void operator delete[]( void * p ); + +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_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 0 ); + BOOST_TEST( px[1].v == 0 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + + { + boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1 ); + BOOST_TEST( px[1].v == 1 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2 ); + BOOST_TEST( px[1].v == 1+2 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2, 3 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2+3 ); + BOOST_TEST( px[1].v == 1+2+3 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2, 3, 4 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2+3+4 ); + BOOST_TEST( px[1].v == 1+2+3+4 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2, 3, 4, 5 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2+3+4+5 ); + BOOST_TEST( px[1].v == 1+2+3+4+5 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2, 3, 4, 5, 6 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2+3+4+5+6 ); + BOOST_TEST( px[1].v == 1+2+3+4+5+6 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2, 3, 4, 5, 6, 7 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2+3+4+5+6+7 ); + BOOST_TEST( px[1].v == 1+2+3+4+5+6+7 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2, 3, 4, 5, 6, 7, 8 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2+3+4+5+6+7+8 ); + BOOST_TEST( px[1].v == 1+2+3+4+5+6+7+8 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2+3+4+5+6+7+8+9 ); + BOOST_TEST( px[1].v == 1+2+3+4+5+6+7+8+9 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + +#endif + + return boost::report_errors(); +} diff --git a/test/allocate_shared_array_create_test.cpp b/test/allocate_shared_array_create_test.cpp new file mode 100644 index 0000000..2e03be6 --- /dev/null +++ b/test/allocate_shared_array_create_test.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +class type { +public: + static int instances; + explicit type(int a=0, int b=0, int c=0, int d=0, int e=0, int f=0, int g=0, int h=0, int i=0) + : a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h), i(i) { + instances++; + } + ~type() { + instances--; + } + const int a; + const int b; + const int c; + const int d; + const int e; + const int f; + const int g; + const int h; + const int i; +private: + type(const type&); + type& operator=(const type&); +}; + +int type::instances = 0; + +int main() { +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, 1, 2, 3, 4, 5, 6, 7, 8, 9); + BOOST_TEST(type::instances == 2); + BOOST_TEST(a1[0].a == 1); + BOOST_TEST(a1[0].d == 4); + BOOST_TEST(a1[1].f == 6); + BOOST_TEST(a1[1].i == 9); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 2, 3, 4, 5, 6, 7, 8, 9); + BOOST_TEST(type::instances == 2); + BOOST_TEST(a1[0].a == 1); + BOOST_TEST(a1[0].d == 4); + BOOST_TEST(a1[1].f == 6); + BOOST_TEST(a1[1].i == 9); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, 1, 2, 3, 4, 5, 6, 7); + BOOST_TEST(type::instances == 4); + BOOST_TEST(a1[0][0].a == 1); + BOOST_TEST(a1[0][1].d == 4); + BOOST_TEST(a1[1][0].f == 6); + BOOST_TEST(a1[1][1].i == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 2, 3, 4, 5, 6, 7); + BOOST_TEST(type::instances == 4); + BOOST_TEST(a1[0][0].a == 1); + BOOST_TEST(a1[0][1].d == 4); + BOOST_TEST(a1[1][0].f == 6); + BOOST_TEST(a1[1][1].i == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, 1, 2, 3, 4, 5); + BOOST_TEST(type::instances == 8); + BOOST_TEST(a1[0][0][0].a == 1); + BOOST_TEST(a1[0][1][0].c == 3); + BOOST_TEST(a1[1][0][1].e == 5); + BOOST_TEST(a1[1][1][1].i == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 2, 3, 4, 5); + BOOST_TEST(type::instances == 8); + BOOST_TEST(a1[0][0][0].a == 1); + BOOST_TEST(a1[0][1][0].c == 3); + BOOST_TEST(a1[1][0][1].e == 5); + BOOST_TEST(a1[1][1][1].i == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, 1, 2, 3); + BOOST_TEST(type::instances == 16); + BOOST_TEST(a1[0][0][0][1].a == 1); + BOOST_TEST(a1[0][0][1][0].c == 3); + BOOST_TEST(a1[0][1][0][0].f == 0); + BOOST_TEST(a1[1][0][0][0].i == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 2, 3); + BOOST_TEST(type::instances == 16); + BOOST_TEST(a1[0][0][0][1].a == 1); + BOOST_TEST(a1[0][0][1][0].c == 3); + BOOST_TEST(a1[0][1][0][0].f == 0); + BOOST_TEST(a1[1][0][0][0].i == 0); + } +#endif + return boost::report_errors(); +} diff --git a/test/allocate_shared_array_esft_test.cpp b/test/allocate_shared_array_esft_test.cpp new file mode 100644 index 0000000..2315421 --- /dev/null +++ b/test/allocate_shared_array_esft_test.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include +#include + +class type + : public boost::enable_shared_from_this { +public: + static unsigned int instances; + explicit type() { + instances++; + } + ~type() { + instances--; + } +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); + try { + a1[0].shared_from_this(); + BOOST_ERROR("shared_from_this did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 3); + } + } + return boost::report_errors(); +} diff --git a/test/allocate_shared_array_init_test.cpp b/test/allocate_shared_array_init_test.cpp new file mode 100644 index 0000000..6411aa8 --- /dev/null +++ b/test/allocate_shared_array_init_test.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +class type { +public: + type(int value) + : value(value) { + } + const int value; +private: + type& operator=(const type&); +}; + +int main() { +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + BOOST_TEST(a1[0].value == 0); + BOOST_TEST(a1[1].value == 1); + BOOST_TEST(a1[2].value == 2); + BOOST_TEST(a1[3].value == 3); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + BOOST_TEST(a1[0].value == 0); + BOOST_TEST(a1[1].value == 1); + BOOST_TEST(a1[2].value == 2); + BOOST_TEST(a1[3].value == 3); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + BOOST_TEST(a1[0].value == 0); + BOOST_TEST(a1[1].value == 1); + BOOST_TEST(a1[2].value == 2); + BOOST_TEST(a1[3].value == 3); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + BOOST_TEST(a1[0].value == 0); + BOOST_TEST(a1[1].value == 1); + BOOST_TEST(a1[2].value == 2); + BOOST_TEST(a1[3].value == 3); + } +#endif + return boost::report_errors(); +} diff --git a/test/allocate_shared_array_test.cpp b/test/allocate_shared_array_test.cpp new file mode 100644 index 0000000..91f3fb5 --- /dev/null +++ b/test/allocate_shared_array_test.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include +#include +#include + +class type { +public: + static unsigned int instances; + explicit type(int = 0, int = 0) + : member() { + instances++; + } + ~type() { + instances--; + } +private: + type(const type&); + type& operator=(const type&); + double member; +}; + +unsigned int type::instances = 0; + +int main() { + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); + int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 0); + BOOST_TEST(a1[2] == 0); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); + const int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 0); + BOOST_TEST(a1[2] == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3, 1, 5); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 5); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3, 1, 5); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 5); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#endif + return boost::report_errors(); +} diff --git a/test/allocate_shared_array_throws_test.cpp b/test/allocate_shared_array_throws_test.cpp new file mode 100644 index 0000000..d52104c --- /dev/null +++ b/test/allocate_shared_array_throws_test.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +class type { +public: + static unsigned int instances; + explicit type() { + if (instances == 5) { + throw true; + } + instances++; + } + ~type() { + instances--; + } +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { + BOOST_TEST(type::instances == 0); + try { + boost::allocate_shared(std::allocator(), 6); + BOOST_ERROR("allocate_shared did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + try { + boost::allocate_shared(std::allocator(), 3); + BOOST_ERROR("allocate_shared did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + return boost::report_errors(); +} diff --git a/test/allocate_shared_arrays_create_test.cpp b/test/allocate_shared_arrays_create_test.cpp new file mode 100644 index 0000000..fd44aa0 --- /dev/null +++ b/test/allocate_shared_arrays_create_test.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +int main() { +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { {0, 1}, {2, 3} }); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 2); + BOOST_TEST(a1[1][1] == 3); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { {0, 1}, {2, 3} }); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 2); + BOOST_TEST(a1[1][1] == 3); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, {0, 1}); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 1); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, { {0, 1}, {2, 3} }); + BOOST_TEST(a1[0][0][0] == 0); + BOOST_TEST(a1[0][0][1] == 1); + BOOST_TEST(a1[1][1][0] == 2); + BOOST_TEST(a1[1][1][1] == 3); + } +#endif + return boost::report_errors(); +} diff --git a/test/allocate_shared_arrays_test.cpp b/test/allocate_shared_arrays_test.cpp new file mode 100644 index 0000000..ab22c23 --- /dev/null +++ b/test/allocate_shared_arrays_test.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +class type { +public: + static unsigned int instances; + explicit type(int = 0, int = 0) + : member() { + instances++; + } + ~type() { + instances--; + } +private: + type(const type&); + type& operator=(const type&); + double member; +}; + +unsigned int type::instances = 0; + +int main() { + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1[0][0][1] == 0); + BOOST_TEST(a1[0][1][0] == 0); + BOOST_TEST(a1[1][0][0] == 0); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1[0][0][1] == 0); + BOOST_TEST(a1[0][1][0] == 0); + BOOST_TEST(a1[1][0][0] == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, 1, 5); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 5); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, 1, 5); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 5); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#endif + return boost::report_errors(); +} diff --git a/test/array_fail_ap_spa_a.cpp b/test/array_fail_ap_spa_a.cpp new file mode 100644 index 0000000..0524827 --- /dev/null +++ b/test/array_fail_ap_spa_a.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + std::auto_ptr px; + boost::shared_ptr px2; px2 = px; +} diff --git a/test/array_fail_ap_spa_c.cpp b/test/array_fail_ap_spa_c.cpp new file mode 100644 index 0000000..bc76316 --- /dev/null +++ b/test/array_fail_ap_spa_c.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + std::auto_ptr px; + boost::shared_ptr px2( px ); +} diff --git a/test/array_fail_ap_spa_ma.cpp b/test/array_fail_ap_spa_ma.cpp new file mode 100644 index 0000000..e26a548 --- /dev/null +++ b/test/array_fail_ap_spa_ma.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + boost::shared_ptr px2; px2 = std::auto_ptr(); +} diff --git a/test/array_fail_ap_spa_mc.cpp b/test/array_fail_ap_spa_mc.cpp new file mode 100644 index 0000000..d53eeff --- /dev/null +++ b/test/array_fail_ap_spa_mc.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + boost::shared_ptr px2(( std::auto_ptr() )); +} diff --git a/test/array_fail_array_access.cpp b/test/array_fail_array_access.cpp new file mode 100644 index 0000000..abfacbe --- /dev/null +++ b/test/array_fail_array_access.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::shared_ptr px( new X ); + px[ 0 ]; +} diff --git a/test/array_fail_dereference.cpp b/test/array_fail_dereference.cpp new file mode 100644 index 0000000..081d5b4 --- /dev/null +++ b/test/array_fail_dereference.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::shared_ptr px( new X[ 1 ] ); + *px; +} diff --git a/test/array_fail_member_access.cpp b/test/array_fail_member_access.cpp new file mode 100644 index 0000000..8051ad1 --- /dev/null +++ b/test/array_fail_member_access.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2012 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 + +struct X +{ + int m; +}; + +int main() +{ + boost::shared_ptr px( new X[ 1 ] ); + px->m = 0; +} diff --git a/test/array_fail_sp_spa_a.cpp b/test/array_fail_sp_spa_a.cpp new file mode 100644 index 0000000..e1e2bb6 --- /dev/null +++ b/test/array_fail_sp_spa_a.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::shared_ptr px; + boost::shared_ptr px2; px2 = px; +} diff --git a/test/array_fail_sp_spa_c.cpp b/test/array_fail_sp_spa_c.cpp new file mode 100644 index 0000000..c65df88 --- /dev/null +++ b/test/array_fail_sp_spa_c.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::shared_ptr px; + boost::shared_ptr px2( px ); +} diff --git a/test/array_fail_sp_spa_ma.cpp b/test/array_fail_sp_spa_ma.cpp new file mode 100644 index 0000000..a1253a0 --- /dev/null +++ b/test/array_fail_sp_spa_ma.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::shared_ptr px2; px2 = boost::shared_ptr(); +} diff --git a/test/array_fail_sp_spa_mc.cpp b/test/array_fail_sp_spa_mc.cpp new file mode 100644 index 0000000..75c014c --- /dev/null +++ b/test/array_fail_sp_spa_mc.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::shared_ptr px2(( boost::shared_ptr() )); +} diff --git a/test/array_fail_sp_wpa_a.cpp b/test/array_fail_sp_wpa_a.cpp new file mode 100644 index 0000000..8b88512 --- /dev/null +++ b/test/array_fail_sp_wpa_a.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + boost::shared_ptr px; + boost::weak_ptr px2; px2 = px; +} diff --git a/test/array_fail_sp_wpa_c.cpp b/test/array_fail_sp_wpa_c.cpp new file mode 100644 index 0000000..fc7cd5b --- /dev/null +++ b/test/array_fail_sp_wpa_c.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + boost::shared_ptr px; + boost::weak_ptr px2( px ); +} diff --git a/test/array_fail_sp_wpa_ma.cpp b/test/array_fail_sp_wpa_ma.cpp new file mode 100644 index 0000000..578e10b --- /dev/null +++ b/test/array_fail_sp_wpa_ma.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + boost::weak_ptr px2; px2 = boost::shared_ptr(); +} diff --git a/test/array_fail_sp_wpa_mc.cpp b/test/array_fail_sp_wpa_mc.cpp new file mode 100644 index 0000000..ca62eaf --- /dev/null +++ b/test/array_fail_sp_wpa_mc.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + boost::weak_ptr px2(( boost::shared_ptr() )); +} diff --git a/test/array_fail_spa_sp_a.cpp b/test/array_fail_spa_sp_a.cpp new file mode 100644 index 0000000..4d6d323 --- /dev/null +++ b/test/array_fail_spa_sp_a.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::shared_ptr px; + boost::shared_ptr px2; px2 = px; +} diff --git a/test/array_fail_spa_sp_c.cpp b/test/array_fail_spa_sp_c.cpp new file mode 100644 index 0000000..9015483 --- /dev/null +++ b/test/array_fail_spa_sp_c.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::shared_ptr px; + boost::shared_ptr px2( px ); +} diff --git a/test/array_fail_spa_sp_ma.cpp b/test/array_fail_spa_sp_ma.cpp new file mode 100644 index 0000000..6511887 --- /dev/null +++ b/test/array_fail_spa_sp_ma.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::shared_ptr px2; px2 = boost::shared_ptr(); +} diff --git a/test/array_fail_spa_sp_mc.cpp b/test/array_fail_spa_sp_mc.cpp new file mode 100644 index 0000000..46f6e30 --- /dev/null +++ b/test/array_fail_spa_sp_mc.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::shared_ptr px2(( boost::shared_ptr() )); +} diff --git a/test/array_fail_spa_spa_a.cpp b/test/array_fail_spa_spa_a.cpp new file mode 100644 index 0000000..edb248d --- /dev/null +++ b/test/array_fail_spa_spa_a.cpp @@ -0,0 +1,23 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +struct Y: public X +{ +}; + +int main() +{ + boost::shared_ptr px; + boost::shared_ptr px2; px2 = px; +} diff --git a/test/array_fail_spa_spa_c.cpp b/test/array_fail_spa_spa_c.cpp new file mode 100644 index 0000000..a1833ee --- /dev/null +++ b/test/array_fail_spa_spa_c.cpp @@ -0,0 +1,23 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +struct Y: public X +{ +}; + +int main() +{ + boost::shared_ptr px; + boost::shared_ptr px2( px ); +} diff --git a/test/array_fail_spa_spa_ma.cpp b/test/array_fail_spa_spa_ma.cpp new file mode 100644 index 0000000..8c81693 --- /dev/null +++ b/test/array_fail_spa_spa_ma.cpp @@ -0,0 +1,22 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +struct Y: public X +{ +}; + +int main() +{ + boost::shared_ptr px2; px2 = boost::shared_ptr(); +} diff --git a/test/array_fail_spa_spa_mc.cpp b/test/array_fail_spa_spa_mc.cpp new file mode 100644 index 0000000..606d937 --- /dev/null +++ b/test/array_fail_spa_spa_mc.cpp @@ -0,0 +1,22 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +struct Y: public X +{ +}; + +int main() +{ + boost::shared_ptr px2(( boost::shared_ptr() )); +} diff --git a/test/array_fail_spa_wp_a.cpp b/test/array_fail_spa_wp_a.cpp new file mode 100644 index 0000000..14c122e --- /dev/null +++ b/test/array_fail_spa_wp_a.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + boost::shared_ptr px; + boost::weak_ptr px2; px2 = px; +} diff --git a/test/array_fail_spa_wp_c.cpp b/test/array_fail_spa_wp_c.cpp new file mode 100644 index 0000000..9c22a5b --- /dev/null +++ b/test/array_fail_spa_wp_c.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + boost::shared_ptr px; + boost::weak_ptr px2( px ); +} diff --git a/test/array_fail_spa_wp_ma.cpp b/test/array_fail_spa_wp_ma.cpp new file mode 100644 index 0000000..49c1eb0 --- /dev/null +++ b/test/array_fail_spa_wp_ma.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + boost::weak_ptr px2; px2 = boost::shared_ptr(); +} diff --git a/test/array_fail_spa_wp_mc.cpp b/test/array_fail_spa_wp_mc.cpp new file mode 100644 index 0000000..738946c --- /dev/null +++ b/test/array_fail_spa_wp_mc.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + boost::weak_ptr px2(( boost::shared_ptr() )); +} diff --git a/test/array_fail_spa_wpa_a.cpp b/test/array_fail_spa_wpa_a.cpp new file mode 100644 index 0000000..9c65f1c --- /dev/null +++ b/test/array_fail_spa_wpa_a.cpp @@ -0,0 +1,24 @@ +// +// Copyright (c) 2012 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 +{ +}; + +struct Y: public X +{ +}; + +int main() +{ + boost::shared_ptr px; + boost::weak_ptr px2; px2 = px; +} diff --git a/test/array_fail_spa_wpa_c.cpp b/test/array_fail_spa_wpa_c.cpp new file mode 100644 index 0000000..ff2ae22 --- /dev/null +++ b/test/array_fail_spa_wpa_c.cpp @@ -0,0 +1,24 @@ +// +// Copyright (c) 2012 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 +{ +}; + +struct Y: public X +{ +}; + +int main() +{ + boost::shared_ptr px; + boost::weak_ptr px2( px ); +} diff --git a/test/array_fail_spa_wpa_ma.cpp b/test/array_fail_spa_wpa_ma.cpp new file mode 100644 index 0000000..cb2725e --- /dev/null +++ b/test/array_fail_spa_wpa_ma.cpp @@ -0,0 +1,23 @@ +// +// Copyright (c) 2012 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 +{ +}; + +struct Y: public X +{ +}; + +int main() +{ + boost::weak_ptr px2; px2 = boost::shared_ptr(); +} diff --git a/test/array_fail_spa_wpa_mc.cpp b/test/array_fail_spa_wpa_mc.cpp new file mode 100644 index 0000000..9b07933 --- /dev/null +++ b/test/array_fail_spa_wpa_mc.cpp @@ -0,0 +1,23 @@ +// +// Copyright (c) 2012 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 +{ +}; + +struct Y: public X +{ +}; + +int main() +{ + boost::weak_ptr px2(( boost::shared_ptr() )); +} diff --git a/test/array_fail_up_spa_a.cpp b/test/array_fail_up_spa_a.cpp new file mode 100644 index 0000000..8b9f246 --- /dev/null +++ b/test/array_fail_up_spa_a.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + std::unique_ptr px; + boost::shared_ptr px2; px2 = px; +} diff --git a/test/array_fail_up_spa_c.cpp b/test/array_fail_up_spa_c.cpp new file mode 100644 index 0000000..1bbc5c0 --- /dev/null +++ b/test/array_fail_up_spa_c.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + std::unique_ptr px; + boost::shared_ptr px2( px ); +} diff --git a/test/array_fail_up_spa_ma.cpp b/test/array_fail_up_spa_ma.cpp new file mode 100644 index 0000000..fcd612d --- /dev/null +++ b/test/array_fail_up_spa_ma.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + boost::shared_ptr px2; px2 = std::unique_ptr(); +} diff --git a/test/array_fail_up_spa_mc.cpp b/test/array_fail_up_spa_mc.cpp new file mode 100644 index 0000000..6a20d6e --- /dev/null +++ b/test/array_fail_up_spa_mc.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + boost::shared_ptr px2(( std::unique_ptr() )); +} diff --git a/test/array_fail_upa_sp_a.cpp b/test/array_fail_upa_sp_a.cpp new file mode 100644 index 0000000..b44e07e --- /dev/null +++ b/test/array_fail_upa_sp_a.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + std::unique_ptr px; + boost::shared_ptr px2; px2 = px; +} diff --git a/test/array_fail_upa_sp_c.cpp b/test/array_fail_upa_sp_c.cpp new file mode 100644 index 0000000..fe62044 --- /dev/null +++ b/test/array_fail_upa_sp_c.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + std::unique_ptr px; + boost::shared_ptr px2( px ); +} diff --git a/test/array_fail_upa_sp_ma.cpp b/test/array_fail_upa_sp_ma.cpp new file mode 100644 index 0000000..1b2a2b2 --- /dev/null +++ b/test/array_fail_upa_sp_ma.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + boost::shared_ptr px2; px2 = std::unique_ptr(); +} diff --git a/test/array_fail_upa_sp_mc.cpp b/test/array_fail_upa_sp_mc.cpp new file mode 100644 index 0000000..d314a01 --- /dev/null +++ b/test/array_fail_upa_sp_mc.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 +{ +}; + +int main() +{ + boost::shared_ptr px2(( std::unique_ptr() )); +} diff --git a/test/array_fail_wp_wpa_a.cpp b/test/array_fail_wp_wpa_a.cpp new file mode 100644 index 0000000..ea82eb9 --- /dev/null +++ b/test/array_fail_wp_wpa_a.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::weak_ptr px; + boost::weak_ptr px2; px2 = px; +} diff --git a/test/array_fail_wp_wpa_c.cpp b/test/array_fail_wp_wpa_c.cpp new file mode 100644 index 0000000..9f5609c --- /dev/null +++ b/test/array_fail_wp_wpa_c.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::weak_ptr px; + boost::weak_ptr px2( px ); +} diff --git a/test/array_fail_wp_wpa_ma.cpp b/test/array_fail_wp_wpa_ma.cpp new file mode 100644 index 0000000..79af4d7 --- /dev/null +++ b/test/array_fail_wp_wpa_ma.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::weak_ptr px2; px2 = boost::weak_ptr(); +} diff --git a/test/array_fail_wp_wpa_mc.cpp b/test/array_fail_wp_wpa_mc.cpp new file mode 100644 index 0000000..18a9d8a --- /dev/null +++ b/test/array_fail_wp_wpa_mc.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::weak_ptr px2(( boost::weak_ptr() )); +} diff --git a/test/array_fail_wpa_wp_a.cpp b/test/array_fail_wpa_wp_a.cpp new file mode 100644 index 0000000..19d0026 --- /dev/null +++ b/test/array_fail_wpa_wp_a.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::weak_ptr px; + boost::weak_ptr px2; px2 = px; +} diff --git a/test/array_fail_wpa_wp_c.cpp b/test/array_fail_wpa_wp_c.cpp new file mode 100644 index 0000000..d4b75dd --- /dev/null +++ b/test/array_fail_wpa_wp_c.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::weak_ptr px; + boost::weak_ptr px2( px ); +} diff --git a/test/array_fail_wpa_wp_ma.cpp b/test/array_fail_wpa_wp_ma.cpp new file mode 100644 index 0000000..5c33c8b --- /dev/null +++ b/test/array_fail_wpa_wp_ma.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::weak_ptr px2; px2 = boost::weak_ptr(); +} diff --git a/test/array_fail_wpa_wp_mc.cpp b/test/array_fail_wpa_wp_mc.cpp new file mode 100644 index 0000000..8375e6b --- /dev/null +++ b/test/array_fail_wpa_wp_mc.cpp @@ -0,0 +1,18 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +int main() +{ + boost::weak_ptr px2(( boost::weak_ptr() )); +} diff --git a/test/array_fail_wpa_wpa_a.cpp b/test/array_fail_wpa_wpa_a.cpp new file mode 100644 index 0000000..29aeaa6 --- /dev/null +++ b/test/array_fail_wpa_wpa_a.cpp @@ -0,0 +1,23 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +struct Y: public X +{ +}; + +int main() +{ + boost::weak_ptr px; + boost::weak_ptr px2; px2 = px; +} diff --git a/test/array_fail_wpa_wpa_c.cpp b/test/array_fail_wpa_wpa_c.cpp new file mode 100644 index 0000000..98a574e --- /dev/null +++ b/test/array_fail_wpa_wpa_c.cpp @@ -0,0 +1,23 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +struct Y: public X +{ +}; + +int main() +{ + boost::weak_ptr px; + boost::weak_ptr px2( px ); +} diff --git a/test/array_fail_wpa_wpa_ma.cpp b/test/array_fail_wpa_wpa_ma.cpp new file mode 100644 index 0000000..eb638de --- /dev/null +++ b/test/array_fail_wpa_wpa_ma.cpp @@ -0,0 +1,22 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +struct Y: public X +{ +}; + +int main() +{ + boost::weak_ptr px2; px2 = boost::weak_ptr(); +} diff --git a/test/array_fail_wpa_wpa_mc.cpp b/test/array_fail_wpa_wpa_mc.cpp new file mode 100644 index 0000000..77d4f75 --- /dev/null +++ b/test/array_fail_wpa_wpa_mc.cpp @@ -0,0 +1,22 @@ +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +struct Y: public X +{ +}; + +int main() +{ + boost::weak_ptr px2(( boost::weak_ptr() )); +} diff --git a/test/make_shared_array_args_test.cpp b/test/make_shared_array_args_test.cpp new file mode 100644 index 0000000..c308c7a --- /dev/null +++ b/test/make_shared_array_args_test.cpp @@ -0,0 +1,172 @@ +// make_shared_array_args_test.cpp +// +// Copyright 2007-2009, 2012 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 & ); + + void * operator new[]( std::size_t n ); + void operator delete[]( void * p ); + +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_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 0 ); + BOOST_TEST( px[1].v == 0 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + + { + boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1 ); + BOOST_TEST( px[1].v == 1 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2 ); + BOOST_TEST( px[1].v == 1+2 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2+3 ); + BOOST_TEST( px[1].v == 1+2+3 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2+3+4 ); + BOOST_TEST( px[1].v == 1+2+3+4 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2+3+4+5 ); + BOOST_TEST( px[1].v == 1+2+3+4+5 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5, 6 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2+3+4+5+6 ); + BOOST_TEST( px[1].v == 1+2+3+4+5+6 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5, 6, 7 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2+3+4+5+6+7 ); + BOOST_TEST( px[1].v == 1+2+3+4+5+6+7 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5, 6, 7, 8 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2+3+4+5+6+7+8 ); + BOOST_TEST( px[1].v == 1+2+3+4+5+6+7+8 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( px[0].v == 1+2+3+4+5+6+7+8+9 ); + BOOST_TEST( px[1].v == 1+2+3+4+5+6+7+8+9 ); + + px.reset(); + + BOOST_TEST( X::instances == 0 ); + } + +#endif + + return boost::report_errors(); +} diff --git a/test/make_shared_array_create_test.cpp b/test/make_shared_array_create_test.cpp new file mode 100644 index 0000000..46db862 --- /dev/null +++ b/test/make_shared_array_create_test.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +class type { +public: + static int instances; + explicit type(int a=0, int b=0, int c=0, int d=0, int e=0, int f=0, int g=0, int h=0, int i=0) + : a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h), i(i) { + instances++; + } + ~type() { + instances--; + } + const int a; + const int b; + const int c; + const int d; + const int e; + const int f; + const int g; + const int h; + const int i; +private: + type(const type&); + type& operator=(const type&); +}; + +int type::instances = 0; + +int main() { +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(2, 1, 2, 3, 4, 5, 6, 7, 8, 9); + BOOST_TEST(type::instances == 2); + BOOST_TEST(a1[0].a == 1); + BOOST_TEST(a1[0].d == 4); + BOOST_TEST(a1[1].f == 6); + BOOST_TEST(a1[1].i == 9); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(1, 2, 3, 4, 5, 6, 7, 8, 9); + BOOST_TEST(type::instances == 2); + BOOST_TEST(a1[0].a == 1); + BOOST_TEST(a1[0].d == 4); + BOOST_TEST(a1[1].f == 6); + BOOST_TEST(a1[1].i == 9); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(2, 1, 2, 3, 4, 5, 6, 7); + BOOST_TEST(type::instances == 4); + BOOST_TEST(a1[0][0].a == 1); + BOOST_TEST(a1[0][1].d == 4); + BOOST_TEST(a1[1][0].f == 6); + BOOST_TEST(a1[1][1].i == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(1, 2, 3, 4, 5, 6, 7); + BOOST_TEST(type::instances == 4); + BOOST_TEST(a1[0][0].a == 1); + BOOST_TEST(a1[0][1].d == 4); + BOOST_TEST(a1[1][0].f == 6); + BOOST_TEST(a1[1][1].i == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(2, 1, 2, 3, 4, 5); + BOOST_TEST(type::instances == 8); + BOOST_TEST(a1[0][0][0].a == 1); + BOOST_TEST(a1[0][1][0].c == 3); + BOOST_TEST(a1[1][0][1].e == 5); + BOOST_TEST(a1[1][1][1].i == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(1, 2, 3, 4, 5); + BOOST_TEST(type::instances == 8); + BOOST_TEST(a1[0][0][0].a == 1); + BOOST_TEST(a1[0][1][0].c == 3); + BOOST_TEST(a1[1][0][1].e == 5); + BOOST_TEST(a1[1][1][1].i == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(2, 1, 2, 3); + BOOST_TEST(type::instances == 16); + BOOST_TEST(a1[0][0][0][1].a == 1); + BOOST_TEST(a1[0][0][1][0].c == 3); + BOOST_TEST(a1[0][1][0][0].f == 0); + BOOST_TEST(a1[1][0][0][0].i == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(1, 2, 3); + BOOST_TEST(type::instances == 16); + BOOST_TEST(a1[0][0][0][1].a == 1); + BOOST_TEST(a1[0][0][1][0].c == 3); + BOOST_TEST(a1[0][1][0][0].f == 0); + BOOST_TEST(a1[1][0][0][0].i == 0); + } +#endif + return boost::report_errors(); +} diff --git a/test/make_shared_array_esft_test.cpp b/test/make_shared_array_esft_test.cpp new file mode 100644 index 0000000..9d0adb1 --- /dev/null +++ b/test/make_shared_array_esft_test.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include +#include + +class type + : public boost::enable_shared_from_this { +public: + static unsigned int instances; + explicit type() { + instances++; + } + ~type() { + instances--; + } +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(3); + try { + a1[0].shared_from_this(); + BOOST_ERROR("shared_from_this did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 3); + } + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(3); + try { + a1[0].shared_from_this(); + BOOST_ERROR("shared_from_this did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 3); + } + } + return boost::report_errors(); +} diff --git a/test/make_shared_array_init_test.cpp b/test/make_shared_array_init_test.cpp new file mode 100644 index 0000000..6a4c5d5 --- /dev/null +++ b/test/make_shared_array_init_test.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +class type { +public: + type(int value) + : value(value) { + } + const int value; +private: + type& operator=(const type&); +}; + +int main() { +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + BOOST_TEST(a1[0].value == 0); + BOOST_TEST(a1[1].value == 1); + BOOST_TEST(a1[2].value == 2); + BOOST_TEST(a1[3].value == 3); + } + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + BOOST_TEST(a1[0].value == 0); + BOOST_TEST(a1[1].value == 1); + BOOST_TEST(a1[2].value == 2); + BOOST_TEST(a1[3].value == 3); + } + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + BOOST_TEST(a1[0].value == 0); + BOOST_TEST(a1[1].value == 1); + BOOST_TEST(a1[2].value == 2); + BOOST_TEST(a1[3].value == 3); + } + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + BOOST_TEST(a1[0].value == 0); + BOOST_TEST(a1[1].value == 1); + BOOST_TEST(a1[2].value == 2); + BOOST_TEST(a1[3].value == 3); + } +#endif + return boost::report_errors(); +} diff --git a/test/make_shared_array_test.cpp b/test/make_shared_array_test.cpp new file mode 100644 index 0000000..d9b9134 --- /dev/null +++ b/test/make_shared_array_test.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include +#include +#include + +class type { +public: + static unsigned int instances; + explicit type(int = 0, int = 0) + : member() { + instances++; + } + ~type() { + instances--; + } +private: + type(const type&); + type& operator=(const type&); + double member; +}; + +unsigned int type::instances = 0; + +int main() { + { + boost::shared_ptr a1 = boost::make_shared(3); + int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 0); + BOOST_TEST(a1[2] == 0); + } + { + boost::shared_ptr a1 = boost::make_shared(3); + const int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 0); + BOOST_TEST(a1[2] == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(3); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(3); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(3, 1, 5); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(1, 5); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(3, 1, 5); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(1, 5); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#endif + { + boost::shared_ptr a1 = boost::make_shared_noinit(3); + int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + { + boost::shared_ptr a1 = boost::make_shared_noinit(3); + const int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + const int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(3); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(3); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + return boost::report_errors(); +} diff --git a/test/make_shared_array_throws_test.cpp b/test/make_shared_array_throws_test.cpp new file mode 100644 index 0000000..7e06d41 --- /dev/null +++ b/test/make_shared_array_throws_test.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +class type { +public: + static unsigned int instances; + explicit type() { + if (instances == 5) { + throw true; + } + instances++; + } + ~type() { + instances--; + } +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { + BOOST_TEST(type::instances == 0); + try { + boost::make_shared(6); + BOOST_ERROR("make_shared did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + try { + boost::make_shared(3); + BOOST_ERROR("make_shared did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + try { + boost::make_shared_noinit(6); + BOOST_ERROR("make_shared_noinit did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + try { + boost::make_shared_noinit(3); + BOOST_ERROR("make_shared_noinit did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + return boost::report_errors(); +} diff --git a/test/make_shared_arrays_create_test.cpp b/test/make_shared_arrays_create_test.cpp new file mode 100644 index 0000000..b5b96d5 --- /dev/null +++ b/test/make_shared_arrays_create_test.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include +#include + +int main() { +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + { + boost::shared_ptr a1 = boost::make_shared({ {0, 1}, {2, 3} }); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 2); + BOOST_TEST(a1[1][1] == 3); + } + { + boost::shared_ptr a1 = boost::make_shared({ {0, 1}, {2, 3} }); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 2); + BOOST_TEST(a1[1][1] == 3); + } + { + boost::shared_ptr a1 = boost::make_shared(2, {0, 1}); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 1); + } + { + boost::shared_ptr a1 = boost::make_shared(2, { {0, 1}, {2, 3} }); + BOOST_TEST(a1[0][0][0] == 0); + BOOST_TEST(a1[0][0][1] == 1); + BOOST_TEST(a1[1][1][0] == 2); + BOOST_TEST(a1[1][1][1] == 3); + } +#endif + return boost::report_errors(); +} diff --git a/test/make_shared_arrays_test.cpp b/test/make_shared_arrays_test.cpp new file mode 100644 index 0000000..eb79d4f --- /dev/null +++ b/test/make_shared_arrays_test.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +class type { +public: + static unsigned int instances; + explicit type(int = 0, int = 0) + : member() { + instances++; + } + ~type() { + instances--; + } +private: + type(const type&); + type& operator=(const type&); + double member; +}; + +unsigned int type::instances = 0; + +int main() { + { + boost::shared_ptr a1 = boost::make_shared(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1[0][0][1] == 0); + BOOST_TEST(a1[0][1][0] == 0); + BOOST_TEST(a1[1][0][0] == 0); + } + { + boost::shared_ptr a1 = boost::make_shared(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1[0][0][1] == 0); + BOOST_TEST(a1[0][1][0] == 0); + BOOST_TEST(a1[1][0][0] == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(2, 1, 5); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(1, 5); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(2, 1, 5); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(1, 5); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#endif + { + boost::shared_ptr a1 = boost::make_shared_noinit(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + { + boost::shared_ptr a1 = boost::make_shared_noinit(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + return boost::report_errors(); +} diff --git a/test/shared_ptr_convertible_test.cpp b/test/shared_ptr_convertible_test.cpp new file mode 100644 index 0000000..7f49e1f --- /dev/null +++ b/test/shared_ptr_convertible_test.cpp @@ -0,0 +1,71 @@ +#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::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(); +} diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp index 7b4de34..656a42a 100644 --- a/test/smart_ptr_test.cpp +++ b/test/smart_ptr_test.cpp @@ -236,7 +236,7 @@ void test() ca2.reset(); BOOST_TEST( ca.use_count() == 2 ); BOOST_TEST( ca3.use_count() == 2 ); - BOOST_TEST( ca2.use_count() == 1 ); + BOOST_TEST( ca2.use_count() == 0 ); ca.reset(); BOOST_TEST( ca.get() == 0 ); @@ -269,7 +269,7 @@ void test() udta2.reset(); BOOST_TEST( udta2.get() == 0 ); BOOST_TEST( udta.use_count() == 1 ); - BOOST_TEST( udta2.use_count() == 1 ); + BOOST_TEST( udta2.use_count() == 0 ); BOOST_TEST( UDT_use_count == 4 ); // reality check diff --git a/test/sp_array_cv_test.cpp b/test/sp_array_cv_test.cpp new file mode 100644 index 0000000..8618fb0 --- /dev/null +++ b/test/sp_array_cv_test.cpp @@ -0,0 +1,60 @@ +// +// sp_array_cv_test.cpp +// +// Copyright (c) 2012 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 + +struct X +{ +}; + +class B +{ +}; + +class D: public B +{ +}; + +#define TEST_CONV( T, U ) \ + { \ + boost::shared_ptr< T > p1; \ + boost::shared_ptr< U > p2( p1 ); \ + p2 = p1; \ + boost::shared_ptr< U > p3 = boost::shared_ptr< T >(); \ + p3 = boost::shared_ptr< T >(); \ + } + +#define TEST_CV_TRUE( T, U ) \ + TEST_CONV( T, U ) \ + TEST_CONV( T, const U ) \ + TEST_CONV( T, volatile U ) \ + TEST_CONV( T, const volatile U ) \ + TEST_CONV( const T, const U ) \ + TEST_CONV( const T, const volatile U ) \ + TEST_CONV( volatile T, volatile U ) \ + TEST_CONV( volatile T, const volatile U ) \ + TEST_CONV( const volatile T, const volatile U ) + +int main() +{ + TEST_CV_TRUE( X, X ) + TEST_CV_TRUE( X, void ) + TEST_CV_TRUE( D, B ) + + TEST_CV_TRUE( X[], X[] ) + TEST_CV_TRUE( X[3], X[3] ) + + TEST_CV_TRUE( X[3], X[] ) + + TEST_CV_TRUE( X[], void ) + TEST_CV_TRUE( X[3], void ) + + return 0; +} diff --git a/test/sp_array_n_test.cpp b/test/sp_array_n_test.cpp new file mode 100644 index 0000000..ccbcc26 --- /dev/null +++ b/test/sp_array_n_test.cpp @@ -0,0 +1,248 @@ +// +// sp_array_n_test.cpp +// +// Copyright (c) 2012 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 + +class X: public boost::enable_shared_from_this< X > +{ +public: + + static int allocations; + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + + void* operator new[]( std::size_t n ) + { + ++allocations; + return ::operator new[]( n ); + } + + void operator delete[]( void* p ) + { + --allocations; + ::operator delete[]( p ); + } + +private: + + X( X const& ); + X& operator=( X const& ); +}; + +int X::allocations = 0; +int X::instances = 0; + +template< class T> class array_deleter +{ +public: + + static int calls; + + void operator()( T * p ) const + { + ++calls; + delete[] p; + } + +private: + + template< class Y > void operator()( Y * p ) const; +}; + +template< class T > int array_deleter< T >::calls = 0; + +int main() +{ + BOOST_TEST( X::allocations == 0 ); + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr px; + BOOST_TEST( !px ); + + BOOST_TEST( X::allocations == 0 ); + BOOST_TEST( X::instances == 0 ); + + boost::shared_ptr px2( new X[ 3 ] ); + BOOST_TEST( px2 ); + + try + { + px2[0].shared_from_this(); + BOOST_ERROR( "px2[0].shared_from_this() failed to throw" ); + } + catch( boost::bad_weak_ptr const& ) + { + } + catch( ... ) + { + BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" ); + } + + BOOST_TEST( X::allocations == 1 ); + BOOST_TEST( X::instances == 3 ); + + { + X & rx = px2[ 0 ]; + BOOST_TEST( &rx == px2.get() ); + } + + boost::shared_ptr px3( px2 ); + BOOST_TEST( px3 == px2 ); + BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) ); + + { + X const & rx = px3[ 1 ]; + BOOST_TEST( &rx == px3.get() + 1 ); + } + + px3.reset(); + px3 = px2; + BOOST_TEST( px3 == px2 ); + BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) ); + + boost::shared_ptr px4( px2 ); + BOOST_TEST( px4 == px2 ); + BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) ); + + { + X volatile & rx = px4[ 2 ]; + BOOST_TEST( &rx == px4.get() + 2 ); + } + + px4.reset(); + px4 = px2; + BOOST_TEST( px4 == px2 ); + BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) ); + + boost::shared_ptr px5( px2 ); + BOOST_TEST( px5 == px2 ); + BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) ); + + px5.reset(); + px5 = px2; + BOOST_TEST( px5 == px2 ); + BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) ); + + boost::weak_ptr wp( px ); + BOOST_TEST( wp.lock() == px ); + + boost::weak_ptr wp2( px2 ); + BOOST_TEST( wp2.lock() == px2 ); + + wp2.reset(); + wp2 = px2; + BOOST_TEST( wp2.lock() == px2 ); + + boost::weak_ptr wp3( px2 ); + BOOST_TEST( wp3.lock() == px2 ); + + wp3.reset(); + wp3 = px2; + BOOST_TEST( wp3.lock() == px2 ); + + boost::weak_ptr wp4( px2 ); + BOOST_TEST( wp4.lock() == px2 ); + + wp4.reset(); + wp4 = px2; + BOOST_TEST( wp4.lock() == px2 ); + + boost::weak_ptr wp5( px2 ); + BOOST_TEST( wp5.lock() == px2 ); + + wp5.reset(); + wp5 = px2; + BOOST_TEST( wp5.lock() == px2 ); + + px2.reset(); + + BOOST_TEST( X::allocations == 1 ); + BOOST_TEST( X::instances == 3 ); + + px3.reset(); + px4.reset(); + px5.reset(); + + BOOST_TEST( X::allocations == 0 ); + BOOST_TEST( X::instances == 0 ); + + BOOST_TEST( wp2.lock() == 0 ); + BOOST_TEST( wp3.lock() == 0 ); + BOOST_TEST( wp4.lock() == 0 ); + BOOST_TEST( wp5.lock() == 0 ); + } + + { + boost::shared_ptr px( new X[ 5 ], array_deleter< X >() ); + BOOST_TEST( X::allocations == 1 ); + BOOST_TEST( X::instances == 5 ); + + try + { + px[0].shared_from_this(); + BOOST_ERROR( "px[0].shared_from_this() failed to throw" ); + } + catch( boost::bad_weak_ptr const& ) + { + } + catch( ... ) + { + BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" ); + } + + px.reset(); + + BOOST_TEST( X::allocations == 0 ); + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( array_deleter< X >::calls == 1 ); + } + + { + boost::shared_ptr px( new X[ 6 ], array_deleter< X >(), std::allocator< X >() ); + BOOST_TEST( X::allocations == 1 ); + BOOST_TEST( X::instances == 6 ); + + try + { + px[0].shared_from_this(); + BOOST_ERROR( "px[0].shared_from_this() failed to throw" ); + } + catch( boost::bad_weak_ptr const& ) + { + } + catch( ... ) + { + BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" ); + } + + px.reset(); + + BOOST_TEST( X::allocations == 0 ); + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( array_deleter< X >::calls == 2 ); + } + + return boost::report_errors(); +} diff --git a/test/sp_array_test.cpp b/test/sp_array_test.cpp new file mode 100644 index 0000000..0c7f597 --- /dev/null +++ b/test/sp_array_test.cpp @@ -0,0 +1,311 @@ +// +// sp_array_test.cpp +// +// Copyright (c) 2012 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 + +class X: public boost::enable_shared_from_this< X > +{ +public: + + static int allocations; + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + + void* operator new[]( std::size_t n ) + { + ++allocations; + return ::operator new[]( n ); + } + + void operator delete[]( void* p ) + { + --allocations; + ::operator delete[]( p ); + } + +private: + + X( X const& ); + X& operator=( X const& ); +}; + +int X::allocations = 0; +int X::instances = 0; + +template< class T> class array_deleter +{ +public: + + static int calls; + + void operator()( T * p ) const + { + ++calls; + delete[] p; + } + +private: + + template< class Y > void operator()( Y * p ) const; +}; + +template< class T > int array_deleter< T >::calls = 0; + +int main() +{ + BOOST_TEST( X::allocations == 0 ); + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr px; + BOOST_TEST( !px ); + + BOOST_TEST( X::allocations == 0 ); + BOOST_TEST( X::instances == 0 ); + + boost::shared_ptr px2( new X[ 3 ] ); + BOOST_TEST( px2 ); + + try + { + px2[0].shared_from_this(); + BOOST_ERROR( "px2[0].shared_from_this() failed to throw" ); + } + catch( boost::bad_weak_ptr const& ) + { + } + catch( ... ) + { + BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" ); + } + + BOOST_TEST( X::allocations == 1 ); + BOOST_TEST( X::instances == 3 ); + + { + X & rx = px2[ 0 ]; + BOOST_TEST( &rx == px2.get() ); + } + + boost::shared_ptr px3( px2 ); + BOOST_TEST( px3 == px2 ); + BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) ); + + { + X const & rx = px3[ 1 ]; + BOOST_TEST( &rx == px3.get() + 1 ); + } + + px3.reset(); + px3 = px2; + BOOST_TEST( px3 == px2 ); + BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) ); + + boost::shared_ptr px4( px2 ); + BOOST_TEST( px4 == px2 ); + BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) ); + + { + X volatile & rx = px4[ 2 ]; + BOOST_TEST( &rx == px4.get() + 2 ); + } + + px4.reset(); + px4 = px2; + BOOST_TEST( px4 == px2 ); + BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) ); + + boost::shared_ptr px5( px2 ); + BOOST_TEST( px5 == px2 ); + BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) ); + + px5.reset(); + px5 = px2; + BOOST_TEST( px5 == px2 ); + BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) ); + + boost::weak_ptr wp( px ); + BOOST_TEST( wp.lock() == px ); + + boost::weak_ptr wp2( px2 ); + BOOST_TEST( wp2.lock() == px2 ); + + wp2.reset(); + wp2 = px2; + BOOST_TEST( wp2.lock() == px2 ); + + boost::weak_ptr wp3( px2 ); + BOOST_TEST( wp3.lock() == px2 ); + + wp3.reset(); + wp3 = px2; + BOOST_TEST( wp3.lock() == px2 ); + + boost::weak_ptr wp4( px2 ); + BOOST_TEST( wp4.lock() == px2 ); + + wp4.reset(); + wp4 = px2; + BOOST_TEST( wp4.lock() == px2 ); + + boost::weak_ptr wp5( px2 ); + BOOST_TEST( wp5.lock() == px2 ); + + wp5.reset(); + wp5 = px2; + BOOST_TEST( wp5.lock() == px2 ); + + px2.reset(); + + BOOST_TEST( X::allocations == 1 ); + BOOST_TEST( X::instances == 3 ); + + px3.reset(); + px4.reset(); + px5.reset(); + + BOOST_TEST( X::allocations == 0 ); + BOOST_TEST( X::instances == 0 ); + + BOOST_TEST( wp2.lock() == 0 ); + BOOST_TEST( wp3.lock() == 0 ); + BOOST_TEST( wp4.lock() == 0 ); + BOOST_TEST( wp5.lock() == 0 ); + } + +#if !defined( BOOST_NO_CXX11_SMART_PTR ) + + { + std::unique_ptr px( new X[ 4 ] ); + BOOST_TEST( X::allocations == 1 ); + BOOST_TEST( X::instances == 4 ); + + boost::shared_ptr px2( std::move( px ) ); + BOOST_TEST( X::allocations == 1 ); + BOOST_TEST( X::instances == 4 ); + BOOST_TEST( px.get() == 0 ); + + try + { + px2[0].shared_from_this(); + BOOST_ERROR( "px2[0].shared_from_this() failed to throw" ); + } + catch( boost::bad_weak_ptr const& ) + { + } + catch( ... ) + { + BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" ); + } + + px2.reset(); + + BOOST_TEST( X::allocations == 0 ); + BOOST_TEST( X::instances == 0 ); + } + + { + std::unique_ptr px( new X[ 4 ] ); + BOOST_TEST( X::allocations == 1 ); + BOOST_TEST( X::instances == 4 ); + + boost::shared_ptr px2; + px2 = std::move( px ); + BOOST_TEST( X::allocations == 1 ); + BOOST_TEST( X::instances == 4 ); + BOOST_TEST( px.get() == 0 ); + + try + { + px2[0].shared_from_this(); + BOOST_ERROR( "px2[0].shared_from_this() failed to throw" ); + } + catch( boost::bad_weak_ptr const& ) + { + } + catch( ... ) + { + BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" ); + } + + px2.reset(); + + BOOST_TEST( X::allocations == 0 ); + BOOST_TEST( X::instances == 0 ); + } + +#endif + + { + boost::shared_ptr px( new X[ 5 ], array_deleter< X >() ); + BOOST_TEST( X::allocations == 1 ); + BOOST_TEST( X::instances == 5 ); + + try + { + px[0].shared_from_this(); + BOOST_ERROR( "px[0].shared_from_this() failed to throw" ); + } + catch( boost::bad_weak_ptr const& ) + { + } + catch( ... ) + { + BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" ); + } + + px.reset(); + + BOOST_TEST( X::allocations == 0 ); + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( array_deleter< X >::calls == 1 ); + } + + { + boost::shared_ptr px( new X[ 6 ], array_deleter< X >(), std::allocator< X >() ); + BOOST_TEST( X::allocations == 1 ); + BOOST_TEST( X::instances == 6 ); + + try + { + px[0].shared_from_this(); + BOOST_ERROR( "px[0].shared_from_this() failed to throw" ); + } + catch( boost::bad_weak_ptr const& ) + { + } + catch( ... ) + { + BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" ); + } + + px.reset(); + + BOOST_TEST( X::allocations == 0 ); + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( array_deleter< X >::calls == 2 ); + } + + return boost::report_errors(); +} diff --git a/test/sp_convertible_test.cpp b/test/sp_convertible_test.cpp index 7f49e1f..05b15c1 100644 --- a/test/sp_convertible_test.cpp +++ b/test/sp_convertible_test.cpp @@ -2,70 +2,92 @@ // sp_convertible_test.cpp // -// Copyright (c) 2008 Peter Dimov +// Copyright (c) 2012 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 // -class incomplete; +class X; -struct X +class B { }; -struct Y +class D: public B { }; -struct Z: public X -{ -}; +#define TEST_CV_TRUE( T, U ) \ + BOOST_TEST(( sp_convertible< T, U >::value == true )); \ + BOOST_TEST(( sp_convertible< T, const U >::value == true )); \ + BOOST_TEST(( sp_convertible< T, volatile U >::value == true )); \ + BOOST_TEST(( sp_convertible< T, const volatile U >::value == true )); \ + BOOST_TEST(( sp_convertible< const T, U >::value == false )); \ + BOOST_TEST(( sp_convertible< const T, const U >::value == true )); \ + BOOST_TEST(( sp_convertible< const T, volatile U >::value == false )); \ + BOOST_TEST(( sp_convertible< const T, const volatile U >::value == true )); \ + BOOST_TEST(( sp_convertible< volatile T, U >::value == false )); \ + BOOST_TEST(( sp_convertible< volatile T, const U >::value == false )); \ + BOOST_TEST(( sp_convertible< volatile T, volatile U >::value == true )); \ + BOOST_TEST(( sp_convertible< volatile T, const volatile U >::value == true )); \ + BOOST_TEST(( sp_convertible< const volatile T, U >::value == false )); \ + BOOST_TEST(( sp_convertible< const volatile T, const U >::value == false )); \ + BOOST_TEST(( sp_convertible< const volatile T, volatile U >::value == false )); \ + BOOST_TEST(( sp_convertible< const volatile T, const volatile U >::value == true )); -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; -} +#define TEST_CV_FALSE( T, U ) \ + BOOST_TEST(( sp_convertible< T, U >::value == false )); \ + BOOST_TEST(( sp_convertible< T, const U >::value == false )); \ + BOOST_TEST(( sp_convertible< T, volatile U >::value == false )); \ + BOOST_TEST(( sp_convertible< T, const volatile U >::value == false )); \ + BOOST_TEST(( sp_convertible< const T, U >::value == false )); \ + BOOST_TEST(( sp_convertible< const T, const U >::value == false )); \ + BOOST_TEST(( sp_convertible< const T, volatile U >::value == false )); \ + BOOST_TEST(( sp_convertible< const T, const volatile U >::value == false )); \ + BOOST_TEST(( sp_convertible< volatile T, U >::value == false )); \ + BOOST_TEST(( sp_convertible< volatile T, const U >::value == false )); \ + BOOST_TEST(( sp_convertible< volatile T, volatile U >::value == false )); \ + BOOST_TEST(( sp_convertible< volatile T, const volatile U >::value == false )); \ + BOOST_TEST(( sp_convertible< const volatile T, U >::value == false )); \ + BOOST_TEST(( sp_convertible< const volatile T, const U >::value == false )); \ + BOOST_TEST(( sp_convertible< const volatile T, volatile U >::value == false )); \ + BOOST_TEST(( sp_convertible< const volatile T, const volatile U >::value == false )); int main() { - boost::shared_ptr p1; - BOOST_TEST( 1 == f( p1 ) ); - BOOST_TEST( 1 == f( boost::shared_ptr() ) ); +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) - boost::shared_ptr p2; - BOOST_TEST( 4 == g( p2 ) ); - BOOST_TEST( 4 == g( boost::shared_ptr() ) ); + using boost::detail::sp_convertible; + + TEST_CV_TRUE( X, X ) + TEST_CV_TRUE( X, void ) + TEST_CV_FALSE( void, X ) + TEST_CV_TRUE( D, B ) + TEST_CV_FALSE( B, D ) + + TEST_CV_TRUE( X[], X[] ) + TEST_CV_FALSE( D[], B[] ) + + TEST_CV_TRUE( X[3], X[3] ) + TEST_CV_FALSE( X[3], X[4] ) + TEST_CV_FALSE( D[3], B[3] ) + + TEST_CV_TRUE( X[3], X[] ) + TEST_CV_FALSE( X[], X[3] ) + + TEST_CV_TRUE( X[], void ) + TEST_CV_FALSE( void, X[] ) + + TEST_CV_TRUE( X[3], void ) + TEST_CV_FALSE( void, X[3] ) + +#endif return boost::report_errors(); } From 2805ae9362ce1133ed9a3da2b6f932ae83164440 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 16 Nov 2012 14:09:18 +0000 Subject: [PATCH 106/140] Merged revision(s) 81341-81342 from trunk: Add additional overload for allocate_shared and make_shared array forms that take initializer list of T for the array types T[M][N] ........ Minor style change: Fix indentation in allocate_shared_array.hpp and make_shared_array.hpp ........ [SVN r81366] --- .../boost/smart_ptr/allocate_shared_array.hpp | 25 ++++++++++++++++++- .../boost/smart_ptr/detail/array_traits.hpp | 10 +++++--- include/boost/smart_ptr/make_shared_array.hpp | 24 +++++++++++++++++- make_shared_array.html | 18 +++++++++++-- test/allocate_shared_arrays_create_test.cpp | 14 +++++++++++ test/make_shared_arrays_create_test.cpp | 14 +++++++++++ 6 files changed, 98 insertions(+), 7 deletions(-) diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index b2aa826..904902c 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -98,10 +98,10 @@ namespace boost { inline typename detail::sp_if_size_array::type allocate_shared(const A& allocator, std::initializer_list::type> list) { - BOOST_ASSERT(list.size() == detail::array_size::size); typedef typename detail::array_inner::type T1; typedef typename detail::array_base::type T2; typedef const T2 T3; + BOOST_ASSERT(list.size() == detail::array_size::size); T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; @@ -138,6 +138,29 @@ namespace boost { d2->construct_list(p2, n1, p3, n0); return shared_ptr(s1, p1); } + template + inline typename detail::sp_if_size_array::type + allocate_shared(const A& allocator, + std::initializer_list::type> list) { + typedef typename detail::array_inner::type T1; + typedef typename detail::array_base::type T2; + typedef const T2 T3; + BOOST_ASSERT(list.size() == detail::array_size::size); + T1* p1 = 0; + T2* p2 = 0; + T3* p3 = 0; + std::size_t n0 = detail::array_total::size; + std::size_t n1 = detail::array_total::size; + detail::allocate_array_helper a1(allocator, n1, &p2); + detail::array_deleter d1; + shared_ptr s1(p1, d1, a1); + detail::array_deleter* d2; + p3 = reinterpret_cast(list.begin()); + p1 = reinterpret_cast(p2); + d2 = get_deleter >(s1); + d2->construct_list(p2, n1, p3, n0); + return shared_ptr(s1, p1); + } #endif } diff --git a/include/boost/smart_ptr/detail/array_traits.hpp b/include/boost/smart_ptr/detail/array_traits.hpp index 068629a..3b80f46 100644 --- a/include/boost/smart_ptr/detail/array_traits.hpp +++ b/include/boost/smart_ptr/detail/array_traits.hpp @@ -24,7 +24,7 @@ namespace boost { template struct array_size { }; - template + template struct array_size { enum { size = N @@ -49,17 +49,21 @@ namespace boost { struct array_inner { typedef T type; }; - template + template struct array_inner { typedef T type; }; template struct arrays_inner { }; - template + template struct arrays_inner { typedef T type; }; + template + struct arrays_inner { + typedef T type; + }; } } diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index f9a39ff..70083b1 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -96,10 +96,10 @@ namespace boost { template inline typename detail::sp_if_size_array::type make_shared(std::initializer_list::type> list) { - BOOST_ASSERT(list.size() == detail::array_size::size); typedef typename detail::array_inner::type T1; typedef typename detail::array_base::type T2; typedef const T2 T3; + BOOST_ASSERT(list.size() == detail::array_size::size); T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; @@ -136,6 +136,28 @@ namespace boost { d2->construct_list(p2, n1, p3, n0); return shared_ptr(s1, p1); } + template + inline typename detail::sp_if_size_array::type + make_shared(std::initializer_list::type> list) { + typedef typename detail::array_inner::type T1; + typedef typename detail::array_base::type T2; + typedef const T2 T3; + BOOST_ASSERT(list.size() == detail::array_size::size); + T1* p1 = 0; + T2* p2 = 0; + T3* p3 = 0; + std::size_t n0 = detail::array_total::size; + std::size_t n1 = detail::array_total::size; + detail::make_array_helper a1(n1, &p2); + detail::array_deleter d1; + shared_ptr s1(p1, d1, a1); + detail::array_deleter* d2; + p3 = reinterpret_cast(list.begin()); + p1 = reinterpret_cast(p2); + d2 = get_deleter >(s1); + d2->construct_list(p2, n1, p3, n0); + return shared_ptr(s1, p1); + } #endif template inline typename detail::sp_if_array::type diff --git a/make_shared_array.html b/make_shared_array.html index 4739b3a..9c46926 100644 --- a/make_shared_array.html +++ b/make_shared_array.html @@ -56,7 +56,10 @@ template<typename T, typename... Args> shared_ptr<T[][N]> make_shared(size_t size, initializer_list<T> list); - + + template<typename T, typename... Args> + shared_ptr<T[M][N]> make_shared(initializer_list<T> list); + template<typename T, typename A, typename... Args> shared_ptr<T[]> allocate_shared(const A& allocator, initializer_list<T> list); @@ -65,6 +68,9 @@ template<typename T, typename A, typename... Args> shared_ptr<T[][N]> allocate_shared(const A& allocator, size_t size, initializer_list<T> list); + + template<typename T, typename A, typename... Args> + shared_ptr<T[M][N]> allocate_shared(const A& allocator, initializer_list<T> list); #endif template<typename T> @@ -117,7 +123,15 @@ template<typename T, typename A, typename... Args> constructor of T for each array element.

    Example

    -
    boost::shared_ptr<int[]> array = boost::make_shared<int[]>(size);
    +
    boost::shared_ptr<int[]> a1 = boost::make_shared<int[]>(size);
    +boost::shared_ptr<point[5]> a2 = boost::make_shared<point[5]>(x, y);
    +boost::shared_ptr<int[5]> a3 = boost::make_shared<int[5]>();
    +boost::shared_ptr<int[]> a4 = boost::make_shared<int[]>({1, 2, 3});
    +boost::shared_ptr<int[3]> a5 = boost::make_shared<int[3]>({1, 2, 3});
    +boost::shared_ptr<int[][3]> a6 = boost::make_shared<int[][3]>(size, {1, 2, 3});
    +boost::shared_ptr<int[5][3]> a7 = boost::make_shared<int[5][3]>({1, 2, 3});
    +boost::shared_ptr<int[]> a8 = boost::make_shared_noinit<int[]>(size);
    +boost::shared_ptr<int[5]> a9 = boost::make_shared_noinit<int[5]>();

    $Date: 2012-10-30 10:12:25 -0800 (Tue, 30 Oct 2012) $

    Copyright 2012 Glen Fernandes. Distributed under the Boost diff --git a/test/allocate_shared_arrays_create_test.cpp b/test/allocate_shared_arrays_create_test.cpp index fd44aa0..03a2d7e 100644 --- a/test/allocate_shared_arrays_create_test.cpp +++ b/test/allocate_shared_arrays_create_test.cpp @@ -25,6 +25,13 @@ int main() { BOOST_TEST(a1[1][0] == 2); BOOST_TEST(a1[1][1] == 3); } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), {0, 1}); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 1); + } { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, {0, 1}); BOOST_TEST(a1[0][0] == 0); @@ -39,6 +46,13 @@ int main() { BOOST_TEST(a1[1][1][0] == 2); BOOST_TEST(a1[1][1][1] == 3); } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { {0, 1}, {2, 3} }); + BOOST_TEST(a1[0][0][0] == 0); + BOOST_TEST(a1[0][0][1] == 1); + BOOST_TEST(a1[1][1][0] == 2); + BOOST_TEST(a1[1][1][1] == 3); + } #endif return boost::report_errors(); } diff --git a/test/make_shared_arrays_create_test.cpp b/test/make_shared_arrays_create_test.cpp index b5b96d5..e468378 100644 --- a/test/make_shared_arrays_create_test.cpp +++ b/test/make_shared_arrays_create_test.cpp @@ -26,6 +26,13 @@ int main() { BOOST_TEST(a1[1][0] == 2); BOOST_TEST(a1[1][1] == 3); } + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1 }); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 1); + } { boost::shared_ptr a1 = boost::make_shared(2, {0, 1}); BOOST_TEST(a1[0][0] == 0); @@ -40,6 +47,13 @@ int main() { BOOST_TEST(a1[1][1][0] == 2); BOOST_TEST(a1[1][1][1] == 3); } + { + boost::shared_ptr a1 = boost::make_shared({ {0, 1}, {2, 3} }); + BOOST_TEST(a1[0][0][0] == 0); + BOOST_TEST(a1[0][0][1] == 1); + BOOST_TEST(a1[1][1][0] == 2); + BOOST_TEST(a1[1][1][1] == 3); + } #endif return boost::report_errors(); } From 215771c83d137bbc8574746cb8c8790a77665b9d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 16 Nov 2012 14:11:25 +0000 Subject: [PATCH 107/140] Merged [81348] from trunk. Fixes #7693. [SVN r81367] --- include/boost/smart_ptr/detail/sp_counted_base.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp index fd9eab4..17bd517 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp @@ -35,12 +35,12 @@ #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined(__PATHSCALE__) # include -#elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER ) && !defined(__PATHSCALE__) -# include - #elif defined(__HP_aCC) && defined(__ia64) # include +#elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER ) && !defined(__PATHSCALE__) +# include + #elif defined( __IBMCPP__ ) && defined( __powerpc ) # include From c7b6e56b30beb587f2693e9748740a8faf15d83a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 21 Nov 2012 15:38:06 +0000 Subject: [PATCH 108/140] Merged revision(s) 81368, 81399, 81407-81409, 81419, 81430-81431, 81437 from trunk: Apply BOOST_NOEXCEPT patch. Refs #7523. ........ Replace std::forward with detail::sp_forward. ........ Cosmetic changes in make_shared_array.hpp and allocate_shared_array.hpp ........ Documentation of make_shared_array: Minor corrections ........ Make make_shared_array.hpp and allocate_shared_array.hpp consistent with namespace qualification in rest of smart_ptr. ........ Update smart_ptr.htm with link to make_shared_array.htm which lists the many overloads of make_shared and allocate_shared for arrays. ........ Update documentation for make_shared and allocate_shared array forms. ........ Minor corrections in make_shared_array.html documentation. ........ Borland fixes. ........ [SVN r81457] --- .../boost/smart_ptr/allocate_shared_array.hpp | 159 +++++++------- .../detail/allocate_array_helper.hpp | 4 +- .../smart_ptr/detail/make_array_helper.hpp | 2 +- .../boost/smart_ptr/detail/operator_bool.hpp | 10 +- include/boost/smart_ptr/detail/sp_forward.hpp | 39 ++++ .../smart_ptr/enable_shared_from_this.hpp | 8 +- include/boost/smart_ptr/intrusive_ptr.hpp | 12 +- include/boost/smart_ptr/make_shared_array.hpp | 199 +++++++++--------- .../boost/smart_ptr/make_shared_object.hpp | 22 +- include/boost/smart_ptr/scoped_array.hpp | 12 +- include/boost/smart_ptr/scoped_ptr.hpp | 10 +- include/boost/smart_ptr/shared_array.hpp | 38 ++-- include/boost/smart_ptr/shared_ptr.hpp | 92 +++++--- include/boost/smart_ptr/weak_ptr.hpp | 41 ++-- make_shared_array.html | 106 ++++++++-- smart_ptr.htm | 11 + 16 files changed, 448 insertions(+), 317 deletions(-) create mode 100644 include/boost/smart_ptr/detail/sp_forward.hpp diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index 904902c..e6fa081 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include @@ -20,146 +21,146 @@ namespace boost { template - inline typename detail::sp_if_array::type + inline typename boost::detail::sp_if_array::type allocate_shared(const A& allocator, std::size_t size) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; T1* p1 = 0; T2* p2 = 0; - std::size_t n1 = size * detail::array_total::size; - detail::allocate_array_helper a1(allocator, n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + std::size_t n1 = size * boost::detail::array_total::size; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct(p2, n1); - return shared_ptr(s1, p1); + return boost::shared_ptr(s1, p1); } #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) template - inline typename detail::sp_if_array::type + inline typename boost::detail::sp_if_array::type allocate_shared(const A& allocator, std::size_t size, Args&&... args) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; T1* p1 = 0; T2* p2 = 0; - std::size_t n1 = size * detail::array_total::size; - detail::allocate_array_helper a1(allocator, n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + std::size_t n1 = size * boost::detail::array_total::size; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct(p2, n1, std::forward(args)...); - return shared_ptr(s1, p1); + d2 = get_deleter >(s1); + d2->construct(p2, n1, boost::detail::sp_forward(args)...); + return boost::shared_ptr(s1, p1); } template - inline typename detail::sp_if_size_array::type + inline typename boost::detail::sp_if_size_array::type allocate_shared(const A& allocator, Args&&... args) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; T1* p1 = 0; T2* p2 = 0; - std::size_t n1 = detail::array_total::size; - detail::allocate_array_helper a1(allocator, n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + std::size_t n1 = boost::detail::array_total::size; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct(p2, n1, std::forward(args)...); - return shared_ptr(s1, p1); + d2 = get_deleter >(s1); + d2->construct(p2, n1, boost::detail::sp_forward(args)...); + return boost::shared_ptr(s1, p1); } #endif #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) template - inline typename detail::sp_if_array::type + inline typename boost::detail::sp_if_array::type allocate_shared(const A& allocator, - std::initializer_list::type> list) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + std::initializer_list::type> list) { + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; typedef const T2 T3; T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n1 = list.size() * detail::array_total::size; - detail::allocate_array_helper a1(allocator, n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + std::size_t n1 = list.size() * boost::detail::array_total::size; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_list(p2, n1, p3); - return shared_ptr(s1, p1); + return boost::shared_ptr(s1, p1); } template - inline typename detail::sp_if_size_array::type + inline typename boost::detail::sp_if_size_array::type allocate_shared(const A& allocator, - std::initializer_list::type> list) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + std::initializer_list::type> list) { + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; typedef const T2 T3; - BOOST_ASSERT(list.size() == detail::array_size::size); + BOOST_ASSERT(list.size() == boost::detail::array_size::size); T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n1 = detail::array_total::size; - detail::allocate_array_helper a1(allocator, n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + std::size_t n1 = boost::detail::array_total::size; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_list(p2, n1, p3); - return shared_ptr(s1, p1); + return boost::shared_ptr(s1, p1); } template - inline typename detail::sp_if_array::type + inline typename boost::detail::sp_if_array::type allocate_shared(const A& allocator, std::size_t size, - std::initializer_list::type> list) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + std::initializer_list::type> list) { + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; typedef const T2 T3; T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n0 = detail::array_total::size; + std::size_t n0 = boost::detail::array_total::size; std::size_t n1 = n0 * list.size(); - detail::allocate_array_helper a1(allocator, n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_list(p2, n1, p3, n0); - return shared_ptr(s1, p1); + return boost::shared_ptr(s1, p1); } template - inline typename detail::sp_if_size_array::type + inline typename boost::detail::sp_if_size_array::type allocate_shared(const A& allocator, - std::initializer_list::type> list) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + std::initializer_list::type> list) { + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; typedef const T2 T3; - BOOST_ASSERT(list.size() == detail::array_size::size); + BOOST_ASSERT(list.size() == boost::detail::array_size::size); T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n0 = detail::array_total::size; - std::size_t n1 = detail::array_total::size; - detail::allocate_array_helper a1(allocator, n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + std::size_t n0 = boost::detail::array_total::size; + std::size_t n1 = boost::detail::array_total::size; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_list(p2, n1, p3, n0); - return shared_ptr(s1, p1); + return boost::shared_ptr(s1, p1); } #endif } diff --git a/include/boost/smart_ptr/detail/allocate_array_helper.hpp b/include/boost/smart_ptr/detail/allocate_array_helper.hpp index bfb4dec..dee34ad 100644 --- a/include/boost/smart_ptr/detail/allocate_array_helper.hpp +++ b/include/boost/smart_ptr/detail/allocate_array_helper.hpp @@ -57,7 +57,7 @@ namespace boost { return allocator.max_size(); } pointer allocate(size_type count, const void* value = 0) { - std::size_t a1 = alignment_of::value; + std::size_t a1 = boost::alignment_of::value; std::size_t n1 = count * sizeof(Y) + a1 - 1; char* p1 = A3(allocator).allocate(n1 + size, value); char* p2 = p1 + n1; @@ -68,7 +68,7 @@ namespace boost { return reinterpret_cast(p1); } void deallocate(pointer memory, size_type count) { - std::size_t a1 = alignment_of::value; + std::size_t a1 = boost::alignment_of::value; std::size_t n1 = count * sizeof(Y) + a1 - 1; char* p1 = reinterpret_cast(memory); A3(allocator).deallocate(p1, n1 + size); diff --git a/include/boost/smart_ptr/detail/make_array_helper.hpp b/include/boost/smart_ptr/detail/make_array_helper.hpp index 96fa3f9..4d92be3 100644 --- a/include/boost/smart_ptr/detail/make_array_helper.hpp +++ b/include/boost/smart_ptr/detail/make_array_helper.hpp @@ -52,7 +52,7 @@ namespace boost { return static_cast(-1) / sizeof(Y); } pointer allocate(size_type count, const void* = 0) { - std::size_t a1 = alignment_of::value; + std::size_t a1 = boost::alignment_of::value; std::size_t n1 = count * sizeof(Y) + a1 - 1; void* p1 = ::operator new(n1 + size); char* p2 = static_cast(p1) + n1; diff --git a/include/boost/smart_ptr/detail/operator_bool.hpp b/include/boost/smart_ptr/detail/operator_bool.hpp index 1d5be11..e38593f 100644 --- a/include/boost/smart_ptr/detail/operator_bool.hpp +++ b/include/boost/smart_ptr/detail/operator_bool.hpp @@ -8,7 +8,7 @@ #if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) - operator bool () const + operator bool () const BOOST_NOEXCEPT { return px != 0; } @@ -21,7 +21,7 @@ typedef void (*unspecified_bool_type)( this_type*** ); - operator unspecified_bool_type() const // never throws + operator unspecified_bool_type() const BOOST_NOEXCEPT { return px == 0? 0: unspecified_bool; } @@ -33,7 +33,7 @@ typedef element_type * (this_type::*unspecified_bool_type)() const; - operator unspecified_bool_type() const // never throws + operator unspecified_bool_type() const BOOST_NOEXCEPT { return px == 0? 0: &this_type::get; } @@ -42,7 +42,7 @@ typedef element_type * this_type::*unspecified_bool_type; - operator unspecified_bool_type() const // never throws + operator unspecified_bool_type() const BOOST_NOEXCEPT { return px == 0? 0: &this_type::px; } @@ -50,7 +50,7 @@ #endif // operator! is redundant, but some compilers need it - bool operator! () const // never throws + bool operator! () const BOOST_NOEXCEPT { return px == 0; } diff --git a/include/boost/smart_ptr/detail/sp_forward.hpp b/include/boost/smart_ptr/detail/sp_forward.hpp new file mode 100644 index 0000000..25c4d48 --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_forward.hpp @@ -0,0 +1,39 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_FORWARD_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_FORWARD_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_forward.hpp +// +// Copyright 2008,2012 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 +{ + +#if defined( BOOST_HAS_RVALUE_REFS ) + +template< class T > T&& sp_forward( T & t ) BOOST_NOEXCEPT +{ + return static_cast< T&& >( t ); +} + +#endif + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_FORWARD_HPP_INCLUDED diff --git a/include/boost/smart_ptr/enable_shared_from_this.hpp b/include/boost/smart_ptr/enable_shared_from_this.hpp index f7b1445..3230f02 100644 --- a/include/boost/smart_ptr/enable_shared_from_this.hpp +++ b/include/boost/smart_ptr/enable_shared_from_this.hpp @@ -25,20 +25,20 @@ template class enable_shared_from_this { protected: - enable_shared_from_this() + enable_shared_from_this() BOOST_NOEXCEPT { } - enable_shared_from_this(enable_shared_from_this const &) + enable_shared_from_this(enable_shared_from_this const &) BOOST_NOEXCEPT { } - enable_shared_from_this & operator=(enable_shared_from_this const &) + enable_shared_from_this & operator=(enable_shared_from_this const &) BOOST_NOEXCEPT { return *this; } - ~enable_shared_from_this() + ~enable_shared_from_this() BOOST_NOEXCEPT // ~weak_ptr newer throws, so this call also must not throw { } diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp index a575223..01e2429 100644 --- a/include/boost/smart_ptr/intrusive_ptr.hpp +++ b/include/boost/smart_ptr/intrusive_ptr.hpp @@ -58,7 +58,7 @@ public: typedef T element_type; - intrusive_ptr(): px( 0 ) + intrusive_ptr() BOOST_NOEXCEPT : px( 0 ) { } @@ -110,12 +110,12 @@ public: #if defined( BOOST_HAS_RVALUE_REFS ) - intrusive_ptr(intrusive_ptr && rhs): px( rhs.px ) + intrusive_ptr(intrusive_ptr && rhs) BOOST_NOEXCEPT : px( rhs.px ) { rhs.px = 0; } - intrusive_ptr & operator=(intrusive_ptr && rhs) + intrusive_ptr & operator=(intrusive_ptr && rhs) BOOST_NOEXCEPT { this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this); return *this; @@ -135,7 +135,7 @@ public: return *this; } - void reset() + void reset() BOOST_NOEXCEPT { this_type().swap( *this ); } @@ -145,7 +145,7 @@ public: this_type( rhs ).swap( *this ); } - T * get() const + T * get() const BOOST_NOEXCEPT { return px; } @@ -165,7 +165,7 @@ public: // implicit conversion to "bool" #include - void swap(intrusive_ptr & rhs) + void swap(intrusive_ptr & rhs) BOOST_NOEXCEPT { T * tmp = px; px = rhs.px; diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index 70083b1..36e0ddd 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include @@ -20,178 +21,178 @@ namespace boost { template - inline typename detail::sp_if_array::type + inline typename boost::detail::sp_if_array::type make_shared(std::size_t size) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; T1* p1 = 0; T2* p2 = 0; - std::size_t n1 = size * detail::array_total::size; - detail::make_array_helper a1(n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + std::size_t n1 = size * boost::detail::array_total::size; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct(p2, n1); - return shared_ptr(s1, p1); + return boost::shared_ptr(s1, p1); } #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) template - inline typename detail::sp_if_array::type + inline typename boost::detail::sp_if_array::type make_shared(std::size_t size, Args&&... args) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; T1* p1 = 0; T2* p2 = 0; - std::size_t n1 = size * detail::array_total::size; - detail::make_array_helper a1(n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + std::size_t n1 = size * boost::detail::array_total::size; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct(p2, n1, std::forward(args)...); - return shared_ptr(s1, p1); + d2 = get_deleter >(s1); + d2->construct(p2, n1, boost::detail::sp_forward(args)...); + return boost::shared_ptr(s1, p1); } template - inline typename detail::sp_if_size_array::type + inline typename boost::detail::sp_if_size_array::type make_shared(Args&&... args) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; T1* p1 = 0; T2* p2 = 0; - std::size_t n1 = detail::array_total::size; - detail::make_array_helper a1(n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + std::size_t n1 = boost::detail::array_total::size; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct(p2, n1, std::forward(args)...); - return shared_ptr(s1, p1); + d2 = get_deleter >(s1); + d2->construct(p2, n1, boost::detail::sp_forward(args)...); + return boost::shared_ptr(s1, p1); } #endif #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) template - inline typename detail::sp_if_array::type - make_shared(std::initializer_list::type> list) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + inline typename boost::detail::sp_if_array::type + make_shared(std::initializer_list::type> list) { + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; typedef const T2 T3; T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n1 = list.size() * detail::array_total::size; - detail::make_array_helper a1(n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + std::size_t n1 = list.size() * boost::detail::array_total::size; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_list(p2, n1, p3); - return shared_ptr(s1, p1); + return boost::shared_ptr(s1, p1); } template - inline typename detail::sp_if_size_array::type - make_shared(std::initializer_list::type> list) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + inline typename boost::detail::sp_if_size_array::type + make_shared(std::initializer_list::type> list) { + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; typedef const T2 T3; - BOOST_ASSERT(list.size() == detail::array_size::size); + BOOST_ASSERT(list.size() == boost::detail::array_size::size); T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n1 = detail::array_total::size; - detail::make_array_helper a1(n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + std::size_t n1 = boost::detail::array_total::size; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_list(p2, n1, p3); - return shared_ptr(s1, p1); + return boost::shared_ptr(s1, p1); } template - inline typename detail::sp_if_array::type + inline typename boost::detail::sp_if_array::type make_shared(std::size_t size, - std::initializer_list::type> list) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + std::initializer_list::type> list) { + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; typedef const T2 T3; T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n0 = detail::array_total::size; + std::size_t n0 = boost::detail::array_total::size; std::size_t n1 = n0 * size; - detail::make_array_helper a1(n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_list(p2, n1, p3, n0); - return shared_ptr(s1, p1); + return boost::shared_ptr(s1, p1); } template - inline typename detail::sp_if_size_array::type - make_shared(std::initializer_list::type> list) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + inline typename boost::detail::sp_if_size_array::type + make_shared(std::initializer_list::type> list) { + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; typedef const T2 T3; - BOOST_ASSERT(list.size() == detail::array_size::size); + BOOST_ASSERT(list.size() == boost::detail::array_size::size); T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n0 = detail::array_total::size; - std::size_t n1 = detail::array_total::size; - detail::make_array_helper a1(n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + std::size_t n0 = boost::detail::array_total::size; + std::size_t n1 = boost::detail::array_total::size; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_list(p2, n1, p3, n0); - return shared_ptr(s1, p1); + return boost::shared_ptr(s1, p1); } #endif template - inline typename detail::sp_if_array::type + inline typename boost::detail::sp_if_array::type make_shared_noinit(std::size_t size) { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; T1* p1 = 0; T2* p2 = 0; - std::size_t n1 = size * detail::array_total::size; - detail::make_array_helper a1(n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + std::size_t n1 = size * boost::detail::array_total::size; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_noinit(p2, n1); - return shared_ptr(s1, p1); + return boost::shared_ptr(s1, p1); } template - inline typename detail::sp_if_size_array::type + inline typename boost::detail::sp_if_size_array::type make_shared_noinit() { - typedef typename detail::array_inner::type T1; - typedef typename detail::array_base::type T2; + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; T1* p1 = 0; T2* p2 = 0; - std::size_t n1 = detail::array_total::size; - detail::make_array_helper a1(n1, &p2); - detail::array_deleter d1; - shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; + std::size_t n1 = boost::detail::array_total::size; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_noinit(p2, n1); - return shared_ptr(s1, p1); + return boost::shared_ptr(s1, p1); } } diff --git a/include/boost/smart_ptr/make_shared_object.hpp b/include/boost/smart_ptr/make_shared_object.hpp index 3872909..c6e28aa 100644 --- a/include/boost/smart_ptr/make_shared_object.hpp +++ b/include/boost/smart_ptr/make_shared_object.hpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -67,12 +68,12 @@ private: public: - sp_ms_deleter(): initialized_( false ) + sp_ms_deleter() BOOST_NOEXCEPT : initialized_( false ) { } // optimization: do not copy storage_ - sp_ms_deleter( sp_ms_deleter const & ): initialized_( false ) + sp_ms_deleter( sp_ms_deleter const & ) BOOST_NOEXCEPT : initialized_( false ) { } @@ -86,26 +87,17 @@ public: destroy(); } - void * address() + void * address() BOOST_NOEXCEPT { return storage_.data_; } - void set_initialized() + void set_initialized() BOOST_NOEXCEPT { initialized_ = true; } }; -#if defined( BOOST_HAS_RVALUE_REFS ) - -template< class T > T&& sp_forward( T & t ) -{ - return static_cast< T&& >( t ); -} - -#endif - template< class T > struct sp_if_not_array { typedef boost::shared_ptr< T > type; @@ -117,12 +109,16 @@ template< class T > struct sp_if_not_array< T[] > { }; +#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 ) + template< class T, std::size_t N > struct sp_if_not_array< T[N] > { }; #endif +#endif + } // namespace detail #if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING ) diff --git a/include/boost/smart_ptr/scoped_array.hpp b/include/boost/smart_ptr/scoped_array.hpp index 483460f..83352e2 100644 --- a/include/boost/smart_ptr/scoped_array.hpp +++ b/include/boost/smart_ptr/scoped_array.hpp @@ -53,7 +53,7 @@ public: typedef T element_type; - explicit scoped_array( T * p = 0 ) : px( p ) // never throws + explicit scoped_array( T * p = 0 ) BOOST_NOEXCEPT : px( p ) { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_array_constructor_hook( px ); @@ -68,20 +68,20 @@ public: boost::checked_array_delete( px ); } - void reset(T * p = 0) // never throws + void reset(T * p = 0) // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) { BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors this_type(p).swap(*this); } - T & operator[](std::ptrdiff_t i) const // never throws + T & operator[](std::ptrdiff_t i) const // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) { BOOST_ASSERT( px != 0 ); BOOST_ASSERT( i >= 0 ); return px[i]; } - T * get() const // never throws + T * get() const BOOST_NOEXCEPT { return px; } @@ -89,7 +89,7 @@ public: // implicit conversion to "bool" #include - void swap(scoped_array & b) // never throws + void swap(scoped_array & b) BOOST_NOEXCEPT { T * tmp = b.px; b.px = px; @@ -97,7 +97,7 @@ public: } }; -template inline void swap(scoped_array & a, scoped_array & b) // never throws +template inline void swap(scoped_array & a, scoped_array & b) BOOST_NOEXCEPT { a.swap(b); } diff --git a/include/boost/smart_ptr/scoped_ptr.hpp b/include/boost/smart_ptr/scoped_ptr.hpp index df479e5..3ccf697 100644 --- a/include/boost/smart_ptr/scoped_ptr.hpp +++ b/include/boost/smart_ptr/scoped_ptr.hpp @@ -63,7 +63,7 @@ public: #ifndef BOOST_NO_AUTO_PTR - explicit scoped_ptr( std::auto_ptr p ): px( p.release() ) // never throws + explicit scoped_ptr( std::auto_ptr p ) BOOST_NOEXCEPT : px( p.release() ) { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_scalar_constructor_hook( px ); @@ -98,7 +98,7 @@ public: return px; } - T * get() const // never throws + T * get() const BOOST_NOEXCEPT { return px; } @@ -106,7 +106,7 @@ public: // implicit conversion to "bool" #include - void swap(scoped_ptr & b) // never throws + void swap(scoped_ptr & b) BOOST_NOEXCEPT { T * tmp = b.px; b.px = px; @@ -114,14 +114,14 @@ public: } }; -template inline void swap(scoped_ptr & a, scoped_ptr & b) // never throws +template inline void swap(scoped_ptr & a, scoped_ptr & b) BOOST_NOEXCEPT { a.swap(b); } // get_pointer(p) is a generic way to say p.get() -template inline T * get_pointer(scoped_ptr const & p) +template inline T * get_pointer(scoped_ptr const & p) BOOST_NOEXCEPT { return p.get(); } diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp index 3e79582..ac64099 100644 --- a/include/boost/smart_ptr/shared_array.hpp +++ b/include/boost/smart_ptr/shared_array.hpp @@ -56,7 +56,7 @@ public: typedef T element_type; - shared_array(): px( 0 ), pn() // never throws + shared_array() BOOST_NOEXCEPT : px( 0 ), pn() { } @@ -90,11 +90,11 @@ public: // ... except in C++0x, move disables the implicit copy - shared_array( shared_array const & r ): px( r.px ), pn( r.pn ) // never throws + shared_array( shared_array const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn ) { } - shared_array( shared_array && r ): px( r.px ), pn() // never throws + shared_array( shared_array && r ) BOOST_NOEXCEPT : px( r.px ), pn() { pn.swap( r.pn ); r.px = 0; @@ -114,7 +114,7 @@ public: shared_array( shared_array const & r ) #endif - : px( r.px ), pn( r.pn ) // never throws + BOOST_NOEXCEPT : px( r.px ), pn( r.pn ) // never throws { boost::detail::sp_assert_convertible< Y[], T[] >(); } @@ -122,13 +122,13 @@ public: // aliasing template< class Y > - shared_array( shared_array const & r, element_type * p ): px( p ), pn( r.pn ) // never throws + shared_array( shared_array const & r, element_type * p ) BOOST_NOEXCEPT : px( p ), pn( r.pn ) { } // assignment - shared_array & operator=( shared_array const & r ) // never throws + shared_array & operator=( shared_array const & r ) BOOST_NOEXCEPT { this_type( r ).swap( *this ); return *this; @@ -137,7 +137,7 @@ public: #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400) template - shared_array & operator=( shared_array const & r ) // never throws + shared_array & operator=( shared_array const & r ) BOOST_NOEXCEPT { this_type( r ).swap( *this ); return *this; @@ -147,14 +147,14 @@ public: #if defined( BOOST_HAS_RVALUE_REFS ) - shared_array & operator=( shared_array && r ) // never throws + shared_array & operator=( shared_array && r ) BOOST_NOEXCEPT { this_type( static_cast< shared_array && >( r ) ).swap( *this ); return *this; } template - shared_array & operator=( shared_array && r ) // never throws + shared_array & operator=( shared_array && r ) BOOST_NOEXCEPT { this_type( static_cast< shared_array && >( r ) ).swap( *this ); return *this; @@ -162,7 +162,7 @@ public: #endif - void reset() // never throws + void reset() BOOST_NOEXCEPT { this_type().swap( *this ); } @@ -188,14 +188,14 @@ public: this_type( r, p ).swap( *this ); } - T & operator[] (std::ptrdiff_t i) const // never throws + T & operator[] (std::ptrdiff_t i) const // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) { BOOST_ASSERT(px != 0); BOOST_ASSERT(i >= 0); return px[i]; } - T * get() const // never throws + T * get() const BOOST_NOEXCEPT { return px; } @@ -203,17 +203,17 @@ public: // implicit conversion to "bool" #include - bool unique() const // never throws + bool unique() const BOOST_NOEXCEPT { return pn.unique(); } - long use_count() const // never throws + long use_count() const BOOST_NOEXCEPT { return pn.use_count(); } - void swap(shared_array & other) // never throws + void swap(shared_array & other) BOOST_NOEXCEPT { std::swap(px, other.px); pn.swap(other.pn); @@ -233,22 +233,22 @@ private: }; // shared_array -template inline bool operator==(shared_array const & a, shared_array const & b) // never throws +template inline bool operator==(shared_array const & a, shared_array const & b) BOOST_NOEXCEPT { return a.get() == b.get(); } -template inline bool operator!=(shared_array const & a, shared_array const & b) // never throws +template inline bool operator!=(shared_array const & a, shared_array const & b) BOOST_NOEXCEPT { return a.get() != b.get(); } -template inline bool operator<(shared_array const & a, shared_array const & b) // never throws +template inline bool operator<(shared_array const & a, shared_array const & b) BOOST_NOEXCEPT { return std::less()(a.get(), b.get()); } -template void swap(shared_array & a, shared_array & b) // never throws +template void swap(shared_array & a, shared_array & b) BOOST_NOEXCEPT { a.swap(b); } diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index f9fe0d3..6f4064b 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -81,11 +81,15 @@ template< class T > struct sp_element< T[] > typedef T type; }; +#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 ) + template< class T, std::size_t N > struct sp_element< T[N] > { typedef T type; }; +#endif + #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) // sp_dereference, return type of operator* @@ -126,11 +130,15 @@ template< class T > struct sp_dereference< T[] > typedef void type; }; +#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 ) + template< class T, std::size_t N > struct sp_dereference< T[N] > { typedef void type; }; +#endif + #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) // sp_member_access, return type of operator-> @@ -147,11 +155,15 @@ template< class T > struct sp_member_access< T[] > typedef void type; }; +#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 ) + template< class T, std::size_t N > struct sp_member_access< T[N] > { typedef void type; }; +#endif + #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) // sp_array_access, return type of operator[] @@ -168,11 +180,15 @@ template< class T > struct sp_array_access< T[] > typedef T & type; }; +#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 ) + template< class T, std::size_t N > struct sp_array_access< T[N] > { typedef T & type; }; +#endif + #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) // sp_extent, for operator[] index check @@ -324,7 +340,7 @@ public: typedef typename boost::detail::sp_element< T >::type element_type; - shared_ptr(): px( 0 ), pn() // never throws in 1.30+ + shared_ptr() BOOST_NOEXCEPT : px( 0 ), pn() // never throws in 1.30+ { } @@ -358,7 +374,7 @@ public: // ... except in C++0x, move disables the implicit copy - shared_ptr( shared_ptr const & r ): px( r.px ), pn( r.pn ) // never throws + shared_ptr( shared_ptr const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn ) { } @@ -374,7 +390,8 @@ public: } template - shared_ptr( weak_ptr const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws + shared_ptr( weak_ptr const & r, boost::detail::sp_nothrow_tag ) + BOOST_NOEXCEPT : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) { if( !pn.empty() ) { @@ -392,24 +409,26 @@ public: shared_ptr( shared_ptr const & r ) #endif - : px( r.px ), pn( r.pn ) // never throws + BOOST_NOEXCEPT : px( r.px ), pn( r.pn ) { boost::detail::sp_assert_convertible< Y, T >(); } // aliasing template< class Y > - shared_ptr( shared_ptr const & r, element_type * p ): px( p ), pn( r.pn ) // never throws + shared_ptr( shared_ptr const & r, element_type * p ) BOOST_NOEXCEPT : px( p ), pn( r.pn ) { } template - shared_ptr(shared_ptr const & r, boost::detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) + shared_ptr(shared_ptr const & r, boost::detail::static_cast_tag) + BOOST_NOEXCEPT : 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) + shared_ptr(shared_ptr const & r, boost::detail::const_cast_tag) + BOOST_NOEXCEPT : px(const_cast(r.px)), pn(r.pn) { } @@ -480,7 +499,7 @@ public: // assignment - shared_ptr & operator=( shared_ptr const & r ) // never throws + shared_ptr & operator=( shared_ptr const & r ) BOOST_NOEXCEPT { this_type(r).swap(*this); return *this; @@ -489,7 +508,7 @@ public: #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400) template - shared_ptr & operator=(shared_ptr const & r) // never throws + shared_ptr & operator=(shared_ptr const & r) BOOST_NOEXCEPT { this_type(r).swap(*this); return *this; @@ -523,7 +542,7 @@ public: #if defined( BOOST_HAS_RVALUE_REFS ) - shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws + shared_ptr( shared_ptr && r ) BOOST_NOEXCEPT : px( r.px ), pn() { pn.swap( r.pn ); r.px = 0; @@ -539,7 +558,7 @@ public: shared_ptr( shared_ptr && r ) #endif - : px( r.px ), pn() // never throws + BOOST_NOEXCEPT : px( r.px ), pn() { boost::detail::sp_assert_convertible< Y, T >(); @@ -547,14 +566,14 @@ public: r.px = 0; } - shared_ptr & operator=( shared_ptr && r ) // never throws + shared_ptr & operator=( shared_ptr && r ) BOOST_NOEXCEPT { this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); return *this; } template - shared_ptr & operator=( shared_ptr && r ) // never throws + shared_ptr & operator=( shared_ptr && r ) BOOST_NOEXCEPT { this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); return *this; @@ -562,7 +581,7 @@ public: #endif - void reset() // never throws in 1.30+ + void reset() BOOST_NOEXCEPT // never throws in 1.30+ { this_type().swap(*this); } @@ -587,20 +606,23 @@ public: { this_type( r, p ).swap( *this ); } - - typename boost::detail::sp_dereference< T >::type operator* () const // never throws + + // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) + typename boost::detail::sp_dereference< T >::type operator* () const { BOOST_ASSERT( px != 0 ); return *px; } - - typename boost::detail::sp_member_access< T >::type operator-> () const // never throws + + // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) + typename boost::detail::sp_member_access< T >::type operator-> () const { BOOST_ASSERT( px != 0 ); return px; } - - typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const // never throws + + // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) + typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const { BOOST_ASSERT( px != 0 ); BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) ); @@ -608,7 +630,7 @@ public: return px[ i ]; } - element_type * get() const // never throws + element_type * get() const BOOST_NOEXCEPT { return px; } @@ -616,28 +638,28 @@ public: // implicit conversion to "bool" #include - bool unique() const // never throws + bool unique() const BOOST_NOEXCEPT { return pn.unique(); } - long use_count() const // never throws + long use_count() const BOOST_NOEXCEPT { return pn.use_count(); } - void swap( shared_ptr & other ) // never throws + void swap( shared_ptr & other ) BOOST_NOEXCEPT { std::swap(px, other.px); pn.swap(other.pn); } - template bool owner_before( shared_ptr const & rhs ) const + template bool owner_before( shared_ptr const & rhs ) const BOOST_NOEXCEPT { return pn < rhs.pn; } - template bool owner_before( weak_ptr const & rhs ) const + template bool owner_before( weak_ptr const & rhs ) const BOOST_NOEXCEPT { return pn < rhs.pn; } @@ -647,7 +669,7 @@ public: return pn.get_deleter( ti ); } - bool _internal_equiv( shared_ptr const & r ) const + bool _internal_equiv( shared_ptr const & r ) const BOOST_NOEXCEPT { return px == r.px && pn == r.pn; } @@ -670,12 +692,12 @@ private: }; // shared_ptr -template inline bool operator==(shared_ptr const & a, shared_ptr const & b) +template inline bool operator==(shared_ptr const & a, shared_ptr const & b) BOOST_NOEXCEPT { return a.get() == b.get(); } -template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) +template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) BOOST_NOEXCEPT { return a.get() != b.get(); } @@ -684,19 +706,19 @@ template inline bool operator!=(shared_ptr const & a, share // Resolve the ambiguity between our op!= and the one in rel_ops -template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) +template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) BOOST_NOEXCEPT { return a.get() != b.get(); } #endif -template inline bool operator<(shared_ptr const & a, shared_ptr const & b) +template inline bool operator<(shared_ptr const & a, shared_ptr const & b) BOOST_NOEXCEPT { return a.owner_before( b ); } -template inline void swap(shared_ptr & a, shared_ptr & b) +template inline void swap(shared_ptr & a, shared_ptr & b) BOOST_NOEXCEPT { a.swap(b); } @@ -741,7 +763,7 @@ template shared_ptr shared_polymorphic_downcast(shared_ptr< // get_pointer() enables boost::mem_fn to recognize shared_ptr -template inline T * get_pointer(shared_ptr const & p) +template inline T * get_pointer(shared_ptr const & p) BOOST_NOEXCEPT { return p.get(); } @@ -854,7 +876,7 @@ template D * get_deleter(shared_ptr const & p) #if !defined(BOOST_SP_NO_ATOMIC_ACCESS) -template inline bool atomic_is_lock_free( shared_ptr const * /*p*/ ) +template inline bool atomic_is_lock_free( shared_ptr const * /*p*/ ) BOOST_NOEXCEPT { return false; } @@ -933,7 +955,7 @@ template inline bool atomic_compare_exchange_explicit( shared_ptr * template< class T > struct hash; -template< class T > std::size_t hash_value( boost::shared_ptr const & p ) +template< class T > std::size_t hash_value( boost::shared_ptr const & p ) BOOST_NOEXCEPT { return boost::hash< T* >()( p.get() ); } diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp index 62b6afe..59cdd45 100644 --- a/include/boost/smart_ptr/weak_ptr.hpp +++ b/include/boost/smart_ptr/weak_ptr.hpp @@ -31,7 +31,7 @@ public: typedef typename boost::detail::sp_element< T >::type element_type; - weak_ptr(): px(0), pn() // never throws in 1.30+ + weak_ptr() BOOST_NOEXCEPT : px(0), pn() // never throws in 1.30+ { } @@ -41,11 +41,11 @@ public: // ... except in C++0x, move disables the implicit copy - weak_ptr( weak_ptr const & r ): px( r.px ), pn( r.pn ) // never throws + weak_ptr( weak_ptr const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn ) { } - weak_ptr & operator=( weak_ptr const & r ) // never throws + weak_ptr & operator=( weak_ptr const & r ) BOOST_NOEXCEPT { px = r.px; pn = r.pn; @@ -81,7 +81,7 @@ public: weak_ptr( weak_ptr const & r ) #endif - : px(r.lock().get()), pn(r.pn) // never throws + BOOST_NOEXCEPT : px(r.lock().get()), pn(r.pn) { boost::detail::sp_assert_convertible< Y, T >(); } @@ -98,20 +98,21 @@ public: weak_ptr( weak_ptr && r ) #endif - : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) // never throws + BOOST_NOEXCEPT : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) { boost::detail::sp_assert_convertible< Y, T >(); r.px = 0; } // for better efficiency in the T == Y case - weak_ptr( weak_ptr && r ): px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) // never throws + weak_ptr( weak_ptr && r ) + BOOST_NOEXCEPT : px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) { r.px = 0; } // for better efficiency in the T == Y case - weak_ptr & operator=( weak_ptr && r ) // never throws + weak_ptr & operator=( weak_ptr && r ) BOOST_NOEXCEPT { this_type( static_cast< weak_ptr && >( r ) ).swap( *this ); return *this; @@ -130,7 +131,7 @@ public: weak_ptr( shared_ptr const & r ) #endif - : px( r.px ), pn( r.pn ) // never throws + BOOST_NOEXCEPT : px( r.px ), pn( r.pn ) { boost::detail::sp_assert_convertible< Y, T >(); } @@ -138,7 +139,7 @@ public: #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) template - weak_ptr & operator=( weak_ptr const & r ) // never throws + weak_ptr & operator=( weak_ptr const & r ) BOOST_NOEXCEPT { boost::detail::sp_assert_convertible< Y, T >(); @@ -151,7 +152,7 @@ public: #if defined( BOOST_HAS_RVALUE_REFS ) template - weak_ptr & operator=( weak_ptr && r ) + weak_ptr & operator=( weak_ptr && r ) BOOST_NOEXCEPT { this_type( static_cast< weak_ptr && >( r ) ).swap( *this ); return *this; @@ -160,7 +161,7 @@ public: #endif template - weak_ptr & operator=( shared_ptr const & r ) // never throws + weak_ptr & operator=( shared_ptr const & r ) BOOST_NOEXCEPT { boost::detail::sp_assert_convertible< Y, T >(); @@ -172,17 +173,17 @@ public: #endif - shared_ptr lock() const // never throws + shared_ptr lock() const BOOST_NOEXCEPT { return shared_ptr( *this, boost::detail::sp_nothrow_tag() ); } - long use_count() const // never throws + long use_count() const BOOST_NOEXCEPT { return pn.use_count(); } - bool expired() const // never throws + bool expired() const BOOST_NOEXCEPT { return pn.use_count() == 0; } @@ -192,12 +193,12 @@ public: return pn.empty(); } - void reset() // never throws in 1.30+ + void reset() BOOST_NOEXCEPT // never throws in 1.30+ { this_type().swap(*this); } - void swap(this_type & other) // never throws + void swap(this_type & other) BOOST_NOEXCEPT { std::swap(px, other.px); pn.swap(other.pn); @@ -210,12 +211,12 @@ public: pn = r.pn; } - template bool owner_before( weak_ptr const & rhs ) const + template bool owner_before( weak_ptr const & rhs ) const BOOST_NOEXCEPT { return pn < rhs.pn; } - template bool owner_before( shared_ptr const & rhs ) const + template bool owner_before( shared_ptr const & rhs ) const BOOST_NOEXCEPT { return pn < rhs.pn; } @@ -237,12 +238,12 @@ private: }; // weak_ptr -template inline bool operator<(weak_ptr const & a, weak_ptr const & b) +template inline bool operator<(weak_ptr const & a, weak_ptr const & b) BOOST_NOEXCEPT { return a.owner_before( b ); } -template void swap(weak_ptr & a, weak_ptr & b) +template void swap(weak_ptr & a, weak_ptr & b) BOOST_NOEXCEPT { a.swap(b); } diff --git a/make_shared_array.html b/make_shared_array.html index 9c46926..2c0d5fc 100644 --- a/make_shared_array.html +++ b/make_shared_array.html @@ -12,12 +12,14 @@ Synopsis
    Free Functions
    Example
    + History

    Introduction

    -

    One criticism of Boost shared_array is - the lack of utility similar to make_shared - which ensures only a single allocation for an array. A second criticism - is Boost shared_array does not support custom allocators - and so also lacks an allocate_shared utility.

    +

    Originally the Boost function templates make_shared and + allocate_shared were for efficient allocation of single + objects only. There was a need to have efficient, single, allocation of + arrays. One criticism of shared_array was + always the lack of a make_shared utility + which ensures only a single allocation for an array.

    The header files <boost/smart_ptr/make_shared_array.hpp> and <boost/smart_ptr/allocate_shared_array.hpp> provide new function templates, make_shared and allocate_shared, @@ -32,17 +34,17 @@ template<typename T, typename A> shared_ptr<T[]> allocate_shared(const A& allocator, size_t size); - + #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) template<typename T, typename... Args> shared_ptr<T[]> make_shared(size_t size, Args&&... args); - + template<typename T, typename... Args> shared_ptr<T[N]> make_shared(Args&&... args); - + template<typename T, typename A, typename... Args> - shared_ptr<T> allocate_shared(const A& allocator, size_t size, Args&&... args); - + shared_ptr<T[]> allocate_shared(const A& allocator, size_t size, Args&&... args); + template<typename T, typename A, typename... Args> shared_ptr<T[N]> allocate_shared(const A& allocator, Args&&... args); #endif @@ -50,40 +52,40 @@ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) template<typename T, typename... Args> shared_ptr<T[]> make_shared(initializer_list<T> list); - + template<typename T, typename... Args> shared_ptr<T[N]> make_shared(initializer_list<T> list); - + template<typename T, typename... Args> shared_ptr<T[][N]> make_shared(size_t size, initializer_list<T> list); - + template<typename T, typename... Args> shared_ptr<T[M][N]> make_shared(initializer_list<T> list); template<typename T, typename A, typename... Args> shared_ptr<T[]> allocate_shared(const A& allocator, initializer_list<T> list); - + template<typename T, typename A, typename... Args> shared_ptr<T[N]> allocate_shared(const A& allocator, initializer_list<T> list); - + template<typename T, typename A, typename... Args> shared_ptr<T[][N]> allocate_shared(const A& allocator, size_t size, initializer_list<T> list); - + template<typename T, typename A, typename... Args> shared_ptr<T[M][N]> allocate_shared(const A& allocator, initializer_list<T> list); #endif template<typename T> - shared_ptr<T> make_shared_noinit(size_t size); - + shared_ptr<T[]> make_shared_noinit(size_t size); + template<typename T> shared_ptr<T[N]> make_shared_noinit(); }

    Free Functions

    template<typename T, typename... Args>
    -    shared_ptr<T> make_shared(size_t size, Args&&... args);
    +    shared_ptr<T[]> make_shared(size_t size, Args&&... args);
     template<typename T, typename A, typename... Args>
    -    shared_ptr<T> allocate_shared(const A& allocator, size_t size, Args&&... args);
    + shared_ptr<T[]> allocate_shared(const A& allocator, size_t size, Args&&... args);

    Requires: The expression new(pointer) T(forward<Args>(args)...), where @@ -122,16 +124,74 @@ template<typename T, typename A, typename... Args> take any constructor arguments. These overloads invoke the default constructor of T for each array element.

    +
    template<typename T, typename... Args>
    +    shared_ptr<T[N]> make_shared(Args&&... args);
    +template<typename T, typename A, typename... Args>
    +    shared_ptr<T[N]> allocate_shared(const A& allocator, Args&&... args);
    +
    +

    Description: These overloads of the utilities above are for a + fixed size array.

    +
    +
    template<typename T, typename... Args>
    +    shared_ptr<T[]> make_shared(initializer_list<T> list);
    +template<typename T, typename A, typename... Args>
    +    shared_ptr<T[]> allocate_shared(const A& allocator, initializer_list<T> list);
    +
    +

    Description: These overloads initialize the array elements + from the initializer list.

    +
    +
    template<typename T, typename... Args>
    +    shared_ptr<T[N]> make_shared(initializer_list<T> list);
    +template<typename T, typename A, typename... Args>
    +    shared_ptr<T[N]> allocate_shared(const A& allocator, initializer_list<T> list);
    +
    +

    Description: These overloads of the utilities above are for a + fixed size array.

    +
    +
    template<typename T, typename... Args>
    +    shared_ptr<T[][N]> make_shared(size_t size, initializer_list<T> list);
    +template<typename T, typename A, typename... Args>
    +    shared_ptr<T[][N]> allocate_shared(const A& allocator, size_t size, initializer_list<T> list);
    +
    +

    Description: These overloads initialize inner array elements + from the initializer list.

    +
    +
    template<typename T, typename... Args>
    +    shared_ptr<T[M][N]> make_shared(initializer_list<T> list);
    +template<typename T, typename A, typename... Args>
    +    shared_ptr<T[M][N]> allocate_shared(const A& allocator, initializer_list<T> list);
    +
    +

    Description: These overloads of the utilities above are for a + fixed size array.

    +
    +
    template<typename T>
    +    shared_ptr<T[]> make_shared_noinit(size_t size);
    +
    +

    Description: This overload does not perform value + initialization of elements.

    +
    +
    template<typename T>
    +    shared_ptr<T[N]> make_shared_noinit();
    +
    +

    Description: This overload of the utility above is used for a + fixed size array.

    +

    Example

    -
    boost::shared_ptr<int[]> a1 = boost::make_shared<int[]>(size);
    -boost::shared_ptr<point[5]> a2 = boost::make_shared<point[5]>(x, y);
    -boost::shared_ptr<int[5]> a3 = boost::make_shared<int[5]>();
    +    

    An example of each overload of make_shared for arrays:

    +
    +
    boost::shared_ptr<point[]> a1 = boost::make_shared<point[]>(size);
    +boost::shared_ptr<point[]> a2 = boost::make_shared<point[]>(size, x, y);
    +boost::shared_ptr<point[5]> a3 = boost::make_shared<point[5]>(x, y);
     boost::shared_ptr<int[]> a4 = boost::make_shared<int[]>({1, 2, 3});
     boost::shared_ptr<int[3]> a5 = boost::make_shared<int[3]>({1, 2, 3});
     boost::shared_ptr<int[][3]> a6 = boost::make_shared<int[][3]>(size, {1, 2, 3});
     boost::shared_ptr<int[5][3]> a7 = boost::make_shared<int[5][3]>({1, 2, 3});
     boost::shared_ptr<int[]> a8 = boost::make_shared_noinit<int[]>(size);
     boost::shared_ptr<int[5]> a9 = boost::make_shared_noinit<int[5]>();
    +
    +

    History

    +

    November 2012. Glen Fernandes contributed implementations of + make_shared and allocate_shared for arrays.


    $Date: 2012-10-30 10:12:25 -0800 (Tue, 30 Oct 2012) $

    Copyright 2012 Glen Fernandes. Distributed under the Boost diff --git a/smart_ptr.htm b/smart_ptr.htm index 92ad2be..10fe5d6 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -70,6 +70,11 @@ <boost/make_shared.hpp> Efficient creation of shared_ptr objects. + + make_shared and allocate_shared for arrays + <boost/make_shared.hpp> + Efficient creation of shared_ptr arrays. +

    A test program, smart_ptr_test.cpp, is @@ -126,6 +131,12 @@

    Functions which destroy objects of the pointed to type are prohibited from throwing exceptions by the common requirements.

    History and Acknowledgements

    +

    November 2012. Glen Fernandes provided implementations of make_shared + and allocate_shared for arrays. They achieve a single allocation for an + array that can be initialized with constructor arguments or initializer lists + as well as overloads for default initialization and no value initialization. + See the make_shared and allocate_shared for + arrays page for more information.

    January 2002. Peter Dimov reworked all four classes, adding features, fixing bugs, and splitting them into four separate headers, and added weak_ptr. See the compatibility page for a summary of the From 2346941b153ba46cb4352eb256b05e49986ed6d3 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Fri, 30 Nov 2012 17:29:36 +0000 Subject: [PATCH 109/140] Merged revision(s) 81608-81610 from trunk: Optimization: Add specializations of make_array_helper, allocate_array_helper, and array_deleter for fixed size arrays to avoid storing size. ........ Consistent formatting across overloads of make_shared and allocate_shared (array forms). ........ More consistency in type parameters in helper details of allocate_shared and make_shared. ........ [SVN r81635] --- .../boost/smart_ptr/allocate_shared_array.hpp | 76 +++++++------- .../detail/allocate_array_helper.hpp | 93 +++++++++++++++--- .../boost/smart_ptr/detail/array_deleter.hpp | 67 ++++++++++++- .../smart_ptr/detail/make_array_helper.hpp | 86 ++++++++++++++-- include/boost/smart_ptr/make_shared_array.hpp | 98 +++++++++---------- 5 files changed, 311 insertions(+), 109 deletions(-) diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index e6fa081..4a7de24 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -28,12 +28,12 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct(p2, n1); return boost::shared_ptr(s1, p1); } @@ -46,12 +46,12 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct(p2, n1, boost::detail::sp_forward(args)...); return boost::shared_ptr(s1, p1); } @@ -62,14 +62,14 @@ namespace boost { typedef typename boost::detail::array_base::type T2; T1* p1 = 0; T2* p2 = 0; - std::size_t n1 = boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + enum { N = boost::detail::array_total::size }; + boost::detail::allocate_array_helper a1(allocator, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct(p2, n1, boost::detail::sp_forward(args)...); + d2 = get_deleter >(s1); + d2->construct(p2, boost::detail::sp_forward(args)...); return boost::shared_ptr(s1, p1); } #endif @@ -85,13 +85,13 @@ namespace boost { T2* p2 = 0; T3* p3 = 0; std::size_t n1 = list.size() * boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_list(p2, n1, p3); return boost::shared_ptr(s1, p1); } @@ -106,15 +106,15 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n1 = boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + enum { N = boost::detail::array_total::size }; + boost::detail::allocate_array_helper a1(allocator, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3); + d2 = get_deleter >(s1); + d2->construct_list(p2, p3); return boost::shared_ptr(s1, p1); } template @@ -127,16 +127,16 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n0 = boost::detail::array_total::size; - std::size_t n1 = n0 * list.size(); - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + enum { M = boost::detail::array_total::size }; + std::size_t n1 = M * list.size(); + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3, n0); + d2 = get_deleter >(s1); + d2->construct_list(p2, n1, p3, M); return boost::shared_ptr(s1, p1); } template @@ -150,16 +150,16 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n0 = boost::detail::array_total::size; - std::size_t n1 = boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + enum { M = boost::detail::array_total::size }; + enum { N = boost::detail::array_total::size }; + boost::detail::allocate_array_helper a1(allocator, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3, n0); + d2 = get_deleter >(s1); + d2->construct_list(p2, p3, M); return boost::shared_ptr(s1, p1); } #endif diff --git a/include/boost/smart_ptr/detail/allocate_array_helper.hpp b/include/boost/smart_ptr/detail/allocate_array_helper.hpp index dee34ad..f7c64fe 100644 --- a/include/boost/smart_ptr/detail/allocate_array_helper.hpp +++ b/include/boost/smart_ptr/detail/allocate_array_helper.hpp @@ -13,8 +13,10 @@ namespace boost { namespace detail { - template - class allocate_array_helper { + template + class allocate_array_helper; + template + class allocate_array_helper { template friend class allocate_array_helper; typedef typename A::template rebind ::other A2; @@ -29,20 +31,15 @@ namespace boost { typedef typename A2::difference_type difference_type; template struct rebind { - typedef allocate_array_helper other; + typedef allocate_array_helper other; }; allocate_array_helper(const A& allocator, std::size_t size, T** data) : allocator(allocator), size(sizeof(T) * size), data(data) { } - allocate_array_helper(const allocate_array_helper& other) - : allocator(other.allocator), - size(other.size), - data(other.data) { - } template - allocate_array_helper(const allocate_array_helper& other) + allocate_array_helper(const allocate_array_helper& other) : allocator(other.allocator), size(other.size), data(other.data) { @@ -80,11 +77,11 @@ namespace boost { allocator.destroy(memory); } template - bool operator==(const allocate_array_helper& other) const { + bool operator==(const allocate_array_helper& other) const { return allocator == other.allocator; } template - bool operator!=(const allocate_array_helper& other) const { + bool operator!=(const allocate_array_helper& other) const { return !(*this == other); } private: @@ -92,6 +89,80 @@ namespace boost { std::size_t size; T** data; }; + template + class allocate_array_helper { + template + friend class allocate_array_helper; + typedef typename A::template rebind ::other A2; + typedef typename A::template rebind::other A3; + public: + typedef typename A2::value_type value_type; + typedef typename A2::pointer pointer; + typedef typename A2::const_pointer const_pointer; + typedef typename A2::reference reference; + typedef typename A2::const_reference const_reference; + typedef typename A2::size_type size_type; + typedef typename A2::difference_type difference_type; + template + struct rebind { + typedef allocate_array_helper other; + }; + allocate_array_helper(const A& allocator, T** data) + : allocator(allocator), + data(data) { + } + template + allocate_array_helper(const allocate_array_helper& other) + : allocator(other.allocator), + data(other.data) { + } + pointer address(reference value) const { + return allocator.address(value); + } + const_pointer address(const_reference value) const { + return allocator.address(value); + } + size_type max_size() const { + return allocator.max_size(); + } + pointer allocate(size_type count, const void* value = 0) { + std::size_t a1 = boost::alignment_of::value; + std::size_t n1 = count * sizeof(Y) + a1 - 1; + char* p1 = A3(allocator).allocate(n1 + N1, value); + char* p2 = p1 + n1; + while (std::size_t(p2) % a1 != 0) { + p2--; + } + *data = reinterpret_cast(p2); + return reinterpret_cast(p1); + } + void deallocate(pointer memory, size_type count) { + std::size_t a1 = boost::alignment_of::value; + std::size_t n1 = count * sizeof(Y) + a1 - 1; + char* p1 = reinterpret_cast(memory); + A3(allocator).deallocate(p1, n1 + N1); + } + void construct(pointer memory, const Y& value) { + allocator.construct(memory, value); + } + void destroy(pointer memory) { + allocator.destroy(memory); + } + template + bool operator==(const allocate_array_helper& other) const { + return allocator == other.allocator; + } + template + bool operator!=(const allocate_array_helper& other) const { + return !(*this == other); + } + private: + enum { + N1 = N * sizeof(T) + }; + A2 allocator; + T** data; + }; } } diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index 273dcac..b43f5fa 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -15,7 +15,9 @@ namespace boost { namespace detail { template - class array_deleter { + class array_deleter; + template + class array_deleter { public: array_deleter() : size(0) { @@ -70,6 +72,69 @@ namespace boost { std::size_t size; T* object; }; + template + class array_deleter { + public: + array_deleter() + : object(0) { + } + ~array_deleter() { + destroy(); + } + void construct(T* memory) { + object = memory; + for (std::size_t i = 0; i < N; i++) { + void* p1 = object + i; + ::new(p1) T(); + } + } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + template + void construct(T* memory, Args&&... args) { + object = memory; + for (std::size_t i = 0; i < N; i++) { + void* p1 = object + i; + ::new(p1) T(args...); + } + } +#endif +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + void construct_list(T* memory, const T* list) { + object = memory; + for (std::size_t i = 0; i < N; i++) { + void* p1 = object + i; + ::new(p1) T(list[i]); + } + } + void construct_list(T* memory, const T* list, std::size_t n) { + object = memory; + for (std::size_t i = 0; i < N; i++) { + void* p1 = object + i; + ::new(p1) T(list[i % n]); + } + } +#endif + void construct_noinit(T* memory) { + object = memory; + for (std::size_t i = 0; i < N; i++) { + void* p1 = object + i; + ::new(p1) T; + } + } + void operator()(const void*) { + destroy(); + } + private: + void destroy() { + if (object) { + for (std::size_t i = N; i > 0; ) { + object[--i].~T(); + } + object = 0; + } + } + T* object; + }; } } diff --git a/include/boost/smart_ptr/detail/make_array_helper.hpp b/include/boost/smart_ptr/detail/make_array_helper.hpp index 4d92be3..38c9dc9 100644 --- a/include/boost/smart_ptr/detail/make_array_helper.hpp +++ b/include/boost/smart_ptr/detail/make_array_helper.hpp @@ -13,8 +13,10 @@ namespace boost { namespace detail { - template - class make_array_helper { + template + class make_array_helper; + template + class make_array_helper { template friend class make_array_helper; public: @@ -27,18 +29,14 @@ namespace boost { typedef ptrdiff_t difference_type; template struct rebind { - typedef make_array_helper other; + typedef make_array_helper other; }; make_array_helper(std::size_t size, T** data) : size(sizeof(T) * size), data(data) { } - make_array_helper(const make_array_helper& other) - : size(other.size), - data(other.data) { - } template - make_array_helper(const make_array_helper& other) + make_array_helper(const make_array_helper& other) : size(other.size), data(other.data) { } @@ -74,17 +72,85 @@ namespace boost { memory->~Y(); } template - bool operator==(const make_array_helper& other) const { + bool operator==(const make_array_helper& other) const { return true; } template - bool operator!=(const make_array_helper& other) const { + bool operator!=(const make_array_helper& other) const { return !(*this == other); } private: std::size_t size; T** data; }; + template + class make_array_helper { + template + friend class make_array_helper; + public: + typedef Y value_type; + typedef Y* pointer; + typedef const Y* const_pointer; + typedef Y& reference; + typedef const Y& const_reference; + typedef std::size_t size_type; + typedef ptrdiff_t difference_type; + template + struct rebind { + typedef make_array_helper other; + }; + make_array_helper(T** data) + : data(data) { + } + template + make_array_helper(const make_array_helper& other) + : data(other.data) { + } + pointer address(reference value) const { + return &value; + } + const_pointer address(const_reference value) const { + return &value; + } + size_type max_size() const { + return static_cast(-1) / sizeof(Y); + } + pointer allocate(size_type count, const void* = 0) { + std::size_t a1 = boost::alignment_of::value; + std::size_t n1 = count * sizeof(Y) + a1 - 1; + void* p1 = ::operator new(n1 + N1); + char* p2 = static_cast(p1) + n1; + while (std::size_t(p2) % a1 != 0) { + p2--; + } + *data = reinterpret_cast(p2); + return reinterpret_cast(p1); + } + void deallocate(pointer memory, size_type) { + void* p1 = memory; + ::operator delete(p1); + } + void construct(pointer memory, const Y& value) { + void* p1 = memory; + ::new(p1) Y(value); + } + void destroy(pointer memory) { + memory->~Y(); + } + template + bool operator==(const make_array_helper& other) const { + return true; + } + template + bool operator!=(const make_array_helper& other) const { + return !(*this == other); + } + private: + enum { + N1 = N * sizeof(T) + }; + T** data; + }; } } diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index 36e0ddd..d1eeac7 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -28,12 +28,12 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct(p2, n1); return boost::shared_ptr(s1, p1); } @@ -46,12 +46,12 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct(p2, n1, boost::detail::sp_forward(args)...); return boost::shared_ptr(s1, p1); } @@ -62,14 +62,14 @@ namespace boost { typedef typename boost::detail::array_base::type T2; T1* p1 = 0; T2* p2 = 0; - std::size_t n1 = boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + enum { N = boost::detail::array_total::size }; + boost::detail::make_array_helper a1(&p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct(p2, n1, boost::detail::sp_forward(args)...); + d2 = get_deleter >(s1); + d2->construct(p2, boost::detail::sp_forward(args)...); return boost::shared_ptr(s1, p1); } #endif @@ -84,13 +84,13 @@ namespace boost { T2* p2 = 0; T3* p3 = 0; std::size_t n1 = list.size() * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_list(p2, n1, p3); return boost::shared_ptr(s1, p1); } @@ -104,15 +104,15 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n1 = boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + enum { N = boost::detail::array_total::size }; + boost::detail::make_array_helper a1(&p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3); + d2 = get_deleter >(s1); + d2->construct_list(p2, p3); return boost::shared_ptr(s1, p1); } template @@ -125,16 +125,16 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n0 = boost::detail::array_total::size; - std::size_t n1 = n0 * size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + enum { M = boost::detail::array_total::size }; + std::size_t n1 = M * size; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3, n0); + d2 = get_deleter >(s1); + d2->construct_list(p2, n1, p3, M); return boost::shared_ptr(s1, p1); } template @@ -147,16 +147,16 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n0 = boost::detail::array_total::size; - std::size_t n1 = boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + enum { M = boost::detail::array_total::size }; + enum { N = boost::detail::array_total::size }; + boost::detail::make_array_helper a1(&p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3, n0); + d2 = get_deleter >(s1); + d2->construct_list(p2, p3, M); return boost::shared_ptr(s1, p1); } #endif @@ -168,12 +168,12 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_noinit(p2, n1); return boost::shared_ptr(s1, p1); } @@ -184,14 +184,14 @@ namespace boost { typedef typename boost::detail::array_base::type T2; T1* p1 = 0; T2* p2 = 0; - std::size_t n1 = boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + enum { N = boost::detail::array_total::size }; + boost::detail::make_array_helper a1(&p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; - p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct_noinit(p2, n1); + boost::detail::array_deleter* d2; + p1 = reinterpret_cast(p2); + d2 = get_deleter >(s1); + d2->construct_noinit(p2); return boost::shared_ptr(s1, p1); } } From ea55019260054abb3bc6beccb4abf046a374afb9 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sun, 2 Dec 2012 23:15:55 +0000 Subject: [PATCH 110/140] Merged revision(s) 81641-81643,81658,81669,81681 from trunk: Use const T (&)[N] for fixed size arrays instead of std::initializer in overloads of make_shared and allocate_shared for arrays. ........ Use BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX instead for certain overloads of make_shared and allocate_shared ........ Code consistency: Use the same style of #if conditional compilation checks in allocate_shared_array.hpp and make_shared_array.hpp. ........ Change make_shared and allocate_shared array form overload for size and inner array initialization list to use const T(&)[N] instead of std::initializer_list. ........ Move two tests for allocate_shared and make_shared within check for BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX ........ Make specializations of detail array_deleter consistent. ........ [SVN r81682] --- .../boost/smart_ptr/allocate_shared_array.hpp | 55 +++++++++-------- .../boost/smart_ptr/detail/array_deleter.hpp | 55 +++++++++-------- .../boost/smart_ptr/detail/array_traits.hpp | 17 +----- include/boost/smart_ptr/make_shared_array.hpp | 60 +++++++++++-------- make_shared_array.html | 44 +++++++------- test/allocate_shared_array_init_test.cpp | 34 ++++++----- test/allocate_shared_arrays_create_test.cpp | 30 +++++++--- test/make_shared_array_init_test.cpp | 34 ++++++----- test/make_shared_arrays_create_test.cpp | 31 +++++++--- 9 files changed, 203 insertions(+), 157 deletions(-) diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index 4a7de24..0c17edd 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -29,12 +29,12 @@ namespace boost { T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct(p2, n1); + d2->construct(p2); return boost::shared_ptr(s1, p1); } #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) @@ -47,12 +47,12 @@ namespace boost { T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct(p2, n1, boost::detail::sp_forward(args)...); + d2->construct(p2, boost::detail::sp_forward(args)...); return boost::shared_ptr(s1, p1); } template @@ -60,9 +60,11 @@ namespace boost { allocate_shared(const A& allocator, Args&&... args) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; + enum { + N = boost::detail::array_total::size + }; T1* p1 = 0; T2* p2 = 0; - enum { N = boost::detail::array_total::size }; boost::detail::allocate_array_helper a1(allocator, &p2); boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); @@ -86,32 +88,34 @@ namespace boost { T3* p3 = 0; std::size_t n1 = list.size() * boost::detail::array_total::size; boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3); + d2->construct_list(p2, p3); return boost::shared_ptr(s1, p1); } +#endif +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) template inline typename boost::detail::sp_if_size_array::type - allocate_shared(const A& allocator, - std::initializer_list::type> list) { + allocate_shared(const A& allocator, const T& list) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef const T2 T3; - BOOST_ASSERT(list.size() == boost::detail::array_size::size); + enum { + N = boost::detail::array_total::size + }; T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - enum { N = boost::detail::array_total::size }; boost::detail::allocate_array_helper a1(allocator, &p2); boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); boost::detail::array_deleter* d2; - p3 = reinterpret_cast(list.begin()); + p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); d2->construct_list(p2, p3); @@ -120,43 +124,46 @@ namespace boost { template inline typename boost::detail::sp_if_array::type allocate_shared(const A& allocator, std::size_t size, - std::initializer_list::type> list) { + const typename boost::detail::array_inner::type& list) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef const T2 T3; + enum { + M = boost::detail::array_total::size + }; T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - enum { M = boost::detail::array_total::size }; - std::size_t n1 = M * list.size(); + std::size_t n1 = M * size; boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); boost::detail::array_deleter* d2; - p3 = reinterpret_cast(list.begin()); + p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3, M); + d2->construct_list(p2, p3, M); return boost::shared_ptr(s1, p1); } template inline typename boost::detail::sp_if_size_array::type allocate_shared(const A& allocator, - std::initializer_list::type> list) { + const typename boost::detail::array_inner::type& list) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef const T2 T3; - BOOST_ASSERT(list.size() == boost::detail::array_size::size); + enum { + M = boost::detail::array_total::size, + N = boost::detail::array_total::size + }; T1* p1 = 0; T2* p2 = 0; - T3* p3 = 0; - enum { M = boost::detail::array_total::size }; - enum { N = boost::detail::array_total::size }; + T3* p3 = 0; boost::detail::allocate_array_helper a1(allocator, &p2); boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); boost::detail::array_deleter* d2; - p3 = reinterpret_cast(list.begin()); + p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); d2->construct_list(p2, p3, M); diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index b43f5fa..5d89dd8 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -19,44 +19,48 @@ namespace boost { template class array_deleter { public: - array_deleter() - : size(0) { + array_deleter(std::size_t size) + : size(size), + object(0) { } ~array_deleter() { destroy(); } - void construct(T* memory, std::size_t count) { - for (object = memory; size < count; size++) { - void* p1 = object + size; + void construct(T* memory) { + object = memory; + for (std::size_t i = 0; i < size; i++) { + void* p1 = object + i; ::new(p1) T(); } } #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) template - void construct(T* memory, std::size_t count, Args&&... args) { - for (object = memory; size < count; size++) { - void* p1 = object + size; + void construct(T* memory, Args&&... args) { + object = memory; + for (std::size_t i = 0; i < size; i++) { + void* p1 = object + i; ::new(p1) T(args...); } } #endif -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - void construct_list(T* memory, std::size_t count, const T* list) { - for (object = memory; size < count; size++) { - void* p1 = object + size; - ::new(p1) T(list[size]); + void construct_list(T* memory, const T* list) { + object = memory; + for (std::size_t i = 0; i < size; i++) { + void* p1 = object + i; + ::new(p1) T(list[i]); } } - void construct_list(T* memory, std::size_t count, const T* list, std::size_t n) { - for (object = memory; size < count; size++) { - void* p1 = object + size; - ::new(p1) T(list[size % n]); + void construct_list(T* memory, const T* list, std::size_t n) { + object = memory; + for (std::size_t i = 0; i < size; i++) { + void* p1 = object + i; + ::new(p1) T(list[i % n]); } } -#endif - void construct_noinit(T* memory, std::size_t count) { - for (object = memory; size < count; size++) { - void* p1 = object + size; + void construct_noinit(T* memory) { + object = memory; + for (std::size_t i = 0; i < size; i++) { + void* p1 = object + i; ::new(p1) T; } } @@ -65,8 +69,11 @@ namespace boost { } private: void destroy() { - while (size > 0) { - object[--size].~T(); + if (object) { + for (std::size_t i = size; i > 0; ) { + object[--i].~T(); + } + object = 0; } } std::size_t size; @@ -98,7 +105,6 @@ namespace boost { } } #endif -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) void construct_list(T* memory, const T* list) { object = memory; for (std::size_t i = 0; i < N; i++) { @@ -113,7 +119,6 @@ namespace boost { ::new(p1) T(list[i % n]); } } -#endif void construct_noinit(T* memory) { object = memory; for (std::size_t i = 0; i < N; i++) { diff --git a/include/boost/smart_ptr/detail/array_traits.hpp b/include/boost/smart_ptr/detail/array_traits.hpp index 3b80f46..3ef482a 100644 --- a/include/boost/smart_ptr/detail/array_traits.hpp +++ b/include/boost/smart_ptr/detail/array_traits.hpp @@ -22,8 +22,7 @@ namespace boost { typedef typename array_base::type type; }; template - struct array_size { - }; + struct array_size; template struct array_size { enum { @@ -43,8 +42,7 @@ namespace boost { }; }; template - struct array_inner { - }; + struct array_inner; template struct array_inner { typedef T type; @@ -53,17 +51,6 @@ namespace boost { struct array_inner { typedef T type; }; - template - struct arrays_inner { - }; - template - struct arrays_inner { - typedef T type; - }; - template - struct arrays_inner { - typedef T type; - }; } } diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index d1eeac7..89ff8f1 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -29,12 +29,12 @@ namespace boost { T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct(p2, n1); + d2->construct(p2); return boost::shared_ptr(s1, p1); } #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) @@ -47,12 +47,12 @@ namespace boost { T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct(p2, n1, boost::detail::sp_forward(args)...); + d2->construct(p2, boost::detail::sp_forward(args)...); return boost::shared_ptr(s1, p1); } template @@ -60,9 +60,11 @@ namespace boost { make_shared(Args&&... args) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; + enum { + N = boost::detail::array_total::size + }; T1* p1 = 0; T2* p2 = 0; - enum { N = boost::detail::array_total::size }; boost::detail::make_array_helper a1(&p2); boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); @@ -85,31 +87,34 @@ namespace boost { T3* p3 = 0; std::size_t n1 = list.size() * boost::detail::array_total::size; boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3); + d2->construct_list(p2, p3); return boost::shared_ptr(s1, p1); - } + } +#endif +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) template inline typename boost::detail::sp_if_size_array::type - make_shared(std::initializer_list::type> list) { + make_shared(const T& list) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef const T2 T3; - BOOST_ASSERT(list.size() == boost::detail::array_size::size); + enum { + N = boost::detail::array_total::size + }; T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - enum { N = boost::detail::array_total::size }; boost::detail::make_array_helper a1(&p2); boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); boost::detail::array_deleter* d2; - p3 = reinterpret_cast(list.begin()); + p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); d2->construct_list(p2, p3); @@ -118,42 +123,45 @@ namespace boost { template inline typename boost::detail::sp_if_array::type make_shared(std::size_t size, - std::initializer_list::type> list) { + const typename boost::detail::array_inner::type& list) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef const T2 T3; + enum { + M = boost::detail::array_total::size + }; T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - enum { M = boost::detail::array_total::size }; std::size_t n1 = M * size; boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); boost::detail::array_deleter* d2; - p3 = reinterpret_cast(list.begin()); + p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3, M); + d2->construct_list(p2, p3, M); return boost::shared_ptr(s1, p1); } template inline typename boost::detail::sp_if_size_array::type - make_shared(std::initializer_list::type> list) { + make_shared(const typename boost::detail::array_inner::type& list) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef const T2 T3; - BOOST_ASSERT(list.size() == boost::detail::array_size::size); + enum { + M = boost::detail::array_total::size, + N = boost::detail::array_total::size + }; T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - enum { M = boost::detail::array_total::size }; - enum { N = boost::detail::array_total::size }; boost::detail::make_array_helper a1(&p2); boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); boost::detail::array_deleter* d2; - p3 = reinterpret_cast(list.begin()); + p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); d2->construct_list(p2, p3, M); @@ -169,12 +177,12 @@ namespace boost { T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct_noinit(p2, n1); + d2->construct_noinit(p2); return boost::shared_ptr(s1, p1); } template @@ -182,9 +190,11 @@ namespace boost { make_shared_noinit() { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; + enum { + N = boost::detail::array_total::size + }; T1* p1 = 0; T2* p2 = 0; - enum { N = boost::detail::array_total::size }; boost::detail::make_array_helper a1(&p2); boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); diff --git a/make_shared_array.html b/make_shared_array.html index 2c0d5fc..b42d28a 100644 --- a/make_shared_array.html +++ b/make_shared_array.html @@ -12,7 +12,7 @@ Synopsis
    Free Functions
    Example
    - History
    + History

    Introduction

    Originally the Boost function templates make_shared and allocate_shared were for efficient allocation of single @@ -34,7 +34,7 @@ template<typename T, typename A> shared_ptr<T[]> allocate_shared(const A& allocator, size_t size); - + #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) template<typename T, typename... Args> shared_ptr<T[]> make_shared(size_t size, Args&&... args); @@ -48,31 +48,33 @@ template<typename T, typename A, typename... Args> shared_ptr<T[N]> allocate_shared(const A& allocator, Args&&... args); #endif - + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) template<typename T, typename... Args> shared_ptr<T[]> make_shared(initializer_list<T> list); - template<typename T, typename... Args> - shared_ptr<T[N]> make_shared(initializer_list<T> list); - - template<typename T, typename... Args> - shared_ptr<T[][N]> make_shared(size_t size, initializer_list<T> list); - - template<typename T, typename... Args> - shared_ptr<T[M][N]> make_shared(initializer_list<T> list); - template<typename T, typename A, typename... Args> shared_ptr<T[]> allocate_shared(const A& allocator, initializer_list<T> list); +#endif + +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) + template<typename T, typename... Args> + shared_ptr<T[N]> make_shared(const T (&list)[N]); + + template<typename T, typename... Args> + shared_ptr<T[][N]> make_shared(size_t size, const T (&list)[N]); + + template<typename T, typename... Args> + shared_ptr<T[M][N]> make_shared(const T (&list)[N]); template<typename T, typename A, typename... Args> - shared_ptr<T[N]> allocate_shared(const A& allocator, initializer_list<T> list); + shared_ptr<T[N]> allocate_shared(const A& allocator, const T (&list)[N]); template<typename T, typename A, typename... Args> - shared_ptr<T[][N]> allocate_shared(const A& allocator, size_t size, initializer_list<T> list); + shared_ptr<T[][N]> allocate_shared(const A& allocator, size_t size, const T (&list)[N]); template<typename T, typename A, typename... Args> - shared_ptr<T[M][N]> allocate_shared(const A& allocator, initializer_list<T> list); + shared_ptr<T[M][N]> allocate_shared(const A& allocator, const T (&list)[N]); #endif template<typename T> @@ -141,25 +143,25 @@ template<typename T, typename A, typename... Args> from the initializer list.

    template<typename T, typename... Args>
    -    shared_ptr<T[N]> make_shared(initializer_list<T> list);
    +    shared_ptr<T[N]> make_shared(const T (&list)[N]);
     template<typename T, typename A, typename... Args>
    -    shared_ptr<T[N]> allocate_shared(const A& allocator, initializer_list<T> list);
    + shared_ptr<T[N]> allocate_shared(const A& allocator, const T (&list)[N]);

    Description: These overloads of the utilities above are for a fixed size array.

    template<typename T, typename... Args>
    -    shared_ptr<T[][N]> make_shared(size_t size, initializer_list<T> list);
    +    shared_ptr<T[][N]> make_shared(size_t size, const T (&list)[N]);
     template<typename T, typename A, typename... Args>
    -    shared_ptr<T[][N]> allocate_shared(const A& allocator, size_t size, initializer_list<T> list);
    + shared_ptr<T[][N]> allocate_shared(const A& allocator, size_t size, const T (&list)[N]);

    Description: These overloads initialize inner array elements from the initializer list.

    template<typename T, typename... Args>
    -    shared_ptr<T[M][N]> make_shared(initializer_list<T> list);
    +    shared_ptr<T[M][N]> make_shared(const T (&list)[N]);
     template<typename T, typename A, typename... Args>
    -    shared_ptr<T[M][N]> allocate_shared(const A& allocator, initializer_list<T> list);
    + shared_ptr<T[M][N]> allocate_shared(const A& allocator, const T (&list)[N]);

    Description: These overloads of the utilities above are for a fixed size array.

    diff --git a/test/allocate_shared_array_init_test.cpp b/test/allocate_shared_array_init_test.cpp index 6411aa8..1ff437f 100644 --- a/test/allocate_shared_array_init_test.cpp +++ b/test/allocate_shared_array_init_test.cpp @@ -28,13 +28,6 @@ int main() { BOOST_TEST(a1[2] == 2); BOOST_TEST(a1[3] == 3); } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); BOOST_TEST(a1[0] == 0); @@ -42,13 +35,6 @@ int main() { BOOST_TEST(a1[2] == 2); BOOST_TEST(a1[3] == 3); } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); BOOST_TEST(a1[0].value == 0); @@ -57,14 +43,30 @@ int main() { BOOST_TEST(a1[3].value == 3); } { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); BOOST_TEST(a1[0].value == 0); BOOST_TEST(a1[1].value == 1); BOOST_TEST(a1[2].value == 2); BOOST_TEST(a1[3].value == 3); } +#endif +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); BOOST_TEST(a1[0].value == 0); BOOST_TEST(a1[1].value == 1); BOOST_TEST(a1[2].value == 2); diff --git a/test/allocate_shared_arrays_create_test.cpp b/test/allocate_shared_arrays_create_test.cpp index 03a2d7e..8645179 100644 --- a/test/allocate_shared_arrays_create_test.cpp +++ b/test/allocate_shared_arrays_create_test.cpp @@ -11,6 +11,13 @@ int main() { #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), {0, 1, 2, 3}); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { {0, 1}, {2, 3} }); BOOST_TEST(a1[0][0] == 0); @@ -18,6 +25,15 @@ int main() { BOOST_TEST(a1[1][0] == 2); BOOST_TEST(a1[1][1] == 3); } +#endif +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), {0, 1, 2, 3}); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { {0, 1}, {2, 3} }); BOOST_TEST(a1[0][0] == 0); @@ -25,13 +41,6 @@ int main() { BOOST_TEST(a1[1][0] == 2); BOOST_TEST(a1[1][1] == 3); } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), {0, 1}); - BOOST_TEST(a1[0][0] == 0); - BOOST_TEST(a1[0][1] == 1); - BOOST_TEST(a1[1][0] == 0); - BOOST_TEST(a1[1][1] == 1); - } { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, {0, 1}); BOOST_TEST(a1[0][0] == 0); @@ -46,6 +55,13 @@ int main() { BOOST_TEST(a1[1][1][0] == 2); BOOST_TEST(a1[1][1][1] == 3); } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), {0, 1}); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 1); + } { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { {0, 1}, {2, 3} }); BOOST_TEST(a1[0][0][0] == 0); diff --git a/test/make_shared_array_init_test.cpp b/test/make_shared_array_init_test.cpp index 6a4c5d5..fd61caf 100644 --- a/test/make_shared_array_init_test.cpp +++ b/test/make_shared_array_init_test.cpp @@ -28,13 +28,6 @@ int main() { BOOST_TEST(a1[2] == 2); BOOST_TEST(a1[3] == 3); } - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } { boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); BOOST_TEST(a1[0] == 0); @@ -42,13 +35,6 @@ int main() { BOOST_TEST(a1[2] == 2); BOOST_TEST(a1[3] == 3); } - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } { boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); BOOST_TEST(a1[0].value == 0); @@ -57,14 +43,30 @@ int main() { BOOST_TEST(a1[3].value == 3); } { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); BOOST_TEST(a1[0].value == 0); BOOST_TEST(a1[1].value == 1); BOOST_TEST(a1[2].value == 2); BOOST_TEST(a1[3].value == 3); } +#endif +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); BOOST_TEST(a1[0].value == 0); BOOST_TEST(a1[1].value == 1); BOOST_TEST(a1[2].value == 2); diff --git a/test/make_shared_arrays_create_test.cpp b/test/make_shared_arrays_create_test.cpp index e468378..eb08759 100644 --- a/test/make_shared_arrays_create_test.cpp +++ b/test/make_shared_arrays_create_test.cpp @@ -8,10 +8,16 @@ */ #include #include -#include int main() { #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + { + boost::shared_ptr a1 = boost::make_shared({0, 1, 2, 3}); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } { boost::shared_ptr a1 = boost::make_shared({ {0, 1}, {2, 3} }); BOOST_TEST(a1[0][0] == 0); @@ -19,6 +25,15 @@ int main() { BOOST_TEST(a1[1][0] == 2); BOOST_TEST(a1[1][1] == 3); } +#endif +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) + { + boost::shared_ptr a1 = boost::make_shared({0, 1, 2, 3}); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } { boost::shared_ptr a1 = boost::make_shared({ {0, 1}, {2, 3} }); BOOST_TEST(a1[0][0] == 0); @@ -26,13 +41,6 @@ int main() { BOOST_TEST(a1[1][0] == 2); BOOST_TEST(a1[1][1] == 3); } - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1 }); - BOOST_TEST(a1[0][0] == 0); - BOOST_TEST(a1[0][1] == 1); - BOOST_TEST(a1[1][0] == 0); - BOOST_TEST(a1[1][1] == 1); - } { boost::shared_ptr a1 = boost::make_shared(2, {0, 1}); BOOST_TEST(a1[0][0] == 0); @@ -47,6 +55,13 @@ int main() { BOOST_TEST(a1[1][1][0] == 2); BOOST_TEST(a1[1][1][1] == 3); } + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1 }); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 1); + } { boost::shared_ptr a1 = boost::make_shared({ {0, 1}, {2, 3} }); BOOST_TEST(a1[0][0][0] == 0); From 88c2baa20b4cf39162fa824bef7a50cbef7c7958 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 3 Dec 2012 15:42:15 +0000 Subject: [PATCH 111/140] Merged revision(s) 81684-81685 from trunk: For fixed size arrays upon constructor exception thrown destroy correctly. ........ Minor cosmetic change in detail array_deleter ........ [SVN r81695] --- .../boost/smart_ptr/detail/array_deleter.hpp | 156 ++++++++++++------ test/allocate_shared_array_throws_test.cpp | 16 ++ test/make_shared_array_throws_test.cpp | 16 ++ 3 files changed, 135 insertions(+), 53 deletions(-) diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index 5d89dd8..b07b00a 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -1,9 +1,9 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012 Glen Joseph Fernandes * glenfe at live dot com * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt * or copy at http://boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP @@ -19,58 +19,83 @@ namespace boost { template class array_deleter { public: - array_deleter(std::size_t size) + array_deleter(std::size_t size) : size(size), object(0) { } ~array_deleter() { - destroy(); + destroy(size); } void construct(T* memory) { - object = memory; - for (std::size_t i = 0; i < size; i++) { - void* p1 = object + i; - ::new(p1) T(); + std::size_t i = 0; + try { + for (object = memory; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(); + } + } catch (...) { + destroy(i); + throw; } } #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) template void construct(T* memory, Args&&... args) { - object = memory; - for (std::size_t i = 0; i < size; i++) { - void* p1 = object + i; - ::new(p1) T(args...); + std::size_t i = 0; + try { + for (object = memory; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(args...); + } + } catch (...) { + destroy(i); + throw; } } #endif void construct_list(T* memory, const T* list) { - object = memory; - for (std::size_t i = 0; i < size; i++) { - void* p1 = object + i; - ::new(p1) T(list[i]); + std::size_t i = 0; + try { + for (object = memory; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i]); + } + } catch (...) { + destroy(i); + throw; } } void construct_list(T* memory, const T* list, std::size_t n) { - object = memory; - for (std::size_t i = 0; i < size; i++) { - void* p1 = object + i; - ::new(p1) T(list[i % n]); + std::size_t i = 0; + try { + for (object = memory; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i % n]); + } + } catch (...) { + destroy(i); + throw; } } void construct_noinit(T* memory) { - object = memory; - for (std::size_t i = 0; i < size; i++) { - void* p1 = object + i; - ::new(p1) T; + std::size_t i = 0; + try { + for (object = memory; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T; + } + } catch (...) { + destroy(i); + throw; } } void operator()(const void*) { - destroy(); + destroy(size); } private: - void destroy() { + void destroy(std::size_t n) { if (object) { - for (std::size_t i = size; i > 0; ) { + for (std::size_t i = n; i > 0; ) { object[--i].~T(); } object = 0; @@ -82,57 +107,82 @@ namespace boost { template class array_deleter { public: - array_deleter() + array_deleter() : object(0) { } ~array_deleter() { - destroy(); + destroy(N); } void construct(T* memory) { - object = memory; - for (std::size_t i = 0; i < N; i++) { - void* p1 = object + i; - ::new(p1) T(); + std::size_t i = 0; + try { + for (object = memory; i < N; i++) { + void* p1 = memory + i; + ::new(p1) T(); + } + } catch (...) { + destroy(i); + throw; } } #if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) template void construct(T* memory, Args&&... args) { - object = memory; - for (std::size_t i = 0; i < N; i++) { - void* p1 = object + i; - ::new(p1) T(args...); + std::size_t i = 0; + try { + for (object = memory; i < N; i++) { + void* p1 = memory + i; + ::new(p1) T(args...); + } + } catch (...) { + destroy(i); + throw; } } #endif void construct_list(T* memory, const T* list) { - object = memory; - for (std::size_t i = 0; i < N; i++) { - void* p1 = object + i; - ::new(p1) T(list[i]); + std::size_t i = 0; + try { + for (object = memory; i < N; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i]); + } + } catch (...) { + destroy(i); + throw; } } void construct_list(T* memory, const T* list, std::size_t n) { - object = memory; - for (std::size_t i = 0; i < N; i++) { - void* p1 = object + i; - ::new(p1) T(list[i % n]); + std::size_t i = 0; + try { + for (object = memory; i < N; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i % n]); + } + } catch (...) { + destroy(i); + throw; } } void construct_noinit(T* memory) { - object = memory; - for (std::size_t i = 0; i < N; i++) { - void* p1 = object + i; - ::new(p1) T; + std::size_t i = 0; + try { + for (object = memory; i < N; i++) { + void* p1 = memory + i; + ::new(p1) T; + } + } catch (...) { + destroy(i); + throw; } } void operator()(const void*) { - destroy(); + destroy(N); } private: - void destroy() { + void destroy(std::size_t n) { if (object) { - for (std::size_t i = N; i > 0; ) { + for (std::size_t i = n; i > 0; ) { object[--i].~T(); } object = 0; diff --git a/test/allocate_shared_array_throws_test.cpp b/test/allocate_shared_array_throws_test.cpp index d52104c..65a7985 100644 --- a/test/allocate_shared_array_throws_test.cpp +++ b/test/allocate_shared_array_throws_test.cpp @@ -43,5 +43,21 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + BOOST_TEST(type::instances == 0); + try { + boost::allocate_shared(std::allocator()); + BOOST_ERROR("allocate_shared did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + try { + boost::allocate_shared(std::allocator()); + BOOST_ERROR("allocate_shared did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } +#endif return boost::report_errors(); } diff --git a/test/make_shared_array_throws_test.cpp b/test/make_shared_array_throws_test.cpp index 7e06d41..4faf193 100644 --- a/test/make_shared_array_throws_test.cpp +++ b/test/make_shared_array_throws_test.cpp @@ -43,6 +43,22 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + BOOST_TEST(type::instances == 0); + try { + boost::make_shared(); + BOOST_ERROR("make_shared did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + try { + boost::make_shared(); + BOOST_ERROR("make_shared did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } +#endif BOOST_TEST(type::instances == 0); try { boost::make_shared_noinit(6); From 32fe0b8f26fa124d8a211fe230943360d74d9041 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 5 Dec 2012 03:44:40 +0000 Subject: [PATCH 112/140] Merged revision(s) 81488 from trunk: Apply patch from #7722. Fixes #7722. [SVN r81714] --- include/boost/smart_ptr/detail/shared_count.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp index be4f65b..5d22f86 100644 --- a/include/boost/smart_ptr/detail/shared_count.hpp +++ b/include/boost/smart_ptr/detail/shared_count.hpp @@ -35,7 +35,10 @@ // rather than including directly: #include // std::auto_ptr #include // std::less -#include // std::bad_alloc + +#ifdef BOOST_NO_EXCEPTIONS +# include // std::bad_alloc +#endif #if !defined( BOOST_NO_CXX11_SMART_PTR ) # include From 3551d17566448d40778b4de940c81db0674c44d4 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 5 Dec 2012 04:13:51 +0000 Subject: [PATCH 113/140] Merged revision 81463 from trunk: Update shared_ptr casts. ........ [SVN r81715] --- include/boost/smart_ptr/shared_ptr.hpp | 85 ++++------- test/Jamfile.v2 | 1 + test/sp_array_cast_test.cpp | 202 +++++++++++++++++++++++++ 3 files changed, 229 insertions(+), 59 deletions(-) create mode 100644 test/sp_array_cast_test.cpp diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 6f4064b..3e2e1d2 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -62,11 +62,6 @@ class enable_shared_from_raw; namespace detail { -struct static_cast_tag {}; -struct const_cast_tag {}; -struct dynamic_cast_tag {}; -struct polymorphic_cast_tag {}; - // sp_element, element_type template< class T > struct sp_element @@ -420,36 +415,6 @@ public: { } - template - shared_ptr(shared_ptr const & r, boost::detail::static_cast_tag) - BOOST_NOEXCEPT : px(static_cast(r.px)), pn(r.pn) - { - } - - template - shared_ptr(shared_ptr const & r, boost::detail::const_cast_tag) - BOOST_NOEXCEPT : 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 @@ -723,42 +688,44 @@ template inline void swap(shared_ptr & a, shared_ptr & b) BOOST_N a.swap(b); } -template shared_ptr static_pointer_cast(shared_ptr const & r) +template shared_ptr static_pointer_cast( shared_ptr const & r ) BOOST_NOEXCEPT { - return shared_ptr(r, boost::detail::static_cast_tag()); + (void) static_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename shared_ptr::element_type E; + + E * p = static_cast< E* >( r.get() ); + return shared_ptr( r, p ); } -template shared_ptr const_pointer_cast(shared_ptr const & r) +template shared_ptr const_pointer_cast( shared_ptr const & r ) BOOST_NOEXCEPT { - return shared_ptr(r, boost::detail::const_cast_tag()); + (void) const_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename shared_ptr::element_type E; + + E * p = const_cast< E* >( r.get() ); + return shared_ptr( r, p ); } -template shared_ptr dynamic_pointer_cast(shared_ptr const & r) +template shared_ptr dynamic_pointer_cast( shared_ptr const & r ) BOOST_NOEXCEPT { - return shared_ptr(r, boost::detail::dynamic_cast_tag()); + (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename shared_ptr::element_type E; + + E * p = dynamic_cast< E* >( r.get() ); + return p? shared_ptr( r, p ): shared_ptr(); } -// shared_*_cast names are deprecated. Use *_pointer_cast instead. - -template shared_ptr shared_static_cast(shared_ptr const & r) +template shared_ptr reinterpret_pointer_cast( shared_ptr const & r ) BOOST_NOEXCEPT { - return shared_ptr(r, boost::detail::static_cast_tag()); -} + (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); -template shared_ptr shared_dynamic_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::dynamic_cast_tag()); -} + typedef typename shared_ptr::element_type E; -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); + E * p = reinterpret_cast< E* >( r.get() ); + return shared_ptr( r, p ); } // get_pointer() enables boost::mem_fn to recognize shared_ptr diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e3b41c0..2c95dd9 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -74,6 +74,7 @@ import testing ; [ compile sp_array_cv_test.cpp ] [ run sp_convertible_test.cpp ] [ run sp_array_n_test.cpp ] + [ run sp_array_cast_test.cpp ] [ compile-fail array_fail_spa_sp_c.cpp ] [ compile-fail array_fail_sp_spa_c.cpp ] diff --git a/test/sp_array_cast_test.cpp b/test/sp_array_cast_test.cpp new file mode 100644 index 0000000..5af7eb5 --- /dev/null +++ b/test/sp_array_cast_test.cpp @@ -0,0 +1,202 @@ +// +// sp_array_cast_test.cpp +// +// Copyright (c) 2012 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 +{ +}; + +void static_cast_test() +{ + { + boost::shared_ptr pv; + + boost::shared_ptr pi = boost::static_pointer_cast( pv ); + BOOST_TEST( pi.get() == 0 ); + + boost::shared_ptr pi2 = boost::static_pointer_cast( pv ); + BOOST_TEST( pi2.get() == 0 ); + + boost::shared_ptr px = boost::static_pointer_cast( pv ); + BOOST_TEST( px.get() == 0 ); + + boost::shared_ptr px2 = boost::static_pointer_cast( pv ); + BOOST_TEST( px2.get() == 0 ); + } + + { + boost::shared_ptr pi( new int[2] ); + boost::shared_ptr pv( pi ); + + boost::shared_ptr pi2 = boost::static_pointer_cast( pv ); + BOOST_TEST(pi.get() == pi2.get()); + BOOST_TEST(!(pi < pi2 || pi2 < pi)); + + boost::shared_ptr pi3 = boost::static_pointer_cast( pv ); + BOOST_TEST(pi.get() == pi3.get()); + BOOST_TEST(!(pi < pi3 || pi3 < pi)); + + boost::shared_ptr pv2( pi3 ); + + boost::shared_ptr pi4 = boost::static_pointer_cast( pv2 ); + BOOST_TEST(pi.get() == pi4.get()); + BOOST_TEST(!(pi < pi4 || pi4 < pi)); + } + + { + boost::shared_ptr px( new X[4] ); + boost::shared_ptr pv( px ); + + boost::shared_ptr px2 = boost::static_pointer_cast( pv ); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + + boost::shared_ptr px3 = boost::static_pointer_cast( pv ); + BOOST_TEST(px.get() == px3.get()); + BOOST_TEST(!(px < px3 || px3 < px)); + + boost::shared_ptr pv2( px3 ); + + boost::shared_ptr px4 = boost::static_pointer_cast( pv2 ); + BOOST_TEST(px.get() == px4.get()); + BOOST_TEST(!(px < px4 || px4 < px)); + } +} + +void const_cast_test() +{ + { + boost::shared_ptr px; + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST( px2.get() == 0 ); + } + + { + boost::shared_ptr px; + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST( px2.get() == 0 ); + } + + { + boost::shared_ptr px; + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST( px2.get() == 0 ); + } + + { + boost::shared_ptr px; + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST( px2.get() == 0 ); + } + + { + boost::shared_ptr px( new int[3] ); + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + } + + { + boost::shared_ptr px( new int[3] ); + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + } + + { + boost::shared_ptr px( new X[4] ); + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + } + + { + boost::shared_ptr px( new X[4] ); + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + } +} + +void reinterpret_cast_test() +{ + { + boost::shared_ptr pi; + BOOST_TEST( pi.get() == 0 ); + + boost::shared_ptr pi2 = boost::reinterpret_pointer_cast( pi ); + BOOST_TEST( pi2.get() == 0 ); + + boost::shared_ptr pi3 = boost::reinterpret_pointer_cast( pi2 ); + BOOST_TEST( pi3.get() == 0 ); + } + + { + boost::shared_ptr px; + BOOST_TEST( px.get() == 0 ); + + boost::shared_ptr px2 = boost::reinterpret_pointer_cast( px ); + BOOST_TEST( px2.get() == 0 ); + + boost::shared_ptr px3 = boost::reinterpret_pointer_cast( px2 ); + BOOST_TEST( px3.get() == 0 ); + } + + { + boost::shared_ptr pi( new int[2] ); + + boost::shared_ptr pi2 = boost::reinterpret_pointer_cast( pi ); + BOOST_TEST(pi.get() == pi2.get()); + BOOST_TEST(!(pi < pi2 || pi2 < pi)); + + boost::shared_ptr pi3 = boost::reinterpret_pointer_cast( pi2 ); + BOOST_TEST(pi.get() == pi3.get()); + BOOST_TEST(!(pi < pi3 || pi3 < pi)); + + boost::shared_ptr pi4 = boost::reinterpret_pointer_cast( pi3 ); + BOOST_TEST(pi.get() == pi4.get()); + BOOST_TEST(!(pi < pi4 || pi4 < pi)); + } + + { + boost::shared_ptr px( new X[4] ); + + boost::shared_ptr px2 = boost::reinterpret_pointer_cast( px ); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + + boost::shared_ptr px3 = boost::reinterpret_pointer_cast( px2 ); + BOOST_TEST(px.get() == px3.get()); + BOOST_TEST(!(px < px3 || px3 < px)); + + boost::shared_ptr px4 = boost::reinterpret_pointer_cast( px3 ); + BOOST_TEST(px.get() == px4.get()); + BOOST_TEST(!(px < px4 || px4 < px)); + } +} + +int main() +{ + static_cast_test(); + const_cast_test(); + reinterpret_cast_test(); + + return boost::report_errors(); +} From 08e589451029534009bcedc37c14ba1f3465a6f5 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 5 Dec 2012 04:28:20 +0000 Subject: [PATCH 114/140] Merged revisions 81700,81703 from trunk: Add overloads of make_shared and allocate_shared for arrays for E&& where E is typename boost::detail::array_base::type ........ Update documentation and remove unused code. ........ [SVN r81716] --- .../boost/smart_ptr/allocate_shared_array.hpp | 40 +++++++++++++++++++ .../boost/smart_ptr/detail/array_deleter.hpp | 32 ++++++++++++++- .../boost/smart_ptr/detail/array_traits.hpp | 12 ++---- .../boost/smart_ptr/detail/sp_if_array.hpp | 6 +-- include/boost/smart_ptr/make_shared_array.hpp | 39 ++++++++++++++++++ make_shared_array.html | 36 ++++++++++++++++- test/allocate_shared_arrays_create_test.cpp | 27 +++++++++++++ test/make_shared_arrays_create_test.cpp | 27 +++++++++++++ 8 files changed, 203 insertions(+), 16 deletions(-) diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index 0c17edd..a98d97e 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -169,6 +169,46 @@ namespace boost { d2->construct_list(p2, p3, M); return boost::shared_ptr(s1, p1); } +#if defined(BOOST_HAS_RVALUE_REFS) + template + inline typename boost::detail::sp_if_array::type + allocate_shared(const A& allocator, std::size_t size, + typename boost::detail::array_base::type&& value) { + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; + T1* p1 = 0; + T2* p2 = 0; + std::size_t n1 = size * boost::detail::array_total::size; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1(n1); + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; + p1 = reinterpret_cast(p2); + d2 = get_deleter >(s1); + d2->construct(p2, boost::detail::sp_forward(value)); + return boost::shared_ptr(s1, p1); + } + template + inline typename boost::detail::sp_if_size_array::type + allocate_shared(const A& allocator, + typename boost::detail::array_base::type&& value) { + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; + enum { + N = boost::detail::array_total::size + }; + T1* p1 = 0; + T2* p2 = 0; + boost::detail::allocate_array_helper a1(allocator, &p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; + p1 = reinterpret_cast(p2); + d2 = get_deleter >(s1); + d2->construct(p2, boost::detail::sp_forward(value)); + return boost::shared_ptr(s1, p1); + } +#endif #endif } diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index b07b00a..40e9d57 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -38,7 +38,20 @@ namespace boost { throw; } } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if defined(BOOST_HAS_RVALUE_REFS) + void construct(T* memory, T&& value) { + std::size_t i = 0; + try { + for (object = memory; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(value); + } + } catch (...) { + destroy(i); + throw; + } + } +#if defined(BOOST_HAS_VARIADIC_TMPL) template void construct(T* memory, Args&&... args) { std::size_t i = 0; @@ -52,6 +65,7 @@ namespace boost { throw; } } +#endif #endif void construct_list(T* memory, const T* list) { std::size_t i = 0; @@ -125,7 +139,20 @@ namespace boost { throw; } } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if defined(BOOST_HAS_RVALUE_REFS) + void construct(T* memory, T&& value) { + std::size_t i = 0; + try { + for (object = memory; i < N; i++) { + void* p1 = memory + i; + ::new(p1) T(value); + } + } catch (...) { + destroy(i); + throw; + } + } +#if defined(BOOST_HAS_VARIADIC_TMPL) template void construct(T* memory, Args&&... args) { std::size_t i = 0; @@ -139,6 +166,7 @@ namespace boost { throw; } } +#endif #endif void construct_list(T* memory, const T* list) { std::size_t i = 0; diff --git a/include/boost/smart_ptr/detail/array_traits.hpp b/include/boost/smart_ptr/detail/array_traits.hpp index 3ef482a..8ef7874 100644 --- a/include/boost/smart_ptr/detail/array_traits.hpp +++ b/include/boost/smart_ptr/detail/array_traits.hpp @@ -17,19 +17,15 @@ namespace boost { struct array_base { typedef typename boost::remove_cv::type type; }; + template + struct array_base { + typedef typename array_base::type type; + }; template struct array_base { typedef typename array_base::type type; }; template - struct array_size; - template - struct array_size { - enum { - size = N - }; - }; - template struct array_total { enum { size = 1 diff --git a/include/boost/smart_ptr/detail/sp_if_array.hpp b/include/boost/smart_ptr/detail/sp_if_array.hpp index 3ba3a0e..661e178 100644 --- a/include/boost/smart_ptr/detail/sp_if_array.hpp +++ b/include/boost/smart_ptr/detail/sp_if_array.hpp @@ -14,15 +14,13 @@ namespace boost { namespace detail { template - struct sp_if_array { - }; + struct sp_if_array; template struct sp_if_array { typedef boost::shared_ptr type; }; template - struct sp_if_size_array { - }; + struct sp_if_size_array; template struct sp_if_size_array { typedef boost::shared_ptr type; diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index 89ff8f1..b4fd9f6 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -167,6 +167,45 @@ namespace boost { d2->construct_list(p2, p3, M); return boost::shared_ptr(s1, p1); } +#if defined(BOOST_HAS_RVALUE_REFS) + template + inline typename boost::detail::sp_if_array::type + make_shared(std::size_t size, + typename boost::detail::array_base::type&& value) { + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; + T1* p1 = 0; + T2* p2 = 0; + std::size_t n1 = size * boost::detail::array_total::size; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1(n1); + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; + p1 = reinterpret_cast(p2); + d2 = get_deleter >(s1); + d2->construct(p2, boost::detail::sp_forward(value)); + return boost::shared_ptr(s1, p1); + } + template + inline typename boost::detail::sp_if_size_array::type + make_shared(typename boost::detail::array_base::type&& value) { + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; + enum { + N = boost::detail::array_total::size + }; + T1* p1 = 0; + T2* p2 = 0; + boost::detail::make_array_helper a1(&p2); + boost::detail::array_deleter d1; + boost::shared_ptr s1(p1, d1, a1); + boost::detail::array_deleter* d2; + p1 = reinterpret_cast(p2); + d2 = get_deleter >(s1); + d2->construct(p2, boost::detail::sp_forward(value)); + return boost::shared_ptr(s1, p1); + } +#endif #endif template inline typename boost::detail::sp_if_array::type diff --git a/make_shared_array.html b/make_shared_array.html index b42d28a..c1db41f 100644 --- a/make_shared_array.html +++ b/make_shared_array.html @@ -75,6 +75,20 @@ template<typename T, typename A, typename... Args> shared_ptr<T[M][N]> allocate_shared(const A& allocator, const T (&list)[N]); + +#if defined(BOOST_HAS_RVALUE_REFS) + template<typename T> + shared_ptr<T[]> make_shared(size_t size, T&& value); + + template<typename T> + shared_ptr<T[N]> make_shared(T&& value); + + template<typename T, typename A> + shared_ptr<T[]> allocate_shared(const A& allocator, size_t size, T&& value); + + template<typename T, typename A> + shared_ptr<T[N]> allocate_shared(const A& allocator, T&& value); +#endif #endif template<typename T> @@ -162,6 +176,22 @@ template<typename T, typename A, typename... Args> shared_ptr<T[M][N]> make_shared(const T (&list)[N]); template<typename T, typename A, typename... Args> shared_ptr<T[M][N]> allocate_shared(const A& allocator, const T (&list)[N]); +
    +

    Description: These overloads of the utilities above are for a + fixed size array.

    +
    +
    template<typename T>
    +    shared_ptr<T[]> make_shared(size_t size, T&& value);
    +template<typename T, typename A>
    +    shared_ptr<T[]> allocate_shared(const A& allocator, size_t size, T&& value);
    +
    +

    Description: These overloads initialize array elements with + the given value.

    +
    +
    template<typename T>
    +    shared_ptr<T[N]> make_shared(T&& value);
    +template<typename T, typename A>
    +    shared_ptr<T[N]> allocate_shared(const A& allocator, T&& value);

    Description: These overloads of the utilities above are for a fixed size array.

    @@ -188,8 +218,10 @@ boost::shared_ptr<int[]> a4 = boost::make_shared<int[]>({1, 2, 3}); boost::shared_ptr<int[3]> a5 = boost::make_shared<int[3]>({1, 2, 3}); boost::shared_ptr<int[][3]> a6 = boost::make_shared<int[][3]>(size, {1, 2, 3}); boost::shared_ptr<int[5][3]> a7 = boost::make_shared<int[5][3]>({1, 2, 3}); -boost::shared_ptr<int[]> a8 = boost::make_shared_noinit<int[]>(size); -boost::shared_ptr<int[5]> a9 = boost::make_shared_noinit<int[5]>(); +boost::shared_ptr<point[]> a8 = boost::make_shared<point[]>(size, {x, y}); +boost::shared_ptr<point[5]> a9 = boost::make_shared<point[5]>({x, y}); +boost::shared_ptr<int[]> a10 = boost::make_shared_noinit<int[]>(size); +boost::shared_ptr<int[5]> a11 = boost::make_shared_noinit<int[5]>();

    History

    November 2012. Glen Fernandes contributed implementations of diff --git a/test/allocate_shared_arrays_create_test.cpp b/test/allocate_shared_arrays_create_test.cpp index 8645179..4c53e91 100644 --- a/test/allocate_shared_arrays_create_test.cpp +++ b/test/allocate_shared_arrays_create_test.cpp @@ -9,6 +9,17 @@ #include #include +class type { +public: + type(int x, int y) + : x(x), y(y) { + } + const int x; + const int y; +private: + type& operator=(const type&); +}; + int main() { #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) { @@ -69,6 +80,22 @@ int main() { BOOST_TEST(a1[1][1][0] == 2); BOOST_TEST(a1[1][1][1] == 3); } +#if defined(BOOST_HAS_RVALUE_REFS) + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 4, {1, 2}); + BOOST_TEST(a1[0].x == 1); + BOOST_TEST(a1[1].y == 2); + BOOST_TEST(a1[2].x == 1); + BOOST_TEST(a1[3].y == 2); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), {1, 2}); + BOOST_TEST(a1[0].x == 1); + BOOST_TEST(a1[1].y == 2); + BOOST_TEST(a1[2].x == 1); + BOOST_TEST(a1[3].y == 2); + } +#endif #endif return boost::report_errors(); } diff --git a/test/make_shared_arrays_create_test.cpp b/test/make_shared_arrays_create_test.cpp index eb08759..7fc36bd 100644 --- a/test/make_shared_arrays_create_test.cpp +++ b/test/make_shared_arrays_create_test.cpp @@ -9,6 +9,17 @@ #include #include +class type { +public: + type(int x, int y) + : x(x), y(y) { + } + const int x; + const int y; +private: + type& operator=(const type&); +}; + int main() { #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) { @@ -69,6 +80,22 @@ int main() { BOOST_TEST(a1[1][1][0] == 2); BOOST_TEST(a1[1][1][1] == 3); } +#if defined(BOOST_HAS_RVALUE_REFS) + { + boost::shared_ptr a1 = boost::make_shared(4, {1, 2}); + BOOST_TEST(a1[0].x == 1); + BOOST_TEST(a1[1].y == 2); + BOOST_TEST(a1[2].x == 1); + BOOST_TEST(a1[3].y == 2); + } + { + boost::shared_ptr a1 = boost::make_shared({1, 2}); + BOOST_TEST(a1[0].x == 1); + BOOST_TEST(a1[1].y == 2); + BOOST_TEST(a1[2].x == 1); + BOOST_TEST(a1[3].y == 2); + } +#endif #endif return boost::report_errors(); } From c03bfd0b4d2b57cf6771162c3e2d84dc6d8164cd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 8 Dec 2012 00:57:04 +0000 Subject: [PATCH 115/140] Merged revision(s) 81730-81731, 81776 from trunk: Fix get_pointer for the array case, add operator= for unique_ptr, update auto_ptr signatures to use rvalue reference when available. ........ Update shared_ptr.htm. ........ Add more unique_ptr tests. ........ [SVN r81781] --- include/boost/smart_ptr/shared_ptr.hpp | 45 +- shared_ptr.htm | 968 +++++++++++++------------ test/sp_unique_ptr_test.cpp | 87 +++ 3 files changed, 644 insertions(+), 456 deletions(-) diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 3e2e1d2..e472d12 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -418,17 +418,30 @@ public: #ifndef BOOST_NO_AUTO_PTR template - explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn() + explicit shared_ptr( std::auto_ptr & r ): px(r.get()), pn() { boost::detail::sp_assert_convertible< Y, T >(); Y * tmp = r.get(); - pn = boost::detail::shared_count(r); + pn = boost::detail::shared_count( r ); boost::detail::sp_deleter_construct( this, tmp ); } -#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) +#if defined( BOOST_HAS_RVALUE_REFS ) + + template + shared_ptr( std::auto_ptr && r ): px(r.get()), pn() + { + boost::detail::sp_assert_convertible< Y, T >(); + + Y * tmp = r.get(); + pn = boost::detail::shared_count( r ); + + boost::detail::sp_deleter_construct( this, tmp ); + } + +#elif !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() @@ -486,11 +499,20 @@ public: template shared_ptr & operator=( std::auto_ptr & r ) { - this_type(r).swap(*this); + this_type( r ).swap( *this ); return *this; } -#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) +#if defined( BOOST_HAS_RVALUE_REFS ) + + template + shared_ptr & operator=( std::auto_ptr && r ) + { + this_type( static_cast< std::auto_ptr && >( r ) ).swap( *this ); + return *this; + } + +#elif !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 ) @@ -503,6 +525,17 @@ public: #endif // BOOST_NO_AUTO_PTR +#if !defined( BOOST_NO_CXX11_SMART_PTR ) + + template + shared_ptr & operator=( std::unique_ptr && r ) + { + this_type( static_cast< std::unique_ptr && >( r ) ).swap(*this); + return *this; + } + +#endif + // Move support #if defined( BOOST_HAS_RVALUE_REFS ) @@ -730,7 +763,7 @@ template shared_ptr reinterpret_pointer_cast( shared_ptr // get_pointer() enables boost::mem_fn to recognize shared_ptr -template inline T * get_pointer(shared_ptr const & p) BOOST_NOEXCEPT +template inline typename shared_ptr::element_type * get_pointer(shared_ptr const & p) BOOST_NOEXCEPT { return p.get(); } diff --git a/shared_ptr.htm b/shared_ptr.htm index 77e1fa8..87e61b4 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -2,410 +2,496 @@ shared_ptr - + - -

    boost.png (6897 bytes)shared_ptr class template

    -

    Introduction
    - Best Practices
    - Synopsis
    - Members
    - Free Functions
    - Example
    - Handle/Body Idiom
    - Thread Safety
    - Frequently Asked Questions
    - Smart Pointer Timings
    - Programming Techniques

    -

    Introduction

    -

    The shared_ptr class template stores a pointer to a dynamically allocated - object, typically with a C++ new-expression. The object pointed to is - guaranteed to be deleted when the last shared_ptr pointing to it is - destroyed or reset. See the example.

    -

    Every shared_ptr meets the CopyConstructible and Assignable - requirements of the C++ Standard Library, and so can be used in standard - library containers. Comparison operators are supplied so that shared_ptr + +

    boost::shared_ptr class template

    +

    Introduction
    + Best Practices
    + Synopsis
    + Members
    + Free Functions
    + Example
    + Handle/Body Idiom
    + Thread Safety
    + Frequently Asked Questions
    + Smart Pointer Timings
    + Programming Techniques

    +

    Introduction

    +

    The shared_ptr class template stores a pointer to a dynamically allocated + object, typically with a C++ new-expression. The object pointed to is + guaranteed to be deleted when the last shared_ptr pointing to it is + destroyed or reset.

    +
    Example:
    shared_ptr<X> p1( new X );
    +shared_ptr<void> p2( new int(5) );
    +
    + +

    shared_ptr deletes the exact pointer that has been passed at construction time, + complete with its original type, regardless of the template parameter. In the second example above, + when p2 is destroyed or reset, it will call delete on the original int* + that has been passed to the constructor, even though p2 itself is of type + shared_ptr<void> and stores a pointer of type void*.

    + +

    Every shared_ptr meets the CopyConstructible, MoveConstructible, + CopyAssignable and MoveAssignable + requirements of the C++ Standard Library, and can be used in standard + library containers. Comparison operators are supplied so that shared_ptr works with the standard library's associative containers.

    -

    Normally, a shared_ptr cannot correctly hold a pointer to a dynamically - allocated array. See shared_array for - that usage.

    -

    Because the implementation uses reference counting, cycles of shared_ptr instances - will not be reclaimed. For example, if main() holds a shared_ptr to - A, which directly or indirectly holds a shared_ptr back to A, - A's use count will be 2. Destruction of the original shared_ptr will - leave A dangling with a use count of 1. Use weak_ptr +

    Because the implementation uses reference counting, cycles of shared_ptr instances + will not be reclaimed. For example, if main() holds a shared_ptr to + A, which directly or indirectly holds a shared_ptr back to A, + A's use count will be 2. Destruction of the original shared_ptr will + leave A dangling with a use count of 1. Use weak_ptr to "break cycles."

    -

    The class template is parameterized on T, the type of the object pointed - to. shared_ptr and most of its member functions place no - requirements on T; it is allowed to be an incomplete type, or - void. Member functions that do place additional requirements (constructors, - reset) are explicitly documented below.

    -

    shared_ptr<T> can be implicitly converted to shared_ptr<U> - whenever T* can be implicitly converted to U*. - In particular, shared_ptr<T> is implicitly convertible - to shared_ptr<T const>, to shared_ptr<U> - where U is an accessible base of T, and to - shared_ptr<void>.

    -

    shared_ptr is now part of TR1, the first C++ - Library Technical Report. The latest draft of TR1 is available - at the following location:

    -

    http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf - (1.36Mb PDF)

    -

    This implementation conforms to the TR1 specification, with the only exception - that it resides in namespace boost instead of std::tr1.

    -

    Best Practices

    -

    A simple guideline that nearly eliminates the possibility of memory leaks is: - always use a named smart pointer variable to hold the result of new. - Every occurence of the new keyword in the code should have the - form:

    -
    shared_ptr<T> p(new Y);
    -

    It is, of course, acceptable to use another smart pointer in place of shared_ptr - above; having T and Y be the same type, or - passing arguments to Y's constructor is also OK.

    -

    If you observe this guideline, it naturally follows that you will have no - explicit deletes; try/catch constructs will - be rare.

    -

    Avoid using unnamed shared_ptr temporaries to save typing; to - see why this is dangerous, consider this example:

    -
    void f(shared_ptr<int>, int);
    +		

    The class template is parameterized on T, the type of the object pointed + to. shared_ptr and most of its member functions place no + requirements on T; it is allowed to be an incomplete type, or + void. Member functions that do place additional requirements (constructors, + reset) are explicitly documented below.

    +

    shared_ptr<T> can be implicitly converted to shared_ptr<U> + whenever T* can be implicitly converted to U*. + In particular, shared_ptr<T> is implicitly convertible + to shared_ptr<T const>, to shared_ptr<U> + where U is an accessible base of T, and to + shared_ptr<void>.

    +

    shared_ptr is now part of the C++11 Standard, as std::shared_ptr.

    +

    Starting with Boost release 1.53, shared_ptr can be used to hold a pointer to a dynamically + allocated array. This is accomplished by using an array type (T[] or T[N]) as + the template parameter. There is almost no difference between using an unsized array, T[], + and a sized array, T[N]; the latter just enables operator[] to perform a range check + on the index.

    +
    Example:
    shared_ptr<double[1024]> p1( new double(1024) );
    +shared_ptr<double[]> p2( new double(n) );
    +
    + +

    Best Practices

    +

    A simple guideline that nearly eliminates the possibility of memory leaks is: + always use a named smart pointer variable to hold the result of new. + Every occurence of the new keyword in the code should have the + form:

    +
    shared_ptr<T> p(new Y);
    +

    It is, of course, acceptable to use another smart pointer in place of shared_ptr + above; having T and Y be the same type, or + passing arguments to Y's constructor is also OK.

    +

    If you observe this guideline, it naturally follows that you will have no + explicit delete statements; try/catch constructs will + be rare.

    +

    Avoid using unnamed shared_ptr temporaries to save typing; to + see why this is dangerous, consider this example:

    +
    void f(shared_ptr<int>, int);
     int g();
     
     void ok()
     {
    -    shared_ptr<int> p(new int(2));
    -    f(p, g());
    +    shared_ptr<int> p( new int(2) );
    +    f( p, g() );
     }
     
     void bad()
     {
    -    f(shared_ptr<int>(new int(2)), g());
    +    f( shared_ptr<int>( new int(2) ), g() );
     }
    -
    -

    The function ok follows the guideline to the letter, whereas - bad constructs the temporary shared_ptr in place, +

    +

    The function ok follows the guideline to the letter, whereas + bad constructs the temporary shared_ptr in place, admitting the possibility of a memory leak. Since function arguments are - evaluated in unspecified order, it is possible for new int(2) to - be evaluated first, g() second, and we may never get to the - shared_ptr constructor if g throws an exception. - See Herb Sutter's treatment (also - here) of the issue for more information.

    -

    The exception safety problem described above may also be eliminated by using + evaluated in unspecified order, it is possible for new int(2) to + be evaluated first, g() second, and we may never get to the + shared_ptrconstructor if g throws an exception. + See Herb Sutter's treatment (also + here) of the issue for more information.

    +

    The exception safety problem described above may also be eliminated by using the make_shared or allocate_shared - factory functions defined in boost/make_shared.hpp. These factory functions also provide - an efficiency benefit by consolidating allocations.

    -

    Synopsis

    + factory functions defined in boost/make_shared.hpp. + These factory functions also provide an efficiency benefit by consolidating allocations.

    +

    Synopsis

    namespace boost {
     
       class bad_weak_ptr: public std::exception;
     
    -  template<class T> class weak_ptr;
    +  template<class T> class weak_ptr;
     
       template<class T> class shared_ptr {
     
         public:
     
    -      typedef T element_type;
    +      typedef see below element_type;
     
    -      shared_ptr(); // never throws
    -      template<class Y> explicit shared_ptr(Y * p);
    -      template<class Y, class D> shared_ptr(Y * p, D d);
    -      template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
    -      ~shared_ptr(); // never throws
    +      shared_ptr(); // never throws
     
    -      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);
    +      template<class Y> explicit shared_ptr(Y * p);
    +      template<class Y, class D> shared_ptr(Y * p, D d);
    +      template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
     
    -      shared_ptr & operator=(shared_ptr const & r); // never throws
    -      template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
    -      template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
    +      ~shared_ptr(); // never throws
     
    -      void reset(); // never throws
    -      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
    +      shared_ptr(shared_ptr const & r); // never throws
    +      template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
     
    -      T & operator*() const; // never throws
    -      T * operator->() const; // never throws
    -      T * get() const; // never throws
    +      shared_ptr(shared_ptr && r); // never throws
    +      template<class Y> shared_ptr(shared_ptr<Y> && r); // never throws
     
    -      bool unique() const; // never throws
    -      long use_count() const; // never throws
    +      template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p); // never throws
     
    -      operator unspecified-bool-type() const; // never throws
    +      template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
     
    -      void swap(shared_ptr & b); // never throws
    +      template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
    +      template<class Y> shared_ptr(std::auto_ptr<Y> && r);
    +
    +      template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
    +
    +      shared_ptr & operator=(shared_ptr const & r); // never throws
    +      template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
    +
    +      shared_ptr & operator=(shared_ptr const && r); // never throws
    +      template<class Y> shared_ptr & operator=(shared_ptr<Y> const && r); // never throws
    +
    +      template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
    +      template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r);
    +
    +      template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);
    +
    +      void reset(); // never throws
    +
    +      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, element_type * p); // never throws
    +
    +      T & operator*() const; // never throws; only valid when T is not an array type
    +      T * operator->() const; // never throws; only valid when T is not an array type
    +
    +      element_type & operator[]( std::ptrdiff_t i ) const; // never throws; only valid when T is an array type
    +
    +      element_type * get() const; // never throws
    +
    +      bool unique() const; // never throws
    +      long use_count() const; // never throws
    +
    +      operator unspecified-bool-type() const; // never throws
    +
    +      void swap(shared_ptr & b); // never throws
    +      
    +      template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const; // never throws
    +      template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const; // never throws
       };
     
       template<class T, class U>
    -    bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
    +    bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
     
       template<class T, class U>
    -    bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
    +    bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
     
       template<class T, class U>
    -    bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
    +    bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
     
    -  template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
    +  template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
     
    -  template<class T> T * get_pointer(shared_ptr<T> const & p); // never throws
    +  template<class T> typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p); // never throws
     
       template<class T, class U>
    -    shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws
    +    shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws
     
       template<class T, class U>
    -    shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws
    +    shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws
     
       template<class T, class U>
    -    shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r); // never throws
    +    shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r); // never throws
    +
    +  template<class T, class U>
    +    shared_ptr<T> reinterpet_pointer_cast(shared_ptr<U> const & r); // never throws
     
       template<class E, class T, class Y>
    -    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
    +    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
     
       template<class D, class T>
    -    D * get_deleter(shared_ptr<T> const & p);
    +    D * get_deleter(shared_ptr<T> const & p);
     }
    -

    Members

    -

    element_type

    -
    typedef T element_type;
    +

    Members

    +

    element_type

    +
    typedef ... element_type;
    -

    Provides the type of the template parameter T.

    +

    element_type is T when T is not an array type, + and U when T is U[] or U[N].

    -

    constructors

    +

    default constructor

    shared_ptr(); // never throws
    -

    Effects: Constructs an empty shared_ptr.

    +

    Effects: Constructs an empty shared_ptr.

    Postconditions: use_count() == 0 && get() == 0.

    Throws: nothing.

    -

    [The nothrow guarantee is important, since reset() is specified +

    [The nothrow guarantee is important, since reset() is specified in terms of the default constructor; this implies that the constructor must not - allocate memory.]

    + allocate memory.]

    +

    pointer constructor

    template<class Y> explicit shared_ptr(Y * p);
    -

    Requirements: p must be convertible to T *. Y - must be a complete type. The expression delete p must be - well-formed, must not invoke undefined behavior, and must not throw exceptions. +

    Requirements: + Y must be a complete type. + The expression delete[] p, when T is an array type, or delete p, + when T is not an array type, + must be well-formed, must not invoke undefined behavior, and must not throw exceptions. + When T is U[N], Y (*) [N] must be convertible to T*; + when T is U[], Y (*) [] must be convertible to T*; + otherwise, Y* must be convertible to T*.

    -

    Effects: Constructs a shared_ptr that owns the pointer p.

    +

    Effects: + When T is not an array type, constructs a shared_ptr that owns + the pointer p. + Otherwise, constructs a shared_ptr that owns + p and a deleter of an unspecified type that calls delete[] p.

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

    -

    Throws: std::bad_alloc, or an implementation-defined +

    Throws: std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    -

    Exception safety: If an exception is thrown, delete p is - called.

    -

    Notes: p must be a pointer to an object that was - allocated via a C++ new expression or be 0. The postcondition that - use count is 1 holds even if p is 0; invoking delete - on a pointer that has a value of 0 is harmless.

    +

    Exception safety: If an exception is thrown, the constructor calls + delete[] p, when T is an array type, + or delete p, when T is not an array type.

    +

    Notes: p must be a pointer to an object that was + allocated via a C++ new expression or be 0. The postcondition that + use count is 1 holds even if p is 0; invoking delete + on a pointer that has a value of 0 is harmless.

    -

    [This constructor has been changed to a template in order to remember the actual - pointer type passed. The destructor will call delete with the - same pointer, complete with its original type, even when T does - not have a virtual destructor, or is void.

    -

    The optional intrusive counting support has been dropped as it exposes too much - implementation details and doesn't interact well with weak_ptr. - The current implementation uses a different mechanism, - enable_shared_from_this, to solve the "shared_ptr from - this" problem.]

    - +

    [This constructor is a template in order to remember the actual + pointer type passed. The destructor will call delete with the + same pointer, complete with its original type, even when T does + not have a virtual destructor, or is void.]

    +

    constructors taking a deleter

    template<class Y, class D> shared_ptr(Y * p, D d);
     template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
    -

    Requirements: p must be convertible to T *. D - must be CopyConstructible. The copy constructor and destructor - of D must not throw. The expression d(p) must be - well-formed, must not invoke undefined behavior, and must not throw exceptions. - A must be an Allocator, as described in section 20.1.5 (Allocator - requirements) of the C++ Standard. +

    Requirements: + D must be CopyConstructible. The copy constructor and destructor + of D must not throw. The expression d(p) must be + well-formed, must not invoke undefined behavior, and must not throw exceptions. + A must be an Allocator, as described in section 20.1.5 + (Allocator requirements) of the C++ Standard. + When T is U[N], Y (*) [N] must be convertible to T*; + when T is U[], Y (*) [] must be convertible to T*; + otherwise, Y* must be convertible to T*.

    -

    Effects: Constructs a shared_ptr that owns the pointer - p and the deleter d. The second constructor allocates - memory using a copy of a.

    +

    Effects: Constructs a shared_ptr that owns the pointer + p and the deleter d. The second constructor allocates + memory using a copy of a.

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

    -

    Throws: std::bad_alloc, or an implementation-defined +

    Throws: std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    Exception safety: If an exception is thrown, d(p) is called.

    -

    Notes: When the the time comes to delete the object pointed to by p, - the stored copy of d is invoked with the stored copy of p +

    Notes: When the the time comes to delete the object pointed to by p, + the stored copy of d is invoked with the stored copy of p as an argument.

    -

    [Custom deallocators allow a factory function returning a shared_ptr +

    [Custom deallocators allow a factory function returning a shared_ptr to insulate the user from its memory allocation strategy. Since the deallocator is not part of the type, changing the allocation strategy does not break source or binary compatibility, and does not require a client recompilation. For - example, a "no-op" deallocator is useful when returning a shared_ptr - to a statically allocated object, and other variations allow a shared_ptr - to be used as a wrapper for another smart pointer, easing interoperability.

    -

    The support for custom deallocators does not impose significant overhead. Other - shared_ptr features still require a deallocator to be kept.

    -

    The requirement that the copy constructor of D does not throw comes from - the pass by value. If the copy constructor throws, the pointer is leaked. - Removing the requirement requires a pass by (const) reference.

    -

    The main problem with pass by reference lies in its interaction with rvalues. A - const reference may still cause a copy, and will require a const operator(). A - non-const reference won't bind to an rvalue at all. A good solution to this - problem is the rvalue reference proposed in - N1377/N1385.]

    + example, a "no-op" deallocator is useful when returning a shared_ptr + to a statically allocated object, and other variations allow a shared_ptr + to be used as a wrapper for another smart pointer, easing interoperability.

    +

    The support for custom deallocators does not impose significant overhead. Other + shared_ptr features still require a deallocator to be kept.

    +

    The requirement that the copy constructor of D does not throw comes from + the pass by value. If the copy constructor throws, the pointer would leak.]

    +

    copy and converting constructors

    shared_ptr(shared_ptr const & r); // never throws
     template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
    -

    Effects: If r is empty, constructs an empty shared_ptr; - otherwise, constructs a shared_ptr that shares ownership with r.

    +

    Requires: Y* should be convertible to T*.

    +

    Effects: If r is empty, constructs an empty shared_ptr; + otherwise, constructs a shared_ptr that shares ownership with r.

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

    Throws: nothing.

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

    move constructors

    +
    shared_ptr(shared_ptr && r); // never throws
    +template<class Y> shared_ptr(shared_ptr<Y> && r); // never throws
    -

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

    +

    Requires: Y* should be convertible to T*.

    +

    Effects: Move-constructs a shared_ptr from r.

    +

    Postconditions: *this contains the old value of r. r is empty and r.get() == 0.

    +

    Throws: nothing.

    +
    +

    aliasing constructor

    +
    template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * 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);
    +

    weak_ptr constructor

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

    Effects: Constructs a shared_ptr that shares ownership with - r and stores a copy of the pointer stored in r.

    +

    Requires: Y* should be convertible to T*.

    +

    Effects: Constructs a shared_ptr that shares ownership with + r and stores a copy of the pointer stored in r.

    Postconditions: use_count() == r.use_count().

    -

    Throws: bad_weak_ptr when r.use_count() == 0.

    +

    Throws: bad_weak_ptr when r.use_count() == 0.

    Exception safety: If an exception is thrown, the constructor has no effect.

    -
    template<class Y> shared_ptr(std::auto_ptr<Y> & r);
    -
    -

    Effects: Constructs a shared_ptr, as if by storing a copy of r.release().

    +

    auto_ptr constructors

    +
    template<class Y> shared_ptr(std::auto_ptr<Y> & r);
    +template<class Y> shared_ptr(std::auto_ptr<Y> && r);
    +
    +

    Requires: Y* should be convertible to T*.

    +

    Effects: Constructs a shared_ptr, as if by storing a copy of r.release().

    Postconditions: use_count() == 1.

    -

    Throws: std::bad_alloc, or an implementation-defined +

    Throws: std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    -

    Exception safety: If an exception is thrown, the constructor has no - effect.

    -
    -

    [This constructor takes a the source auto_ptr by reference and - not by value, and cannot accept auto_ptr temporaries. This is - by design, as the constructor offers the strong guarantee; an rvalue reference - would solve this problem, too.]

    -

    destructor

    +

    Exception safety: If an exception is thrown, the constructor has no + effect.

    +
    +

    unique_ptr constructor

    +
    template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
    +
    +

    Requires: Y* should be convertible to T*.

    +

    Effects: + Equivalent to shared_ptr( r.release(), r.get_deleter() ) when D is not a reference type. + Otherwise, equivalent to shared_ptr( r.release(), del ), where del is a deleter + that stores the reference rd returned from r.get_deleter() and del(p) calls rd(p).

    +

    Postconditions: use_count() == 1.

    +

    Throws: std::bad_alloc, or an implementation-defined + exception when a resource other than memory could not be obtained.

    +

    Exception safety: If an exception is thrown, the constructor has no + effect.

    +
    +

    destructor

    ~shared_ptr(); // never throws
    -
    -

    Effects:

    -
      -
    • - If *this is empty, or shares ownership with - another shared_ptr instance (use_count() > 1), - there are no side effects. -
    • - Otherwise, if *this owns a pointer p - and a deleter d, d(p) - is called. -
    • - Otherwise, *this owns a pointer p, - and delete p is called.
    -

    Throws: nothing.

    -
    -

    assignment

    +
    +

    Effects:

    +
      +
    • + If *this is empty, or shares ownership with + another shared_ptr instance (use_count() > 1), + there are no side effects.
    • +
    • + Otherwise, if *this owns a pointer p + and a deleter d, d(p) + is called.
    • +
    • + Otherwise, *this owns a pointer p, + and delete p is called.
    • +
    +

    Throws: nothing.

    +
    +

    assignment

    shared_ptr & operator=(shared_ptr const & r); // never throws
     template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
     template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
    -
    -

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

    -

    Returns: *this.

    -

    Notes: The use count updates caused by the temporary object construction +

    +

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

    +

    Returns: *this.

    +

    Notes: The use count updates caused by the temporary object construction and destruction are not considered observable side effects, and the implementation is free to meet the effects (and the implied guarantees) via - different means, without creating a temporary. In particular, in the example:

    + different means, without creating a temporary. In particular, in the example:

    shared_ptr<int> p(new int);
     shared_ptr<void> q(p);
     p = p;
     q = p;
     

    both assignments may be no-ops.

    -
    -

    reset

    +
    +
    shared_ptr & operator=(shared_ptr && r); // never throws
    +template<class Y> shared_ptr & operator=(shared_ptr<Y> && r); // never throws
    +template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r);
    +template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);
    +
    +

    Effects: Equivalent to shared_ptr( std::move(r) ).swap(*this).

    +

    Returns: *this.

    +
    +

    reset

    void reset(); // never throws
    -
    -

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

    -
    +
    +

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

    +
    template<class Y> void reset(Y * p);
    -
    -

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

    -
    +
    +

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

    +
    template<class Y, class D> void reset(Y * p, D d);
    -
    -

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

    -
    +
    +

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

    +
    template<class Y, class D, class A> void reset(Y * p, D d, A a);
    -
    -

    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

    +
    +

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

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

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

    +
    +

    indirection

    T & operator*() const; // never throws
    -

    Requirements: The stored pointer must not be 0.

    +

    Requirements: T should not be an array type. The stored pointer must not be 0.

    Returns: a reference to the object pointed to by the stored pointer.

    Throws: nothing.

    T * operator->() const; // never throws
    -

    Requirements: The stored pointer must not be 0.

    +

    Requirements: T should not be an array type. The stored pointer must not be 0.

    Returns: the stored pointer.

    Throws: nothing.

    -

    get

    -
    T * get() const; // never throws
    +
    element_type & operator[]( std::ptrdiff_t i ) const; // never throws
    +
    +

    Requirements: T should be an array type. The stored pointer must not be 0. + i >= 0. If T is U[N], i < N.

    +

    Returns: get()[ i ].

    +

    Throws: nothing.

    +
    +

    get

    +
    element_type * get() const; // never throws

    Returns: the stored pointer.

    Throws: nothing.

    -

    unique

    +

    unique

    bool unique() const; // never throws

    Returns: use_count() == 1.

    Throws: nothing.

    -

    Notes: unique() may be faster than use_count(). +

    Notes: unique() may be faster than use_count(). If you are using unique() to implement copy on write, do not rely - on a specific value when the stored pointer is zero.

    + on a specific value when the stored pointer is zero.

    -

    use_count

    +

    use_count

    long use_count() const; // never throws
    -

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

    +

    Returns: the number of shared_ptr objects, *this included, + 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.

    +

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

    -

    conversions

    +

    conversions

    operator unspecified-bool-type () const; // never throws

    Returns: an unspecified value that, when used in boolean contexts, is equivalent to get() != 0.

    Throws: nothing.

    -

    Notes: This conversion operator allows shared_ptr objects to be +

    Notes: This conversion operator allows shared_ptr objects to be used in boolean contexts, like if (p && p->valid()) {}. The actual target type is typically a pointer to a member function, avoiding - many of the implicit conversion pitfalls.

    + many of the implicit conversion pitfalls.

    -

    [The conversion to bool is not merely syntactic sugar. It allows shared_ptrs - to be declared in conditions when using dynamic_pointer_cast - or weak_ptr::lock.]

    -

    swap

    +

    [The conversion to bool is not merely syntactic sugar. It allows shared_ptrs + to be declared in conditions when using dynamic_pointer_cast + or weak_ptr::lock.]

    +

    swap

    void swap(shared_ptr & b); // never throws

    Effects: Exchanges the contents of the two smart pointers.

    Throws: nothing.

    -

    Free Functions

    -

    comparison

    +

    Free Functions

    +

    comparison

    template<class T, class U>
       bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
    @@ -422,147 +508,143 @@ q = p; bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

    Returns: an unspecified value such that

    -
      -
    • - operator< is a strict weak ordering as described in section 25.3 [lib.alg.sorting] - of the C++ standard; -
    • - under the equivalence relation defined by operator<, !(a - < b) && !(b < a), two shared_ptr instances - are equivalent if and only if they share ownership or are both empty.
    +
      +
    • + operator< is a strict weak ordering as described in section 25.3 [lib.alg.sorting] + of the C++ standard;
    • +
    • + under the equivalence relation defined by operator<, !(a + < b) && !(b < a), two shared_ptr instances + are equivalent if and only if they share ownership or are both empty.

    Throws: nothing.

    -

    Notes: Allows shared_ptr objects to be used as keys in - associative containers.

    +

    Notes: Allows shared_ptr objects to be used as keys in + associative containers.

    -

    [Operator< has been preferred over a std::less - specialization for consistency and legality reasons, as std::less - is required to return the results of operator<, and many - standard algorithms use operator< instead of std::less - for comparisons when a predicate is not supplied. Composite objects, like std::pair, - also implement their operator< in terms of their contained - subobjects' operator<.

    -

    The rest of the comparison operators are omitted by design.]

    -

    swap

    +

    [Operator< has been preferred over a std::less + specialization for consistency and legality reasons, as std::less + is required to return the results of operator<, and many + standard algorithms use operator< instead of std::less + for comparisons when a predicate is not supplied. Composite objects, like std::pair, + also implement their operator< in terms of their contained + subobjects' operator<.

    +

    The rest of the comparison operators are omitted by design.]

    +

    swap

    template<class T>
       void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
    -
    -

    Effects: Equivalent to a.swap(b).

    -

    Throws: nothing.

    -

    Notes: Matches the interface of std::swap. Provided as an aid to - generic programming.

    -
    -

    [swap is defined in the same namespace as shared_ptr - as this is currently the only legal way to supply a swap function - that has a chance to be used by the standard library.]

    -

    get_pointer

    +
    +

    Effects: Equivalent to a.swap(b).

    +

    Throws: nothing.

    +

    Notes: Matches the interface of std::swap. Provided as an aid to + generic programming.

    +
    +

    [swap is defined in the same namespace as shared_ptr + as this is currently the only legal way to supply a swap function + that has a chance to be used by the standard library.]

    +

    get_pointer

    template<class T>
    -  T * get_pointer(shared_ptr<T> const & p); // never throws
    -
    -

    Returns: p.get().

    -

    Throws: nothing.

    -

    Notes: Provided as an aid to generic programming. Used by - mem_fn.

    -
    -

    static_pointer_cast

    + typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p); // never throws +
    +

    Returns: p.get().

    +

    Throws: nothing.

    +

    Notes: Provided as an aid to generic programming. Used by + mem_fn.

    +
    +

    static_pointer_cast

    template<class T, class U>
       shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws
    -
    -

    Requires: The expression static_cast<T*>(r.get()) - must be well-formed.

    -

    Returns: If r is empty, an empty shared_ptr<T>; - otherwise, a shared_ptr<T> object that stores a copy of - static_cast<T*>(r.get()) and shares ownership with r.

    -

    Throws: nothing.

    -

    Notes: the seemingly equivalent expression

    -

    shared_ptr<T>(static_cast<T*>(r.get()))

    -

    will eventually result in undefined behavior, attempting to delete the same +

    +

    Requires: The expression static_cast<T*>( (U*)0 ) + must be well-formed.

    +

    Returns: shared_ptr<T>( r, static_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

    +

    Throws: nothing.

    +

    Notes: the seemingly equivalent expression + shared_ptr<T>(static_cast<T*>(r.get())) + will eventually result in undefined behavior, attempting to delete the same object twice.

    -
    -

    const_pointer_cast

    +
    +

    const_pointer_cast

    template<class T, class U>
       shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws
    -
    -

    Requires: The expression const_cast<T*>(r.get()) - must be well-formed.

    -

    Returns: If r is empty, an empty shared_ptr<T>; - otherwise, a shared_ptr<T> object that stores a copy of - const_cast<T*>(r.get()) and shares ownership with r.

    -

    Throws: nothing.

    -

    Notes: the seemingly equivalent expression

    -

    shared_ptr<T>(const_cast<T*>(r.get()))

    -

    will eventually result in undefined behavior, attempting to delete the same - object twice.

    -
    -

    dynamic_pointer_cast

    +
    +

    Requires: The expression const_cast<T*>( (U*)0 ) + must be well-formed.

    +

    Returns: shared_ptr<T>( r, const_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

    +

    Throws: nothing.

    +
    +

    dynamic_pointer_cast

    template<class T, class U>
       shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r);
    -
    -

    Requires: The expression dynamic_cast<T*>(r.get()) - must be well-formed and its behavior defined.

    -

    Returns:

    -
      -
    • - When dynamic_cast<T*>(r.get()) returns a nonzero value, a - shared_ptr<T> object that stores a copy of it and shares - ownership with r; -
    • - Otherwise, an empty shared_ptr<T> object.
    -

    Throws: nothing.

    -

    Notes: the seemingly equivalent expression

    -

    shared_ptr<T>(dynamic_cast<T*>(r.get()))

    -

    will eventually result in undefined behavior, attempting to delete the same - object twice.

    -
    -

    operator<<

    +
    +

    Requires: The expression dynamic_cast<T*>( (U*)0 ) + must be well-formed.

    +

    Returns:

    +
      +
    • + When dynamic_cast<typename shared_ptr<T>::element_type*>(r.get()) returns a nonzero value p, + shared_ptr<T>(r, p);
    • +
    • + Otherwise, shared_ptr<T>().
    +

    Throws: nothing.

    +
    +

    reinterpret_pointer_cast

    +
    template<class T, class U>
    +  shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r); // never throws
    +
    +

    Requires: The expression reinterpret_cast<T*>( (U*)0 ) + must be well-formed.

    +

    Returns: shared_ptr<T>( r, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

    +

    Throws: nothing.

    +
    +

    operator<<

    template<class E, class T, class Y>
         std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
    -
    -

    Effects: os << p.get();.

    -

    Returns: os.

    -
    -

    get_deleter

    +
    +

    Effects: os << p.get();.

    +

    Returns: os.

    +
    +

    get_deleter

    template<class D, class T>
         D * get_deleter(shared_ptr<T> const & 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 - complete example program. The program builds a std::vector and std::set - of shared_ptr objects.

    -

    Note that after the containers have been populated, some of the shared_ptr +

    +

    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 + complete example program. The program builds a std::vector and std::set + of shared_ptr objects.

    +

    Note that after the containers have been populated, some of the shared_ptr objects will have a use count of 1 rather than a use count of 2, since the set - is a std::set rather than a std::multiset, and thus does not + is a std::set rather than a std::multiset, and thus does not contain duplicate entries. Furthermore, the use count may be even higher at - various times while push_back and insert container operations are + various times while push_back and insert container operations are performed. More complicated yet, the container operations may throw exceptions under a variety of circumstances. Getting the memory management and exception handling in this example right without a smart pointer would be a nightmare.

    -

    Handle/Body Idiom

    -

    One common usage of shared_ptr is to implement a handle/body (also called +

    Handle/Body Idiom

    +

    One common usage of shared_ptr is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) in the header file.

    -

    The shared_ptr_example2_test.cpp - sample program includes a header file, shared_ptr_example2.hpp, - which uses a shared_ptr<> to an incomplete type to hide the +

    The shared_ptr_example2_test.cpp + sample program includes a header file, shared_ptr_example2.hpp, + which uses a shared_ptr to an incomplete type to hide the implementation. The instantiation of member functions which require a complete - type occurs in the shared_ptr_example2.cpp + type occurs in the shared_ptr_example2.cpp implementation file. Note that there is no need for an explicit destructor. - Unlike ~scoped_ptr, ~shared_ptr does not require that T be a complete + Unlike ~scoped_ptr, ~shared_ptr does not require that T be a complete type.

    -

    Thread Safety

    -

    shared_ptr objects offer the same level of thread safety as - built-in types. A shared_ptr instance can be "read" (accessed - using only const operations) simultaneously by multiple threads. Different shared_ptr - instances can be "written to" (accessed using mutable operations such as operator= - or reset) simultaneosly by multiple threads (even +

    Thread Safety

    +

    shared_ptr objects offer the same level of thread safety as + built-in types. A shared_ptr instance can be "read" (accessed + using only const operations) simultaneously by multiple threads. Different shared_ptr + instances can be "written to" (accessed using mutable operations such as operator= + or reset) simultaneosly by multiple threads (even when these instances are copies, and share the same reference count underneath.)

    -

    Any other simultaneous accesses result in undefined behavior.

    -

    Examples:

    +

    Any other simultaneous accesses result in undefined behavior.

    +

    Examples:

    shared_ptr<int> p(new int(42));
     
     //--- Example 1 ---
    @@ -606,89 +688,78 @@ p3.reset(new int(1));
     p3.reset(new int(2)); // undefined, multiple writes
     

     

    -

    Starting with Boost release 1.33.0, shared_ptr uses a lock-free - implementation on the following platforms:

    -
      -
    • - GNU GCC on x86 or x86-64; -
    • - GNU GCC on IA64; -
    • - Metrowerks CodeWarrior on PowerPC; -
    • - GNU GCC on PowerPC; -
    • - Windows.
    -

    If your program is single-threaded and does not link to any libraries that might - have used shared_ptr in its default configuration, you can - #define the macro BOOST_SP_DISABLE_THREADS on a - project-wide basis to switch to ordinary non-atomic reference count updates.

    -

    (Defining BOOST_SP_DISABLE_THREADS in some, but not all, +

    Starting with Boost release 1.33.0, shared_ptr uses a lock-free + implementation on most common platforms.

    +

    If your program is single-threaded and does not link to any libraries that might + have used shared_ptr in its default configuration, you can + #define the macro BOOST_SP_DISABLE_THREADS on a + project-wide basis to switch to ordinary non-atomic reference count updates.

    +

    (Defining BOOST_SP_DISABLE_THREADS in some, but not all, translation units is technically a violation of the One Definition Rule and undefined behavior. Nevertheless, the implementation attempts to do its best to accommodate the request to use non-atomic updates in those translation units. - No guarantees, though.)

    -

    You can define the macro BOOST_SP_USE_PTHREADS to turn off the - lock-free platform-specific implementation and fall back to the generic pthread_mutex_t-based - code.

    -

    Frequently Asked Questions

    -

    Q. There are several variations of shared pointers, with different + No guarantees, though.)

    +

    You can define the macro BOOST_SP_USE_PTHREADS to turn off the + lock-free platform-specific implementation and fall back to the generic + pthread_mutex_t-based code.

    +

    Frequently Asked Questions

    +

    Q. There are several variations of shared pointers, with different tradeoffs; why does the smart pointer library supply only a single implementation? It would be useful to be able to experiment with each type so - as to find the most suitable for the job at hand?

    -

    - A. An important goal of shared_ptr is to provide a + as to find the most suitable for the job at hand?

    +

    + A. An important goal of shared_ptr is to provide a standard shared-ownership pointer. Having a single pointer type is important for stable library interfaces, since different shared pointers typically cannot interoperate, i.e. a reference counted pointer (used by library A) cannot share - ownership with a linked pointer (used by library B.)
    -

    -

    Q. Why doesn't shared_ptr have template parameters supplying - traits or policies to allow extensive user customization?

    -

    - A. Parameterization discourages users. The shared_ptr template is + ownership with a linked pointer (used by library B.) +

    +

    Q. Why doesn't shared_ptr have template parameters supplying + traits or policies to allow extensive user customization?

    +

    + A. Parameterization discourages users. The shared_ptr template is carefully crafted to meet common needs without extensive parameterization. Some day a highly configurable smart pointer may be invented that is also very easy - to use and very hard to misuse. Until then, shared_ptr is the smart + to use and very hard to misuse. Until then, shared_ptr is the smart pointer of choice for a wide range of applications. (Those interested in policy - based smart pointers should read - Modern C++ Design by Andrei Alexandrescu.)
    -

    -

    Q. I am not convinced. Default parameters can be used where appropriate - to hide the complexity. Again, why not policies?

    -

    - A. Template parameters affect the type. See the answer to the first - question above.
    -

    -

    Q. Why doesn't shared_ptr use a linked list implementation?

    -

    + based smart pointers should read + Modern C++ Design by Andrei Alexandrescu.) +

    +

    Q. I am not convinced. Default parameters can be used where appropriate + to hide the complexity. Again, why not policies?

    +

    + A. Template parameters affect the type. See the answer to the first + question above. +

    +

    Q. Why doesn't shared_ptr use a linked list implementation?

    +

    A. A linked list implementation does not offer enough advantages to - offset the added cost of an extra pointer. See timings + offset the added cost of an extra pointer. See timings page. In addition, it is expensive to make a linked list implementation thread - safe.
    -

    -

    Q. Why doesn't shared_ptr (or any of the other Boost smart - pointers) supply an automatic conversion to T*?

    -

    - A. Automatic conversion is believed to be too error prone.
    -

    -

    Q. Why does shared_ptr supply use_count()?

    -

    + safe. +

    +

    Q. Why doesn't shared_ptr (or any of the other Boost smart + pointers) supply an automatic conversion to T*?

    +

    + A. Automatic conversion is believed to be too error prone. +

    +

    Q. Why does shared_ptr supply use_count()?

    +

    A. As an aid to writing test cases and debugging displays. One of the - progenitors had use_count(), and it was useful in tracking down bugs in a - complex project that turned out to have cyclic-dependencies.
    -

    -

    Q. Why doesn't shared_ptr specify complexity requirements?

    -

    + progenitors had use_count(), and it was useful in tracking down bugs in a + complex project that turned out to have cyclic-dependencies. +

    +

    Q. Why doesn't shared_ptr specify complexity requirements?

    +

    A. Because complexity requirements limit implementors and complicate the - specification without apparent benefit to shared_ptr users. For example, + specification without apparent benefit to shared_ptr users. For example, error-checking implementations might become non-conforming if they had to meet - stringent complexity requirements.
    -

    -

    Q. Why doesn't shared_ptr provide a release() function?

    -

    - A. shared_ptr cannot give away ownership unless it's unique() - because the other copy will still destroy the object.

    + stringent complexity requirements. +

    +

    Q. Why doesn't shared_ptr provide a release() function?

    +

    + A. shared_ptr cannot give away ownership unless it's unique() + because the other copy will still destroy the object.

    Consider:

    shared_ptr<int> a(new int);
     shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
    @@ -698,25 +769,22 @@ int * p = a.release();
     // Who owns p now? b will still call delete on it in its destructor.

    Furthermore, the pointer returned by release() would be difficult - to deallocate reliably, as the source shared_ptr could have been created - with a custom deleter.
    + to deallocate reliably, as the source shared_ptr could have been created + with a custom deleter.

    -

    Q. Why is operator->() const, but its return value is a - non-const pointer to the element type?

    -

    +

    Q. Why is operator->() const, but its return value is a + non-const pointer to the element type?

    +

    A. Shallow copy pointers, including raw pointers, typically don't propagate constness. It makes little sense for them to do so, as you can always obtain a non-const pointer from a const one and then proceed to modify the - object through it.shared_ptr is "as close to raw pointers as possible - but no closer".
    -
    -

    -
    -

    - $Date$

    + object through it. shared_ptr is "as close to raw pointers as possible + but no closer". +

    +

    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, 2012 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/sp_unique_ptr_test.cpp b/test/sp_unique_ptr_test.cpp index 70c5aff..69bbaf9 100644 --- a/test/sp_unique_ptr_test.cpp +++ b/test/sp_unique_ptr_test.cpp @@ -91,6 +91,66 @@ int main() p2.reset(); p3.reset(); BOOST_TEST( X::instances == 0 ); + + p2 = std::unique_ptr( new X ); + BOOST_TEST( X::instances == 1 ); + + p2 = std::unique_ptr( new X ); + BOOST_TEST( X::instances == 1 ); + + p2.reset(); + BOOST_TEST( X::instances == 0 ); + } + + { + BOOST_TEST( X::instances == 0 ); + + std::unique_ptr p( new X ); + BOOST_TEST( X::instances == 1 ); + + boost::shared_ptr p2( std::move( p ) ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + boost::shared_ptr p3 = p2->shared_from_this(); + BOOST_TEST( p2 == p3 ); + BOOST_TEST( !(p2 < p3) && !(p3 < p2) ); + + p2.reset(); + p3.reset(); + BOOST_TEST( X::instances == 0 ); + + p2 = std::unique_ptr( new X ); + BOOST_TEST( X::instances == 1 ); + + p2 = std::unique_ptr( new X ); + BOOST_TEST( X::instances == 1 ); + + p2.reset(); + BOOST_TEST( X::instances == 0 ); + } + + { + BOOST_TEST( X::instances == 0 ); + + std::unique_ptr p( new X ); + BOOST_TEST( X::instances == 1 ); + + boost::shared_ptr p2( std::move( p ) ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + p2.reset(); + BOOST_TEST( X::instances == 0 ); + + p2 = std::unique_ptr( new X ); + BOOST_TEST( X::instances == 1 ); + + p2 = std::unique_ptr( new X ); + BOOST_TEST( X::instances == 1 ); + + p2.reset(); + BOOST_TEST( X::instances == 0 ); } { @@ -105,6 +165,15 @@ int main() p2.reset(); BOOST_TEST( Y::instances == 0 ); + + p2 = std::unique_ptr( new Y, YD() ); + BOOST_TEST( Y::instances == 1 ); + + p2 = std::unique_ptr( new Y, YD() ); + BOOST_TEST( Y::instances == 1 ); + + p2.reset(); + BOOST_TEST( Y::instances == 0 ); } { @@ -121,6 +190,15 @@ int main() p2.reset(); BOOST_TEST( Y::instances == 0 ); + + p2 = std::unique_ptr( new Y, yd ); + BOOST_TEST( Y::instances == 1 ); + + p2 = std::unique_ptr( new Y, yd ); + BOOST_TEST( Y::instances == 1 ); + + p2.reset(); + BOOST_TEST( Y::instances == 0 ); } { @@ -137,6 +215,15 @@ int main() p2.reset(); BOOST_TEST( Y::instances == 0 ); + + p2 = std::unique_ptr( new Y, yd ); + BOOST_TEST( Y::instances == 1 ); + + p2 = std::unique_ptr( new Y, yd ); + BOOST_TEST( Y::instances == 1 ); + + p2.reset(); + BOOST_TEST( Y::instances == 0 ); } return boost::report_errors(); From b306c9751ff4281dbb894dc07a5a5c5e54c71339 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sat, 8 Dec 2012 18:30:27 +0000 Subject: [PATCH 116/140] Merged revision(s) 81748-81750,81752,81759,81782 from trunk: Refactoring in detail array_deleter before adding support for special-casing trivially default-constructible construction and trivially destroyable destruction. ........ Special case array construction for trivially default-constructible types and array destruction for trivially-destroyable types. ........ Optimization in initialization overload of array_construct for compilers to optimize it into the equivalent of a memset ........ Correctly use r-value reference semantics for Args and T in array utilities ........ Change ordering of overload definitions in array_utility.hpp ........ Convert function parameter for inner array size into template parameter and make identifiers in array_deleter consistent with those in array_utility ........ [SVN r81800] --- .../boost/smart_ptr/allocate_shared_array.hpp | 5 +- .../boost/smart_ptr/detail/array_deleter.hpp | 180 ++++-------------- .../boost/smart_ptr/detail/array_utility.hpp | 136 +++++++++++++ include/boost/smart_ptr/make_shared_array.hpp | 5 +- 4 files changed, 180 insertions(+), 146 deletions(-) create mode 100644 include/boost/smart_ptr/detail/array_utility.hpp diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index a98d97e..dc24ca2 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include @@ -142,7 +141,7 @@ namespace boost { p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct_list(p2, p3, M); + d2->construct_list(p2, p3); return boost::shared_ptr(s1, p1); } template @@ -166,7 +165,7 @@ namespace boost { p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct_list(p2, p3, M); + d2->construct_list(p2, p3); return boost::shared_ptr(s1, p1); } #if defined(BOOST_HAS_RVALUE_REFS) diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index 40e9d57..8ef0d11 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -9,8 +9,8 @@ #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP #define BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP -#include -#include +#include +#include namespace boost { namespace detail { @@ -24,97 +24,47 @@ namespace boost { object(0) { } ~array_deleter() { - destroy(size); + if (object) { + array_destroy(object, size); + } } void construct(T* memory) { - std::size_t i = 0; - try { - for (object = memory; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(); - } - } catch (...) { - destroy(i); - throw; - } + array_construct(memory, size); + object = memory; } #if defined(BOOST_HAS_RVALUE_REFS) void construct(T* memory, T&& value) { - std::size_t i = 0; - try { - for (object = memory; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(value); - } - } catch (...) { - destroy(i); - throw; - } + array_construct(memory, size, sp_forward(value)); + object = memory; } #if defined(BOOST_HAS_VARIADIC_TMPL) template void construct(T* memory, Args&&... args) { - std::size_t i = 0; - try { - for (object = memory; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(args...); - } - } catch (...) { - destroy(i); - throw; - } + array_construct(memory, size, sp_forward(args)...); + object = memory; } #endif #endif void construct_list(T* memory, const T* list) { - std::size_t i = 0; - try { - for (object = memory; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i]); - } - } catch (...) { - destroy(i); - throw; - } + array_construct_list(memory, size, list); + object = memory; } - void construct_list(T* memory, const T* list, std::size_t n) { - std::size_t i = 0; - try { - for (object = memory; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i % n]); - } - } catch (...) { - destroy(i); - throw; - } + template + void construct_list(T* memory, const T* list) { + array_construct_list(memory, size, list); + object = memory; } void construct_noinit(T* memory) { - std::size_t i = 0; - try { - for (object = memory; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T; - } - } catch (...) { - destroy(i); - throw; - } + array_construct_noinit(memory, size); + object = memory; } void operator()(const void*) { - destroy(size); - } - private: - void destroy(std::size_t n) { if (object) { - for (std::size_t i = n; i > 0; ) { - object[--i].~T(); - } + array_destroy(object, size); object = 0; } } + private: std::size_t size; T* object; }; @@ -125,97 +75,47 @@ namespace boost { : object(0) { } ~array_deleter() { - destroy(N); + if (object) { + array_destroy(object, N); + } } void construct(T* memory) { - std::size_t i = 0; - try { - for (object = memory; i < N; i++) { - void* p1 = memory + i; - ::new(p1) T(); - } - } catch (...) { - destroy(i); - throw; - } + array_construct(memory, N); + object = memory; } #if defined(BOOST_HAS_RVALUE_REFS) void construct(T* memory, T&& value) { - std::size_t i = 0; - try { - for (object = memory; i < N; i++) { - void* p1 = memory + i; - ::new(p1) T(value); - } - } catch (...) { - destroy(i); - throw; - } + array_construct(memory, N, sp_forward(value)); + object = memory; } #if defined(BOOST_HAS_VARIADIC_TMPL) template void construct(T* memory, Args&&... args) { - std::size_t i = 0; - try { - for (object = memory; i < N; i++) { - void* p1 = memory + i; - ::new(p1) T(args...); - } - } catch (...) { - destroy(i); - throw; - } + array_construct(memory, N, sp_forward(args)...); + object = memory; } #endif #endif void construct_list(T* memory, const T* list) { - std::size_t i = 0; - try { - for (object = memory; i < N; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i]); - } - } catch (...) { - destroy(i); - throw; - } + array_construct_list(memory, N, list); + object = memory; } - void construct_list(T* memory, const T* list, std::size_t n) { - std::size_t i = 0; - try { - for (object = memory; i < N; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i % n]); - } - } catch (...) { - destroy(i); - throw; - } + template + void construct_list(T* memory, const T* list) { + array_construct_list(memory, N, list); + object = memory; } void construct_noinit(T* memory) { - std::size_t i = 0; - try { - for (object = memory; i < N; i++) { - void* p1 = memory + i; - ::new(p1) T; - } - } catch (...) { - destroy(i); - throw; - } + array_construct_noinit(memory, N); + object = memory; } void operator()(const void*) { - destroy(N); - } - private: - void destroy(std::size_t n) { if (object) { - for (std::size_t i = n; i > 0; ) { - object[--i].~T(); - } + array_destroy(object, N); object = 0; } } + private: T* object; }; } diff --git a/include/boost/smart_ptr/detail/array_utility.hpp b/include/boost/smart_ptr/detail/array_utility.hpp new file mode 100644 index 0000000..b584599 --- /dev/null +++ b/include/boost/smart_ptr/detail/array_utility.hpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP +#define BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP + +#include +#include +#include + +namespace boost { + namespace detail { + template + inline void array_destroy(T*, std::size_t, boost::true_type) { + } + template + inline void array_destroy(T* memory, std::size_t size, boost::false_type) { + for (std::size_t i = size; i > 0; ) { + memory[--i].~T(); + } + } + template + inline void array_destroy(T* memory, std::size_t size) { + boost::has_trivial_destructor type; + array_destroy(memory, size, type); + } + template + inline void array_construct(T* memory, std::size_t size, boost::true_type) { + for (std::size_t i = 0; i < size; i++) { + memory[i] = T(); + } + } + template + inline void array_construct(T* memory, std::size_t size, boost::false_type) { + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(); + } + } catch (...) { + array_destroy(memory, i); + throw; + } + } + template + inline void array_construct(T* memory, std::size_t size) { + boost::has_trivial_default_constructor type; + array_construct(memory, size, type); + } +#if defined(BOOST_HAS_RVALUE_REFS) + template + inline void array_construct(T* memory, std::size_t size, T&& value) { + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(value); + } + } catch (...) { + array_destroy(memory, i); + throw; + } + } +#if defined(BOOST_HAS_VARIADIC_TMPL) + template + inline void array_construct(T* memory, std::size_t size, Args&&... args) { + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(args...); + } + } catch (...) { + array_destroy(memory, i); + throw; + } + } +#endif +#endif + template + inline void array_construct_list(T* memory, std::size_t size, const T* list) { + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i]); + } + } catch (...) { + array_destroy(memory, i); + throw; + } + } + template + inline void array_construct_list(T* memory, std::size_t size, const T* list) { + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i % N]); + } + } catch (...) { + array_destroy(memory, i); + throw; + } + } + template + inline void array_construct_noinit(T*, std::size_t, boost::true_type) { + } + template + inline void array_construct_noinit(T* memory, std::size_t size, boost::false_type) { + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T; + } + } catch (...) { + array_destroy(memory, i); + throw; + } + } + template + inline void array_construct_noinit(T* memory, std::size_t size) { + boost::has_trivial_default_constructor type; + array_construct_noinit(memory, size, type); + } + } +} + +#endif diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index b4fd9f6..cf63ecb 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include @@ -141,7 +140,7 @@ namespace boost { p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct_list(p2, p3, M); + d2->construct_list(p2, p3); return boost::shared_ptr(s1, p1); } template @@ -164,7 +163,7 @@ namespace boost { p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct_list(p2, p3, M); + d2->construct_list(p2, p3); return boost::shared_ptr(s1, p1); } #if defined(BOOST_HAS_RVALUE_REFS) From d42ce8755740855c12457478dd1b3ba06ec4277c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 11 Dec 2012 18:35:21 +0000 Subject: [PATCH 117/140] Merged revision(s) 81780 from trunk: Use explicit operator bool when available; add nullptr support to shared_ptr. Fixes #4116. [SVN r81862] --- .../boost/smart_ptr/detail/operator_bool.hpp | 11 +- include/boost/smart_ptr/intrusive_ptr.hpp | 24 +++ include/boost/smart_ptr/scoped_array.hpp | 25 ++++ include/boost/smart_ptr/scoped_ptr.hpp | 25 ++++ include/boost/smart_ptr/shared_array.hpp | 24 +++ include/boost/smart_ptr/shared_ptr.hpp | 60 +++++++- test/Jamfile.v2 | 2 + test/sp_nullptr_test.cpp | 140 ++++++++++++++++++ test/sp_zero_compare_test.cpp | 78 ++++++++++ 9 files changed, 386 insertions(+), 3 deletions(-) create mode 100644 test/sp_nullptr_test.cpp create mode 100644 test/sp_zero_compare_test.cpp diff --git a/include/boost/smart_ptr/detail/operator_bool.hpp b/include/boost/smart_ptr/detail/operator_bool.hpp index e38593f..8ae1527 100644 --- a/include/boost/smart_ptr/detail/operator_bool.hpp +++ b/include/boost/smart_ptr/detail/operator_bool.hpp @@ -1,12 +1,19 @@ // This header intentionally has no include guards. // -// Copyright (c) 2001-2009 Peter Dimov +// Copyright (c) 2001-2009, 2012 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 -#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) +#if !defined( BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS ) && !defined( BOOST_NO_CXX11_NULLPTR ) + + explicit operator bool () const BOOST_NOEXCEPT + { + return px != 0; + } + +#elif ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) operator bool () const BOOST_NOEXCEPT { diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp index 01e2429..ffb2dba 100644 --- a/include/boost/smart_ptr/intrusive_ptr.hpp +++ b/include/boost/smart_ptr/intrusive_ptr.hpp @@ -218,6 +218,30 @@ template inline bool operator!=(intrusive_ptr const & a, intrusive_p #endif +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +template inline bool operator==( intrusive_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator==( std::nullptr_t, intrusive_ptr const & p ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator!=( intrusive_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +template inline bool operator!=( std::nullptr_t, intrusive_ptr const & p ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +#endif + template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) { return std::less()(a.get(), b.get()); diff --git a/include/boost/smart_ptr/scoped_array.hpp b/include/boost/smart_ptr/scoped_array.hpp index 83352e2..1ddaa07 100644 --- a/include/boost/smart_ptr/scoped_array.hpp +++ b/include/boost/smart_ptr/scoped_array.hpp @@ -11,6 +11,7 @@ // http://www.boost.org/libs/smart_ptr/scoped_array.htm // +#include #include #include #include // in case ptrdiff_t not in std @@ -97,6 +98,30 @@ public: } }; +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +template inline bool operator==( scoped_array const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator==( std::nullptr_t, scoped_array const & p ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator!=( scoped_array const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +template inline bool operator!=( std::nullptr_t, scoped_array const & p ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +#endif + template inline void swap(scoped_array & a, scoped_array & b) BOOST_NOEXCEPT { a.swap(b); diff --git a/include/boost/smart_ptr/scoped_ptr.hpp b/include/boost/smart_ptr/scoped_ptr.hpp index 3ccf697..a75f91f 100644 --- a/include/boost/smart_ptr/scoped_ptr.hpp +++ b/include/boost/smart_ptr/scoped_ptr.hpp @@ -11,6 +11,7 @@ // http://www.boost.org/libs/smart_ptr/scoped_ptr.htm // +#include #include #include #include @@ -114,6 +115,30 @@ public: } }; +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +template inline bool operator==( scoped_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator==( std::nullptr_t, scoped_ptr const & p ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator!=( scoped_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +template inline bool operator!=( std::nullptr_t, scoped_ptr const & p ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +#endif + template inline void swap(scoped_ptr & a, scoped_ptr & b) BOOST_NOEXCEPT { a.swap(b); diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp index ac64099..f54f481 100644 --- a/include/boost/smart_ptr/shared_array.hpp +++ b/include/boost/smart_ptr/shared_array.hpp @@ -243,6 +243,30 @@ template inline bool operator!=(shared_array const & a, shared_array return a.get() != b.get(); } +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +template inline bool operator==( shared_array const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator==( std::nullptr_t, shared_array const & p ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator!=( shared_array const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +template inline bool operator!=( std::nullptr_t, shared_array const & p ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +#endif + template inline bool operator<(shared_array const & a, shared_array const & b) BOOST_NOEXCEPT { return std::less()(a.get(), b.get()); diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index e472d12..3b1ac79 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -41,7 +41,7 @@ #include // for std::swap #include // for std::less #include // for std::bad_cast -#include // for std::size_t +#include // for std::size_t, std::nullptr_t #if !defined(BOOST_NO_IOSTREAM) #if !defined(BOOST_NO_IOSFWD) @@ -339,6 +339,14 @@ public: { } +#if !defined( BOOST_NO_CXX11_NULLPTR ) + + shared_ptr( std::nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn() // never throws + { + } + +#endif + template explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete { @@ -356,6 +364,14 @@ public: boost::detail::sp_deleter_construct( this, p ); } +#if !defined( BOOST_NO_CXX11_NULLPTR ) + + template shared_ptr( std::nullptr_t p, D d ): px( p ), pn( p, d ) + { + } + +#endif + // 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 ) @@ -363,6 +379,14 @@ public: boost::detail::sp_deleter_construct( this, p ); } +#if !defined( BOOST_NO_CXX11_NULLPTR ) + + template shared_ptr( std::nullptr_t p, D d, A a ): px( p ), pn( p, d, a ) + { + } + +#endif + // generated copy constructor, destructor are fine... #if defined( BOOST_HAS_RVALUE_REFS ) @@ -577,6 +601,16 @@ public: return *this; } +#endif + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + + shared_ptr & operator=( std::nullptr_t ) BOOST_NOEXCEPT // never throws + { + this_type().swap(*this); + return *this; + } + #endif void reset() BOOST_NOEXCEPT // never throws in 1.30+ @@ -711,6 +745,30 @@ template inline bool operator!=(shared_ptr const & a, shared_ptr #endif +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +template inline bool operator==( shared_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator==( std::nullptr_t, shared_ptr const & p ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator!=( shared_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +template inline bool operator!=( std::nullptr_t, shared_ptr const & p ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +#endif + template inline bool operator<(shared_ptr const & a, shared_ptr const & b) BOOST_NOEXCEPT { return a.owner_before( b ); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 2c95dd9..9f08375 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -75,6 +75,8 @@ import testing ; [ run sp_convertible_test.cpp ] [ run sp_array_n_test.cpp ] [ run sp_array_cast_test.cpp ] + [ run sp_zero_compare_test.cpp ] + [ run sp_nullptr_test.cpp ] [ compile-fail array_fail_spa_sp_c.cpp ] [ compile-fail array_fail_sp_spa_c.cpp ] diff --git a/test/sp_nullptr_test.cpp b/test/sp_nullptr_test.cpp new file mode 100644 index 0000000..a1779bb --- /dev/null +++ b/test/sp_nullptr_test.cpp @@ -0,0 +1,140 @@ +// +// sp_nullptr_test.cpp +// +// Copyright 2012 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 + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +struct X +{ + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const & ); + X & operator=( X const & ); +}; + +int X::instances = 0; + +void f( std::nullptr_t ) +{ +} + +int main() +{ + { + boost::shared_ptr p( nullptr ); + + BOOST_TEST( p.get() == 0 ); + BOOST_TEST( p.use_count() == 0 ); + + BOOST_TEST( p == nullptr ); + BOOST_TEST( nullptr == p ); + BOOST_TEST( !( p != nullptr ) ); + BOOST_TEST( !( nullptr != p ) ); + } + + { + boost::shared_ptr p( nullptr, f ); + + BOOST_TEST( p.get() == 0 ); + BOOST_TEST( p.use_count() == 1 ); + + BOOST_TEST( p == nullptr ); + BOOST_TEST( nullptr == p ); + BOOST_TEST( !( p != nullptr ) ); + BOOST_TEST( !( nullptr != p ) ); + } + + { + boost::shared_ptr p( nullptr, f, std::allocator() ); + + BOOST_TEST( p.get() == 0 ); + BOOST_TEST( p.use_count() == 1 ); + + BOOST_TEST( p == nullptr ); + BOOST_TEST( nullptr == p ); + BOOST_TEST( !( p != nullptr ) ); + BOOST_TEST( !( nullptr != p ) ); + } + + { + boost::shared_ptr p( new int ); + + BOOST_TEST( p.get() != 0 ); + BOOST_TEST( p.use_count() == 1 ); + + BOOST_TEST( p != nullptr ); + BOOST_TEST( nullptr != p ); + BOOST_TEST( !( p == nullptr ) ); + BOOST_TEST( !( nullptr == p ) ); + + p = nullptr; + + BOOST_TEST( p.get() == 0 ); + BOOST_TEST( p.use_count() == 0 ); + + BOOST_TEST( p == nullptr ); + BOOST_TEST( nullptr == p ); + BOOST_TEST( !( p != nullptr ) ); + BOOST_TEST( !( nullptr != p ) ); + } + + { + BOOST_TEST( X::instances == 0 ); + + boost::shared_ptr p( new X ); + BOOST_TEST( X::instances == 1 ); + + BOOST_TEST( p.get() != 0 ); + BOOST_TEST( p.use_count() == 1 ); + + BOOST_TEST( p != nullptr ); + BOOST_TEST( nullptr != p ); + BOOST_TEST( !( p == nullptr ) ); + BOOST_TEST( !( nullptr == p ) ); + + p = nullptr; + BOOST_TEST( X::instances == 0 ); + + BOOST_TEST( p.get() == 0 ); + BOOST_TEST( p.use_count() == 0 ); + + BOOST_TEST( p == nullptr ); + BOOST_TEST( nullptr == p ); + BOOST_TEST( !( p != nullptr ) ); + BOOST_TEST( !( nullptr != p ) ); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} + +#endif diff --git a/test/sp_zero_compare_test.cpp b/test/sp_zero_compare_test.cpp new file mode 100644 index 0000000..e326d34 --- /dev/null +++ b/test/sp_zero_compare_test.cpp @@ -0,0 +1,78 @@ +// +// sp_zero_compare_test.cpp - == 0, != 0 +// +// Copyright 2012 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 + +struct W +{ +}; + +void intrusive_ptr_add_ref( W* ) +{ +} + +void intrusive_ptr_release( W* ) +{ +} + +int main() +{ + { + boost::scoped_ptr p; + + BOOST_TEST( p == 0 ); + BOOST_TEST( 0 == p ); + BOOST_TEST( !( p != 0 ) ); + BOOST_TEST( !( 0 != p ) ); + } + + { + boost::scoped_array p; + + BOOST_TEST( p == 0 ); + BOOST_TEST( 0 == p ); + BOOST_TEST( !( p != 0 ) ); + BOOST_TEST( !( 0 != p ) ); + } + + { + boost::shared_ptr p; + + BOOST_TEST( p == 0 ); + BOOST_TEST( 0 == p ); + BOOST_TEST( !( p != 0 ) ); + BOOST_TEST( !( 0 != p ) ); + } + + { + boost::shared_array p; + + BOOST_TEST( p == 0 ); + BOOST_TEST( 0 == p ); + BOOST_TEST( !( p != 0 ) ); + BOOST_TEST( !( 0 != p ) ); + } + + { + boost::intrusive_ptr p; + + BOOST_TEST( p == 0 ); + BOOST_TEST( 0 == p ); + BOOST_TEST( !( p != 0 ) ); + BOOST_TEST( !( 0 != p ) ); + } + + return boost::report_errors(); +} From 5fc6fe474b82b9015336d6b6db3bba07d522e6e4 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 11 Dec 2012 18:42:48 +0000 Subject: [PATCH 118/140] Merged revision(s) 81844 from trunk: Correct link to http://www.stroustrup.com/wrapper.pdf in sp_techniques.html ........ [SVN r81863] --- sp_techniques.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sp_techniques.html b/sp_techniques.html index 4b7363b..f869279 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -624,7 +624,7 @@ public:

    Using shared_ptr to wrap member function calls

    shared_ptr implements the ownership semantics required from the Wrap/CallProxy scheme described in Bjarne Stroustrup's article "Wrapping C++ Member Function - Calls" (available online at http://www.research.att.com/~bs/wrapper.pdf). + Calls" (available online at http://www.stroustrup.com/wrapper.pdf). An implementation is given below:

    template<class T> class pointer
     {
    
    From c28bef2e9b12d2aea0437b52c0198a161f391306 Mon Sep 17 00:00:00 2001
    From: Glen Fernandes 
    Date: Wed, 12 Dec 2012 22:57:03 +0000
    Subject: [PATCH 119/140] Merged revision(s) 81858,81859,81865,81867 from
     trunk: Add overloads of allocate_shared_noinit to complement
     make_shared_noinit ........ Explicitly name detail array construct overloads
     for different parameter types. ........ Use _internal_get_untyped_deleter in
     allocate_shared_array and make_shared_array ........ Documentation
     corrections: make_shared_array.html ........
    
    [SVN r81882]
    ---
     .../boost/smart_ptr/allocate_shared_array.hpp | 112 ++++++++++++------
     .../boost/smart_ptr/detail/array_deleter.hpp  |   8 +-
     .../boost/smart_ptr/detail/array_utility.hpp  |   4 +-
     include/boost/smart_ptr/make_shared_array.hpp |  90 +++++++-------
     make_shared_array.html                        |  18 ++-
     test/allocate_shared_array_esft_test.cpp      |  10 ++
     test/allocate_shared_array_test.cpp           |  74 ++++++++++++
     test/allocate_shared_array_throws_test.cpp    |  14 +++
     test/allocate_shared_arrays_test.cpp          |  56 +++++++++
     9 files changed, 293 insertions(+), 93 deletions(-)
    
    diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp
    index dc24ca2..7f78d0e 100644
    --- a/include/boost/smart_ptr/allocate_shared_array.hpp
    +++ b/include/boost/smart_ptr/allocate_shared_array.hpp
    @@ -1,9 +1,9 @@
     /*
    - * Copyright (c) 2012 Glen Joseph Fernandes 
    + * Copyright (c) 2012 Glen Joseph Fernandes
      * glenfe at live dot com
      *
    - * Distributed under the Boost Software License, 
    - * Version 1.0. (See accompanying file LICENSE_1_0.txt 
    + * Distributed under the Boost Software License,
    + * Version 1.0. (See accompanying file LICENSE_1_0.txt
      * or copy at http://boost.org/LICENSE_1_0.txt)
      */
     #ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
    @@ -20,7 +20,7 @@
     
     namespace boost {
         template
    -    inline typename boost::detail::sp_if_array::type 
    +    inline typename boost::detail::sp_if_array::type
         allocate_shared(const A& allocator, std::size_t size) {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
    @@ -30,9 +30,9 @@ namespace boost {
             boost::detail::allocate_array_helper a1(allocator, n1, &p2);
             boost::detail::array_deleter d1(n1);
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    +        typedef boost::detail::array_deleter* D2;
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct(p2);
             return boost::shared_ptr(s1, p1);
         }
    @@ -48,9 +48,9 @@ namespace boost {
             boost::detail::allocate_array_helper a1(allocator, n1, &p2);
             boost::detail::array_deleter d1(n1);
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    +        typedef boost::detail::array_deleter* D2;
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct(p2, boost::detail::sp_forward(args)...);
             return boost::shared_ptr(s1, p1);
         }
    @@ -59,17 +59,17 @@ namespace boost {
         allocate_shared(const A& allocator, Args&&... args) {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
    -        enum { 
    -            N = boost::detail::array_total::size 
    +        enum {
    +            N = boost::detail::array_total::size
             };
             T1* p1 = 0;
             T2* p2 = 0;
             boost::detail::allocate_array_helper a1(allocator, &p2);
             boost::detail::array_deleter d1;
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    +        typedef boost::detail::array_deleter* D2;
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct(p2, boost::detail::sp_forward(args)...);
             return boost::shared_ptr(s1, p1);
         }
    @@ -77,7 +77,7 @@ namespace boost {
     #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
         template
         inline typename boost::detail::sp_if_array::type
    -    allocate_shared(const A& allocator, 
    +    allocate_shared(const A& allocator,
             std::initializer_list::type> list) {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
    @@ -89,10 +89,10 @@ namespace boost {
             boost::detail::allocate_array_helper a1(allocator, n1, &p2);
             boost::detail::array_deleter d1(n1);
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    +        typedef boost::detail::array_deleter* D2;
             p3 = reinterpret_cast(list.begin());
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct_list(p2, p3);
             return boost::shared_ptr(s1, p1);
         }
    @@ -104,8 +104,8 @@ namespace boost {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
             typedef const T2 T3;
    -        enum { 
    -            N = boost::detail::array_total::size 
    +        enum {
    +            N = boost::detail::array_total::size
             };
             T1* p1 = 0;
             T2* p2 = 0;
    @@ -113,21 +113,21 @@ namespace boost {
             boost::detail::allocate_array_helper a1(allocator, &p2);
             boost::detail::array_deleter d1;
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    +        typedef boost::detail::array_deleter* D2;
             p3 = reinterpret_cast(list);
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct_list(p2, p3);
             return boost::shared_ptr(s1, p1);
         }
         template
         inline typename boost::detail::sp_if_array::type
    -    allocate_shared(const A& allocator, std::size_t size, 
    +    allocate_shared(const A& allocator, std::size_t size,
             const typename boost::detail::array_inner::type& list) {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
             typedef const T2 T3;
    -        enum { 
    +        enum {
                 M = boost::detail::array_total::size
             };
             T1* p1 = 0;
    @@ -137,41 +137,41 @@ namespace boost {
             boost::detail::allocate_array_helper a1(allocator, n1, &p2);
             boost::detail::array_deleter d1(n1);
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    +        typedef boost::detail::array_deleter* D2;
             p3 = reinterpret_cast(list);
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct_list(p2, p3);
             return boost::shared_ptr(s1, p1);
         }
         template
         inline typename boost::detail::sp_if_size_array::type
    -    allocate_shared(const A& allocator, 
    +    allocate_shared(const A& allocator,
             const typename boost::detail::array_inner::type& list) {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
             typedef const T2 T3;
    -        enum { 
    -            M = boost::detail::array_total::size, 
    -            N = boost::detail::array_total::size 
    +        enum {
    +            M = boost::detail::array_total::size,
    +            N = boost::detail::array_total::size
             };
             T1* p1 = 0;
             T2* p2 = 0;
    -        T3* p3 = 0;        
    +        T3* p3 = 0;
             boost::detail::allocate_array_helper a1(allocator, &p2);
             boost::detail::array_deleter d1;
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    +        typedef boost::detail::array_deleter* D2;
             p3 = reinterpret_cast(list);
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct_list(p2, p3);
             return boost::shared_ptr(s1, p1);
         }
     #if defined(BOOST_HAS_RVALUE_REFS)
         template
         inline typename boost::detail::sp_if_array::type
    -    allocate_shared(const A& allocator, std::size_t size, 
    +    allocate_shared(const A& allocator, std::size_t size,
             typename boost::detail::array_base::type&& value) {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
    @@ -181,34 +181,70 @@ namespace boost {
             boost::detail::allocate_array_helper a1(allocator, n1, &p2);
             boost::detail::array_deleter d1(n1);
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    +        typedef boost::detail::array_deleter* D2;
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct(p2, boost::detail::sp_forward(value));
             return boost::shared_ptr(s1, p1);
         }
         template
         inline typename boost::detail::sp_if_size_array::type
    -    allocate_shared(const A& allocator, 
    +    allocate_shared(const A& allocator,
             typename boost::detail::array_base::type&& value) {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
    -        enum { 
    -            N = boost::detail::array_total::size 
    +        enum {
    +            N = boost::detail::array_total::size
             };
             T1* p1 = 0;
             T2* p2 = 0;
             boost::detail::allocate_array_helper a1(allocator, &p2);
             boost::detail::array_deleter d1;
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    +        typedef boost::detail::array_deleter* D2;
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct(p2, boost::detail::sp_forward(value));
             return boost::shared_ptr(s1, p1);
         }
     #endif
     #endif
    +    template
    +    inline typename boost::detail::sp_if_array::type
    +    allocate_shared_noinit(const A& allocator, std::size_t size) {
    +        typedef typename boost::detail::array_inner::type T1;
    +        typedef typename boost::detail::array_base::type T2;
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        std::size_t n1 = size * boost::detail::array_total::size;
    +        boost::detail::allocate_array_helper a1(allocator, n1, &p2);
    +        boost::detail::array_deleter d1(n1);
    +        boost::shared_ptr s1(p1, d1, a1);
    +        typedef boost::detail::array_deleter* D2;
    +        p1 = reinterpret_cast(p2);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
    +        d2->construct_noinit(p2);
    +        return boost::shared_ptr(s1, p1);
    +    }
    +    template
    +    inline typename boost::detail::sp_if_size_array::type
    +    allocate_shared_noinit(const A& allocator) {
    +        typedef typename boost::detail::array_inner::type T1;
    +        typedef typename boost::detail::array_base::type T2;
    +        enum {
    +            N = boost::detail::array_total::size
    +        };
    +        T1* p1 = 0;
    +        T2* p2 = 0;
    +        boost::detail::allocate_array_helper a1(allocator, &p2);
    +        boost::detail::array_deleter d1;
    +        boost::shared_ptr s1(p1, d1, a1);
    +        typedef boost::detail::array_deleter* D2;
    +        p1 = reinterpret_cast(p2);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
    +        d2->construct_noinit(p2);
    +        return boost::shared_ptr(s1, p1);
    +    }
     }
     
     #endif
    diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp
    index 8ef0d11..7909265 100644
    --- a/include/boost/smart_ptr/detail/array_deleter.hpp
    +++ b/include/boost/smart_ptr/detail/array_deleter.hpp
    @@ -34,13 +34,13 @@ namespace boost {
                 }
     #if defined(BOOST_HAS_RVALUE_REFS)
                 void construct(T* memory, T&& value) {
    -                array_construct(memory, size, sp_forward(value));
    +                array_construct_value(memory, size, sp_forward(value));
                     object = memory;                
                 }
     #if defined(BOOST_HAS_VARIADIC_TMPL)
                 template
                 void construct(T* memory, Args&&... args) {
    -                array_construct(memory, size, sp_forward(args)...);
    +                array_construct_args(memory, size, sp_forward(args)...);
                     object = memory;
                 }
     #endif
    @@ -85,13 +85,13 @@ namespace boost {
                 }
     #if defined(BOOST_HAS_RVALUE_REFS)
                 void construct(T* memory, T&& value) {
    -                array_construct(memory, N, sp_forward(value));
    +                array_construct_value(memory, N, sp_forward(value));
                     object = memory;                
                 }
     #if defined(BOOST_HAS_VARIADIC_TMPL)
                 template
                 void construct(T* memory, Args&&... args) {
    -                array_construct(memory, N, sp_forward(args)...);
    +                array_construct_args(memory, N, sp_forward(args)...);
                     object = memory;
                 }
     #endif
    diff --git a/include/boost/smart_ptr/detail/array_utility.hpp b/include/boost/smart_ptr/detail/array_utility.hpp
    index b584599..3b685ad 100644
    --- a/include/boost/smart_ptr/detail/array_utility.hpp
    +++ b/include/boost/smart_ptr/detail/array_utility.hpp
    @@ -55,7 +55,7 @@ namespace boost {
             }
     #if defined(BOOST_HAS_RVALUE_REFS)
             template
    -        inline void array_construct(T* memory, std::size_t size, T&& value) {
    +        inline void array_construct_value(T* memory, std::size_t size, T&& value) {
                 std::size_t i = 0;
                 try {
                     for (; i < size; i++) {
    @@ -69,7 +69,7 @@ namespace boost {
             }
     #if defined(BOOST_HAS_VARIADIC_TMPL)
             template
    -        inline void array_construct(T* memory, std::size_t size, Args&&... args) {
    +        inline void array_construct_args(T* memory, std::size_t size, Args&&... args) {
                 std::size_t i = 0;
                 try {
                     for (; i < size; i++) {
    diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp
    index cf63ecb..b9c197c 100644
    --- a/include/boost/smart_ptr/make_shared_array.hpp
    +++ b/include/boost/smart_ptr/make_shared_array.hpp
    @@ -1,9 +1,9 @@
     /*
    - * Copyright (c) 2012 Glen Joseph Fernandes 
    + * Copyright (c) 2012 Glen Joseph Fernandes
      * glenfe at live dot com
      *
    - * Distributed under the Boost Software License, 
    - * Version 1.0. (See accompanying file LICENSE_1_0.txt 
    + * Distributed under the Boost Software License,
    + * Version 1.0. (See accompanying file LICENSE_1_0.txt
      * or copy at http://boost.org/LICENSE_1_0.txt)
      */
     #ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
    @@ -30,9 +30,9 @@ namespace boost {
             boost::detail::make_array_helper a1(n1, &p2);
             boost::detail::array_deleter d1(n1);
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    -        p1 = reinterpret_cast(p2);        
    -        d2 = get_deleter >(s1);
    +        typedef boost::detail::array_deleter* D2;
    +        p1 = reinterpret_cast(p2);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct(p2);
             return boost::shared_ptr(s1, p1);
         }
    @@ -48,9 +48,9 @@ namespace boost {
             boost::detail::make_array_helper a1(n1, &p2);
             boost::detail::array_deleter d1(n1);
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    -        p1 = reinterpret_cast(p2);        
    -        d2 = get_deleter >(s1);
    +        typedef boost::detail::array_deleter* D2;
    +        p1 = reinterpret_cast(p2);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct(p2, boost::detail::sp_forward(args)...);
             return boost::shared_ptr(s1, p1);
         }
    @@ -59,17 +59,17 @@ namespace boost {
         make_shared(Args&&... args) {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
    -        enum { 
    -            N = boost::detail::array_total::size 
    +        enum {
    +            N = boost::detail::array_total::size
             };
             T1* p1 = 0;
             T2* p2 = 0;
             boost::detail::make_array_helper a1(&p2);
             boost::detail::array_deleter d1;
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    -        p1 = reinterpret_cast(p2);        
    -        d2 = get_deleter >(s1);
    +        typedef boost::detail::array_deleter* D2;
    +        p1 = reinterpret_cast(p2);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct(p2, boost::detail::sp_forward(args)...);
             return boost::shared_ptr(s1, p1);
         }
    @@ -88,13 +88,13 @@ namespace boost {
             boost::detail::make_array_helper a1(n1, &p2);
             boost::detail::array_deleter d1(n1);
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;        
    +        typedef boost::detail::array_deleter* D2;
             p3 = reinterpret_cast(list.begin());
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct_list(p2, p3);
             return boost::shared_ptr(s1, p1);
    -    }    
    +    }
     #endif
     #if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
         template
    @@ -103,8 +103,8 @@ namespace boost {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
             typedef const T2 T3;
    -        enum { 
    -            N = boost::detail::array_total::size 
    +        enum {
    +            N = boost::detail::array_total::size
             };
             T1* p1 = 0;
             T2* p2 = 0;
    @@ -112,22 +112,22 @@ namespace boost {
             boost::detail::make_array_helper a1(&p2);
             boost::detail::array_deleter d1;
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;        
    +        typedef boost::detail::array_deleter* D2;
             p3 = reinterpret_cast(list);
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct_list(p2, p3);
             return boost::shared_ptr(s1, p1);
         }
         template
         inline typename boost::detail::sp_if_array::type
    -    make_shared(std::size_t size, 
    +    make_shared(std::size_t size,
             const typename boost::detail::array_inner::type& list) {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
             typedef const T2 T3;
    -        enum { 
    -            M = boost::detail::array_total::size 
    +        enum {
    +            M = boost::detail::array_total::size
             };
             T1* p1 = 0;
             T2* p2 = 0;
    @@ -136,10 +136,10 @@ namespace boost {
             boost::detail::make_array_helper a1(n1, &p2);
             boost::detail::array_deleter d1(n1);
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;        
    +        typedef boost::detail::array_deleter* D2;
             p3 = reinterpret_cast(list);
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct_list(p2, p3);
             return boost::shared_ptr(s1, p1);
         }
    @@ -149,9 +149,9 @@ namespace boost {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
             typedef const T2 T3;
    -        enum { 
    +        enum {
                 M = boost::detail::array_total::size,
    -            N = boost::detail::array_total::size 
    +            N = boost::detail::array_total::size
             };
             T1* p1 = 0;
             T2* p2 = 0;
    @@ -159,17 +159,17 @@ namespace boost {
             boost::detail::make_array_helper a1(&p2);
             boost::detail::array_deleter d1;
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;        
    +        typedef boost::detail::array_deleter* D2;
             p3 = reinterpret_cast(list);
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct_list(p2, p3);
             return boost::shared_ptr(s1, p1);
         }
     #if defined(BOOST_HAS_RVALUE_REFS)
         template
         inline typename boost::detail::sp_if_array::type
    -    make_shared(std::size_t size, 
    +    make_shared(std::size_t size,
             typename boost::detail::array_base::type&& value) {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
    @@ -179,9 +179,9 @@ namespace boost {
             boost::detail::make_array_helper a1(n1, &p2);
             boost::detail::array_deleter d1(n1);
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    +        typedef boost::detail::array_deleter* D2;
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct(p2, boost::detail::sp_forward(value));
             return boost::shared_ptr(s1, p1);
         }
    @@ -190,17 +190,17 @@ namespace boost {
         make_shared(typename boost::detail::array_base::type&& value) {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
    -        enum { 
    -            N = boost::detail::array_total::size 
    +        enum {
    +            N = boost::detail::array_total::size
             };
             T1* p1 = 0;
             T2* p2 = 0;
             boost::detail::make_array_helper a1(&p2);
             boost::detail::array_deleter d1;
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    +        typedef boost::detail::array_deleter* D2;
             p1 = reinterpret_cast(p2);
    -        d2 = get_deleter >(s1);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct(p2, boost::detail::sp_forward(value));
             return boost::shared_ptr(s1, p1);
         }
    @@ -217,9 +217,9 @@ namespace boost {
             boost::detail::make_array_helper a1(n1, &p2);
             boost::detail::array_deleter d1(n1);
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    -        p1 = reinterpret_cast(p2);        
    -        d2 = get_deleter >(s1);
    +        typedef boost::detail::array_deleter* D2;
    +        p1 = reinterpret_cast(p2);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct_noinit(p2);
             return boost::shared_ptr(s1, p1);
         }
    @@ -228,17 +228,17 @@ namespace boost {
         make_shared_noinit() {
             typedef typename boost::detail::array_inner::type T1;
             typedef typename boost::detail::array_base::type T2;
    -        enum { 
    -            N = boost::detail::array_total::size 
    +        enum {
    +            N = boost::detail::array_total::size
             };
             T1* p1 = 0;
             T2* p2 = 0;
             boost::detail::make_array_helper a1(&p2);
             boost::detail::array_deleter d1;
             boost::shared_ptr s1(p1, d1, a1);
    -        boost::detail::array_deleter* d2;
    -        p1 = reinterpret_cast(p2);     
    -        d2 = get_deleter >(s1);
    +        typedef boost::detail::array_deleter* D2;
    +        p1 = reinterpret_cast(p2);
    +        D2 d2 = static_cast(s1._internal_get_untyped_deleter());
             d2->construct_noinit(p2);
             return boost::shared_ptr(s1, p1);
         }
    diff --git a/make_shared_array.html b/make_shared_array.html
    index c1db41f..1f0f4d3 100644
    --- a/make_shared_array.html
    +++ b/make_shared_array.html
    @@ -96,6 +96,12 @@
     
         template<typename T>
         shared_ptr<T[N]> make_shared_noinit();
    +    
    +    template<typename T, typename A>
    +    shared_ptr<T[]> allocate_shared_noinit(const A& allocator, size_t size);
    +
    +    template<typename T, typename A>
    +    shared_ptr<T[N]> allocate_shared_noinit(const A& allocator);
     }

    Free Functions

    template<typename T, typename... Args>
    @@ -197,15 +203,19 @@ template<typename T, typename A>
             fixed size array.

    template<typename T>
    -    shared_ptr<T[]> make_shared_noinit(size_t size);
    + shared_ptr<T[]> make_shared_noinit(size_t size); +template<typename T, typename A> + shared_ptr<T[]> allocate_shared_noinit(const A& allocator, size_t size);
    -

    Description: This overload does not perform value +

    Description: These overloads do not perform any value initialization of elements.

    template<typename T>
    -    shared_ptr<T[N]> make_shared_noinit();
    + shared_ptr<T[N]> make_shared_noinit(); +template<typename T, typename A> + shared_ptr<T[N]> allocate_shared_noinit(const A& allocator);
    -

    Description: This overload of the utility above is used for a +

    Description: These overloads of the utilities above are for a fixed size array.

    Example

    diff --git a/test/allocate_shared_array_esft_test.cpp b/test/allocate_shared_array_esft_test.cpp index 2315421..cea73c6 100644 --- a/test/allocate_shared_array_esft_test.cpp +++ b/test/allocate_shared_array_esft_test.cpp @@ -38,5 +38,15 @@ int main() { BOOST_TEST(type::instances == 3); } } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 3); + try { + a1[0].shared_from_this(); + BOOST_ERROR("shared_from_this did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 3); + } + } return boost::report_errors(); } diff --git a/test/allocate_shared_array_test.cpp b/test/allocate_shared_array_test.cpp index 91f3fb5..84ef3a8 100644 --- a/test/allocate_shared_array_test.cpp +++ b/test/allocate_shared_array_test.cpp @@ -121,5 +121,79 @@ int main() { BOOST_TEST(type::instances == 0); } #endif + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 3); + int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 3); + const int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + const int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 3); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 3); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } return boost::report_errors(); } diff --git a/test/allocate_shared_array_throws_test.cpp b/test/allocate_shared_array_throws_test.cpp index 65a7985..d300f2c 100644 --- a/test/allocate_shared_array_throws_test.cpp +++ b/test/allocate_shared_array_throws_test.cpp @@ -59,5 +59,19 @@ int main() { BOOST_TEST(type::instances == 0); } #endif + BOOST_TEST(type::instances == 0); + try { + boost::allocate_shared_noinit(std::allocator(), 6); + BOOST_ERROR("allocate_shared_noinit did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + try { + boost::allocate_shared_noinit(std::allocator(), 3); + BOOST_ERROR("allocate_shared_noinit did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } return boost::report_errors(); } diff --git a/test/allocate_shared_arrays_test.cpp b/test/allocate_shared_arrays_test.cpp index ab22c23..7c719ce 100644 --- a/test/allocate_shared_arrays_test.cpp +++ b/test/allocate_shared_arrays_test.cpp @@ -100,5 +100,61 @@ int main() { BOOST_TEST(type::instances == 0); } #endif + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } return boost::report_errors(); } From 7ab4f6ce92a54b5a804efddd4e0d6cb818a53ca4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 13 Dec 2012 14:53:09 +0000 Subject: [PATCH 120/140] Merged revision(s) 72437 from trunk: Lock-free sp_counted_base for SNC/PS3, thanks Peter Dimov [SVN r81898] --- .../smart_ptr/detail/sp_counted_base.hpp | 3 + .../detail/sp_counted_base_snc_ps3.hpp | 161 ++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp index 17bd517..9ced2b9 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp @@ -32,6 +32,9 @@ #elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 ) # include +#elif defined( __SNC__ ) +# include + #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined(__PATHSCALE__) # include diff --git a/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp b/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp new file mode 100644 index 0000000..e51e676 --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp @@ -0,0 +1,161 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SNC_PS3_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SNC_PS3_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 +// Copyright (c) 2011 Emil Dotchevski +// +// 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 // uint32_t + +namespace boost +{ + +namespace detail +{ + +inline uint32_t compare_and_swap( uint32_t * dest_, uint32_t compare_, uint32_t swap_ ) +{ + return __builtin_cellAtomicCompareAndSwap32(dest_,compare_,swap_); +} + +inline uint32_t atomic_fetch_and_add( uint32_t * pw, uint32_t dv ) +{ + // long r = *pw; + // *pw += dv; + // return r; + + for( ;; ) + { + uint32_t r = *pw; + + if( __builtin_expect((compare_and_swap(pw, r, r + dv) == r), 1) ) + { + return r; + } + } +} + +inline void atomic_increment( uint32_t * pw ) +{ + (void) __builtin_cellAtomicIncr32( pw ); +} + +inline uint32_t atomic_decrement( uint32_t * pw ) +{ + return __builtin_cellAtomicDecr32( pw ); +} + +inline uint32_t atomic_conditional_increment( uint32_t * pw ) +{ + // long r = *pw; + // if( r != 0 ) ++*pw; + // return r; + + for( ;; ) + { + uint32_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 & ); + + uint32_t use_count_; // #shared + uint32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_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< uint32_t const volatile & >( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SNC_PS3_HPP_INCLUDED From c14369aac9aafae47687522fded11e52d74f48c4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 13 Dec 2012 14:57:12 +0000 Subject: [PATCH 121/140] Merged revision(s) 81860-81861 from trunk: Change make_shared to use the new _internal_get_untyped_deleter. Fixes #6830. ........ Add allocate_shared_noinit. ........ [SVN r81899] --- .../boost/smart_ptr/detail/shared_count.hpp | 5 + .../detail/sp_counted_base_acc_ia64.hpp | 1 + .../smart_ptr/detail/sp_counted_base_aix.hpp | 1 + .../detail/sp_counted_base_cw_ppc.hpp | 1 + .../detail/sp_counted_base_cw_x86.hpp | 1 + .../detail/sp_counted_base_gcc_ia64.hpp | 1 + .../detail/sp_counted_base_gcc_mips.hpp | 1 + .../detail/sp_counted_base_gcc_ppc.hpp | 1 + .../detail/sp_counted_base_gcc_sparc.hpp | 1 + .../detail/sp_counted_base_gcc_x86.hpp | 1 + .../smart_ptr/detail/sp_counted_base_nt.hpp | 1 + .../smart_ptr/detail/sp_counted_base_pt.hpp | 1 + .../detail/sp_counted_base_snc_ps3.hpp | 1 + .../detail/sp_counted_base_solaris.hpp | 1 + .../smart_ptr/detail/sp_counted_base_spin.hpp | 1 + .../smart_ptr/detail/sp_counted_base_sync.hpp | 1 + .../detail/sp_counted_base_vacpp_ppc.hpp | 1 + .../smart_ptr/detail/sp_counted_base_w32.hpp | 1 + .../smart_ptr/detail/sp_counted_impl.hpp | 15 +++ .../boost/smart_ptr/make_shared_object.hpp | 114 ++++++++++++------ include/boost/smart_ptr/shared_ptr.hpp | 27 +++-- 21 files changed, 129 insertions(+), 49 deletions(-) diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp index 5d22f86..e91179d 100644 --- a/include/boost/smart_ptr/detail/shared_count.hpp +++ b/include/boost/smart_ptr/detail/shared_count.hpp @@ -447,6 +447,11 @@ public: { return pi_? pi_->get_deleter( ti ): 0; } + + void * get_untyped_deleter() const + { + return pi_? pi_->get_untyped_deleter(): 0; + } }; diff --git a/include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp b/include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp index dffd995..cebc243 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp @@ -104,6 +104,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp b/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp index 0208678..fe6c727 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp @@ -96,6 +96,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp index 51ac56a..6c268e8 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp @@ -124,6 +124,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp b/include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp index 1234e78..81eba6f 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp @@ -112,6 +112,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp index d122a49..f6e3904 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp @@ -111,6 +111,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp index 3f1f449..545c8ae 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp @@ -135,6 +135,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp index 7f5c414..2e5bc0e 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp @@ -135,6 +135,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp index 21fa59d..c6d20ce 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp @@ -120,6 +120,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp index 4d7fa8d..173dce5 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp @@ -127,6 +127,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_nt.hpp b/include/boost/smart_ptr/detail/sp_counted_base_nt.hpp index dfd70e7..5c901f9 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_nt.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_nt.hpp @@ -59,6 +59,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp b/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp index 3c56fec..a742c3d 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp @@ -70,6 +70,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp b/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp index e51e676..a043e02 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp @@ -115,6 +115,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp b/include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp index d1b6bec..0e05fef 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp @@ -62,6 +62,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_spin.hpp b/include/boost/smart_ptr/detail/sp_counted_base_spin.hpp index bbd11e6..77734e7 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_spin.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_spin.hpp @@ -84,6 +84,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_sync.hpp b/include/boost/smart_ptr/detail/sp_counted_base_sync.hpp index 41f654e..fafed0e 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_sync.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_sync.hpp @@ -109,6 +109,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp index 842f58f..162f309 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp @@ -104,6 +104,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_w32.hpp b/include/boost/smart_ptr/detail/sp_counted_base_w32.hpp index 06aa456..ff394dc 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_w32.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_w32.hpp @@ -67,6 +67,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; void add_ref_copy() { diff --git a/include/boost/smart_ptr/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp index aab39bd..d15cd3c 100644 --- a/include/boost/smart_ptr/detail/sp_counted_impl.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp @@ -83,6 +83,11 @@ public: return 0; } + virtual void * get_untyped_deleter() + { + return 0; + } + #if defined(BOOST_SP_USE_STD_ALLOCATOR) void * operator new( std::size_t ) @@ -153,6 +158,11 @@ public: return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast( del ): 0; } + virtual void * get_untyped_deleter() + { + return &reinterpret_cast( del ); + } + #if defined(BOOST_SP_USE_STD_ALLOCATOR) void * operator new( std::size_t ) @@ -226,6 +236,11 @@ public: { return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast( d_ ): 0; } + + virtual void * get_untyped_deleter() + { + return &reinterpret_cast( d_ ); + } }; #ifdef __CODEGUARD__ diff --git a/include/boost/smart_ptr/make_shared_object.hpp b/include/boost/smart_ptr/make_shared_object.hpp index c6e28aa..aff19b9 100644 --- a/include/boost/smart_ptr/make_shared_object.hpp +++ b/include/boost/smart_ptr/make_shared_object.hpp @@ -135,7 +135,7 @@ template< class T > typename boost::detail::sp_if_not_array< T >::type make_shar { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -148,11 +148,28 @@ template< class T > typename boost::detail::sp_if_not_array< T >::type make_shar return boost::shared_ptr< T >( pt, pt2 ); } +template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared_noinit() +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); + + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); + + void * pv = pd->address(); + + ::new( pv ) T; + pd->set_initialized(); + + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); +} + template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -165,6 +182,23 @@ template< class T, class A > typename boost::detail::sp_if_not_array< T >::type return boost::shared_ptr< T >( pt, pt2 ); } +template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared_noinit( A const & a ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); + + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); + + void * pv = pd->address(); + + ::new( pv ) T; + pd->set_initialized(); + + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); +} + #if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) // Variadic templates, rvalue reference @@ -173,7 +207,7 @@ template< class T, class Arg1, class... Args > typename boost::detail::sp_if_not { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -190,7 +224,7 @@ template< class T, class A, class Arg1, class... Args > typename boost::detail:: { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -212,7 +246,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -233,7 +267,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -254,7 +288,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -276,7 +310,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -298,7 +332,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -321,7 +355,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -344,7 +378,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -368,7 +402,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -392,7 +426,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -417,7 +451,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -442,7 +476,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -468,7 +502,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -494,7 +528,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -521,7 +555,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -548,7 +582,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -576,7 +610,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -604,7 +638,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 && a1, A2 && { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -633,7 +667,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -666,7 +700,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1 ) { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -684,7 +718,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -702,7 +736,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -720,7 +754,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -738,7 +772,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -756,7 +790,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -774,7 +808,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -792,7 +826,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -810,7 +844,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -828,7 +862,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -846,7 +880,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -864,7 +898,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -882,7 +916,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -900,7 +934,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -918,7 +952,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -936,7 +970,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -954,7 +988,7 @@ typename boost::detail::sp_if_not_array< T >::type make_shared( A1 const & a1, A { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); @@ -972,7 +1006,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, { boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); - boost::detail::sp_ms_deleter< T > * pd = boost::get_deleter< boost::detail::sp_ms_deleter< T > >( pt ); + boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() ); void * pv = pd->address(); diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 3b1ac79..8954d1d 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -696,11 +696,16 @@ public: return pn < rhs.pn; } - void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const + void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_NOEXCEPT { return pn.get_deleter( ti ); } + void * _internal_get_untyped_deleter() const BOOST_NOEXCEPT + { + return pn.get_untyped_deleter(); + } + bool _internal_equiv( shared_ptr const & r ) const BOOST_NOEXCEPT { return px == r.px && pn == r.pn; @@ -881,9 +886,9 @@ template D * basic_get_deleter(shared_ptr const & p) #else -template D * basic_get_deleter(shared_ptr const & p) +template D * basic_get_deleter( shared_ptr const & p ) BOOST_NOEXCEPT { - return static_cast(p._internal_get_deleter(BOOST_SP_TYPEID(D))); + return static_cast( p._internal_get_deleter(BOOST_SP_TYPEID(D)) ); } #endif @@ -904,11 +909,13 @@ public: { deleter_ = deleter; } - template D* get_deleter() const + + template D* get_deleter() const BOOST_NOEXCEPT { - return boost::detail::basic_get_deleter(deleter_); + return boost::detail::basic_get_deleter( deleter_ ); } - template< class T> void operator()( T* ) + + template< class T> void operator()( T* ) { BOOST_ASSERT( deleter_.use_count() <= 1 ); deleter_.reset(); @@ -917,17 +924,19 @@ public: } // namespace detail -template D * get_deleter(shared_ptr const & p) +template D * get_deleter( shared_ptr const & p ) BOOST_NOEXCEPT { D *del = detail::basic_get_deleter(p); - if(del == 0) + + if(del == 0) { detail::esft2_deleter_wrapper *del_wrapper = detail::basic_get_deleter(p); // 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::esft2_deleter_wrapper::get_deleter(); } - return del; + + return del; } // atomic access From 6a218a5ef244bbb4d809a26ea6878e4dbdcdb28d Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Fri, 14 Dec 2012 18:35:03 +0000 Subject: [PATCH 122/140] Merged revision(s) 81886,81887,81894,81905 from trunk: Use BOOST_NO_CXX11_RVALUE_REFERENCES and BOOST_NO_CXX11_VARIADIC_TEMPLATES instead of the legacy macros. Rename identifiers of detail utility functions. ........ Two detail utility functions identifier renaming reverted ........ Remove -fno-deduce-init-list for certain tests in Jamfile.v2 ........ Correct call to init_list in make_shared and allocate_shared. Move g++ failing case into separate test to not mask other issues. ........ [SVN r81945] --- .../boost/smart_ptr/allocate_shared_array.hpp | 70 +++++++++---------- .../boost/smart_ptr/detail/array_deleter.hpp | 56 +++++++-------- .../boost/smart_ptr/detail/array_utility.hpp | 28 ++++---- include/boost/smart_ptr/make_shared_array.hpp | 68 +++++++++--------- make_shared_array.html | 22 +++--- test/Jamfile.v2 | 2 + test/allocate_shared_array_create_test.cpp | 2 +- test/allocate_shared_array_init_test.cpp | 58 +++++++-------- test/allocate_shared_array_test.cpp | 2 +- test/allocate_shared_array_throws_test.cpp | 2 +- test/allocate_shared_arrays_create_test.cpp | 27 +++---- test/allocate_shared_arrays_init_test.cpp | 23 ++++++ test/allocate_shared_arrays_test.cpp | 2 +- test/make_shared_array_create_test.cpp | 2 +- test/make_shared_array_init_test.cpp | 58 +++++++-------- test/make_shared_array_test.cpp | 2 +- test/make_shared_array_throws_test.cpp | 2 +- test/make_shared_arrays_create_test.cpp | 27 +++---- test/make_shared_arrays_init_test.cpp | 23 ++++++ test/make_shared_arrays_test.cpp | 2 +- 20 files changed, 256 insertions(+), 222 deletions(-) create mode 100644 test/allocate_shared_arrays_init_test.cpp create mode 100644 test/make_shared_arrays_init_test.cpp diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index 7f78d0e..3ee1655 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -33,10 +33,10 @@ namespace boost { typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct(p2); + d2->init(p2); return boost::shared_ptr(s1, p1); } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template inline typename boost::detail::sp_if_array::type allocate_shared(const A& allocator, std::size_t size, Args&&... args) { @@ -51,7 +51,7 @@ namespace boost { typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct(p2, boost::detail::sp_forward(args)...); + d2->init(p2, boost::detail::sp_forward(args)...); return boost::shared_ptr(s1, p1); } template @@ -70,30 +70,7 @@ namespace boost { typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct(p2, boost::detail::sp_forward(args)...); - return boost::shared_ptr(s1, p1); - } -#endif -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - template - inline typename boost::detail::sp_if_array::type - allocate_shared(const A& allocator, - std::initializer_list::type> list) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef const T2 T3; - T1* p1 = 0; - T2* p2 = 0; - T3* p3 = 0; - std::size_t n1 = list.size() * boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1(n1); - boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p3 = reinterpret_cast(list.begin()); - p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct_list(p2, p3); + d2->init(p2, boost::detail::sp_forward(args)...); return boost::shared_ptr(s1, p1); } #endif @@ -117,7 +94,7 @@ namespace boost { p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct_list(p2, p3); + d2->init_list(p2, p3); return boost::shared_ptr(s1, p1); } template @@ -141,7 +118,7 @@ namespace boost { p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct_list(p2, p3); + d2->template init_list(p2, p3); return boost::shared_ptr(s1, p1); } template @@ -165,10 +142,33 @@ namespace boost { p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct_list(p2, p3); + d2->template init_list(p2, p3); return boost::shared_ptr(s1, p1); } -#if defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + template + inline typename boost::detail::sp_if_array::type + allocate_shared(const A& allocator, + std::initializer_list::type> list) { + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; + typedef const T2 T3; + T1* p1 = 0; + T2* p2 = 0; + T3* p3 = 0; + std::size_t n1 = list.size() * boost::detail::array_total::size; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1(n1); + boost::shared_ptr s1(p1, d1, a1); + typedef boost::detail::array_deleter* D2; + p3 = reinterpret_cast(list.begin()); + p1 = reinterpret_cast(p2); + D2 d2 = static_cast(s1._internal_get_untyped_deleter()); + d2->init_list(p2, p3); + return boost::shared_ptr(s1, p1); + } +#endif +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template inline typename boost::detail::sp_if_array::type allocate_shared(const A& allocator, std::size_t size, @@ -184,7 +184,7 @@ namespace boost { typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct(p2, boost::detail::sp_forward(value)); + d2->init(p2, boost::detail::sp_forward(value)); return boost::shared_ptr(s1, p1); } template @@ -204,7 +204,7 @@ namespace boost { typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct(p2, boost::detail::sp_forward(value)); + d2->init(p2, boost::detail::sp_forward(value)); return boost::shared_ptr(s1, p1); } #endif @@ -223,7 +223,7 @@ namespace boost { typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct_noinit(p2); + d2->noinit(p2); return boost::shared_ptr(s1, p1); } template @@ -242,7 +242,7 @@ namespace boost { typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct_noinit(p2); + d2->noinit(p2); return boost::shared_ptr(s1, p1); } } diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index 7909265..11f23fa 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -28,34 +28,34 @@ namespace boost { array_destroy(object, size); } } - void construct(T* memory) { - array_construct(memory, size); + void init(T* memory) { + array_init(memory, size); object = memory; } -#if defined(BOOST_HAS_RVALUE_REFS) - void construct(T* memory, T&& value) { - array_construct_value(memory, size, sp_forward(value)); +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + void init(T* memory, T&& value) { + array_init_value(memory, size, sp_forward(value)); object = memory; } -#if defined(BOOST_HAS_VARIADIC_TMPL) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template - void construct(T* memory, Args&&... args) { - array_construct_args(memory, size, sp_forward(args)...); + void init(T* memory, Args&&... args) { + array_init_args(memory, size, sp_forward(args)...); object = memory; } #endif #endif - void construct_list(T* memory, const T* list) { - array_construct_list(memory, size, list); + void init_list(T* memory, const T* list) { + array_init_list(memory, size, list); object = memory; } template - void construct_list(T* memory, const T* list) { - array_construct_list(memory, size, list); + void init_list(T* memory, const T* list) { + array_init_list(memory, size, list); object = memory; } - void construct_noinit(T* memory) { - array_construct_noinit(memory, size); + void noinit(T* memory) { + array_noinit(memory, size); object = memory; } void operator()(const void*) { @@ -79,34 +79,34 @@ namespace boost { array_destroy(object, N); } } - void construct(T* memory) { - array_construct(memory, N); + void init(T* memory) { + array_init(memory, N); object = memory; } -#if defined(BOOST_HAS_RVALUE_REFS) - void construct(T* memory, T&& value) { - array_construct_value(memory, N, sp_forward(value)); +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + void init(T* memory, T&& value) { + array_init_value(memory, N, sp_forward(value)); object = memory; } -#if defined(BOOST_HAS_VARIADIC_TMPL) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template - void construct(T* memory, Args&&... args) { - array_construct_args(memory, N, sp_forward(args)...); + void init(T* memory, Args&&... args) { + array_init_args(memory, N, sp_forward(args)...); object = memory; } #endif #endif - void construct_list(T* memory, const T* list) { - array_construct_list(memory, N, list); + void init_list(T* memory, const T* list) { + array_init_list(memory, N, list); object = memory; } template - void construct_list(T* memory, const T* list) { - array_construct_list(memory, N, list); + void init_list(T* memory, const T* list) { + array_init_list(memory, N, list); object = memory; } - void construct_noinit(T* memory) { - array_construct_noinit(memory, N); + void noinit(T* memory) { + array_noinit(memory, N); object = memory; } void operator()(const void*) { diff --git a/include/boost/smart_ptr/detail/array_utility.hpp b/include/boost/smart_ptr/detail/array_utility.hpp index 3b685ad..35694f0 100644 --- a/include/boost/smart_ptr/detail/array_utility.hpp +++ b/include/boost/smart_ptr/detail/array_utility.hpp @@ -30,13 +30,13 @@ namespace boost { array_destroy(memory, size, type); } template - inline void array_construct(T* memory, std::size_t size, boost::true_type) { + inline void array_init(T* memory, std::size_t size, boost::true_type) { for (std::size_t i = 0; i < size; i++) { memory[i] = T(); } } template - inline void array_construct(T* memory, std::size_t size, boost::false_type) { + inline void array_init(T* memory, std::size_t size, boost::false_type) { std::size_t i = 0; try { for (; i < size; i++) { @@ -49,13 +49,13 @@ namespace boost { } } template - inline void array_construct(T* memory, std::size_t size) { + inline void array_init(T* memory, std::size_t size) { boost::has_trivial_default_constructor type; - array_construct(memory, size, type); + array_init(memory, size, type); } -#if defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template - inline void array_construct_value(T* memory, std::size_t size, T&& value) { + inline void array_init_value(T* memory, std::size_t size, T&& value) { std::size_t i = 0; try { for (; i < size; i++) { @@ -67,9 +67,9 @@ namespace boost { throw; } } -#if defined(BOOST_HAS_VARIADIC_TMPL) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template - inline void array_construct_args(T* memory, std::size_t size, Args&&... args) { + inline void array_init_args(T* memory, std::size_t size, Args&&... args) { std::size_t i = 0; try { for (; i < size; i++) { @@ -84,7 +84,7 @@ namespace boost { #endif #endif template - inline void array_construct_list(T* memory, std::size_t size, const T* list) { + inline void array_init_list(T* memory, std::size_t size, const T* list) { std::size_t i = 0; try { for (; i < size; i++) { @@ -97,7 +97,7 @@ namespace boost { } } template - inline void array_construct_list(T* memory, std::size_t size, const T* list) { + inline void array_init_list(T* memory, std::size_t size, const T* list) { std::size_t i = 0; try { for (; i < size; i++) { @@ -110,10 +110,10 @@ namespace boost { } } template - inline void array_construct_noinit(T*, std::size_t, boost::true_type) { + inline void array_noinit(T*, std::size_t, boost::true_type) { } template - inline void array_construct_noinit(T* memory, std::size_t size, boost::false_type) { + inline void array_noinit(T* memory, std::size_t size, boost::false_type) { std::size_t i = 0; try { for (; i < size; i++) { @@ -126,9 +126,9 @@ namespace boost { } } template - inline void array_construct_noinit(T* memory, std::size_t size) { + inline void array_noinit(T* memory, std::size_t size) { boost::has_trivial_default_constructor type; - array_construct_noinit(memory, size, type); + array_noinit(memory, size, type); } } } diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index b9c197c..eb0578d 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -33,10 +33,10 @@ namespace boost { typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct(p2); + d2->init(p2); return boost::shared_ptr(s1, p1); } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template inline typename boost::detail::sp_if_array::type make_shared(std::size_t size, Args&&... args) { @@ -51,7 +51,7 @@ namespace boost { typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct(p2, boost::detail::sp_forward(args)...); + d2->init(p2, boost::detail::sp_forward(args)...); return boost::shared_ptr(s1, p1); } template @@ -70,29 +70,7 @@ namespace boost { typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct(p2, boost::detail::sp_forward(args)...); - return boost::shared_ptr(s1, p1); - } -#endif -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - template - inline typename boost::detail::sp_if_array::type - make_shared(std::initializer_list::type> list) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef const T2 T3; - T1* p1 = 0; - T2* p2 = 0; - T3* p3 = 0; - std::size_t n1 = list.size() * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1(n1); - boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p3 = reinterpret_cast(list.begin()); - p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct_list(p2, p3); + d2->init(p2, boost::detail::sp_forward(args)...); return boost::shared_ptr(s1, p1); } #endif @@ -116,7 +94,7 @@ namespace boost { p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct_list(p2, p3); + d2->init_list(p2, p3); return boost::shared_ptr(s1, p1); } template @@ -140,7 +118,7 @@ namespace boost { p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct_list(p2, p3); + d2->template init_list(p2, p3); return boost::shared_ptr(s1, p1); } template @@ -163,10 +141,32 @@ namespace boost { p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct_list(p2, p3); + d2->template init_list(p2, p3); return boost::shared_ptr(s1, p1); } -#if defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + template + inline typename boost::detail::sp_if_array::type + make_shared(std::initializer_list::type> list) { + typedef typename boost::detail::array_inner::type T1; + typedef typename boost::detail::array_base::type T2; + typedef const T2 T3; + T1* p1 = 0; + T2* p2 = 0; + T3* p3 = 0; + std::size_t n1 = list.size() * boost::detail::array_total::size; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1(n1); + boost::shared_ptr s1(p1, d1, a1); + typedef boost::detail::array_deleter* D2; + p3 = reinterpret_cast(list.begin()); + p1 = reinterpret_cast(p2); + D2 d2 = static_cast(s1._internal_get_untyped_deleter()); + d2->init_list(p2, p3); + return boost::shared_ptr(s1, p1); + } +#endif +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template inline typename boost::detail::sp_if_array::type make_shared(std::size_t size, @@ -182,7 +182,7 @@ namespace boost { typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct(p2, boost::detail::sp_forward(value)); + d2->init(p2, boost::detail::sp_forward(value)); return boost::shared_ptr(s1, p1); } template @@ -201,7 +201,7 @@ namespace boost { typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct(p2, boost::detail::sp_forward(value)); + d2->init(p2, boost::detail::sp_forward(value)); return boost::shared_ptr(s1, p1); } #endif @@ -220,7 +220,7 @@ namespace boost { typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct_noinit(p2); + d2->noinit(p2); return boost::shared_ptr(s1, p1); } template @@ -239,7 +239,7 @@ namespace boost { typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->construct_noinit(p2); + d2->noinit(p2); return boost::shared_ptr(s1, p1); } } diff --git a/make_shared_array.html b/make_shared_array.html index 1f0f4d3..fb75790 100644 --- a/make_shared_array.html +++ b/make_shared_array.html @@ -35,7 +35,7 @@ template<typename T, typename A> shared_ptr<T[]> allocate_shared(const A& allocator, size_t size); -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template<typename T, typename... Args> shared_ptr<T[]> make_shared(size_t size, Args&&... args); @@ -48,15 +48,7 @@ template<typename T, typename A, typename... Args> shared_ptr<T[N]> allocate_shared(const A& allocator, Args&&... args); #endif - -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - template<typename T, typename... Args> - shared_ptr<T[]> make_shared(initializer_list<T> list); - - template<typename T, typename A, typename... Args> - shared_ptr<T[]> allocate_shared(const A& allocator, initializer_list<T> list); -#endif - + #if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) template<typename T, typename... Args> shared_ptr<T[N]> make_shared(const T (&list)[N]); @@ -76,7 +68,15 @@ template<typename T, typename A, typename... Args> shared_ptr<T[M][N]> allocate_shared(const A& allocator, const T (&list)[N]); -#if defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + template<typename T, typename... Args> + shared_ptr<T[]> make_shared(initializer_list<T> list); + + template<typename T, typename A, typename... Args> + shared_ptr<T[]> allocate_shared(const A& allocator, initializer_list<T> list); +#endif + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template<typename T> shared_ptr<T[]> make_shared(size_t size, T&& value); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 9f08375..1ed197a 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -139,6 +139,7 @@ import testing ; [ run make_shared_array_create_test.cpp ] [ run make_shared_array_init_test.cpp ] [ run make_shared_arrays_create_test.cpp ] + [ run make_shared_arrays_init_test.cpp ] [ run make_shared_array_throws_test.cpp ] [ run make_shared_array_esft_test.cpp ] [ run make_shared_array_args_test.cpp ] @@ -147,6 +148,7 @@ import testing ; [ run allocate_shared_array_create_test.cpp ] [ run allocate_shared_array_init_test.cpp ] [ run allocate_shared_arrays_create_test.cpp ] + [ run allocate_shared_arrays_init_test.cpp ] [ run allocate_shared_array_throws_test.cpp ] [ run allocate_shared_array_esft_test.cpp ] [ run allocate_shared_array_args_test.cpp ] diff --git a/test/allocate_shared_array_create_test.cpp b/test/allocate_shared_array_create_test.cpp index 2e03be6..90b6b96 100644 --- a/test/allocate_shared_array_create_test.cpp +++ b/test/allocate_shared_array_create_test.cpp @@ -36,7 +36,7 @@ private: int type::instances = 0; int main() { -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) BOOST_TEST(type::instances == 0); { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, 1, 2, 3, 4, 5, 6, 7, 8, 9); diff --git a/test/allocate_shared_array_init_test.cpp b/test/allocate_shared_array_init_test.cpp index 1ff437f..c75b41f 100644 --- a/test/allocate_shared_array_init_test.cpp +++ b/test/allocate_shared_array_init_test.cpp @@ -20,6 +20,35 @@ private: }; int main() { +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + BOOST_TEST(a1[0].value == 0); + BOOST_TEST(a1[1].value == 1); + BOOST_TEST(a1[2].value == 2); + BOOST_TEST(a1[3].value == 3); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); + BOOST_TEST(a1[0].value == 0); + BOOST_TEST(a1[1].value == 1); + BOOST_TEST(a1[2].value == 2); + BOOST_TEST(a1[3].value == 3); + } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); @@ -50,35 +79,6 @@ int main() { BOOST_TEST(a1[3].value == 3); } #endif -#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); - BOOST_TEST(a1[0].value == 0); - BOOST_TEST(a1[1].value == 1); - BOOST_TEST(a1[2].value == 2); - BOOST_TEST(a1[3].value == 3); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); - BOOST_TEST(a1[0].value == 0); - BOOST_TEST(a1[1].value == 1); - BOOST_TEST(a1[2].value == 2); - BOOST_TEST(a1[3].value == 3); - } #endif return boost::report_errors(); } diff --git a/test/allocate_shared_array_test.cpp b/test/allocate_shared_array_test.cpp index 84ef3a8..f27e5e8 100644 --- a/test/allocate_shared_array_test.cpp +++ b/test/allocate_shared_array_test.cpp @@ -73,7 +73,7 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) BOOST_TEST(type::instances == 0); { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3, 1, 5); diff --git a/test/allocate_shared_array_throws_test.cpp b/test/allocate_shared_array_throws_test.cpp index d300f2c..bb5ac52 100644 --- a/test/allocate_shared_array_throws_test.cpp +++ b/test/allocate_shared_array_throws_test.cpp @@ -43,7 +43,7 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) BOOST_TEST(type::instances == 0); try { boost::allocate_shared(std::allocator()); diff --git a/test/allocate_shared_arrays_create_test.cpp b/test/allocate_shared_arrays_create_test.cpp index 4c53e91..a7e95d7 100644 --- a/test/allocate_shared_arrays_create_test.cpp +++ b/test/allocate_shared_arrays_create_test.cpp @@ -21,22 +21,6 @@ private: }; int main() { -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), {0, 1, 2, 3}); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { {0, 1}, {2, 3} }); - BOOST_TEST(a1[0][0] == 0); - BOOST_TEST(a1[0][1] == 1); - BOOST_TEST(a1[1][0] == 2); - BOOST_TEST(a1[1][1] == 3); - } -#endif #if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), {0, 1, 2, 3}); @@ -80,7 +64,16 @@ int main() { BOOST_TEST(a1[1][1][0] == 2); BOOST_TEST(a1[1][1][1] == 3); } -#if defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), {0, 1, 2, 3}); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } +#endif +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 4, {1, 2}); BOOST_TEST(a1[0].x == 1); diff --git a/test/allocate_shared_arrays_init_test.cpp b/test/allocate_shared_arrays_init_test.cpp new file mode 100644 index 0000000..76173fa --- /dev/null +++ b/test/allocate_shared_arrays_init_test.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +int main() { +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { {0, 1}, {2, 3} }); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 2); + BOOST_TEST(a1[1][1] == 3); + } +#endif + return boost::report_errors(); +} diff --git a/test/allocate_shared_arrays_test.cpp b/test/allocate_shared_arrays_test.cpp index 7c719ce..c0746d3 100644 --- a/test/allocate_shared_arrays_test.cpp +++ b/test/allocate_shared_arrays_test.cpp @@ -62,7 +62,7 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) BOOST_TEST(type::instances == 0); { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, 1, 5); diff --git a/test/make_shared_array_create_test.cpp b/test/make_shared_array_create_test.cpp index 46db862..0bdd635 100644 --- a/test/make_shared_array_create_test.cpp +++ b/test/make_shared_array_create_test.cpp @@ -36,7 +36,7 @@ private: int type::instances = 0; int main() { -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) BOOST_TEST(type::instances == 0); { boost::shared_ptr a1 = boost::make_shared(2, 1, 2, 3, 4, 5, 6, 7, 8, 9); diff --git a/test/make_shared_array_init_test.cpp b/test/make_shared_array_init_test.cpp index fd61caf..11dcb1c 100644 --- a/test/make_shared_array_init_test.cpp +++ b/test/make_shared_array_init_test.cpp @@ -20,6 +20,35 @@ private: }; int main() { +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + BOOST_TEST(a1[0].value == 0); + BOOST_TEST(a1[1].value == 1); + BOOST_TEST(a1[2].value == 2); + BOOST_TEST(a1[3].value == 3); + } + { + boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); + BOOST_TEST(a1[0].value == 0); + BOOST_TEST(a1[1].value == 1); + BOOST_TEST(a1[2].value == 2); + BOOST_TEST(a1[3].value == 3); + } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) { boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); @@ -50,35 +79,6 @@ int main() { BOOST_TEST(a1[3].value == 3); } #endif -#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); - BOOST_TEST(a1[0].value == 0); - BOOST_TEST(a1[1].value == 1); - BOOST_TEST(a1[2].value == 2); - BOOST_TEST(a1[3].value == 3); - } - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); - BOOST_TEST(a1[0].value == 0); - BOOST_TEST(a1[1].value == 1); - BOOST_TEST(a1[2].value == 2); - BOOST_TEST(a1[3].value == 3); - } #endif return boost::report_errors(); } diff --git a/test/make_shared_array_test.cpp b/test/make_shared_array_test.cpp index d9b9134..8193553 100644 --- a/test/make_shared_array_test.cpp +++ b/test/make_shared_array_test.cpp @@ -73,7 +73,7 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) BOOST_TEST(type::instances == 0); { boost::shared_ptr a1 = boost::make_shared(3, 1, 5); diff --git a/test/make_shared_array_throws_test.cpp b/test/make_shared_array_throws_test.cpp index 4faf193..69e9b88 100644 --- a/test/make_shared_array_throws_test.cpp +++ b/test/make_shared_array_throws_test.cpp @@ -43,7 +43,7 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) BOOST_TEST(type::instances == 0); try { boost::make_shared(); diff --git a/test/make_shared_arrays_create_test.cpp b/test/make_shared_arrays_create_test.cpp index 7fc36bd..c6a1b4f 100644 --- a/test/make_shared_arrays_create_test.cpp +++ b/test/make_shared_arrays_create_test.cpp @@ -21,22 +21,6 @@ private: }; int main() { -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - { - boost::shared_ptr a1 = boost::make_shared({0, 1, 2, 3}); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::make_shared({ {0, 1}, {2, 3} }); - BOOST_TEST(a1[0][0] == 0); - BOOST_TEST(a1[0][1] == 1); - BOOST_TEST(a1[1][0] == 2); - BOOST_TEST(a1[1][1] == 3); - } -#endif #if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) { boost::shared_ptr a1 = boost::make_shared({0, 1, 2, 3}); @@ -80,7 +64,16 @@ int main() { BOOST_TEST(a1[1][1][0] == 2); BOOST_TEST(a1[1][1][1] == 3); } -#if defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + { + boost::shared_ptr a1 = boost::make_shared({0, 1, 2, 3}); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 2); + BOOST_TEST(a1[3] == 3); + } +#endif +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) { boost::shared_ptr a1 = boost::make_shared(4, {1, 2}); BOOST_TEST(a1[0].x == 1); diff --git a/test/make_shared_arrays_init_test.cpp b/test/make_shared_arrays_init_test.cpp new file mode 100644 index 0000000..1646d5a --- /dev/null +++ b/test/make_shared_arrays_init_test.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +int main() { +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + { + boost::shared_ptr a1 = boost::make_shared({ {0, 1}, {2, 3} }); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 2); + BOOST_TEST(a1[1][1] == 3); + } +#endif + return boost::report_errors(); +} diff --git a/test/make_shared_arrays_test.cpp b/test/make_shared_arrays_test.cpp index eb79d4f..e03a13c 100644 --- a/test/make_shared_arrays_test.cpp +++ b/test/make_shared_arrays_test.cpp @@ -62,7 +62,7 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) BOOST_TEST(type::instances == 0); { boost::shared_ptr a1 = boost::make_shared(2, 1, 5); From 5ba33125190c4458b9f8d34af820428f5d0cee99 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 15 Dec 2012 20:20:20 +0000 Subject: [PATCH 123/140] Merged revision(s) 81900-81901 from trunk: Replace use of BOOST_HAS_RVALUE_REFS with !BOOST_NO_CXX11_RVALUE_REFERENCES. ........ Replace use of BOOST_HAS_VARIADIC_TMPL with !BOOST_NO_CXX11_VARIADIC_TEMPLATES. ........ [SVN r81979] --- include/boost/smart_ptr/detail/shared_count.hpp | 4 ++-- include/boost/smart_ptr/detail/sp_forward.hpp | 2 +- include/boost/smart_ptr/intrusive_ptr.hpp | 2 +- include/boost/smart_ptr/make_shared_object.hpp | 4 ++-- include/boost/smart_ptr/shared_array.hpp | 4 ++-- include/boost/smart_ptr/shared_ptr.hpp | 8 ++++---- include/boost/smart_ptr/weak_ptr.hpp | 6 +++--- make_shared.html | 2 +- test/allocate_shared_array_args_test.cpp | 2 +- test/intrusive_ptr_move_test.cpp | 4 ++-- test/make_shared_array_args_test.cpp | 2 +- test/make_shared_perfect_forwarding_test.cpp | 6 +++--- test/shared_ptr_move_test.cpp | 4 ++-- test/weak_ptr_move_test.cpp | 4 ++-- 14 files changed, 27 insertions(+), 27 deletions(-) diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp index e91179d..f055fd0 100644 --- a/include/boost/smart_ptr/detail/shared_count.hpp +++ b/include/boost/smart_ptr/detail/shared_count.hpp @@ -382,7 +382,7 @@ public: if( pi_ != 0 ) pi_->add_ref_copy(); } -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) shared_count(shared_count && r): pi_(r.pi_) // nothrow #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) @@ -494,7 +494,7 @@ public: // Move support -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) weak_count(weak_count && r): pi_(r.pi_) // nothrow #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) diff --git a/include/boost/smart_ptr/detail/sp_forward.hpp b/include/boost/smart_ptr/detail/sp_forward.hpp index 25c4d48..5f1d190 100644 --- a/include/boost/smart_ptr/detail/sp_forward.hpp +++ b/include/boost/smart_ptr/detail/sp_forward.hpp @@ -23,7 +23,7 @@ namespace boost namespace detail { -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template< class T > T&& sp_forward( T & t ) BOOST_NOEXCEPT { diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp index ffb2dba..64a2923 100644 --- a/include/boost/smart_ptr/intrusive_ptr.hpp +++ b/include/boost/smart_ptr/intrusive_ptr.hpp @@ -108,7 +108,7 @@ public: // Move support -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) intrusive_ptr(intrusive_ptr && rhs) BOOST_NOEXCEPT : px( rhs.px ) { diff --git a/include/boost/smart_ptr/make_shared_object.hpp b/include/boost/smart_ptr/make_shared_object.hpp index aff19b9..89a7116 100644 --- a/include/boost/smart_ptr/make_shared_object.hpp +++ b/include/boost/smart_ptr/make_shared_object.hpp @@ -199,7 +199,7 @@ template< class T, class A > typename boost::detail::sp_if_not_array< T >::type return boost::shared_ptr< T >( pt, pt2 ); } -#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) // Variadic templates, rvalue reference @@ -237,7 +237,7 @@ template< class T, class A, class Arg1, class... Args > typename boost::detail:: return boost::shared_ptr< T >( pt, pt2 ); } -#elif defined( BOOST_HAS_RVALUE_REFS ) +#elif !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) // For example MSVC 10.0 diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp index f54f481..38047ff 100644 --- a/include/boost/smart_ptr/shared_array.hpp +++ b/include/boost/smart_ptr/shared_array.hpp @@ -86,7 +86,7 @@ public: // generated copy constructor, destructor are fine... -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) // ... except in C++0x, move disables the implicit copy @@ -145,7 +145,7 @@ public: #endif -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) shared_array & operator=( shared_array && r ) BOOST_NOEXCEPT { diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 8954d1d..fd72995 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -389,7 +389,7 @@ public: // generated copy constructor, destructor are fine... -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) // ... except in C++0x, move disables the implicit copy @@ -452,7 +452,7 @@ public: boost::detail::sp_deleter_construct( this, tmp ); } -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template shared_ptr( std::auto_ptr && r ): px(r.get()), pn() @@ -527,7 +527,7 @@ public: return *this; } -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template shared_ptr & operator=( std::auto_ptr && r ) @@ -562,7 +562,7 @@ public: // Move support -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) shared_ptr( shared_ptr && r ) BOOST_NOEXCEPT : px( r.px ), pn() { diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp index 59cdd45..e3e9ad9 100644 --- a/include/boost/smart_ptr/weak_ptr.hpp +++ b/include/boost/smart_ptr/weak_ptr.hpp @@ -37,7 +37,7 @@ public: // generated copy constructor, assignment, destructor are fine... -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) // ... except in C++0x, move disables the implicit copy @@ -86,7 +86,7 @@ public: boost::detail::sp_assert_convertible< Y, T >(); } -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) @@ -149,7 +149,7 @@ public: return *this; } -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template weak_ptr & operator=( weak_ptr && r ) BOOST_NOEXCEPT diff --git a/make_shared.html b/make_shared.html index e47fe2a..e2335d3 100644 --- a/make_shared.html +++ b/make_shared.html @@ -41,7 +41,7 @@ template<typename T, typename A> shared_ptr<T> allocate_shared( A const & ); -#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) // C++0x prototypes +#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) // C++0x prototypes template<typename T, typename... Args> shared_ptr<T> make_shared( Args && ... args ); diff --git a/test/allocate_shared_array_args_test.cpp b/test/allocate_shared_array_args_test.cpp index 1226b94..f3d38b6 100644 --- a/test/allocate_shared_array_args_test.cpp +++ b/test/allocate_shared_array_args_test.cpp @@ -57,7 +57,7 @@ int main() BOOST_TEST( X::instances == 0 ); } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) { boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1 ); diff --git a/test/intrusive_ptr_move_test.cpp b/test/intrusive_ptr_move_test.cpp index 3faf16e..0e89764 100644 --- a/test/intrusive_ptr_move_test.cpp +++ b/test/intrusive_ptr_move_test.cpp @@ -32,7 +32,7 @@ #include #include -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) namespace N { @@ -173,7 +173,7 @@ int main() return boost::report_errors(); } -#else // !defined( BOOST_HAS_RVALUE_REFS ) +#else // defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) int main() { diff --git a/test/make_shared_array_args_test.cpp b/test/make_shared_array_args_test.cpp index c308c7a..8a89429 100644 --- a/test/make_shared_array_args_test.cpp +++ b/test/make_shared_array_args_test.cpp @@ -56,7 +56,7 @@ int main() BOOST_TEST( X::instances == 0 ); } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) +#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) { boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1 ); diff --git a/test/make_shared_perfect_forwarding_test.cpp b/test/make_shared_perfect_forwarding_test.cpp index bd5f5c5..b7ad05d 100644 --- a/test/make_shared_perfect_forwarding_test.cpp +++ b/test/make_shared_perfect_forwarding_test.cpp @@ -12,14 +12,14 @@ #include #include -#if !defined( BOOST_HAS_RVALUE_REFS ) +#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) int main() { return 0; } -#else // BOOST_HAS_RVALUE_REFS +#else // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) class myarg { @@ -95,4 +95,4 @@ int main() return boost::report_errors(); } -#endif // BOOST_HAS_RVALUE_REFS +#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) diff --git a/test/shared_ptr_move_test.cpp b/test/shared_ptr_move_test.cpp index 82ba9d6..e659b24 100644 --- a/test/shared_ptr_move_test.cpp +++ b/test/shared_ptr_move_test.cpp @@ -12,7 +12,7 @@ #include #include -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) struct X { @@ -97,7 +97,7 @@ int main() return boost::report_errors(); } -#else // !defined( BOOST_HAS_RVALUE_REFS ) +#else // defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) int main() { diff --git a/test/weak_ptr_move_test.cpp b/test/weak_ptr_move_test.cpp index 4df3691..dbf2629 100644 --- a/test/weak_ptr_move_test.cpp +++ b/test/weak_ptr_move_test.cpp @@ -12,7 +12,7 @@ #include #include -#if defined( BOOST_HAS_RVALUE_REFS ) +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) struct X { @@ -112,7 +112,7 @@ int main() return boost::report_errors(); } -#else // !defined( BOOST_HAS_RVALUE_REFS ) +#else // defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) int main() { From 049d0698b7845df5dcaf3c7d388cd32ec05fd497 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 16 Dec 2012 16:20:03 +0000 Subject: [PATCH 124/140] Manually apply a change from [58306] that didn't get merged at the time. [SVN r82026] --- include/boost/smart_ptr/shared_ptr.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index fd72995..2d903a3 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -926,11 +926,11 @@ public: template D * get_deleter( shared_ptr const & p ) BOOST_NOEXCEPT { - D *del = detail::basic_get_deleter(p); + D *del = boost::detail::basic_get_deleter(p); if(del == 0) { - detail::esft2_deleter_wrapper *del_wrapper = detail::basic_get_deleter(p); + boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter(p); // 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::esft2_deleter_wrapper::get_deleter(); From c55ffa1cabc7a175e495fb195694c5da0c707419 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 18 Dec 2012 19:09:57 +0000 Subject: [PATCH 125/140] Merge Jamfile.v2 from trunk [SVN r82084] --- test/Jamfile.v2 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 1ed197a..d4f7af1 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -137,18 +137,18 @@ import testing ; [ run make_shared_array_test.cpp ] [ run make_shared_arrays_test.cpp ] [ run make_shared_array_create_test.cpp ] - [ run make_shared_array_init_test.cpp ] - [ run make_shared_arrays_create_test.cpp ] - [ run make_shared_arrays_init_test.cpp ] + [ run make_shared_array_init_test.cpp : : : gcc-4.6.3_0x:-fno-deduce-init-list ] + [ run make_shared_arrays_create_test.cpp : : : gcc-4.6.3_0x:-fno-deduce-init-list ] + [ run make_shared_arrays_init_test.cpp : : : gcc-4.6.3_0x:-fno-deduce-init-list ] [ run make_shared_array_throws_test.cpp ] [ run make_shared_array_esft_test.cpp ] [ run make_shared_array_args_test.cpp ] [ run allocate_shared_array_test.cpp ] [ run allocate_shared_arrays_test.cpp ] [ run allocate_shared_array_create_test.cpp ] - [ run allocate_shared_array_init_test.cpp ] - [ run allocate_shared_arrays_create_test.cpp ] - [ run allocate_shared_arrays_init_test.cpp ] + [ run allocate_shared_array_init_test.cpp : : : gcc-4.6.3_0x:-fno-deduce-init-list ] + [ run allocate_shared_arrays_create_test.cpp : : : gcc-4.6.3_0x:-fno-deduce-init-list ] + [ run allocate_shared_arrays_init_test.cpp : : : gcc-4.6.3_0x:-fno-deduce-init-list ] [ run allocate_shared_array_throws_test.cpp ] [ run allocate_shared_array_esft_test.cpp ] [ run allocate_shared_array_args_test.cpp ] From d3a549e93aa5a009060ea7e8b3632040393e852c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 23 Dec 2012 16:07:27 +0000 Subject: [PATCH 126/140] Merged revision(s) 82188 from trunk: Untabify. [SVN r82189] --- .../boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp | 2 +- include/boost/smart_ptr/shared_ptr.hpp | 8 ++++---- test/array_fail_upa_sp_a.cpp | 2 +- test/array_fail_upa_sp_c.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp b/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp index a043e02..56ed79f 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp @@ -30,7 +30,7 @@ namespace detail inline uint32_t compare_and_swap( uint32_t * dest_, uint32_t compare_, uint32_t swap_ ) { - return __builtin_cellAtomicCompareAndSwap32(dest_,compare_,swap_); + return __builtin_cellAtomicCompareAndSwap32(dest_,compare_,swap_); } inline uint32_t atomic_fetch_and_add( uint32_t * pw, uint32_t dv ) diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 2d903a3..b34b0ac 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -910,12 +910,12 @@ public: deleter_ = deleter; } - template D* get_deleter() const BOOST_NOEXCEPT + template D* get_deleter() const BOOST_NOEXCEPT { return boost::detail::basic_get_deleter( deleter_ ); } - template< class T> void operator()( T* ) + template< class T> void operator()( T* ) { BOOST_ASSERT( deleter_.use_count() <= 1 ); deleter_.reset(); @@ -928,7 +928,7 @@ template D * get_deleter( shared_ptr const & p ) BOOST_NOEX { D *del = boost::detail::basic_get_deleter(p); - if(del == 0) + if(del == 0) { boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter(p); // The following get_deleter method call is fully qualified because @@ -936,7 +936,7 @@ template D * get_deleter( shared_ptr const & p ) BOOST_NOEX if(del_wrapper) del = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter(); } - return del; + return del; } // atomic access diff --git a/test/array_fail_upa_sp_a.cpp b/test/array_fail_upa_sp_a.cpp index b44e07e..4d87fdd 100644 --- a/test/array_fail_upa_sp_a.cpp +++ b/test/array_fail_upa_sp_a.cpp @@ -15,6 +15,6 @@ struct X int main() { - std::unique_ptr px; + std::unique_ptr px; boost::shared_ptr px2; px2 = px; } diff --git a/test/array_fail_upa_sp_c.cpp b/test/array_fail_upa_sp_c.cpp index fe62044..259fda0 100644 --- a/test/array_fail_upa_sp_c.cpp +++ b/test/array_fail_upa_sp_c.cpp @@ -15,6 +15,6 @@ struct X int main() { - std::unique_ptr px; + std::unique_ptr px; boost::shared_ptr px2( px ); } From f6d525759711cfe1c7e51f5d5b296f8974f86d18 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 4 Jan 2013 18:44:47 +0000 Subject: [PATCH 127/140] Merged revision(s) 82349 from trunk: Update documentation for nullptr, owner_before, explicit operator bool. [SVN r82357] --- shared_ptr.htm | 94 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 70 insertions(+), 24 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 87e61b4..c534dd7 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -45,9 +45,10 @@ shared_ptr<void> p2( new int(5) ); to "break cycles."

    The class template is parameterized on T, the type of the object pointed to. shared_ptr and most of its member functions place no - requirements on T; it is allowed to be an incomplete type, or - void. Member functions that do place additional requirements (constructors, - reset) are explicitly documented below.

    + requirements on T; it is allowed to be an incomplete type, or + void. Member functions that do place additional requirements + (constructors, reset) are explicitly + documented below.

    shared_ptr<T> can be implicitly converted to shared_ptr<U> whenever T* can be implicitly converted to U*. In particular, shared_ptr<T> is implicitly convertible @@ -119,10 +120,13 @@ void bad() typedef see below element_type; shared_ptr(); // never throws + shared_ptr(std::nullptr_t); // never throws template<class Y> explicit shared_ptr(Y * p); template<class Y, class D> shared_ptr(Y * p, D d); template<class Y, class D, class A> shared_ptr(Y * p, D d, A a); + template<class D> shared_ptr(std::nullptr_t p, D d); + template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a); ~shared_ptr(); // never throws @@ -152,6 +156,8 @@ void bad() template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r); + shared_ptr & operator=(std::nullptr_t); // never throws + void reset(); // never throws template<class Y> void reset(Y * p); @@ -163,19 +169,19 @@ void bad() T & operator*() const; // never throws; only valid when T is not an array type T * operator->() const; // never throws; only valid when T is not an array type - element_type & operator[]( std::ptrdiff_t i ) const; // never throws; only valid when T is an array type + element_type & operator[](std::ptrdiff_t i) const; // never throws; only valid when T is an array type element_type * get() const; // never throws bool unique() const; // never throws long use_count() const; // never throws - operator unspecified-bool-type() const; // never throws + explicit operator bool() const; // never throws void swap(shared_ptr & b); // never throws - template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const; // never throws - template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const; // never throws + template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const; // never throws + template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const; // never throws }; template<class T, class U> @@ -187,6 +193,18 @@ void bad() template<class T, class U> bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws + template<class T> + bool operator==(shared_ptr<T> const & p, std::nullptr_t); // never throws + + template<class T> + bool operator==(std::nullptr_t, shared_ptr<T> const & p); // never throws + + template<class T> + bool operator!=(shared_ptr<T> const & p, std::nullptr_t); // never throws + + template<class T> + bool operator!=(std::nullptr_t, shared_ptr<T> const & p); // never throws + template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws template<class T> typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p); // never throws @@ -217,7 +235,8 @@ void bad() and U when T is U[] or U[N].

    default constructor

    -
    shared_ptr(); // never throws
    +
    shared_ptr(); // never throws
    +shared_ptr(std::nullptr_t); // never throws

    Effects: Constructs an empty shared_ptr.

    Postconditions: use_count() == 0 && get() == 0.

    @@ -260,7 +279,9 @@ void bad() not have a virtual destructor, or is void.]

    constructors taking a deleter

    template<class Y, class D> shared_ptr(Y * p, D d);
    -template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
    +template<class Y, class D, class A> shared_ptr(Y * p, D d, A a); +template<class D> shared_ptr(std::nullptr_t p, D d); +template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);

    Requirements: D must be CopyConstructible. The copy constructor and destructor @@ -273,8 +294,8 @@ template<class Y, class D, class A> shared_ptr(Y * p, D d, A a); otherwise, Y* must be convertible to T*.

    Effects: Constructs a shared_ptr that owns the pointer - p and the deleter d. The second constructor allocates - memory using a copy of a.

    + p
    and the deleter d. The constructors taking an allocator a + allocate memory using a copy of a.

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

    Throws: std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    @@ -350,8 +371,8 @@ template<class Y> shared_ptr(std::auto_ptr<Y> && r);

    Requires: Y* should be convertible to T*.

    Effects: - Equivalent to shared_ptr( r.release(), r.get_deleter() ) when D is not a reference type. - Otherwise, equivalent to shared_ptr( r.release(), del ), where del is a deleter + Equivalent to shared_ptr(r.release(), r.get_deleter()) when D is not a reference type. + Otherwise, equivalent to shared_ptr(r.release(), del), where del is a deleter that stores the reference rd returned from r.get_deleter() and del(p) calls rd(p).

    Postconditions: use_count() == 1.

    Throws: std::bad_alloc, or an implementation-defined @@ -401,7 +422,12 @@ template<class Y> shared_ptr & operator=(shared_ptr<Y> && template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r); template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);

    -

    Effects: Equivalent to shared_ptr( std::move(r) ).swap(*this).

    +

    Effects: Equivalent to shared_ptr(std::move(r)).swap(*this).

    +

    Returns: *this.

    +
    +
    shared_ptr & operator=(std::nullptr_t); // never throws
    +
    +

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

    Returns: *this.

    reset

    @@ -438,11 +464,11 @@ template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y

    Returns: the stored pointer.

    Throws: nothing.

    -
    element_type & operator[]( std::ptrdiff_t i ) const; // never throws
    +
    element_type & operator[](std::ptrdiff_t i) const; // never throws

    Requirements: T should be an array type. The stored pointer must not be 0. i >= 0. If T is U[N], i < N.

    -

    Returns: get()[ i ].

    +

    Returns: get()[i].

    Throws: nothing.

    get

    @@ -471,15 +497,12 @@ template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y for debugging and testing purposes, not for production code.

    conversions

    -
    operator unspecified-bool-type () const; // never throws
    +
    explicit operator bool() const; // never throws
    -

    Returns: an unspecified value that, when used in boolean contexts, is - equivalent to get() != 0.

    +

    Returns: get() != 0.

    Throws: nothing.

    Notes: This conversion operator allows shared_ptr objects to be - used in boolean contexts, like if (p && p->valid()) {}. - The actual target type is typically a pointer to a member function, avoiding - many of the implicit conversion pitfalls.

    + used in boolean contexts, like if(p && p->valid()) {}.

    [The conversion to bool is not merely syntactic sugar. It allows shared_ptrs to be declared in conditions when using dynamic_pointer_cast @@ -490,6 +513,13 @@ template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y

    Effects: Exchanges the contents of the two smart pointers.

    Throws: nothing.

    +

    swap

    +
    template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const; // never throws
    +template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const; // never throws
    +
    +

    Effects: See the description of operator<.

    +

    Throws: nothing.

    +

    Free Functions

    comparison

    template<class T, class U>
    @@ -504,6 +534,22 @@ template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y
     			

    Returns: a.get() != b.get().

    Throws: nothing.

    +
    template<class T>
    +  bool operator==(shared_ptr<T> const & p, std::nullptr_t); // never throws
    +template<class T>
    +  bool operator==(std::nullptr_t, shared_ptr<T> const & p); // never throws
    +
    +

    Returns: p.get() == 0.

    +

    Throws: nothing.

    +
    +
    template<class T>
    +  bool operator!=(shared_ptr<T> const & p, std::nullptr_t); // never throws
    +template<class T>
    +  bool operator!=(std::nullptr_t, shared_ptr<T> const & p); // never throws
    +
    +

    Returns: p.get() != 0.

    +

    Throws: nothing.

    +
    template<class T, class U>
       bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
    @@ -743,7 +789,7 @@ p3.reset(new int(2)); // undefined, multiple writes

    A. Automatic conversion is believed to be too error prone.

    -

    Q. Why does shared_ptr supply use_count()?

    +

    Q. Why does shared_ptr supply use_count()?

    A. As an aid to writing test cases and debugging displays. One of the progenitors had use_count(), and it was useful in tracking down bugs in a @@ -783,7 +829,7 @@ int * p = a.release();


    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005, 2012 Peter Dimov. Distributed under the Boost Software License, + Copyright 2002-2005, 2012, 2013 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 dcc1713c59132c5b06f55e8b1a444d04627a0597 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 9 Jan 2013 23:41:31 +0000 Subject: [PATCH 128/140] Merged revision(s) 82351 from trunk: Replace std::nullptr_t with boost::detail::sp_nullptr_t. [SVN r82427] --- .../boost/smart_ptr/detail/sp_nullptr_t.hpp | 45 +++++++++++++++++++ include/boost/smart_ptr/intrusive_ptr.hpp | 9 ++-- include/boost/smart_ptr/scoped_array.hpp | 10 ++--- include/boost/smart_ptr/scoped_ptr.hpp | 9 ++-- include/boost/smart_ptr/shared_array.hpp | 9 ++-- include/boost/smart_ptr/shared_ptr.hpp | 19 ++++---- 6 files changed, 75 insertions(+), 26 deletions(-) create mode 100644 include/boost/smart_ptr/detail/sp_nullptr_t.hpp diff --git a/include/boost/smart_ptr/detail/sp_nullptr_t.hpp b/include/boost/smart_ptr/detail/sp_nullptr_t.hpp new file mode 100644 index 0000000..ccbb123 --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_nullptr_t.hpp @@ -0,0 +1,45 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_NULLPTR_T_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_NULLPTR_T_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_nullptr_t.hpp +// +// Copyright 2013 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( BOOST_NO_CXX11_NULLPTR ) + +namespace boost +{ + +namespace detail +{ + +#if defined( __clang__ ) && !defined( _LIBCPP_VERSION ) && !defined( BOOST_NO_CXX11_DECLTYPE ) + + typedef decltype(nullptr) sp_nullptr_t; + +#else + + typedef std::nullptr_t sp_nullptr_t; + +#endif + +} // namespace detail + +} // namespace boost + +#endif // !defined( BOOST_NO_CXX11_NULLPTR ) + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_NULLPTR_T_HPP_INCLUDED diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp index 64a2923..b6f5bcd 100644 --- a/include/boost/smart_ptr/intrusive_ptr.hpp +++ b/include/boost/smart_ptr/intrusive_ptr.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include // for std::less @@ -220,22 +221,22 @@ template inline bool operator!=(intrusive_ptr const & a, intrusive_p #if !defined( BOOST_NO_CXX11_NULLPTR ) -template inline bool operator==( intrusive_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +template inline bool operator==( intrusive_ptr const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT { return p.get() == 0; } -template inline bool operator==( std::nullptr_t, intrusive_ptr const & p ) BOOST_NOEXCEPT +template inline bool operator==( boost::detail::sp_nullptr_t, intrusive_ptr const & p ) BOOST_NOEXCEPT { return p.get() == 0; } -template inline bool operator!=( intrusive_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +template inline bool operator!=( intrusive_ptr const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT { return p.get() != 0; } -template inline bool operator!=( std::nullptr_t, intrusive_ptr const & p ) BOOST_NOEXCEPT +template inline bool operator!=( boost::detail::sp_nullptr_t, intrusive_ptr const & p ) BOOST_NOEXCEPT { return p.get() != 0; } diff --git a/include/boost/smart_ptr/scoped_array.hpp b/include/boost/smart_ptr/scoped_array.hpp index 1ddaa07..e395e28 100644 --- a/include/boost/smart_ptr/scoped_array.hpp +++ b/include/boost/smart_ptr/scoped_array.hpp @@ -14,7 +14,7 @@ #include #include #include -#include // in case ptrdiff_t not in std +#include #include @@ -100,22 +100,22 @@ public: #if !defined( BOOST_NO_CXX11_NULLPTR ) -template inline bool operator==( scoped_array const & p, std::nullptr_t ) BOOST_NOEXCEPT +template inline bool operator==( scoped_array const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT { return p.get() == 0; } -template inline bool operator==( std::nullptr_t, scoped_array const & p ) BOOST_NOEXCEPT +template inline bool operator==( boost::detail::sp_nullptr_t, scoped_array const & p ) BOOST_NOEXCEPT { return p.get() == 0; } -template inline bool operator!=( scoped_array const & p, std::nullptr_t ) BOOST_NOEXCEPT +template inline bool operator!=( scoped_array const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT { return p.get() != 0; } -template inline bool operator!=( std::nullptr_t, scoped_array const & p ) BOOST_NOEXCEPT +template inline bool operator!=( boost::detail::sp_nullptr_t, scoped_array const & p ) BOOST_NOEXCEPT { return p.get() != 0; } diff --git a/include/boost/smart_ptr/scoped_ptr.hpp b/include/boost/smart_ptr/scoped_ptr.hpp index a75f91f..be6722d 100644 --- a/include/boost/smart_ptr/scoped_ptr.hpp +++ b/include/boost/smart_ptr/scoped_ptr.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #ifndef BOOST_NO_AUTO_PTR @@ -117,22 +118,22 @@ public: #if !defined( BOOST_NO_CXX11_NULLPTR ) -template inline bool operator==( scoped_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +template inline bool operator==( scoped_ptr const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT { return p.get() == 0; } -template inline bool operator==( std::nullptr_t, scoped_ptr const & p ) BOOST_NOEXCEPT +template inline bool operator==( boost::detail::sp_nullptr_t, scoped_ptr const & p ) BOOST_NOEXCEPT { return p.get() == 0; } -template inline bool operator!=( scoped_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +template inline bool operator!=( scoped_ptr const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT { return p.get() != 0; } -template inline bool operator!=( std::nullptr_t, scoped_ptr const & p ) BOOST_NOEXCEPT +template inline bool operator!=( boost::detail::sp_nullptr_t, scoped_ptr const & p ) BOOST_NOEXCEPT { return p.get() != 0; } diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp index 38047ff..73a07ae 100644 --- a/include/boost/smart_ptr/shared_array.hpp +++ b/include/boost/smart_ptr/shared_array.hpp @@ -27,6 +27,7 @@ #include #include +#include #include #include // for std::ptrdiff_t @@ -245,22 +246,22 @@ template inline bool operator!=(shared_array const & a, shared_array #if !defined( BOOST_NO_CXX11_NULLPTR ) -template inline bool operator==( shared_array const & p, std::nullptr_t ) BOOST_NOEXCEPT +template inline bool operator==( shared_array const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT { return p.get() == 0; } -template inline bool operator==( std::nullptr_t, shared_array const & p ) BOOST_NOEXCEPT +template inline bool operator==( boost::detail::sp_nullptr_t, shared_array const & p ) BOOST_NOEXCEPT { return p.get() == 0; } -template inline bool operator!=( shared_array const & p, std::nullptr_t ) BOOST_NOEXCEPT +template inline bool operator!=( shared_array const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT { return p.get() != 0; } -template inline bool operator!=( std::nullptr_t, shared_array const & p ) BOOST_NOEXCEPT +template inline bool operator!=( boost::detail::sp_nullptr_t, shared_array const & p ) BOOST_NOEXCEPT { return p.get() != 0; } diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index b34b0ac..d2781c1 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -32,6 +32,7 @@ #include #include #include +#include #if !defined(BOOST_SP_NO_ATOMIC_ACCESS) #include @@ -41,7 +42,7 @@ #include // for std::swap #include // for std::less #include // for std::bad_cast -#include // for std::size_t, std::nullptr_t +#include // for std::size_t #if !defined(BOOST_NO_IOSTREAM) #if !defined(BOOST_NO_IOSFWD) @@ -341,7 +342,7 @@ public: #if !defined( BOOST_NO_CXX11_NULLPTR ) - shared_ptr( std::nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn() // never throws + shared_ptr( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn() // never throws { } @@ -366,7 +367,7 @@ public: #if !defined( BOOST_NO_CXX11_NULLPTR ) - template shared_ptr( std::nullptr_t p, D d ): px( p ), pn( p, d ) + template shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, d ) { } @@ -381,7 +382,7 @@ public: #if !defined( BOOST_NO_CXX11_NULLPTR ) - template shared_ptr( std::nullptr_t p, D d, A a ): px( p ), pn( p, d, a ) + template shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( p, d, a ) { } @@ -605,7 +606,7 @@ public: #if !defined( BOOST_NO_CXX11_NULLPTR ) - shared_ptr & operator=( std::nullptr_t ) BOOST_NOEXCEPT // never throws + shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT // never throws { this_type().swap(*this); return *this; @@ -752,22 +753,22 @@ template inline bool operator!=(shared_ptr const & a, shared_ptr #if !defined( BOOST_NO_CXX11_NULLPTR ) -template inline bool operator==( shared_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +template inline bool operator==( shared_ptr const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT { return p.get() == 0; } -template inline bool operator==( std::nullptr_t, shared_ptr const & p ) BOOST_NOEXCEPT +template inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr const & p ) BOOST_NOEXCEPT { return p.get() == 0; } -template inline bool operator!=( shared_ptr const & p, std::nullptr_t ) BOOST_NOEXCEPT +template inline bool operator!=( shared_ptr const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT { return p.get() != 0; } -template inline bool operator!=( std::nullptr_t, shared_ptr const & p ) BOOST_NOEXCEPT +template inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr const & p ) BOOST_NOEXCEPT { return p.get() != 0; } From 72095a48046979783d3e9b251b7aab799803d68d Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 10 Jan 2013 16:50:34 +0000 Subject: [PATCH 129/140] Merge revision 82408 from trunk: Support BOOST_NO_EXCEPTIONS in detail/array_utility.hpp to allow use when exceptions are disabled ........ [SVN r82432] --- .../boost/smart_ptr/detail/array_utility.hpp | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/include/boost/smart_ptr/detail/array_utility.hpp b/include/boost/smart_ptr/detail/array_utility.hpp index 35694f0..3cf36d7 100644 --- a/include/boost/smart_ptr/detail/array_utility.hpp +++ b/include/boost/smart_ptr/detail/array_utility.hpp @@ -37,6 +37,7 @@ namespace boost { } template inline void array_init(T* memory, std::size_t size, boost::false_type) { +#if !defined(BOOST_NO_EXCEPTIONS) std::size_t i = 0; try { for (; i < size; i++) { @@ -47,6 +48,12 @@ namespace boost { array_destroy(memory, i); throw; } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(); + } +#endif } template inline void array_init(T* memory, std::size_t size) { @@ -56,6 +63,7 @@ namespace boost { #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template inline void array_init_value(T* memory, std::size_t size, T&& value) { +#if !defined(BOOST_NO_EXCEPTIONS) std::size_t i = 0; try { for (; i < size; i++) { @@ -66,10 +74,17 @@ namespace boost { array_destroy(memory, i); throw; } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(value); + } +#endif } #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template inline void array_init_args(T* memory, std::size_t size, Args&&... args) { +#if !defined(BOOST_NO_EXCEPTIONS) std::size_t i = 0; try { for (; i < size; i++) { @@ -80,11 +95,18 @@ namespace boost { array_destroy(memory, i); throw; } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(args...); + } +#endif } #endif #endif template inline void array_init_list(T* memory, std::size_t size, const T* list) { +#if !defined(BOOST_NO_EXCEPTIONS) std::size_t i = 0; try { for (; i < size; i++) { @@ -95,9 +117,16 @@ namespace boost { array_destroy(memory, i); throw; } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i]); + } +#endif } template inline void array_init_list(T* memory, std::size_t size, const T* list) { +#if !defined(BOOST_NO_EXCEPTIONS) std::size_t i = 0; try { for (; i < size; i++) { @@ -108,12 +137,19 @@ namespace boost { array_destroy(memory, i); throw; } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i % N]); + } +#endif } template inline void array_noinit(T*, std::size_t, boost::true_type) { } template inline void array_noinit(T* memory, std::size_t size, boost::false_type) { +#if !defined(BOOST_NO_EXCEPTIONS) std::size_t i = 0; try { for (; i < size; i++) { @@ -124,6 +160,12 @@ namespace boost { array_destroy(memory, i); throw; } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T; + } +#endif } template inline void array_noinit(T* memory, std::size_t size) { From de6dc3a26e1b788a997af8181184e69ac073955a Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 21 Jan 2013 04:36:14 +0000 Subject: [PATCH 130/140] Merge documentation fix from trunk [SVN r82575] --- make_shared_array.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make_shared_array.html b/make_shared_array.html index fb75790..326bb10 100644 --- a/make_shared_array.html +++ b/make_shared_array.html @@ -18,7 +18,7 @@ allocate_shared were for efficient allocation of single objects only. There was a need to have efficient, single, allocation of arrays. One criticism of shared_array was - always the lack of a make_shared utility + always the lack of a make_shared utility which ensures only a single allocation for an array.

    The header files <boost/smart_ptr/make_shared_array.hpp> and <boost/smart_ptr/allocate_shared_array.hpp> provide new function From e39fcad839970fe9e808926297669cdd293a3f8c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 16 Feb 2013 17:21:23 +0000 Subject: [PATCH 131/140] Merged revision(s) 82927 from trunk: Check for BOOST_NO_CXX11_RVALUE_REFERENCES in addition to BOOST_NO_CXX11_SMART_PTR. Fixes #8055. [SVN r82928] --- include/boost/smart_ptr/shared_ptr.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index d2781c1..9259ca0 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -485,7 +485,7 @@ public: #endif // BOOST_NO_AUTO_PTR -#if !defined( BOOST_NO_CXX11_SMART_PTR ) +#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template< class Y, class D > shared_ptr( std::unique_ptr< Y, D > && r ): px( r.get() ), pn() @@ -550,7 +550,7 @@ public: #endif // BOOST_NO_AUTO_PTR -#if !defined( BOOST_NO_CXX11_SMART_PTR ) +#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template shared_ptr & operator=( std::unique_ptr && r ) From 3178d381378e4cd20753b432c414a35b89ee1473 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 18 Feb 2013 18:04:48 +0000 Subject: [PATCH 132/140] Merge revision 82971 from trunk: Identifier renaming in allocate_array_helper, array_deleter, make_array_helper function parameters to satisfy higher warning levels. ........ [SVN r82976] --- .../smart_ptr/detail/allocate_array_helper.hpp | 14 +++++++------- include/boost/smart_ptr/detail/array_deleter.hpp | 4 ++-- .../boost/smart_ptr/detail/make_array_helper.hpp | 14 +++++++------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/boost/smart_ptr/detail/allocate_array_helper.hpp b/include/boost/smart_ptr/detail/allocate_array_helper.hpp index f7c64fe..2eeea2d 100644 --- a/include/boost/smart_ptr/detail/allocate_array_helper.hpp +++ b/include/boost/smart_ptr/detail/allocate_array_helper.hpp @@ -33,10 +33,10 @@ namespace boost { struct rebind { typedef allocate_array_helper other; }; - allocate_array_helper(const A& allocator, std::size_t size, T** data) - : allocator(allocator), - size(sizeof(T) * size), - data(data) { + allocate_array_helper(const A& allocator_, std::size_t size_, T** data_) + : allocator(allocator_), + size(sizeof(T) * size_), + data(data_) { } template allocate_array_helper(const allocate_array_helper& other) @@ -107,9 +107,9 @@ namespace boost { struct rebind { typedef allocate_array_helper other; }; - allocate_array_helper(const A& allocator, T** data) - : allocator(allocator), - data(data) { + allocate_array_helper(const A& allocator_, T** data_) + : allocator(allocator_), + data(data_) { } template allocate_array_helper(const allocate_array_helper& other) diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index 11f23fa..20f84d1 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -19,8 +19,8 @@ namespace boost { template class array_deleter { public: - array_deleter(std::size_t size) - : size(size), + array_deleter(std::size_t size_) + : size(size_), object(0) { } ~array_deleter() { diff --git a/include/boost/smart_ptr/detail/make_array_helper.hpp b/include/boost/smart_ptr/detail/make_array_helper.hpp index 38c9dc9..6cf0483 100644 --- a/include/boost/smart_ptr/detail/make_array_helper.hpp +++ b/include/boost/smart_ptr/detail/make_array_helper.hpp @@ -31,9 +31,9 @@ namespace boost { struct rebind { typedef make_array_helper other; }; - make_array_helper(std::size_t size, T** data) - : size(sizeof(T) * size), - data(data) { + make_array_helper(std::size_t size_, T** data_) + : size(sizeof(T) * size_), + data(data_) { } template make_array_helper(const make_array_helper& other) @@ -72,7 +72,7 @@ namespace boost { memory->~Y(); } template - bool operator==(const make_array_helper& other) const { + bool operator==(const make_array_helper&) const { return true; } template @@ -99,8 +99,8 @@ namespace boost { struct rebind { typedef make_array_helper other; }; - make_array_helper(T** data) - : data(data) { + make_array_helper(T** data_) + : data(data_) { } template make_array_helper(const make_array_helper& other) @@ -138,7 +138,7 @@ namespace boost { memory->~Y(); } template - bool operator==(const make_array_helper& other) const { + bool operator==(const make_array_helper&) const { return true; } template From 579b34726719c48e9b549368b8c4cd817ef98cdb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 7 Mar 2013 08:18:48 +0000 Subject: [PATCH 133/140] Merged revision(s) 83198 from trunk: Avoid stack overflow in make_shared. Fixes #4256. Fixes #7965. [SVN r83341] --- include/boost/smart_ptr/detail/shared_count.hpp | 8 ++++---- include/boost/smart_ptr/make_shared_object.hpp | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp index f055fd0..8e1dd48 100644 --- a/include/boost/smart_ptr/detail/shared_count.hpp +++ b/include/boost/smart_ptr/detail/shared_count.hpp @@ -200,7 +200,7 @@ public: } catch( ... ) { - D()( p ); // delete p + D::operator_fn( p ); // delete p throw; } @@ -210,7 +210,7 @@ public: if( pi_ == 0 ) { - D()( p ); // delete p + D::operator_fn( p ); // delete p boost::throw_exception( std::bad_alloc() ); } @@ -286,7 +286,7 @@ public: } catch(...) { - D()( p ); + D::operator_fn( p ); if( pi_ != 0 ) { @@ -306,7 +306,7 @@ public: } else { - D()( p ); + D::operator_fn( p ); boost::throw_exception( std::bad_alloc() ); } diff --git a/include/boost/smart_ptr/make_shared_object.hpp b/include/boost/smart_ptr/make_shared_object.hpp index 89a7116..52a00ce 100644 --- a/include/boost/smart_ptr/make_shared_object.hpp +++ b/include/boost/smart_ptr/make_shared_object.hpp @@ -87,6 +87,10 @@ public: destroy(); } + static void operator_fn( T* ) // operator() can't be static + { + } + void * address() BOOST_NOEXCEPT { return storage_.data_; From e497aec58a773927d23a9fbe1d52b7f78c562d7e Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 10 Apr 2013 05:03:45 +0000 Subject: [PATCH 134/140] Merge revision(s) 83827 from trunk: Small improvements to make_shared documentation. ........ [SVN r83828] --- make_shared_array.html | 186 ++++++++++++++++++++--------------------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/make_shared_array.html b/make_shared_array.html index 326bb10..2b9b5bd 100644 --- a/make_shared_array.html +++ b/make_shared_array.html @@ -29,85 +29,85 @@ allowing finer control.

    Synopsis

    namespace boost {
    -    template<typename T>
    -    shared_ptr<T[]> make_shared(size_t size);
    +    template<typename U> // U = T[]
    +    shared_ptr<U> make_shared(size_t size);
     
    -    template<typename T, typename A>
    -    shared_ptr<T[]> allocate_shared(const A& allocator, size_t size);
    -    
    -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
    -    template<typename T, typename... Args>
    -    shared_ptr<T[]> make_shared(size_t size, Args&&... args);
    +    template<typename U, typename A> // U = T[]
    +    shared_ptr<U> allocate_shared(const A& allocator, size_t size);
     
    -    template<typename T, typename... Args>
    -    shared_ptr<T[N]> make_shared(Args&&... args);
    +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)   
    +    template<typename U, typename... Args> // U = T[]
    +    shared_ptr<U> make_shared(size_t size, Args&&... args);
     
    -    template<typename T, typename A, typename... Args>
    -    shared_ptr<T[]> allocate_shared(const A& allocator, size_t size, Args&&... args);
    +    template<typename U, typename... Args> // U = T[N]
    +    shared_ptr<U> make_shared(Args&&... args);
     
    -    template<typename T, typename A, typename... Args>
    -    shared_ptr<T[N]> allocate_shared(const A& allocator, Args&&... args);
    +    template<typename U, typename A, typename... Args> // U = T[]
    +    shared_ptr<U> allocate_shared(const A& allocator, size_t size, Args&&... args);
    +
    +    template<typename U, typename A, typename... Args> // U = T[N]
    +    shared_ptr<U> allocate_shared(const A& allocator, Args&&... args);
     #endif
    -        
    -#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
    -    template<typename T, typename... Args>
    -    shared_ptr<T[N]> make_shared(const T (&list)[N]);
     
    -    template<typename T, typename... Args>
    -    shared_ptr<T[][N]> make_shared(size_t size, const T (&list)[N]);
    +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)    
    +    template<typename U, typename... Args> // U = T[N]
    +    shared_ptr<U> make_shared(const T (&list)[N]);
     
    -    template<typename T, typename... Args>
    -    shared_ptr<T[M][N]> make_shared(const T (&list)[N]);
    +    template<typename U, typename... Args> // U = T[][N]
    +    shared_ptr<U> make_shared(size_t size, const T (&list)[N]);
     
    -    template<typename T, typename A, typename... Args>
    -    shared_ptr<T[N]> allocate_shared(const A& allocator, const T (&list)[N]);
    +    template<typename U, typename... Args> // U = T[M][N]
    +    shared_ptr<U> make_shared(const T (&list)[N]);
     
    -    template<typename T, typename A, typename... Args>
    -    shared_ptr<T[][N]> allocate_shared(const A& allocator, size_t size, const T (&list)[N]);
    +    template<typename U, typename A, typename... Args> // U = T[N]
    +    shared_ptr<T[> allocate_shared(const A& allocator, const T (&list)[N]);
     
    -    template<typename T, typename A, typename... Args>
    -    shared_ptr<T[M][N]> allocate_shared(const A& allocator, const T (&list)[N]);
    +    template<typename U, typename A, typename... Args> // U = T[][N]
    +    shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T (&list)[N]);
    +
    +    template<typename U, typename A, typename... Args> // U = T[M][N]
    +    shared_ptr<U> allocate_shared(const A& allocator, const T (&list)[N]);
     
     #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
    -    template<typename T, typename... Args>
    -    shared_ptr<T[]> make_shared(initializer_list<T> list);
    +    template<typename U, typename... Args> // U = T[]
    +    shared_ptr<U> make_shared(initializer_list<T> list);
     
    -    template<typename T, typename A, typename... Args>
    -    shared_ptr<T[]> allocate_shared(const A& allocator, initializer_list<T> list);
    +    template<typename U, typename A, typename... Args> // U = T[]
    +    shared_ptr<U> allocate_shared(const A& allocator, initializer_list<T> list);
     #endif
     
    -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
    -    template<typename T>
    -    shared_ptr<T[]> make_shared(size_t size, T&& value);
    +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)    
    +    template<typename U> // U = T[]
    +    shared_ptr<U> make_shared(size_t size, T&& value);
     
    -    template<typename T>
    -    shared_ptr<T[N]> make_shared(T&& value);
    +    template<typename U> // U = T[N]
    +    shared_ptr<U> make_shared(T&& value);
     
    -    template<typename T, typename A>
    -    shared_ptr<T[]> allocate_shared(const A& allocator, size_t size, T&& value);
    +    template<typename U, typename A> // U = T[]
    +    shared_ptr<U> allocate_shared(const A& allocator, size_t size, T&& value);
     
    -    template<typename T, typename A>
    -    shared_ptr<T[N]> allocate_shared(const A& allocator, T&& value);    
    +    template<typename U, typename A> // U = T[N]
    +    shared_ptr<U> allocate_shared(const A& allocator, T&& value);
     #endif
     #endif
     
    -    template<typename T>
    -    shared_ptr<T[]> make_shared_noinit(size_t size);
    +    template<typename U> // U = T[]
    +    shared_ptr<U> make_shared_noinit(size_t size);
     
    -    template<typename T>
    -    shared_ptr<T[N]> make_shared_noinit();
    -    
    -    template<typename T, typename A>
    -    shared_ptr<T[]> allocate_shared_noinit(const A& allocator, size_t size);
    +    template<typename U> // U = T[N]
    +    shared_ptr<U> make_shared_noinit();
     
    -    template<typename T, typename A>
    -    shared_ptr<T[N]> allocate_shared_noinit(const A& allocator);
    +    template<typename U, typename A> // U = T[]
    +    shared_ptr<U> allocate_shared_noinit(const A& allocator, size_t size);
    +
    +    template<typename U, typename A> // U = T[N]
    +    shared_ptr<U> allocate_shared_noinit(const A& allocator);
     }

    Free Functions

    -
    template<typename T, typename... Args>
    -    shared_ptr<T[]> make_shared(size_t size, Args&&... args);
    -template<typename T, typename A, typename... Args>
    -    shared_ptr<T[]> allocate_shared(const A& allocator, size_t size, Args&&... args);
    +
    template<typename U, typename... Args>
    +    shared_ptr<U> make_shared(size_t size, Args&&... args);
    +template<typename U, typename A, typename... Args>
    +    shared_ptr<U> allocate_shared(const A& allocator, size_t size, Args&&... args);

    Requires: The expression new(pointer) T(forward<Args>(args)...), where @@ -121,7 +121,7 @@ template<typename T, typename A, typename... Args> T and size size and constructs an array of objects in it via the placement new expression new(pointer) T() or - new(pointer) T(forward<Args>(args)...). + new(pointer) T(args...). allocate_shared uses a copy of allocator to allocate memory. If an exception is thrown, has no effect.

    @@ -146,74 +146,74 @@ template<typename T, typename A, typename... Args> take any constructor arguments. These overloads invoke the default constructor of T for each array element.

    -
    template<typename T, typename... Args>
    -    shared_ptr<T[N]> make_shared(Args&&... args);
    -template<typename T, typename A, typename... Args>
    -    shared_ptr<T[N]> allocate_shared(const A& allocator, Args&&... args);
    +
    template<typename U, typename... Args>
    +    shared_ptr<U> make_shared(Args&&... args);
    +template<typename U, typename A, typename... Args>
    +    shared_ptr<U> allocate_shared(const A& allocator, Args&&... args);

    Description: These overloads of the utilities above are for a fixed size array.

    -
    template<typename T, typename... Args>
    -    shared_ptr<T[]> make_shared(initializer_list<T> list);
    -template<typename T, typename A, typename... Args>
    -    shared_ptr<T[]> allocate_shared(const A& allocator, initializer_list<T> list);
    +
    template<typename U, typename... Args>
    +    shared_ptr<U> make_shared(initializer_list<T> list);
    +template<typename U, typename A, typename... Args>
    +    shared_ptr<U> allocate_shared(const A& allocator, initializer_list<T> list);

    Description: These overloads initialize the array elements from the initializer list.

    -
    template<typename T, typename... Args>
    -    shared_ptr<T[N]> make_shared(const T (&list)[N]);
    -template<typename T, typename A, typename... Args>
    -    shared_ptr<T[N]> allocate_shared(const A& allocator, const T (&list)[N]);
    +
    template<typename U, typename... Args>
    +    shared_ptr<U> make_shared(const T (&list)[N]);
    +template<typename U, typename A, typename... Args>
    +    shared_ptr<U> allocate_shared(const A& allocator, const T (&list)[N]);

    Description: These overloads of the utilities above are for a fixed size array.

    -
    template<typename T, typename... Args>
    -    shared_ptr<T[][N]> make_shared(size_t size, const T (&list)[N]);
    -template<typename T, typename A, typename... Args>
    -    shared_ptr<T[][N]> allocate_shared(const A& allocator, size_t size, const T (&list)[N]);
    +
    template<typename U, typename... Args>
    +    shared_ptr<U> make_shared(size_t size, const T (&list)[N]);
    +template<typename U, typename A, typename... Args>
    +    shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T (&list)[N]);

    Description: These overloads initialize inner array elements from the initializer list.

    -
    template<typename T, typename... Args>
    -    shared_ptr<T[M][N]> make_shared(const T (&list)[N]);
    -template<typename T, typename A, typename... Args>
    -    shared_ptr<T[M][N]> allocate_shared(const A& allocator, const T (&list)[N]);
    +
    template<typename U, typename... Args> // U = T[M][N]
    +    shared_ptr<U> make_shared(const T (&list)[N]);
    +template<typename U, typename A, typename... Args> // U = T[M][N]
    +    shared_ptr<U> allocate_shared(const A& allocator, const T (&list)[N]);

    Description: These overloads of the utilities above are for a fixed size array.

    -
    -
    template<typename T>
    -    shared_ptr<T[]> make_shared(size_t size, T&& value);
    -template<typename T, typename A>
    -    shared_ptr<T[]> allocate_shared(const A& allocator, size_t size, T&& value);
    +
    +
    template<typename U>
    +    shared_ptr<U> make_shared(size_t size, T&& value);
    +template<typename U, typename A>
    +    shared_ptr<U> allocate_shared(const A& allocator, size_t size, T&& value);

    Description: These overloads initialize array elements with the given value.

    -
    template<typename T>
    -    shared_ptr<T[N]> make_shared(T&& value);
    -template<typename T, typename A>
    -    shared_ptr<T[N]> allocate_shared(const A& allocator, T&& value);
    +
    template<typename U>
    +    shared_ptr<U> make_shared(T&& value);
    +template<typename U, typename A>
    +    shared_ptr<U> allocate_shared(const A& allocator, T&& value);

    Description: These overloads of the utilities above are for a fixed size array.

    -
    template<typename T>
    -    shared_ptr<T[]> make_shared_noinit(size_t size);
    -template<typename T, typename A>
    -    shared_ptr<T[]> allocate_shared_noinit(const A& allocator, size_t size);
    +
    template<typename U>
    +    shared_ptr<U> make_shared_noinit(size_t size);
    +template<typename U, typename A>
    +    shared_ptr<U> allocate_shared_noinit(const A& allocator, size_t size);

    Description: These overloads do not perform any value initialization of elements.

    -
    template<typename T>
    -    shared_ptr<T[N]> make_shared_noinit();
    -template<typename T, typename A>
    -    shared_ptr<T[N]> allocate_shared_noinit(const A& allocator);
    +
    template<typename U>
    +    shared_ptr<U> make_shared_noinit();
    +template<typename U, typename A>
    +    shared_ptr<U> allocate_shared_noinit(const A& allocator);

    Description: These overloads of the utilities above are for a fixed size array.

    @@ -221,7 +221,7 @@ template<typename T, typename A>

    Example

    An example of each overload of make_shared for arrays:

    -
    boost::shared_ptr<point[]> a1 = boost::make_shared<point[]>(size);
    +    
    boost::shared_ptr<int[]> a1 = boost::make_shared<int[]>(size);
     boost::shared_ptr<point[]> a2 = boost::make_shared<point[]>(size, x, y);
     boost::shared_ptr<point[5]> a3 = boost::make_shared<point[5]>(x, y);
     boost::shared_ptr<int[]> a4 = boost::make_shared<int[]>({1, 2, 3});
    
    From 240c66e63344d1fd827d5586ca3a17eb2face6b2 Mon Sep 17 00:00:00 2001
    From: Glen Fernandes 
    Date: Wed, 10 Apr 2013 05:17:32 +0000
    Subject: [PATCH 135/140] Merge revision(s) 83829 from trunk: More small
     cosmetic documentation changes. ........
    
    [SVN r83830]
    ---
     make_shared_array.html | 86 +++++++++++++++++++++++-------------------
     1 file changed, 48 insertions(+), 38 deletions(-)
    
    diff --git a/make_shared_array.html b/make_shared_array.html
    index 2b9b5bd..3437e9e 100644
    --- a/make_shared_array.html
    +++ b/make_shared_array.html
    @@ -104,10 +104,11 @@
         shared_ptr<U> allocate_shared_noinit(const A& allocator);
     }

    Free Functions

    -
    template<typename U, typename... Args>
    -    shared_ptr<U> make_shared(size_t size, Args&&... args);
    -template<typename U, typename A, typename... Args>
    -    shared_ptr<U> allocate_shared(const A& allocator, size_t size, Args&&... args);
    +
    template<typename U, typename... Args> // U = T[]
    +shared_ptr<U> make_shared(size_t size, Args&&... args);
    +
    +template<typename U, typename A, typename... Args> // U = T[]
    +shared_ptr<U> allocate_shared(const A& allocator, size_t size, Args&&... args);

    Requires: The expression new(pointer) T(forward<Args>(args)...), where @@ -146,74 +147,83 @@ template<typename U, typename A, typename... Args> take any constructor arguments. These overloads invoke the default constructor of T for each array element.

    -
    template<typename U, typename... Args>
    -    shared_ptr<U> make_shared(Args&&... args);
    -template<typename U, typename A, typename... Args>
    -    shared_ptr<U> allocate_shared(const A& allocator, Args&&... args);
    +
    template<typename U, typename... Args> // U = T[N]
    +shared_ptr<U> make_shared(Args&&... args);
    +
    +template<typename U, typename A, typename... Args> // U = T[N]
    +shared_ptr<U> allocate_shared(const A& allocator, Args&&... args);

    Description: These overloads of the utilities above are for a fixed size array.

    -
    template<typename U, typename... Args>
    -    shared_ptr<U> make_shared(initializer_list<T> list);
    -template<typename U, typename A, typename... Args>
    -    shared_ptr<U> allocate_shared(const A& allocator, initializer_list<T> list);
    +
    template<typename U, typename... Args> // U = T[]
    +shared_ptr<U> make_shared(initializer_list<T> list);
    +
    +template<typename U, typename A, typename... Args> // U = T[]
    +shared_ptr<U> allocate_shared(const A& allocator, initializer_list<T> list);

    Description: These overloads initialize the array elements from the initializer list.

    -
    template<typename U, typename... Args>
    -    shared_ptr<U> make_shared(const T (&list)[N]);
    -template<typename U, typename A, typename... Args>
    -    shared_ptr<U> allocate_shared(const A& allocator, const T (&list)[N]);
    +
    template<typename U, typename... Args> // U = T[N]
    +shared_ptr<U> make_shared(const T (&list)[N]);
    +
    +template<typename U, typename A, typename... Args> // U = T[N]
    +shared_ptr<U> allocate_shared(const A& allocator, const T (&list)[N]);

    Description: These overloads of the utilities above are for a fixed size array.

    -
    template<typename U, typename... Args>
    -    shared_ptr<U> make_shared(size_t size, const T (&list)[N]);
    -template<typename U, typename A, typename... Args>
    -    shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T (&list)[N]);
    +
    template<typename U, typename... Args> // U = T[][N]
    +shared_ptr<U> make_shared(size_t size, const T (&list)[N]);
    +
    +template<typename U, typename A, typename... Args> // U = T[][N]
    +shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T (&list)[N]);

    Description: These overloads initialize inner array elements from the initializer list.

    template<typename U, typename... Args> // U = T[M][N]
    -    shared_ptr<U> make_shared(const T (&list)[N]);
    +shared_ptr<U> make_shared(const T (&list)[N]);
    +
     template<typename U, typename A, typename... Args> // U = T[M][N]
    -    shared_ptr<U> allocate_shared(const A& allocator, const T (&list)[N]);
    +shared_ptr<U> allocate_shared(const A& allocator, const T (&list)[N]);

    Description: These overloads of the utilities above are for a fixed size array.

    -
    template<typename U>
    -    shared_ptr<U> make_shared(size_t size, T&& value);
    -template<typename U, typename A>
    -    shared_ptr<U> allocate_shared(const A& allocator, size_t size, T&& value);
    +
    template<typename U> // U = T[]
    +shared_ptr<U> make_shared(size_t size, T&& value);
    +
    +template<typename U, typename A> // U = T[]
    +shared_ptr<U> allocate_shared(const A& allocator, size_t size, T&& value);

    Description: These overloads initialize array elements with the given value.

    -
    template<typename U>
    -    shared_ptr<U> make_shared(T&& value);
    -template<typename U, typename A>
    -    shared_ptr<U> allocate_shared(const A& allocator, T&& value);
    +
    template<typename U> // U = T[N]
    +shared_ptr<U> make_shared(T&& value);
    +
    +template<typename U, typename A> // U = T[N]
    +shared_ptr<U> allocate_shared(const A& allocator, T&& value);

    Description: These overloads of the utilities above are for a fixed size array.

    -
    template<typename U>
    -    shared_ptr<U> make_shared_noinit(size_t size);
    -template<typename U, typename A>
    -    shared_ptr<U> allocate_shared_noinit(const A& allocator, size_t size);
    +
    template<typename U> // U = T[]
    +shared_ptr<U> make_shared_noinit(size_t size);
    +
    +template<typename U, typename A> // U = T[]
    +shared_ptr<U> allocate_shared_noinit(const A& allocator, size_t size);

    Description: These overloads do not perform any value initialization of elements.

    -
    template<typename U>
    -    shared_ptr<U> make_shared_noinit();
    -template<typename U, typename A>
    -    shared_ptr<U> allocate_shared_noinit(const A& allocator);
    +
    template<typename U> // U = T[N]
    +shared_ptr<U> make_shared_noinit();
    +
    +template<typename U, typename A> // U = T[N]
    +shared_ptr<U> allocate_shared_noinit(const A& allocator);

    Description: These overloads of the utilities above are for a fixed size array.

    From 9355404d1045462d5820fa659f28e6573a472e1a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 15 Apr 2013 15:13:20 +0000 Subject: [PATCH 136/140] Merged revision(s) 83914 from trunk: Fix new double(n) to new double[n]. [SVN r83915] --- shared_ptr.htm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index c534dd7..6c0e999 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -61,8 +61,8 @@ shared_ptr<void> p2( new int(5) ); the template parameter. There is almost no difference between using an unsized array, T[], and a sized array, T[N]; the latter just enables operator[] to perform a range check on the index.

    -
    Example:
    shared_ptr<double[1024]> p1( new double(1024) );
    -shared_ptr<double[]> p2( new double(n) );
    +		
    Example:
    shared_ptr<double[1024]> p1( new double[1024] );
    +shared_ptr<double[]> p2( new double[n] );
     

    Best Practices

    From 6eefc6bf81a0edef950e3582a06826ff32e167c2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 26 May 2013 13:39:04 +0000 Subject: [PATCH 137/140] Merge [84506] from trunk: Document that constructors initialize enable_shared_from_this. Fixes #8573. [SVN r84507] --- shared_ptr.htm | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 6c0e999..675fe26 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -262,8 +262,12 @@ shared_ptr(std::nullptr_t); // never throws
    the pointer p. Otherwise, constructs a shared_ptr that owns p and a deleter of an unspecified type that calls delete[] p.

    -

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

    -

    Throws: std::bad_alloc, or an implementation-defined +

    Postconditions: use_count() == 1 && get() == p. + If T is not an array type and p is unambiguously convertible to + enable_shared_from_this<V>* + for some V, p->shared_from_this() returns a copy of + *this.

    +

    Throws: std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    Exception safety: If an exception is thrown, the constructor calls delete[] p, when T is an array type, @@ -296,7 +300,11 @@ template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);

    Effects: Constructs a shared_ptr that owns the pointer p and the deleter d. The constructors taking an allocator a allocate memory using a copy of a.

    -

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

    +

    Postconditions: use_count() == 1 && get() == p. + If T is not an array type and p is unambiguously convertible to + enable_shared_from_this<V>* + for some V, p->shared_from_this() returns a copy of + *this.

    Throws: std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    Exception safety: If an exception is thrown, d(p) is called.

    From fc20a29c991e0b2e6be4b97a2c1e1c8bd304e1d4 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 8 Sep 2013 17:17:18 +0000 Subject: [PATCH 138/140] Merged changes from trunk: added intrusive_ref_counter. [SVN r85609] --- .../boost/smart_ptr/intrusive_ref_counter.hpp | 187 ++++++++++++++++++ intrusive_ptr.html | 4 +- intrusive_ref_counter.html | 95 +++++++++ test/Jamfile.v2 | 1 + test/intrusive_ref_counter_test.cpp | 156 +++++++++++++++ 5 files changed, 442 insertions(+), 1 deletion(-) create mode 100644 include/boost/smart_ptr/intrusive_ref_counter.hpp create mode 100644 intrusive_ref_counter.html create mode 100644 test/intrusive_ref_counter_test.cpp diff --git a/include/boost/smart_ptr/intrusive_ref_counter.hpp b/include/boost/smart_ptr/intrusive_ref_counter.hpp new file mode 100644 index 0000000..82fa8bc --- /dev/null +++ b/include/boost/smart_ptr/intrusive_ref_counter.hpp @@ -0,0 +1,187 @@ +/* + * Copyright Andrey Semashev 2007 - 2013. + * 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) + */ +/*! + * \file intrusive_ref_counter.hpp + * \author Andrey Semashev + * \date 12.03.2009 + * + * This header contains a reference counter class for \c intrusive_ptr. + */ + +#ifndef BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ +#define BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(_MSC_VER) +#pragma warning(push) +// This is a bogus MSVC warning, which is flagged by friend declarations of intrusive_ptr_add_ref and intrusive_ptr_release in intrusive_ref_counter: +// 'name' : the inline specifier cannot be used when a friend declaration refers to a specialization of a function template +// Note that there is no inline specifier in the declarations. +#pragma warning(disable: 4396) +#endif + +namespace boost { + +namespace sp_adl_block { + +/*! + * \brief Thread unsafe reference counter policy for \c intrusive_ref_counter + * + * The policy instructs the \c intrusive_ref_counter base class to implement + * a reference counter suitable for single threaded use only. Pointers to the same + * object with this kind of reference counter must not be used by different threads. + */ +struct thread_unsafe_counter +{ + typedef unsigned int type; + + static unsigned int load(unsigned int const& counter) BOOST_NOEXCEPT + { + return counter; + } + + static void increment(unsigned int& counter) BOOST_NOEXCEPT + { + ++counter; + } + + static unsigned int decrement(unsigned int& counter) BOOST_NOEXCEPT + { + return --counter; + } +}; + +/*! + * \brief Thread safe reference counter policy for \c intrusive_ref_counter + * + * The policy instructs the \c intrusive_ref_counter base class to implement + * a thread-safe reference counter, if the target platform supports multithreading. + */ +struct thread_safe_counter +{ + typedef boost::detail::atomic_count type; + + static unsigned int load(boost::detail::atomic_count const& counter) BOOST_NOEXCEPT + { + return static_cast< unsigned int >(static_cast< long >(counter)); + } + + static void increment(boost::detail::atomic_count& counter) BOOST_NOEXCEPT + { + ++counter; + } + + static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_NOEXCEPT + { + return --counter; + } +}; + +template< typename DerivedT, typename CounterPolicyT = thread_safe_counter > +class intrusive_ref_counter; + +template< typename DerivedT, typename CounterPolicyT > +void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT; +template< typename DerivedT, typename CounterPolicyT > +void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT; + +/*! + * \brief A reference counter base class + * + * This base class can be used with user-defined classes to add support + * for \c intrusive_ptr. The class contains a reference counter defined by the \c CounterPolicyT. + * Upon releasing the last \c intrusive_ptr referencing the object + * derived from the \c intrusive_ref_counter class, operator \c delete + * is automatically called on the pointer to the object. + * + * The other template parameter, \c DerivedT, is the user's class that derives from \c intrusive_ref_counter. + */ +template< typename DerivedT, typename CounterPolicyT > +class intrusive_ref_counter +{ +private: + //! Reference counter type + typedef typename CounterPolicyT::type counter_type; + //! Reference counter + mutable counter_type m_ref_counter; + +public: + /*! + * Default constructor + * + * \post use_count() == 0 + */ + intrusive_ref_counter() BOOST_NOEXCEPT : m_ref_counter(0) + { + } + + /*! + * Copy constructor + * + * \post use_count() == 0 + */ + intrusive_ref_counter(intrusive_ref_counter const&) BOOST_NOEXCEPT : m_ref_counter(0) + { + } + + /*! + * Assignment + * + * \post The reference counter is not modified after assignment + */ + intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_NOEXCEPT { return *this; } + + /*! + * \return The reference counter + */ + unsigned int use_count() const BOOST_NOEXCEPT + { + return CounterPolicyT::load(m_ref_counter); + } + +protected: + /*! + * Destructor + */ + BOOST_DEFAULTED_FUNCTION(~intrusive_ref_counter(), {}) + + friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT; + friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT; +}; + +template< typename DerivedT, typename CounterPolicyT > +inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT +{ + CounterPolicyT::increment(p->m_ref_counter); +} + +template< typename DerivedT, typename CounterPolicyT > +inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT +{ + if (CounterPolicyT::decrement(p->m_ref_counter) == 0) + delete static_cast< const DerivedT* >(p); +} + +} // namespace sp_adl_block + +using sp_adl_block::intrusive_ref_counter; +using sp_adl_block::thread_unsafe_counter; +using sp_adl_block::thread_safe_counter; + +} // namespace boost + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#endif // BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ diff --git a/intrusive_ptr.html b/intrusive_ptr.html index 16097dd..562d27a 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -24,7 +24,9 @@ compilers that support argument-dependent lookup, intrusive_ptr_add_ref and intrusive_ptr_release should be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in - namespace boost.

    + namespace boost. The library provides a helper base class template + intrusive_ref_counter which may + help adding support for intrusive_ptr to user's types.

    The class template is parameterized on T, the type of the object pointed to. intrusive_ptr<T> can be implicitly converted to intrusive_ptr<U> whenever T* can be implicitly converted to U*.

    diff --git a/intrusive_ref_counter.html b/intrusive_ref_counter.html new file mode 100644 index 0000000..72a46e0 --- /dev/null +++ b/intrusive_ref_counter.html @@ -0,0 +1,95 @@ + + + + intrusive_ref_counter + + + +

    boost.png (6897 bytes)basic_intrusive_ref_counter class template

    +

    + Introduction
    + Synopsis
    + Members
    +

    +

    Introduction

    +

    The intrusive_ref_counter class template implements a reference counter for a derived + user's class that is intended to be used with intrusive_ptr. + The base class has associated intrusive_ptr_add_ref and intrusive_ptr_release functions + which modify the reference counter as needed and destroy the user's object when the counter drops to zero.

    +

    The class template is parameterized on DerivedT and CounterPolicyT parameters. + The first parameter is the user's class that derives from intrusive_ref_counter. This type + is needed in order to destroy the object correctly when there are no references to it left.

    +

    The second parameter is a policy that defines the nature of the reference counter. + Boost.SmartPtr provides two such policies: thread_unsafe_counter and thread_safe_counter. The former + instructs the intrusive_ref_counter base class to use a counter only suitable for a single-threaded use. + Pointers to a single object that uses this kind of reference counter must not be used in different threads. The latter policy + makes the reference counter thread-safe, unless the target platform doesn't support threading. Since in modern systems support for + threading is common, the default counter policy is thread_safe_counter.

    +

    Synopsis

    +
    namespace boost {
    +
    +  struct thread_unsafe_counter;
    +  struct thread_safe_counter;
    +
    +  template<class DerivedT, class CounterPolicyT = thread_safe_counter>
    +  class intrusive_ref_counter
    +  {
    +  public:
    +      intrusive_ref_counter() = noexcept;
    +      intrusive_ref_counter(intrusive_ref_counter const & r) = noexcept;
    +
    +      intrusive_ref_counter & operator=(intrusive_ref_counter const & r) noexcept;
    +
    +      unsigned int use_count() const noexcept;
    +
    +  protected:
    +      ~intrusive_ref_counter() = default;
    +  };
    +
    +}
    +

    Members

    +

    constructors

    +
    intrusive_ref_counter();
    +
    +

    Postconditions: use_count() == 0.

    +

    Throws: nothing.

    +

    Notes: The pointer to the constructed object is expected to be passed to intrusive_ptr + constructor, assignment operator or reset() method, which would increment the reference counter.

    +
    +
    intrusive_ref_counter(intrusive_ref_counter const &);
    +
    +

    Postconditions: use_count() == 0.

    +

    Throws: nothing.

    +

    Notes: The pointer to the constructed object is expected to be passed to intrusive_ptr + constructor, assignment operator or reset() method, which would increment the reference counter.

    +
    +

    destructor

    +
    ~intrusive_ref_counter();
    +
    +

    Throws: nothing.

    +

    Effects: Destroys the counter object.

    +

    Notes: The destructor is protected so that the object can only be destroyed through the DerivedT class.

    +
    +

    assignment

    +
    intrusive_ref_counter & operator=(intrusive_ref_counter const & r) noexcept;
    +
    +

    Effects: Does nothing, reference counter is not modified.

    +

    Returns: *this.

    +
    +

    use_count

    +
    unsigned int use_count() const noexcept;
    +
    +

    Returns: The current value of the reference counter.

    +

    Throws: nothing.

    +

    Notes: The returned value may not be actual in multi-threaded applications.

    +
    +
    +

    + $Date$

    +

    + Copyright © 2013 Andrey Semashev. 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.v2 b/test/Jamfile.v2 index d4f7af1..874968a 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -21,6 +21,7 @@ import testing ; [ run get_deleter_test.cpp ] [ run intrusive_ptr_test.cpp ] [ run intrusive_ptr_move_test.cpp ] + [ run intrusive_ref_counter_test.cpp ] [ run atomic_count_test.cpp ] [ run lw_mutex_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] diff --git a/test/intrusive_ref_counter_test.cpp b/test/intrusive_ref_counter_test.cpp new file mode 100644 index 0000000..53d0bd3 --- /dev/null +++ b/test/intrusive_ref_counter_test.cpp @@ -0,0 +1,156 @@ +/* + * Copyright Andrey Semashev 2013. + * 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) + */ +/*! + * \file intrusive_ref_counter_test.cpp + * \author Andrey Semashev + * \date 31.08.2013 + * + * This file contains tests for the \c intrusive_ref_counter base class. + */ + +#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 +#pragma warning(disable: 4355) // 'this' : used in base member initializer list +#pragma warning(disable: 4511) // copy constructor could not be generated +#pragma warning(disable: 4512) // assignment operator could not be generated + +#if (BOOST_MSVC >= 1310) +#pragma warning(disable: 4675) // resolved overload found with Koenig lookup +#endif + +#endif + +#include +#include +#include +#include + +namespace N1 { + +class my_class : + public boost::intrusive_ref_counter< my_class > +{ +public: + static unsigned int destructor_count; + + ~my_class() + { + ++destructor_count; + } +}; + +unsigned int my_class::destructor_count = 0; + +} // namespace N1 + +namespace N2 { + +class my_class : + public boost::intrusive_ref_counter< my_class, boost::thread_unsafe_counter > +{ +public: + static unsigned int destructor_count; + + ~my_class() + { + ++destructor_count; + } +}; + +unsigned int my_class::destructor_count = 0; + +} // namespace N2 + +namespace N3 { + +struct root : + public boost::intrusive_ref_counter< root > +{ + virtual ~root() {} +}; + +} // namespace N3 + +namespace N4 { + +struct X : + public virtual N3::root +{ +}; + +} // namespace N4 + +namespace N5 { + +struct Y : + public virtual N3::root +{ +}; + +} // namespace N5 + +namespace N6 { + +struct Z : + public N4::X, + public N5::Y +{ + static unsigned int destructor_count; + + ~Z() + { + ++destructor_count; + } +}; + +unsigned int Z::destructor_count = 0; + +} // namespace N6 + + +int main() +{ + // The test check that ADL works + { + boost::intrusive_ptr< N1::my_class > p = new N1::my_class(); + p = NULL; + BOOST_TEST(N1::my_class::destructor_count == 1); + } + { + boost::intrusive_ptr< N2::my_class > p = new N2::my_class(); + p = NULL; + BOOST_TEST(N2::my_class::destructor_count == 1); + } + { + N1::my_class* p = new N1::my_class(); + intrusive_ptr_add_ref(p); + intrusive_ptr_release(p); + BOOST_TEST(N1::my_class::destructor_count == 2); + } + + // The test checks that destroying through the base class works + { + boost::intrusive_ptr< N6::Z > p1 = new N6::Z(); + BOOST_TEST(p1->use_count() == 1); + BOOST_TEST(N6::Z::destructor_count == 0); + boost::intrusive_ptr< N3::root > p2 = p1; + BOOST_TEST(p1->use_count() == 2); + BOOST_TEST(N6::Z::destructor_count == 0); + p1 = NULL; + BOOST_TEST(N6::Z::destructor_count == 0); + p2 = NULL; + BOOST_TEST(N6::Z::destructor_count == 1); + } + + return boost::report_errors(); +} From be063927710c8ab05f2fe15abfda9811255b31e8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 24 Oct 2013 14:05:26 +0000 Subject: [PATCH 139/140] Merged revision(s) 85995 from trunk: Remove #pragma intrinsic( _mm_pause ); not needed, not supported on Intel. Closes #6646, #7318. [SVN r86417] --- include/boost/smart_ptr/detail/yield_k.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/smart_ptr/detail/yield_k.hpp b/include/boost/smart_ptr/detail/yield_k.hpp index 23eadd8..14af524 100644 --- a/include/boost/smart_ptr/detail/yield_k.hpp +++ b/include/boost/smart_ptr/detail/yield_k.hpp @@ -30,7 +30,6 @@ #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(); From 106832df66efe6f39769e0c9afad1c808c45bae4 Mon Sep 17 00:00:00 2001 From: Michel Morin Date: Wed, 13 Nov 2013 03:22:55 +0000 Subject: [PATCH 140/140] Merge r86524 (Correct broken links to C++ standard papers); fixes #9212 [SVN r86673] --- smart_ptr.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smart_ptr.htm b/smart_ptr.htm index 10fe5d6..2aba306 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -190,7 +190,7 @@ the full committee, counted_ptr was rejected and surprising transfer-of-ownership semantics were added to auto_ptr.

    References

    -

    [Col-94] Gregory Colvin, +

    [Col-94] Gregory Colvin, Exception Safe Smart Pointers, C++ committee document 94-168/N0555, July, 1994.

    [E&D-94] John R. Ellis & David L. Detlefs,