From ad1b34440501fc9984cbcfd55ab1e45c03aba879 Mon Sep 17 00:00:00 2001
From: Peter Dimov
Date: Sun, 1 Mar 2009 17:10:49 +0000
Subject: [PATCH 001/210] Refs #2394 (fixed in trunk.)
[SVN r51514]
---
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 eb0ff40d621a620bfca945ca62c52d66033f542a Mon Sep 17 00:00:00 2001
From: Peter Dimov
Date: Sun, 1 Mar 2009 17:18:17 +0000
Subject: [PATCH 002/210] Refs #2675 (fixed in trunk.)
[SVN r51515]
---
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 ed32efcc5133175cafb96223e1d35955a025a37f Mon Sep 17 00:00:00 2001
From: Peter Dimov
Date: Sun, 1 Mar 2009 17:27:35 +0000
Subject: [PATCH 003/210] Refs #2662 (applied to trunk.)
[SVN r51516]
---
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 905a3711dbca8321b32a2dcf5478b5f0e75ac784 Mon Sep 17 00:00:00 2001
From: Peter Dimov
Date: Sun, 1 Mar 2009 18:01:19 +0000
Subject: [PATCH 004/210] Refs #2525 (fixed in trunk.)
[SVN r51517]
---
.../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 a378c8c27818eee7c0c8602181c90098a90d08e5 Mon Sep 17 00:00:00 2001
From: Peter Dimov
Date: Sun, 1 Mar 2009 18:42:44 +0000
Subject: [PATCH 005/210] Refs #2814 (fixed in trunk.)
[SVN r51518]
---
.../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 68c939ec5a633fa69e92682c4eee4ec17726cf4c Mon Sep 17 00:00:00 2001
From: Peter Dimov
Date: Sun, 1 Mar 2009 18:54:51 +0000
Subject: [PATCH 006/210] Fix #includes in spinlock_test.cpp,
spinlock_try_test.cpp, yield_k_test.cpp.
[SVN r51519]
---
test/spinlock_test.cpp | 2 +-
test/spinlock_try_test.cpp | 2 +-
test/yield_k_test.cpp | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/test/spinlock_test.cpp b/test/spinlock_test.cpp
index 0820b96..d2c66c0 100644
--- a/test/spinlock_test.cpp
+++ b/test/spinlock_test.cpp
@@ -8,7 +8,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
-#include
+#include
// Sanity check only
diff --git a/test/spinlock_try_test.cpp b/test/spinlock_try_test.cpp
index 59e3390..008b60e 100644
--- a/test/spinlock_try_test.cpp
+++ b/test/spinlock_try_test.cpp
@@ -8,7 +8,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
-#include
+#include
#include
// Sanity check only
diff --git a/test/yield_k_test.cpp b/test/yield_k_test.cpp
index 1e6ab13..593c13d 100644
--- a/test/yield_k_test.cpp
+++ b/test/yield_k_test.cpp
@@ -8,7 +8,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
-#include
+#include
// Sanity check only
From 9c55fbc6c22533e034d9d9877066fc047755d812 Mon Sep 17 00:00:00 2001
From: Peter Dimov
Date: Tue, 3 Mar 2009 19:25:26 +0000
Subject: [PATCH 007/210] Fix enable_shared_from_this-related tickets in trunk.
Refs #2126. Refs #2584.
[SVN r51581]
---
.../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_constructor_test.cpp | 169 -----------
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 +
test/sp_accept_owner_test.cpp | 146 ----------
14 files changed, 824 insertions(+), 407 deletions(-)
create mode 100644 test/allocate_shared_esft_test.cpp
delete mode 100644 test/esft_constructor_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
delete mode 100644 test/sp_accept_owner_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_constructor_test.cpp b/test/esft_constructor_test.cpp
deleted file mode 100644
index 737123e..0000000
--- a/test/esft_constructor_test.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-//
-// esft_constructor_test.cpp
-//
-// A test for the new enable_shared_from_this support for calling
-// shared_from_this from constructors (that is, prior to the
-// object's ownership being passed to an external shared_ptr).
-//
-// Copyright (c) 2008 Frank Mori Hess
-// Copyright (c) 2008 Peter Dimov
-//
-// Distributed under the Boost Software License, Version 1.0.
-//
-// See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#include
-#include
-#include
-#include
-#include
-
-class X: public boost::enable_shared_from_this< X >
-{
-private:
-
- int destroyed_;
- int deleted_;
- int expected_;
-
-private:
-
- X( X const& );
- X& operator=( X const& );
-
-public:
-
- static int instances;
-
-public:
-
- explicit X( int expected, boost::shared_ptr *early_px = 0 ): destroyed_( 0 ), deleted_( 0 ), expected_( expected )
- {
- ++instances;
- if( early_px ) *early_px = shared_from_this();
- }
-
- ~X()
- {
- BOOST_TEST( deleted_ == expected_ );
- BOOST_TEST( destroyed_ == 0 );
- ++destroyed_;
- --instances;
- }
-
- typedef void (*deleter_type)( X* );
-
- static void deleter( X * px )
- {
- ++px->deleted_;
- }
-
- static void deleter2( X * px )
- {
- ++px->deleted_;
- delete px;
- }
-};
-
-int X::instances = 0;
-
-template
-bool are_shared_owners(const boost::shared_ptr &a, const boost::shared_ptr &b)
-{
- return !(a < b) && !(b < a);
-}
-
-struct Y: public boost::enable_shared_from_this
-{};
-
-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 &err)
- {}
- }
-
- 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 &err)
- {
- BOOST_ERROR("y threw bad_weak_ptr");
- }
- }
-
- return boost::report_errors();
-}
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
diff --git a/test/sp_accept_owner_test.cpp b/test/sp_accept_owner_test.cpp
deleted file mode 100644
index e8d1b32..0000000
--- a/test/sp_accept_owner_test.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-//
-// sp_accept_owner_test.cpp
-//
-// Copyright (c) 2008 Peter Dimov
-//
-// Distributed under the Boost Software License, Version 1.0.
-//
-// See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#include
-#include
-#include
-
-namespace N
-{
-
-struct D;
-
-struct X
-{
- X * px_;
-
- D * pd_;
- void * pv_;
-
- X(): px_( 0 ), pd_( 0 ), pv_( 0 )
- {
- }
-};
-
-struct D
-{
- template void operator()( T * p ) const { delete p; }
-};
-
-} // namespace N
-
-#if !defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP )
-
-namespace N
-{
-
-#else
-
-namespace boost
-{
-
-#endif
-
-template inline void sp_accept_owner( boost::shared_ptr * ps, ::N::X * px )
-{
- std::cout << "sp_accept_owner( " << ps << ", " << px << " )\n";
-
- BOOST_TEST( ps->get() == px );
-
- if( px != 0 )
- {
- px->px_ = px;
- }
-}
-
-template inline void sp_accept_owner( boost::shared_ptr * ps, ::N::X * px, ::N::D * pd )
-{
- std::cout << "sp_accept_owner( " << ps << ", " << px << ", (D*)" << pd << " )\n";
-
- BOOST_TEST( ps->get() == px );
-
- if( px != 0 )
- {
- px->px_ = px;
- px->pd_ = pd;
- }
-}
-
-template inline void sp_accept_owner( boost::shared_ptr * ps, ::N::X * px, void * pv )
-{
- std::cout << "sp_accept_owner( " << ps << ", " << px << ", (void*)" << pv << " )\n";
-
- BOOST_TEST( ps->get() == px );
-
- if( px != 0 )
- {
- px->px_ = px;
- px->pv_ = pv;
- }
-}
-
-} // namespace N or boost
-
-struct D2
-{
- template void operator()( T * p ) const { delete p; }
-};
-
-template void test( T* = 0 )
-{
- {
- boost::shared_ptr p( static_cast< T* >( 0 ) );
- }
-
- {
- T * p = new T;
- boost::shared_ptr q( p );
-
- BOOST_TEST( q->px_ == p );
- BOOST_TEST( q->pd_ == 0 );
- BOOST_TEST( q->pv_ == 0 );
- }
-
- {
- T * p = new T;
- boost::shared_ptr q( p, N::D() );
-
- BOOST_TEST( q->px_ == p );
- BOOST_TEST( q->pd_ != 0 );
- BOOST_TEST( q->pv_ == 0 );
- }
-
- {
- T * p = new T;
- boost::shared_ptr q( p, D2() );
-
- BOOST_TEST( q->px_ == p );
- BOOST_TEST( q->pd_ == 0 );
- BOOST_TEST( q->pv_ != 0 );
- }
-}
-
-namespace N2
-{
-
-struct Y: public virtual N::X
-{
-};
-
-} // namespace N2
-
-int main()
-{
- test();
- test();
-
- return boost::report_errors();
-}
From 0610947c4a7141e209b2ac6caca0790da17d06f3 Mon Sep 17 00:00:00 2001
From: Peter Dimov
Date: Sat, 7 Mar 2009 22:21:56 +0000
Subject: [PATCH 008/210] De-optimize assignment into this_type(r).swap(*this)
- turns out that they were not equivalent, leading to leaks in contrived
cases. Refs #2813.
[SVN r51643]
---
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 dc3ffc5f4b3cc82ab6cf0a6ea2dae5ab3d249c9f Mon Sep 17 00:00:00 2001
From: Peter Dimov
Date: Tue, 10 Mar 2009 18:07:13 +0000
Subject: [PATCH 009/210] Attempt to fix como link failure.
[SVN r51686]
---
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 fbc6919eae7bbdc0a4b8924ebcc582c6df782102 Mon Sep 17 00:00:00 2001
From: Frank Mori Hess
Date: Wed, 11 Mar 2009 13:48:51 +0000
Subject: [PATCH 010/210] Adding documentation for make_shared and
allocate_shared to smart_ptr docs. It is adopted from n2351 "Improving
shared_ptr for C++0x, Revision 2". Also includes some minor corrections. Refs
#1897
[SVN r51699]
---
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
+
+
+
+
make_shared and allocate_shared function templates
+ Introduction
+ Synopsis
+ Free Functions
+ Example
+
+ 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.
+
+ 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
+}
+
+ 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).
+
+
+ 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
- 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.
- 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.
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.]
~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.
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.
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.]
@@ -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.]
@@ -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.]
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.
@@ -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.
@@ -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.
@@ -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.
- 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.
- 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.
- 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.
- 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.