From 468c41041b3d7ec0394cea52e3c24b7ba90743f7 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 7 Jul 2000 16:04:40 +0000 Subject: [PATCH 001/513] This commit was generated by cvs2svn to compensate for changes in r4, which included commits to RCS files with non-trunk default branches. [SVN r7621] --- include/boost/smart_ptr.hpp | 369 ++++++++++++++++++++++++++++++++++++ smart_ptr_test.cpp | 263 +++++++++++++++++++++++++ 2 files changed, 632 insertions(+) create mode 100644 include/boost/smart_ptr.hpp create mode 100644 smart_ptr_test.cpp diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp new file mode 100644 index 0000000..e233104 --- /dev/null +++ b/include/boost/smart_ptr.hpp @@ -0,0 +1,369 @@ +// Boost smart_ptr.hpp header file -----------------------------------------// + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. Permission to copy, +// use, modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided "as is" +// without express or implied warranty, and with no claim as to its +// suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. + +// Revision History +// 22 Jun 00 Remove #if continuations to fix GCC 2.95.2 problem (Beman Dawes) +// 1 Feb 00 Additional shared_ptr BOOST_NO_MEMBER_TEMPLATES workarounds +// (Dave Abrahams) +// 31 Dec 99 Condition tightened for no member template friend workaround +// (Dave Abrahams) +// 30 Dec 99 Moved BOOST_NMEMBER_TEMPLATES compatibility code to config.hpp +// (Dave Abrahams) +// 30 Nov 99 added operator ==, operator !=, and std::swap and std::less +// specializations for shared types (Darin Adler) +// 11 Oct 99 replaced op[](int) with op[](std::size_t) (Ed Brey, Valentin +// Bonnard), added shared_ptr workaround for no member template +// friends (Matthew Langston) +// 25 Sep 99 added shared_ptr::swap and shared_array::swap (Luis Coelho). +// 20 Jul 99 changed name to smart_ptr.hpp, #include , +// #include and use boost::noncopyable +// 17 May 99 remove scoped_array and shared_array operator*() as +// unnecessary (Beman Dawes) +// 14 May 99 reorder code so no effects when bad_alloc thrown (Abrahams/Dawes) +// 13 May 99 remove certain throw() specifiers to avoid generated try/catch +// code cost (Beman Dawes) +// 11 May 99 get() added, conversion to T* placed in macro guard (Valentin +// Bonnard, Dave Abrahams, and others argued for elimination +// of the automatic conversion) +// 28 Apr 99 #include fix (Valentin Bonnard) +// 28 Apr 99 rename transfer() to share() for clarity (Dave Abrahams) +// 28 Apr 99 remove unsafe shared_array template conversions(Valentin Bonnard) +// 28 Apr 99 p(r) changed to p(r.px) for clarity (Dave Abrahams) +// 21 Apr 99 reset() self assignment fix (Valentin Bonnard) +// 21 Apr 99 dispose() provided to improve clarity (Valentin Bonnard) +// 27 Apr 99 leak when new throws fixes (Dave Abrahams) +// 21 Oct 98 initial Version (Greg Colvin/Beman Dawes) + +#ifndef BOOST_SMART_PTR_HPP +#define BOOST_SMART_PTR_HPP + +#include // for broken compiler workarounds +#include // for std::size_t +#include // for std::auto_ptr +#include // for std::swap +#include // for boost::noncopyable +#include // for std::less + +namespace boost { + +// scoped_ptr --------------------------------------------------------------// + +// scoped_ptr mimics a built-in pointer except that it guarantees deletion +// of the object pointed to, either on destruction of the scoped_ptr or via +// an explicit reset(). scoped_ptr is a simple solution for simple needs; +// see shared_ptr (below) or std::auto_ptr if your needs are more complex. + +template class scoped_ptr : noncopyable { + + T* ptr; + + public: + typedef T element_type; + + explicit scoped_ptr( T* p=0 ) throw() : ptr(p) {} + ~scoped_ptr() { delete ptr; } + + void reset( T* p=0 ) { if ( ptr != p ) { delete ptr; ptr = p; } } + T& operator*() const throw() { return *ptr; } + T* operator->() const throw() { return ptr; } + T* get() const throw() { return ptr; } +#ifdef BOOST_SMART_PTR_CONVERSION + // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! + operator T*() const throw() { return ptr; } +#endif + }; // scoped_ptr + +// scoped_array ------------------------------------------------------------// + +// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to +// is guaranteed, either on destruction of the scoped_array or via an explicit +// reset(). See shared_array or std::vector if your needs are more complex. + +template class scoped_array : noncopyable { + + T* ptr; + + public: + typedef T element_type; + + explicit scoped_array( T* p=0 ) throw() : ptr(p) {} + ~scoped_array() { delete [] ptr; } + + void reset( T* p=0 ) { if ( ptr != p ) {delete [] ptr; ptr=p;} } + + T* get() const throw() { return ptr; } +#ifdef BOOST_SMART_PTR_CONVERSION + // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! + operator T*() const throw() { return ptr; } +#else + T& operator[](std::size_t i) const throw() { return ptr[i]; } +#endif + }; // scoped_array + +// shared_ptr --------------------------------------------------------------// + +// An enhanced relative of scoped_ptr with reference counted copy semantics. +// The object pointed to is deleted when the last shared_ptr pointing to it +// is destroyed or reset. + +template class shared_ptr { + public: + typedef T element_type; + + explicit shared_ptr(T* p =0) : px(p) { + try { pn = new long(1); } // fix: prevent leak if new throws + catch (...) { delete p; throw; } + } + + shared_ptr(const shared_ptr& r) throw() : px(r.px) { ++*(pn = r.pn); } + + ~shared_ptr() { dispose(); } + + shared_ptr& operator=(const shared_ptr& r) { + share(r.px,r.pn); + return *this; + } + +#if !defined( BOOST_NO_MEMBER_TEMPLATES ) + template + shared_ptr(const shared_ptr& r) throw() : px(r.px) { + ++*(pn = r.pn); + } + + template + shared_ptr(std::auto_ptr& r) { + pn = new long(1); // may throw + px = r.release(); // fix: moved here to stop leak if new throws + } + + template + shared_ptr& operator=(const shared_ptr& r) { + share(r.px,r.pn); + return *this; + } + + template + shared_ptr& operator=(std::auto_ptr& r) { + // code choice driven by guarantee of "no effect if new throws" + if (*pn == 1) { delete px; } + else { // allocate new reference counter + long * tmp = new long(1); // may throw + --*pn; // only decrement once danger of new throwing is past + pn = tmp; + } // allocate new reference counter + px = r.release(); // fix: moved here so doesn't leak if new throws + return *this; + } +#else + shared_ptr(std::auto_ptr& r) { + pn = new long(1); // may throw + px = r.release(); // fix: moved here to stop leak if new throws + } + + shared_ptr& operator=(std::auto_ptr& r) { + // code choice driven by guarantee of "no effect if new throws" + if (*pn == 1) { delete px; } + else { // allocate new reference counter + long * tmp = new long(1); // may throw + --*pn; // only decrement once danger of new throwing is past + pn = tmp; + } // allocate new reference counter + px = r.release(); // fix: moved here so doesn't leak if new throws + return *this; + } +#endif + + void reset(T* p=0) { + if ( px == p ) return; // fix: self-assignment safe + if (--*pn == 0) { delete px; } + else { // allocate new reference counter + try { pn = new long; } // fix: prevent leak if new throws + catch (...) { + ++*pn; // undo effect of --*pn above to meet effects guarantee + delete p; + throw; + } // catch + } // allocate new reference counter + *pn = 1; + px = p; + } // reset + + T& operator*() const throw() { return *px; } + T* operator->() const throw() { return px; } + T* get() const throw() { return px; } + #ifdef BOOST_SMART_PTR_CONVERSION + // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! + operator T*() const throw() { return px; } + #endif + + long use_count() const throw(){ return *pn; } + bool unique() const throw() { return *pn == 1; } + + void swap(shared_ptr& other) throw() + { std::swap(px,other.px); std::swap(pn,other.pn); } + +// Tasteless as this may seem, making all members public allows member templates +// to work in the absence of member template friends. (Matthew Langston) +// Don't split this line into two; that causes problems for some GCC 2.95.2 builds +#if defined(BOOST_NO_MEMBER_TEMPLATES) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) + private: +#endif + + T* px; // contained pointer + long* pn; // ptr to reference counter + +// Don't split this line into two; that causes problems for some GCC 2.95.2 builds +#if !defined( BOOST_NO_MEMBER_TEMPLATES ) && !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) + template friend class shared_ptr; +#endif + + void dispose() { if (--*pn == 0) { delete px; delete pn; } } + + void share(T* rpx, long* rpn) { + if (pn != rpn) { + dispose(); + px = rpx; + ++*(pn = rpn); + } + } // share +}; // shared_ptr + +template + inline bool operator==(const shared_ptr& a, const shared_ptr& b) + { return a.get() == b.get(); } + +template + inline bool operator!=(const shared_ptr& a, const shared_ptr& b) + { return a.get() != b.get(); } + +// shared_array ------------------------------------------------------------// + +// shared_array extends shared_ptr to arrays. +// The array pointed to is deleted when the last shared_array pointing to it +// is destroyed or reset. + +template class shared_array { + public: + typedef T element_type; + + explicit shared_array(T* p =0) : px(p) { + try { pn = new long(1); } // fix: prevent leak if new throws + catch (...) { delete [] p; throw; } + } + + shared_array(const shared_array& r) throw() : px(r.px) { ++*(pn = r.pn); } + + ~shared_array() { dispose(); } + + shared_array& operator=(const shared_array& r) { + if (pn != r.pn) { + dispose(); + px = r.px; + ++*(pn = r.pn); + } + return *this; + } // operator= + + void reset(T* p=0) { + if ( px == p ) return; // fix: self-assignment safe + if (--*pn == 0) { delete [] px; } + else { // allocate new reference counter + try { pn = new long; } // fix: prevent leak if new throws + catch (...) { + ++*pn; // undo effect of --*pn above to meet effects guarantee + delete [] p; + throw; + } // catch + } // allocate new reference counter + *pn = 1; + px = p; + } // reset + + T* get() const throw() { return px; } + #ifdef BOOST_SMART_PTR_CONVERSION + // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! + operator T*() const throw() { return px; } + #else + T& operator[](std::size_t i) const throw() { return px[i]; } + #endif + + long use_count() const throw() { return *pn; } + bool unique() const throw() { return *pn == 1; } + + void swap(shared_array& other) throw() + { std::swap(px,other.px); std::swap(pn,other.pn); } + + private: + + T* px; // contained pointer + long* pn; // ptr to reference counter + + void dispose() { if (--*pn == 0) { delete [] px; delete pn; } } + +}; // shared_array + +template + inline bool operator==(const shared_array& a, const shared_array& b) + { return a.get() == b.get(); } + +template + inline bool operator!=(const shared_array& a, const shared_array& b) + { return a.get() != b.get(); } + +} // namespace boost + +// specializations for things in namespace std -----------------------------// + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +namespace std { + +// Specialize std::swap to use the fast, non-throwing swap that's provided +// as a member function instead of using the default algorithm which creates +// a temporary and uses assignment. + +template + inline void swap(boost::shared_ptr& a, boost::shared_ptr& b) + { a.swap(b); } + +template + inline void swap(boost::shared_array& a, boost::shared_array& b) + { a.swap(b); } + +// Specialize std::less so we can use shared pointers and arrays as keys in +// associative collections. + +// It's still a controversial question whether this is better than supplying +// a full range of comparison operators (<, >, <=, >=). + +template + struct less< boost::shared_ptr > + : binary_function, boost::shared_ptr, bool> + { + bool operator()(const boost::shared_ptr& a, + const boost::shared_ptr& b) const + { return less()(a.get(),b.get()); } + }; + +template + struct less< boost::shared_array > + : binary_function, boost::shared_array, bool> + { + bool operator()(const boost::shared_array& a, + const boost::shared_array& b) const + { return less()(a.get(),b.get()); } + }; + +} // namespace std + +#endif // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_SMART_PTR_HPP + diff --git a/smart_ptr_test.cpp b/smart_ptr_test.cpp new file mode 100644 index 0000000..cd4d61b --- /dev/null +++ b/smart_ptr_test.cpp @@ -0,0 +1,263 @@ +// smart pointer test program ----------------------------------------------// + +// (C) Copyright Beman Dawes 1998, 1999. Permission to copy, use, modify, sell +// and distribute this software is granted provided this copyright notice +// appears in all copies. This software is provided "as is" without express or +// implied warranty, and with no claim as to its suitability for any purpose. + +// Revision History +// 29 Nov 99 added std::swap and associative container tests (Darin Adler) +// 25 Sep 99 added swap tests +// 20 Jul 99 header name changed to .hpp +// 20 Apr 99 additional error tests added. + +#include +#include +#include +#include +#include + +#ifdef NDEBUG +#error This test program makes no sense if NDEBUG is defined +#endif + +using namespace std; +using boost::scoped_ptr; +using boost::scoped_array; +using boost::shared_ptr; +using boost::shared_array; + +template +void ck( const T* v1, T v2 ) { assert( *v1 == v2 ); } + +namespace { + int UDT_use_count; // independent of pointer maintained counts + } + +// user defined type -------------------------------------------------------// + +class UDT { + long value_; + public: + explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; } + ~UDT() { + --UDT_use_count; + cout << "UDT with value " << value_ << " being destroyed" << endl; + } + long value() const { return value_; } + void value( long v ) { value_ = v;; } + }; // UDT + +// main --------------------------------------------------------------------// + +// This isn't a very systematic test; it just hits some of the basics. + +int main() { + + assert( UDT_use_count == 0 ); // reality check + + // test scoped_ptr with a built-in type + long * lp = new long; + scoped_ptr sp ( lp ); + assert( sp.get() == lp ); + assert( lp == sp.get() ); + assert( &*sp == lp ); + + *sp = 1234568901L; + assert( *sp == 1234568901L ); + assert( *lp == 1234568901L ); + ck( static_cast(sp.get()), 1234568901L ); + ck( lp, *sp ); + + sp.reset(); + assert( sp.get() == 0 ); + + // test scoped_ptr with a user defined type + scoped_ptr udt_sp ( new UDT( 999888777 ) ); + assert( udt_sp->value() == 999888777 ); + udt_sp.reset(); + udt_sp.reset( new UDT( 111222333 ) ); + assert( udt_sp->value() == 111222333 ); + udt_sp.reset( new UDT( 333222111 ) ); + assert( udt_sp->value() == 333222111 ); + + // test scoped_array with a build-in type + char * sap = new char [ 100 ]; + scoped_array sa ( sap ); + assert( sa.get() == sap ); + assert( sap == sa.get() ); + + strcpy( sa.get(), "Hot Dog with mustard and relish" ); + assert( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 ); + assert( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 ); + + assert( sa[0] == 'H' ); + assert( sa[30] == 'h' ); + + sa[0] = 'N'; + sa[4] = 'd'; + assert( strcmp( sap, "Not dog with mustard and relish" ) == 0 ); + + sa.reset(); + assert( sa.get() == 0 ); + + // test shared_ptr with a built-in type + int * ip = new int; + shared_ptr cp ( ip ); + assert( ip == cp.get() ); + assert( cp.use_count() == 1 ); + + *cp = 54321; + assert( *cp == 54321 ); + assert( *ip == 54321 ); + ck( static_cast(cp.get()), 54321 ); + ck( static_cast(ip), *cp ); + + shared_ptr cp2 ( cp ); + assert( ip == cp2.get() ); + assert( cp.use_count() == 2 ); + assert( cp2.use_count() == 2 ); + + assert( *cp == 54321 ); + assert( *cp2 == 54321 ); + ck( static_cast(cp2.get()), 54321 ); + ck( static_cast(ip), *cp2 ); + + shared_ptr cp3 ( cp ); + assert( cp.use_count() == 3 ); + assert( cp2.use_count() == 3 ); + assert( cp3.use_count() == 3 ); + cp.reset(); + assert( cp2.use_count() == 2 ); + assert( cp3.use_count() == 2 ); + assert( cp.use_count() == 1 ); + cp.reset( new int ); + *cp = 98765; + assert( *cp == 98765 ); + *cp3 = 87654; + assert( *cp3 == 87654 ); + assert( *cp2 == 87654 ); + cp.swap( cp3 ); + assert( *cp == 87654 ); + assert( *cp2 == 87654 ); + assert( *cp3 == 98765 ); + cp.swap( cp3 ); + assert( *cp == 98765 ); + assert( *cp2 == 87654 ); + assert( *cp3 == 87654 ); + cp2 = cp2; + assert( cp2.use_count() == 2 ); + assert( *cp2 == 87654 ); + cp = cp2; + assert( cp2.use_count() == 3 ); + assert( *cp2 == 87654 ); + assert( cp.use_count() == 3 ); + assert( *cp == 87654 ); + + shared_ptr cp4; + swap( cp2, cp4 ); + assert( cp4.use_count() == 3 ); + assert( *cp4 == 87654 ); + assert( cp2.get() == 0 ); + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + set< shared_ptr > scp; + scp.insert(cp4); + assert( scp.find(cp4) != scp.end() ); + assert( scp.find(cp4) == scp.find( shared_ptr(cp4) ) ); +#endif + + // test shared_array with a built-in type + char * cap = new char [ 100 ]; + shared_array ca ( cap ); + assert( ca.get() == cap ); + assert( cap == ca.get() ); + assert( &ca[0] == cap ); + + strcpy( ca.get(), "Hot Dog with mustard and relish" ); + assert( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 ); + assert( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 ); + + assert( ca[0] == 'H' ); + assert( ca[30] == 'h' ); + + shared_array ca2 ( ca ); + shared_array ca3 ( ca2 ); + + ca[0] = 'N'; + ca[4] = 'd'; + assert( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 ); + assert( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 ); + assert( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 ); + assert( ca.use_count() == 3 ); + assert( ca2.use_count() == 3 ); + assert( ca3.use_count() == 3 ); + ca2.reset(); + assert( ca.use_count() == 2 ); + assert( ca3.use_count() == 2 ); + assert( ca2.use_count() == 1 ); + + ca.reset(); + assert( ca.get() == 0 ); + + shared_array ca4; + swap( ca3, ca4 ); + assert( ca4.use_count() == 1 ); + assert( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); + assert( ca3.get() == 0 ); + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + set< shared_array > sca; + sca.insert(ca4); + assert( sca.find(ca4) != sca.end() ); + assert( sca.find(ca4) == sca.find( shared_array(ca4) ) ); +#endif + + // test shared_array with user defined type + shared_array udta ( new UDT[3] ); + + udta[0].value( 111 ); + udta[1].value( 222 ); + udta[2].value( 333 ); + shared_array udta2 ( udta ); + + assert( udta[0].value() == 111 ); + assert( udta[1].value() == 222 ); + assert( udta[2].value() == 333 ); + assert( udta2[0].value() == 111 ); + assert( udta2[1].value() == 222 ); + assert( udta2[2].value() == 333 ); + udta2.reset(); + assert( udta2.get() == 0 ); + assert( udta.use_count() == 1 ); + assert( udta2.use_count() == 1 ); + + assert( UDT_use_count == 4 ); // reality check + + // test shared_ptr with a user defined type + UDT * up = new UDT; + shared_ptr sup ( up ); + assert( up == sup.get() ); + assert( sup.use_count() == 1 ); + + sup->value( 54321 ) ; + assert( sup->value() == 54321 ); + assert( up->value() == 54321 ); + + shared_ptr sup2; + sup2 = sup; + assert( sup2->value() == 54321 ); + assert( sup.use_count() == 2 ); + assert( sup2.use_count() == 2 ); + sup2 = sup2; + assert( sup2->value() == 54321 ); + assert( sup.use_count() == 2 ); + assert( sup2.use_count() == 2 ); + + cout << "OK" << endl; + + new char[12345]; // deliberate memory leak to verify leaks detected + + return 0; + } // main + From 90b7ec19d115aa2a27a8d3c3fdbe620fbb002bd4 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Mon, 24 Jul 2000 16:21:10 +0000 Subject: [PATCH 002/513] Changed throw() to // never throws. [SVN r7628] --- include/boost/smart_ptr.hpp | 53 ++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index e233104..353e472 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -9,6 +9,8 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 24 Jul 00 Change throw() to // never throws. See lib guidelines +// Exception-specification rationale. (Beman Dawes) // 22 Jun 00 Remove #if continuations to fix GCC 2.95.2 problem (Beman Dawes) // 1 Feb 00 Additional shared_ptr BOOST_NO_MEMBER_TEMPLATES workarounds // (Dave Abrahams) @@ -67,16 +69,16 @@ template class scoped_ptr : noncopyable { public: typedef T element_type; - explicit scoped_ptr( T* p=0 ) throw() : ptr(p) {} + explicit scoped_ptr( T* p=0 ) : ptr(p) {} // never throws ~scoped_ptr() { delete ptr; } void reset( T* p=0 ) { if ( ptr != p ) { delete ptr; ptr = p; } } - T& operator*() const throw() { return *ptr; } - T* operator->() const throw() { return ptr; } - T* get() const throw() { return ptr; } + T& operator*() const { return *ptr; } // never throws + T* operator->() const { return ptr; } // never throws + T* get() const { return ptr; } // never throws #ifdef BOOST_SMART_PTR_CONVERSION // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! - operator T*() const throw() { return ptr; } + operator T*() const { return ptr; } // never throws #endif }; // scoped_ptr @@ -93,17 +95,17 @@ template class scoped_array : noncopyable { public: typedef T element_type; - explicit scoped_array( T* p=0 ) throw() : ptr(p) {} + explicit scoped_array( T* p=0 ) : ptr(p) {} // never throws ~scoped_array() { delete [] ptr; } void reset( T* p=0 ) { if ( ptr != p ) {delete [] ptr; ptr=p;} } - T* get() const throw() { return ptr; } + T* get() const { return ptr; } // never throws #ifdef BOOST_SMART_PTR_CONVERSION // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! - operator T*() const throw() { return ptr; } + operator T*() const { return ptr; } // never throws #else - T& operator[](std::size_t i) const throw() { return ptr[i]; } + T& operator[](std::size_t i) const { return ptr[i]; } // never throws #endif }; // scoped_array @@ -122,7 +124,7 @@ template class shared_ptr { catch (...) { delete p; throw; } } - shared_ptr(const shared_ptr& r) throw() : px(r.px) { ++*(pn = r.pn); } + shared_ptr(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); } // never throws ~shared_ptr() { dispose(); } @@ -133,7 +135,7 @@ template class shared_ptr { #if !defined( BOOST_NO_MEMBER_TEMPLATES ) template - shared_ptr(const shared_ptr& r) throw() : px(r.px) { + shared_ptr(const shared_ptr& r) : px(r.px) { // never throws ++*(pn = r.pn); } @@ -195,18 +197,18 @@ template class shared_ptr { px = p; } // reset - T& operator*() const throw() { return *px; } - T* operator->() const throw() { return px; } - T* get() const throw() { return px; } + T& operator*() const { return *px; } // never throws + T* operator->() const { return px; } // never throws + T* get() const { return px; } // never throws #ifdef BOOST_SMART_PTR_CONVERSION // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! - operator T*() const throw() { return px; } + operator T*() const { return px; } // never throws #endif - long use_count() const throw(){ return *pn; } - bool unique() const throw() { return *pn == 1; } + long use_count() const { return *pn; } // never throws + bool unique() const { return *pn == 1; } // never throws - void swap(shared_ptr& other) throw() + void swap(shared_ptr& other) // never throws { std::swap(px,other.px); std::swap(pn,other.pn); } // Tasteless as this may seem, making all members public allows member templates @@ -258,7 +260,8 @@ template class shared_array { catch (...) { delete [] p; throw; } } - shared_array(const shared_array& r) throw() : px(r.px) { ++*(pn = r.pn); } + shared_array(const shared_array& r) : px(r.px) // never throws + { ++*(pn = r.pn); } ~shared_array() { dispose(); } @@ -286,18 +289,18 @@ template class shared_array { px = p; } // reset - T* get() const throw() { return px; } + T* get() const { return px; } // never throws #ifdef BOOST_SMART_PTR_CONVERSION // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! - operator T*() const throw() { return px; } + operator T*() const { return px; } // never throws #else - T& operator[](std::size_t i) const throw() { return px[i]; } + T& operator[](std::size_t i) const { return px[i]; } // never throws #endif - long use_count() const throw() { return *pn; } - bool unique() const throw() { return *pn == 1; } + long use_count() const { return *pn; } // never throws + bool unique() const { return *pn == 1; } // never throws - void swap(shared_array& other) throw() + void swap(shared_array& other) // never throws { std::swap(px,other.px); std::swap(pn,other.pn); } private: From ed7e13da9f2d7ea2878e0bac3627d7271ab52b07 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 27 Jul 2000 14:18:23 +0000 Subject: [PATCH 003/513] Initial commit [SVN r7638] --- gccspeed.gif | Bin 0 -> 6603 bytes msvcspeed.gif | Bin 0 -> 6169 bytes smarttest.zip | Bin 0 -> 11513 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 gccspeed.gif create mode 100644 msvcspeed.gif create mode 100644 smarttest.zip diff --git a/gccspeed.gif b/gccspeed.gif new file mode 100644 index 0000000000000000000000000000000000000000..d78c06bbf8b6b72380950b597c32ada51e5186b6 GIT binary patch literal 6603 zcmZ?wbh9u|G+;_*{LTOZ#taN;3=A_F7|t*-{AXZbFlI0|W=Jz;m}$&##+czhSlT#^ zAuWwzW*WnpG=~3R)y6X!(q=NuoXK!zCc}TQX5%vqX=fN_o?$q1hT%WhEaU$SY5y5! z{%1JzpW#2)Xk!NBGzR0D48~^|jQ@jeGB!3&Gd7-SY<$Mp_&?ZU<22*6G~=0R#%I!u z|AXCOJkvOBrt!>~#%E?4{|7tE_>6Jd8RMB}jL)1g{ttGg@qgpA|Hd=_8=v`a{2%OS zV~~^6W`Z1*_Mah*0c1~F8px!yGa$7fFBzwSz|6F?Giho6!9FyenU*#)ZRX6hGc(iv zgFS3~1|&W6Oxl?T=@jGmb`^Gw>z|KPAQo(ZyP=FFLAX3qQ%4oc%QAd6?7nR({S%>Uq!HU1BB z$ISmT&-|bH9~{ueph!3~6BNv6{xh6m0EOI{G*H-_IRo-NC>o4G9s-$l2INLitQdo= zJu?$z@R|SMNHRVH^3u#RAn+d?XU6|QKAidg%$fgZ{)3~?7!=$8XM*DM|9^)644^3b zp9YGA|7SqK42oc5P{@H?c?J|1p!hZh`S1TskPrU<2S>m08Bk!&JOeWNKR7iQ{|ANL z%>N*p{(}<-C@s<*EB<5w+o=O0L3zS~<3GcCP8p943l27O2y4Zh*s$<$yMVIS9FL8Q zj&@5JXWcomaq;nf1?Mgq&rKu6gE|wFPI!xCM-WMYIS>a5!UjDNsD<`Y_&e2R| za^)yaKReT-UG8n>h8O-z&HK%2vo@`|x;kQW*4;C@*wfqA z-ripD_|#nQ?d$IDuK4`w?&6)~ z`(5V##ovEO8U8xD_vZ4e`qTIS{x9k4em8cfh{XhU&Y#;aMz(1FnAXg&i(S5vP3#F{ z6aUHbxE9WTtcvX`0?il3ib|C%^pLVTam+d7srmhG>08?$7Vf?}V_vUulltOplVcTg zsx14yD|XcPMua!+R4GY{$}#a2nK084_(o2h z`8zQ3X+vS+$|sXzOCv8$&-&kVTzpokl*)sNo@Ol1!-{sfrq8Qzt5oi@yCr!!^%Uoe z7mFuE&73})>u+Yzf)-w@fF*OvZY3@<-X)P7kSL|Ks;6V3RMyH`QK{)mR;YSrPK%z@ zqM0*m)l04L-D#|^(>>f$Ub^|N<49U3Gxd7p`Y6NOg0ttcYUixw7hRoZaD#2K;3n>S z(?#;9w`Qv^POy}IQuA!-?s;L=LTxGY1u{7&ZoQS-y*B2KQ0BYPGyklnZxQ94EwJ~% z&C^l)B)7iM4f!$C{QAByN1khIxHUosqoR ze_FTR`!nY6|Nr@X!Cn9Fm#2@WWd-qQFTL^g)_WJdZ}(PLO$&a&?f>`Zi{(vIh*#sWi)8u{UiVF zjr&2as1HpNXBM!TpE$@@^`Ti|4#y4w*Ugu01sEDV7IKB3I3%{~L#sj0LY{Pw!&0|C zv{{^4$X9;iu-vZ??GA4eIc}S|e0{sNLujSE(Cy+Qs+&%9Udc}S+~a=q=}n!=fS!3G zn}0~_nXR|J@F_{?sK?ea-<0kYl{l%TkJtC-oK5}EJxNIWk=C6R9|J0E=H0(`L(=%r z)83MhD=$B6-q2pz(O>yddH#c^wkEq6H`x}KNGjdDdTjd{uN=v$*zFdRB^f52tT2cY zxpeNaZQwPQDUCG?w8UA>zqx#B>RQ5mqr`2yWoA+4>Hn8HIK6)?e)zU<64S~jQM0yf zw)px+s-Ne)cCe+3VCzNQ%{q~~8=1Ctt9+KaY$DRf!KoZ_?9GH%-Kr+DuX*UnUe>yP zSS?r~sF7a+I_FUQVZ{MBR|IP4JDaYS?`oA@N z5)3y5{rJ;ir+WDOE~W z`*>WCDq0oz@2%S+r|z9T%uD9|`n-If)ymzkG8cBtTeI}y#@U`Ow`3-DZBUWgD-?J? zC8V)oi<#F~?%?Z>cNxAqx-xEVhsAA`)eVW06g=jh@m|0As-Bq9a?7RMJ0t!}&RDr> ziemWO?kgvr?b)W39$#3SuF=@Fx!p-*y?pEGsLe0Jbsia-x9+*@y8cjL)F&S8Zq{Wt z*`{x6G1+EOJT=z+#LA^x!dlipf4t_ZL$jO9te1 zh-PeA%5l%+^n_EA=7on9*WJ-kvTTwGFFG5VmtC~`*affe##ek7m#)7(^G)7`mNj!` zRvh=f_i5JmJuiIMS6x4S@7u2Ldq4E9uX*kr|E=izz8|kk1MK z3TK=DNv>-?j0?{s$-NFgaVL2O(@Y~#cD;hr%03C*orm^naZflM^X=30{4>wYqG$G4 z=LO7ozCBH_>BrfMbDQUVKl9w~_s{bUd|MW<`@V3J{&k_lZ_A>&kNp|tD=tp(yS!t~ ziws*KlS@ZGu9JA*lesqIR`;BDCSi8}&mIlvmYS<*_I2g-S+7Fdr__Fpe0n=YHaL87 z+m*%K8KT+S?t9;^+O^?W($dVZ*YW*q*8@VfZgf-%d8buwCa^t@8ofBGyfF%P{d1pZ_9Jht&;CnyOdfU71Kx*@0xDKWqr4QURT@g-ihVm ztdZ}zb{t@jQ%YSpY4)~@PdS4{w{v`-c3^T1Of^h2PM}KGP zY&W;_6L#Hlr)S!v)t>jJW&FFQs39+Rq{1p;*QG7bIQ_RAQBRAg4ii0K6w`SM-kCL@udOw@ z_wz_~+_@)KVc}f!P1c{4+wo^rtoGF0-ImGOr8oaK$h=J1vpe+Dy7FYMyPH3zJv-|v zJ$?UwS%)Tb&WE*q)AkrWnPq=H*_U1NCc9;AbArn1`9}6am&2C4w@*{QVegrJe)XOv zo##JaXxIO!SHEZ5w><96^>-7dM<4yPqRx8iwUrO@-|2k{Ra|Sklc{FQ0=usk^%mjg z>F)ka{~qpE-S(l?%zw{~sb8cr?PBNIKgu_K6TrTI`z67BUz*rX9ydGxeZx}uMR&d1 zR_r^U{#LQMDt7AkKpY6W?rJgS}2%v9AAP&8N0P5f6z#b1Ak% zWv-z@0u?#i**)i9&)sMk+In5^+NS!mij8X~R(D>JQn}&5w?aVn35RT?X#}UT8jFe= zn}*&Bp>zSY$l}7r{*O&l%msB?o8ARBa~1j;Z;kOv5578G!hLyg+{J>;&k8b@i#c&f zOjh?5GHgD!uw}{S+FwpCj~32?L$rOd zVf&6xR@+RwwtrP}{oZ2sLTs9ZWZnwZCG2grj9oq<9j`>1Y8{(G+Qa&07)_XAt~Eny z^^01mjG}@U;`WzYqFlPK|5r3jZfd_+UVGT2M_Qx#IzxB3Vz-n^XVwjc@{ES`>)E^} zKKzZIyDfyOw;IlB)j9t)#;mk;r(>Dujb3}V?4#zLQ&fBNI|Qy(2;P_xKi4&1L8wQ0 zVU7FK&cMsv@+r|OAG=p5PLK-p_YUe4a5OuSVc#q)p&1k}wR57(%D8PBfzAk_9)bpvLPnjUwweM}KVT`1?z|_f(|5B%{Ea zSv+p$H2;+XsW-zPxC!RooKpW~T9K)zq_d<`fB1CX!s!ZArdLJEmi(Ol=eT?3kDjKV z;x(Oit(H^wOlny6xN6ml8SR!cr$o-2Ryp(kjLO0gNyD!lHbvJH9=f)^em3*rjTwtA zJ-Z_%+bY!#2HUKCIdlF@QHE_ZKdq>pSvh;h%-Oqk&far#_P(7uA!2b{PwK?XQtvA} zI*QHWo<3*k&)Lt5)3l~FN4U+o*eUtNw}U zm^ts&&Ux~iwF_P51#L|JV3{UsIR8zgxbU*M-fngr79z(zlm2z420wEMnr6%7CHDD+ zrzV?ud|Ogv+5FanN$j(1pM77j%w*xcNQa-n3%{&Pz2>=4YSsLB!7?STw8NS61#VTi zZCkj~e9rC8w8SeyifeAxwYhGq7R0NU zJ+EAPmAU6{a=EXTl~paTn60yH*=qU%juY@_^JDZ;LfYX5}8MT4NwO z?bIyKGq=`M@3iCADxa~cXWy*VGLP$1m*-vEwfcsa2J5!9KiyKcTg|*5rOu;n=jyrY zg4EheuOeKxEsMOdj=gZ5c*wf;%=Ka|>+3V?TRhjZCc6EKa{QB(n{2v4BxHlOx(`RT zJ(qN*(De-mpRM>8wf^L<<)Yj(Qm##uxxG>L_r#i69j8y_9sbY0sZ49rQLi>e$?}L9 z3&MYFy8CLj#_!cy)y+Mb{g&zhD|fA1UA0{Dw&1N3T0Gl*HKYu6qP134P0{?dS+USp zF|#>Eyw&{o3^VTlPwT1tt0RrQ^ICswIi4*4vOKt`bjz&co4vF*M_U^idIu}dn%f_` zWzEm39VfSRRq#qh6i#_K;cr*x%o~Mblehj!+N3;vo8m*YqemtzU%35(+YSXo?|tn% zmMq+{+--Z;i|wJTI~ObN>~`B3S?I~2;OVdD?`OMl*-SW6a!BZDhxwb9Mba~^d0cIEgw$;I%P@93+i1NoZ+OaS z<9^5IbF}dM9wUC{8)DbN11woF+C;LI0SNx6!-z z2Or%aa#(?LqK{0SkmqWCo~XOpwpnv_Z{A)W-netY!krhIk1J$uSG;-5_s=ok-^ZVc zo!D{sL}g5v=;q@R7mw$;oYWNWk1shIai@CDpN2^`Sqpe%cCl?&VcenSdTMFRiH1if zx2Yf4;l4mGO>D}oO$)8JRvMpZ{e5D>o}k||M4fGRPq8SQVxhOhX(?*T zcBh<*EIf10{A{yo>#^HCw>me^eRWn|>fFDThuB!pDel>?&8&G)rRQ-7AGni4Oz9{tn0&8DvPMBA;d^MO59%PlVc&e{6h z?BFGz3t|yxXT%h3i4o=Q6<<)@_Jik~T3gcUE6q{QH#MbXHAq)&y4Vmdc&VoG#MwRK zYrmXcWGN||>*+uHLc@$xlM^q`TX>@S;^m<4mp|1Qn)sf-(<3|0N8CfU_v4vHr@2xt zz6Tba5#MAJa%j`Ra9Qcdx!eB->gFlG*s3aVQs&bU)|y?>x>sY*wr0e(OuTa?;_H=D zPS?tK#Dn*W#(MNDUvrkVxTk`*A^Q0FppMcFzfYyghAjVh{c?n$JBR9D4S^Gj3}?)} zIb-hLx4TQd-5u85xfZV~UTa&S?{WB-#*K)jQ%r6jEPQ^xBer2nW?=PQ(WPfiihZy1 zGDauPl?i*fX5HRRcW2aweYqkie*OQW6Pim8s!J$NjV(QPSIYXSpF&J|LgSqxL7j}= zTf1)DZr(e&UFNR#4YPy0&rJ(EnB8&LZtm?nwgRhorS{9#9Nc?|S?9vzRTrfd&rF?t zJ5#s0?5^ZTUa{ob{Ss-dI%_Y-7T*?Qys7$l(ixw(cb5o0SlxVoYs78FMfYMhc1}qT zc|X@sC{EnmM)iE!6~ToMX66XKjqUxfD{ReSg6GoC)4tNdbulZ`VS$m%G*Tv9A@a17M{Rf5TK&5I(7z8#7QT3+{OZ@uK8wG06J76ozO{YjIpcYJLX-KNu8U0n zwJe~Mw?AW#=jOP(RWlxXoxPI1@pVsV$G*I+%s=`TFehHjxhwqrqR!0M`X_IF7kx5c zYIn+`eO3D|Kk$ya+46$-;H#t~k<5WF1+Cr*8y>#g@{VKSJ1Lj0mSn+q=Xyi;2|kMx z_+lq;#?MjxWoE^_2_M!82+VwTEAIUrzYivr;=k8fa^?%<^eBA!_u-20N58*o_psoZQ=j4x z`)TXasFN=~a_z1Eto>!4VVAtg=U11tmz4L3{uKNX_cg5l{iUa0QdjJkw7vgv(mN5) zuaQ5epZEKGweHOgonR|_LBsdySwFvZ6bq!zw_6%Fx~9_!Kx-Pa-+ z{LE*TDetT;D}~a}O|%aDl=4D2ZzH!_oYr%FS(bHgXQc0|Ug?Mr35QyF<=y5) zd`vplD{J2-6Zt9S)KuO0V{;-ur=6Q?ThAsN^(EudQs4P*bECdyU0WNwzfCs!Th6Vm zx%ZE)HT|AZAZ?CEinYJNO<-oO6)zq!9_e(m14{d?bBtDm!vUH-rQo#h{!Z*;G> zV-;`FJ@90Pa)AZ&+G+tO_UVf^9AXme`e5@^g2nL2op+Nbtk`W~Be+t;HD#mgO^=fE XE|U^`I^D$cj~KekmiOo=FjxZs3WTu? literal 0 HcmV?d00001 diff --git a/msvcspeed.gif b/msvcspeed.gif new file mode 100644 index 0000000000000000000000000000000000000000..56295ee9a506c65a672bf105bb1a0f357377f579 GIT binary patch literal 6169 zcmZ?wbh9u|G+;_*{LTOZ#taN;3=A_F7|t*-{AXZbFlI0|W=Jz;m}$&##+czhSlT#^ zAuWwzW*WnpG=~3R)y6X!(q=NuoXK!zCc}TQX5%vqX=fN_o?$q1hT%WhEaU$SY5y5! z{%1JzpW#2)Xk!NBGzR0D48~^|jQ@jeGB!3&Gd7-SY<$Mp_&?ZU<22*6G~=0R#%I!u z|AXCOJkvOBrt!>~#%E?4{|7tE_>6Jd8RMB}jL)1g{ttGg@qgpA|Hd=_8=v`a{2%OS zV~~^6W`Z1*_Mah*0c1~F8px!yGa$7fFBzwSz|6F?Giho6!9FyenU*#)ZRX6hGc(iv zgFS3~1|&W6Oxl?T=@jGmb`^Gw>z|KPAQo(ZyP=FFLAX3qQ%4oc%QAd6?7nR({S%>Uq!HU1BB z$ISmT&-|bH9~{ueph!3~6BNv6{xh6m0EOI{G*H-_IRo-NC>o4G9s-$l2INLitQdo= zJu?$z@R|SMNHRVH^3u#RAn+d?XU6|QKAidg%$fgZ{)3~?7!=$8XM*DM|9^)644^3b zp9YGA|7SqK42oc5P{@H?c?J|1p!hZh`S1TskPrU<2S>m08Bk!&JOeWNKR7iQ{|ANL z%>N*p{(}<-C@s<*EB<5w+o=O0L3zS~<3GcCP8p943l27O2y4Zh*s$<$yMVIS9FL8Q zj&@5JXWcomaq;nf1?Mgq&rM4_7&HR;LNq5lHJz>*yp6@-LaOg9?ZR6rCxxG%nQxr@ z>Pw`+vkP-P;^lmIP1Xol>ba0DS8Hol;BvLiS$9uuU44Ch!r?Ai?`>;tZqB&8D)#iY zwYRqyJU%tod;7Y(yDL7wx_f&2`uqDE9{y5UwK>iEaHFtx+?gF4lh*Vpd(YD`5O{i8 zQZf178O!xg&n=M6;`7~Aa_juE;PoMAcWsThvhJ#o-JV~nk8X0gAHR3DTKUbr*`>_# zet&MYKIWx0XDh2LW<5)2Zp}T<+aHio z`gKQP^K-xWCEpKR$-HiVA};6u-@SLsXR^!bOqpM$u(Ld{^6gEROO=Ix*%yT0^E7|x z$l_-n-{i_TRjy|1(&NJQR~<8wI#ge=FH8_mQ%&e*6O35kvGdA}3yng2)0I0dO`j$g zTfa+v=x|Xq^T`BZ*-n`r&XYF+d(CFGBzr{YswQ=PV9lH~twWJRsq6j68`rvh&OJ?W z3Fu3|J|*?Pm8r;d*@KdTlT!DEKA6enC@Cdfv*}{o+&nJTH|6Wg z%AuC*r63~Jg%#WsXDIk z`=YUW?KZXC^sDEjw9?F0tqj6=Hy+ThrBv4bpMZ>sFh@m+0jxXRM!#ojY>t%Z)&Y&#v$ z7Il!js8A{0ZIjouPh0id#cEq`3!E0M{qw1nl|}c<1sCyx2^S|CRes(mURcw6K1(rH zes9R-=#mR8o^S6o+J~#$Uz^~(Ea7^}|D&ZhGj)5v-8#DI?4sKRmrKj;{JWU@J-Yb* z-iz0hUcKEOS@~c0$AcE}ydMucULXA)ndSba^f9j@_qE5R>ay3`8P(VQd^YEQ`MaOb z7Z|@u2(>j#jhou6>ssaWVyRu|+Qs&vzk(ND&-?v$hp?U5SzBKp!}rPmT{a#u=j6A3 z?I`;H@ylcTGj|2?of4^jdHi=?NXUiV^L~Hhe!K4Pt3A=Ie?uR~yG{*tTWV)m@o@b= zn_v67-#`5R(%s(b)2HI~|Ns5@{{H`e2A%~B>>dZ0X0;W?9hy_1knZ5Zx~_3s(}QPn z9FA;W0&XHX3t06l7V=#3&G~;Ql!f)!!6TI$8l-g+YfmgWq_?#oT&Ly)C+Cbq;*V6@ zR6A#$al2uAbmp11Ud^D`k{L69&-9PqIN5hU!!n0xU4f2*gNaE-PfX;PR!R%$8~wbKB+mOh(h<+oH2R-E$3w1B*xjYp zP`Pvshu~%pr%9d1bYrv@a~!_rystp8sd$ZtLcH*?y)UzZO%IDJ)k}zJN`2^OpSk3w zR^`#z9{K%kJSSKDOV?`dc^*F9P(ngie7T2Vf5{G?I7Q#irP2TTv_h5U3t4aSI@|b3 zYS9z!Ek}%WqNcG;lp&>V5XN!wO<|^N={NMedszZGc(PNZKrHU>x7A%IVvYA zzMV?B#TrvyD5*Mk<%X(To9F%dHO1~U`yzAIjoKHsh}SL<@!Z_to!l^SdHjjYxeaoc zOit=(I33t2-MX!9VbvC87nxTUe!q^+mH5CUE8+n>)NkICwLxjn_O%rxJEfs zJF4|r*p4?-*N18|#ISqcIK(wAD^v7N%*!mh*O9_2(!SnKV*YXUL|fV>hBa$aPo_qm z%_}pW@%GN6ppzEcD#TW$d|Z=dfBM$7=ZkW;O!l7bvv$VR<&F}NHce7W1VluUT@-1WMlhyK{|9RedrRQO6a<;c+#qNujqpt6|^Y&e7 zQ;F>-9<4pcKfNnw48Hg3?D>-Wk5hl%(ViNA%CGunZvOjwr_cZWWUTdNZfxyG?SwDu zz9+JPC4 zc7>mLB)0ppXJ?TD=rEdQ?wy-x- zxfLfro4lU9kY}3O|L^&yLcVoP{n`Fhr#SWW@7J5AZ)HmR+gW)g=u?c;Maz_1i+*le z6l**w|MnI0>C4V2EM7Lxy2jUfGu!#w)|=;>eo}G}FTc?JaY>AI_lrF#mz6A(HZD>3 zed!hb>(Y#KTb3EWz34XI_2NFo)DG*nnQI%Y+86buUAoeKMA$y^0=r%5l=7Vd`F^33 zbB~Bl6ZSl0xm$AU(zuQ_J7>L`tkSK#&n-PU@$Mma|BW~9OnlZacRM*lxbjA=W=44D z=PYUO=M$NQUN4&a^V01;ovF`y=Im^bbWqWJdG|wIdDanL!AjXL_kP@)&^bZ;jO_R5 zgjAo!O-4Vr{Y{*0{Y7s1*6f!v^4iad-%RzgP^P;U`c4jf_ zJ06!`{oFp|&unv7??~PyrO!{yJzKVSt4rGdIkSY9%&wVU^X{tBxyj%6EtV@Z-ISd5 zCEob9Ue*57dyOLZPkUDX^QZRu^<7MTi#|WuwVgFxY}J=3e|G8E&)X1n`gN}5kHgph z|B3Ictu1=k_-%LU%!`j|%MI(-F04P`Xy9{P@P}E*jE&U|jty%P8myh4``n5`NO`G_tn%)>uf7Nu; z4sDK>76W&|YEzjV5dzzPbaPMa=@9N&V$^f6y<{3k)RKtaYZ8&y+j~VAd$(@xz4N2| zxB7BKg{cp>m=h4~eevbQrN-e;KSPHX*qLj3Cw$A}XZZ@%?sJnS!@ z-p>*_fz31Jaj}v#5xVZj|xA|##@3Xh)$;wMh?M#*?uU~9++HI=#jVUo|W@0<1-g4D=b7E>r zCt1zy5R8B zqVO4$SXT8eDqmouBGUL_fq>LPA*+QVQ47VY7D~)oD79;$%&moTzZNP;EmE>tq!P7A zt!k0rt0`d>Eq`Y$n6i9PuWK%^X1`vS;O`Tb_bMlt@3OSanqa-k(l%;>{VWSduL;gG zyDVI1^}APDcv|&)XIc2(>hq7X2<++$US(~{r5QABseIwm=HR7IUMy{5UiMI9S)6I^ z)ol|3jxY68jjH`zbm;i9+^)rcO?$t4EW4AjOd)-_vFG9sFAYw_L zFSYWn{hzG2GHd?oTfNJ*q;e|VtRtd6om{E%u`T=6a=ovsUP-P#_k4BS=B!^Wnme z>66%3TY7DmsCcw~&c%*<$JQ5obQhAA+0K>B|5`%&_-b`eL4_~brOW+9q_f4m#V7wL z`(Rae&UNnN@U?C?y_t_?rM53vvOLL1Txw2*fbG@R+{!f!#!lP1V$Cb+XOypHEKzw? z-u3lcjYG7@6Zfd#?k1-^?+PR7$+;Id7%pGIv3=8;tcs+{N;{?aA4$<$Z&uoTtMptM zbTVrCugRO%UEDnB%BF|u>tC{472TF9@fO_ws6OVjiP!55ao+L?+=92<1thyA)xFJG zxE0!Om;8IaxlFoIn%lfTT7F`5cC>`{vt6bCr{6Y}tyZi(?K_uy#jmJ5)!n<8JJ+Us z&aFPZeYUjM^6bS^y|>PEFF5{nn_i^LyIJd#W@mglCh#$APkYdg_|t-&-C6Ui4eC0! zZf0G_xH5~2dwI(%4{L9S&DsK|Z;RSK-NI)v{z%hUGFuHNMbLPL&L2{sEV>L1JA^K06cq?oD4 zvg%WgiaSm}{`B>UpcDrYtC%Eb9N!yne*KzD*`nxu8Dr7?H*@w z-OiTRAEE%Wf%$>6@SJ-q0P=qwnn6z3B91R*wIeW(Z;^$vAV!rhfwZ|Jg_NfM*K6=oIFILQr zr}Y(&MN`chE|#esXQs%`+&fDa*V4vFP`Bow&*2s75Rl`G9Sq-o9-nb@R zag~40)!vKEF}c^v_g-2exPQ)^qMEhG7hK$VEQ{mDWJjH?9O?h|?6Oo!OWP|hs~-3w zN9u#pjlGPU%rjKwif+ukbA8>LR_2K}mwdc&L{Y!hG$Ju*YnRTIZ>uGi)*2|WUYjl0 zs{iOQ0U#9Z+J&DcvppESdwi^mG5cq zDHmR>zF_m>`03*pI5*#%zxWQX__-ge_7`2;IdR4{q1w9(lJ8aQzN=GJa?@5Yx})vg z-nI{G?LVDecV+j2ueRqhFE;O{!sJFcKXy%SHt9)ZVZR$C*VuRM#5T>~g3)k*pX}%@= zPC!&HdC%ExMt!Hu_dVRU?2$$51OCLj6}+kc_e!Ys3EXbFwM|y&iENJVKMDSOetUAd zWG_BmTK2Rv@lnveM;>+px^@}IXY5K5zmr(HBmG~J!MmQs*;8kSJuj*g10?!8)YB5Z|Rc&uR;^TRNgVsp1?@1#uSHt0qP zu3Xo%M?;`!p2VCw!K3Reck)#;{aZIt_sxV^Z+7i_bKv&ssa;16Zrx?R_2w$y+w9GU zI*z?vANuy5&x=QPf)6IdnccI?cOV@%|0uQpqs;w} za{oUn?9b%B|C*t5^?|#))cQY734OJB?I*UkpX4Jy3EF=)iT`X?|Jh>x=Qy=V8j=%a zX4W^$TsbxEq_poB=L_|YHu2Ht@1FGR-?09(&&_+$pXZ$PeV?Lu_p>4YB$>6(BI3VV z2=9q13|D>f^+wTGzx7``e80Kvm=rDlHPQa9=#>X*Y198W9WdDWMOkuYNxVzde)r=m zKR3w#XtMv&691#E{zu3BA6@c|oa;Y#drsZ_b3(YL;gZTZ6XNIA&HUMYzu;nK;+4xk z&qi)mHJi)hHhtm#@3ZAY?JB1@{QP<9X-)AAJotAZFDG0I{tET{sFVud5w!QCvH2>=G&`lW^{7Wl)cCD{_S;s<))drL1SAJ zZ@`>~G3RDVzIyiTw%y@_XL&yupJ%5zvE_LG9{C{}9|1cxN7B8{6;f|gc%ID}>ZWimE&c{AU_Cl6hK;G0%e0INmHzi+aZ%MP; zuI{q;qU2_Yx6|Hh|M>9w@ZUvNmv8-&x%YCT-rV!fJ5K+4BW2`d?7n-&)U1;dWo(7P zT_?Y-xmclk@q}IKE*q_heb-&itLb()o{M?1fUR-b`Oq~kCmT6mzTl5qDRYJI#>CD! zxhKm-6IW<(JS=yRbax0isyUD4`-1hsXD%+hnZr5P(BNIi$3Sj(&YDktho|e`jacr) zHc`%3x5)MBwx~v9*1ot#&-Am)Za4}p6#KczJ-sDKCDvt=-W4`ZZj&o)dCpHCN^Lv# z+9iGR*1W?NY-e=K{#>c>Elo5&HP>GC>(3OEuD#O~WBVrmVlkZDlfblnVsn+C%;a5h zN32y>Y>CxVs)$KUY4*)L`dMh=)FjVvo>Z2Z?3>SQn;dsEYP!COOW|7In7d`4*7Q|u z{BkMM{nj$W$mJf+0ds$AIM1%T&368;!_#LiZ&sFENZx1jJM@YB(<=w}IaXbBi2B}V z{HCMr)B*lGE25p&Us$8|`vFUD^CzVf#ZUOYoyoZ=7q7f5Dp2!6WT}^1e*c7@F#%hR zp0j^54d7jC^)-ZliBVW{rlWD^YNuTS=luezC6~&S)@fAVPK)*1djI`Bdy^SIX3pz4 zc3AAY(QO4OwO-VwFIEwGx@PX?6&>$e&TuCm75r@6tNHm#<4uLf zkrKhyi}@5MigW(?^zY;I{3#4Ealclmu335FpSMwHtFz+m6IZ|Kui}t?7rLve^F*71 z{Myq7Io~h;`uOqRzxqc@r-YupHT7aJf8XhiFU}crT>jAdFI?gBZpVdh*Z;c^B>m7z z)-hhm=Cg2vj?3>m(qEQZ_dlBH^MvV_|9Wkuueya_w!Db=vQ;Gdi*RDmZDXl-!SO4$ zz0rB}Y^qi7nh@blN{fxHs}Bff1qLTP*!wq*>6hKDAnxDXcj}e*&F$7-U?J|myX7hO zsoK7~BF+qf3)>88PJOYB3@c7iyfb0x+v%~zrB~CJ8;IHU+B}b+X%iRkZ?`d$^ zUzay@tYwOm5$;!ylDqYAVU5Znm6uJ?Q)iy8dae57x9*)F!}OI5pKPD0cs3L+=(bp* zVk{uJR5HWj)|wT8`ac%Bi#I5J=m}ZSHH9nR%USDPLYvZ_7krPV9M@62dw1^Lx#cBd ztSM~r=g#TfJ^69|@pwCV|8sY{PriTt{D)Zl#SW7_Q}0ZaU&h#YSTniP;zOj#;&3Aq z<=;=6bPQyaPv~#47j)eJereOm1h2@6+Z8gxRbq!~$HR-;%e}sdZ zqbptFhRLU;Tlf^>6caA`Gl>ZqbBWIJm|U`BqJDAQ$$!;f+15*+a_w@vYak`@QTONK zw>;I&QLB7vT3;nz5V0$87nNRcKjrKsQ330M`GMOl7S3psx$Nvyqc7N=SAC^RHl2ZA zl~a{_D~nb0wA*dj5>AsvGEQ%Qo2~3S|HadWvW07(u;t7+Dd9MCv)H1LRp}evOZn*( zD<1N{sJP?CnP)TZHTJi*yM-U)-*ewwu25@%fru-I(8EMs?cWyu=<>AZz%#jQ!H z_e@l{l$(1cxx;hLC5uig|1sm7k^aL}n-;$p&Uao}&h_|fJkjRUx!{={*0dLfW1JfE;+AehZdAH7^#xLcm!|YEx9;zD3olkYzD|u*n_eY6u z-xBKWn;r^O^|`JHQFfbge^T!nf&T&P-RGAYr*?&9PT}8najxP8i+#MaqJC}(E{Z&u zv-n!ac~+f?6E$KTio88+F1qgsSATKfnbOTlgn?j}bN%5h&&U9mCuNIlS5&!3rU;z)*LYUx>BP`L(_<5^Nrp_Ey-|MGV%t6Q zD>F6JZW_;YIh}HVeP`44S9b62_!tTpuUZyu>8Lg{vSYjD!Gn@31?0*OnC#5a&w6C? zNo0A}9hDa+ZiarWF17Xes_qcL+BqwM`(l%1;UWY6^hYf0sZ&Cwvct|wPCHR2dh^o# z@2q|*+vl{$9w=U&q&}aAiz#$>Vg8ICI-#oJyp_w8#V&L_|GoIcESG{6yo$XqO1);y z%-I>CSs(VtjY*HGqU+4j3en|32D0C*%r5;X;LLv7CHuIf_^zY%$9nFM*XP>4E7|f> z!FK~!QEyu9ghz~8WnIOgS3c&=(LA!dlKtNP>v5|BKOVlMD67J`*3Eo{c{=~`tV6bQ zwztoYR{Oq9On(2REPU zD~?xPH@oG7t8U|0#hkur(c)`+nSvk2$Zgr=YpCc{w)DrwSkHHYzklB>oL=6VRAZ1_ zYoj09B~`yJH$CII=tN!f-LtHAT|ImEkZbPA8wW0h73JDm~vN&aHemP5DBgf0xd8u@y?Uy!M)_xjc%^(nonE3bGzdDri?cVE!A&F?~Lv!X(u zR&LFI_?6*jQNqT@1{2p_TJX&K&Z{SHJkyLVlP0~l>ttoo)VG`cU@q(2@@*GN>sGF0 z{vW^pMHYkp{*4SWPg6OW+?Fidv8SM@Sy(BL{p6j;JGQ4pH~*SurFtnZTYu)VMFPvs zM6|qCd#_t~|GKJEdKA-M-*0_)_NeE}x=otbYItJr(`y%BfALv*df%=Pv5pvzoy(@D zZw&ps;9tyASE+^eUdu9Lte+Oz{*DXD_AXvsIj{0>rQ2(^^SPE`)A#>cD<^vWcji>V z=rv}u=lnm}eKbsNgUkMBd4V&nXU9IYTdqCp@xGbIj;ng6w%smK2y(ua{ldo5_x9J>A0i+a;=zh0-3oLuFlPfmS3+C=l|tn@$TZOOQUyQ4!Q01@$TK9 z?1&orPm;IB*Q0ZPd$2Pwl!`Ji2s1D+q$L)Y#205I7Nw?uy95~p1#2Us^Od)Y*6~mH zU$BSq&P4r9bC)0awCYB8G)u>I?)5?n9^8#mg(}yKRlJLIv}eD~fA3zD=5kkN_t_r@ zjh|SyKmRnByR^)0%HG!(t(Q)BJM*mXU)~R%`A?fCsDGIj?sKVn+k$Lxhpy0p8}dQDmYUrmoE$PdopLnwKriTx046E00e{ET(>%)Y+xL zD8|KpHv8cXmnnyIS2nPyO<$6|cjUmJ&a+YvWw!xi2HEjpt?e#^!LI z{QkzRZszo_Q!Zb1(R_WbNR`|0b#ncTys$k%X_h@UlS1!gvGJ=W?f>^`^ZjPSovXB1 zG7sr|XFK?9K~?0cIhKm)>B0McF_iX3NK}Y8t}YfAKh~&pLd9n5mqdQ+FP8u8l}^gv zZSZ1MEOLlv`&Z%rM)`4;?y?4#m0}0q?s;_Sp@YZI@Z7oI-`hU7V!OwF{rHS$b9{F$ zbegh9_-Uzmz>GD|RocG>&ik39;^rhb{{Uvc$ zdG6zi6_WewzdrddvnH60x76;2)q0Un_pBFWHBUT0bAt4lj`(XoBoj&;MP%Lg`n^ng zV9y`dzL!x}{`H>idI#*S>}9KVl%A2^rSiK&+2pZ?v%x)fcCSyOU#DNq?wK$x!Ai%A z!=vTcf+>Mno9aYPTz(vVVapxOl3BLvkNVgYNHSh&Sl0baDo1XL1LITG@|rcN*Iw=5 zw-Y&(zT<;skJIyGmVYWl&D$j<*k|kbE9n)c1m^u(+{}>E^YR_T5ut|NMc!v?BNtuV zu+nmMlKb>b-%hg^RY6^Uj58Bx)awl2guWzW)B(?qiZpO&~`| zGn-@X4B@o_yK+}OQ=A!>a!ShAH{QN#=JDh1krxEHH*ME4|L?h^b#v?2wQAlTK_9(} z56>}LUoL;w^5}Fyneq#BrZ3WXGj|?agmQUMvphQ|U$kj0bN;-kMV%IZCDvB?h?}3u zEf*?u{QO|vaG@%HW8{)<1h-~M>^>)G3{cYl2G>)GS}e7EcKHI_Xx`&2Kv&C9;Ab9H=M zb>c^z{=H8MUN4(IeNCB`t)*?6w!c7sm+s=S+kvJH%-sb!n^y+$XEc9M{+@c)YUzBB zHPcuA7ui=XxmnzK3%A?<=~neGZWy#C=AC|iihonE@T&hQo||X2-kkpX-4`xlb$zbB zh1qB0*PDIXeDYj(?;D>eNiFrZz2~!y8>XjMG+yvnaiOP@(>tf3#AV&3^UaKbD?}3G zPZn{e771&a+3lU_b8bSu*2bg$GwQ6;b7yDIYp{`-!}juY_mz4vwY7^@J_`HybY+$Q z?~fmOpK%15Sa7bDEa!aZ#Qf=R`r0FGQ!l6n7A)FxaMkMvc_DKa>2}TJ`L}7!1I_pM zgzm8Zd@A_Qxay&sxleM3)KY2TY|FP3dS19E-(V^H5W4Wu9n;-qQyEsSSa*C`_r|;H z!kBED%wiknz3)A{Q+L5~%lFwBHk_$Tx7ElbZ8$k^hyS*F9D8NT&(vT4 zv-0vSs~xl2oV;$aUXHvZ?RI$C=knZboxApbTUfweRnocbzq0zI(wpnbnomjc z8w}AY=h-aTN*UkZvP(5T(^%$czv$eetG~P(<)d!ROnrai(&Bm-{y+bI8>`Lvc>i79 zj(;Ea$(EQ@iC@`qN286Q;LKvjAM#Ric|YPzGF5lo=@ysZnyPf^=S7}t?>(-HpGjEj z+TO0eJtKU7{+>Oh<&tk+G2VT`?Xowc?%si1iHHXt%m!wCM%kY$jdtXpd+YCW|99K_ zUe8IhPKjUnAa3<)U(?I#cjf9=_Wl<+rlRlT(~uR00}=I~wAff6GB&ukuHEw~&?BIFBx|J-Te77yn)tOP9AR*Ir1{|E6_% z-PYX!fk*1!_gp_B;WcSq7T=A}_iFaeyle69`y+`5n^&5Ji7jn^J$v?S#Xa)<$3GnH zI&_1#DNDChp)QC^uH(f6M~lSkO7eo2-hZvmUvln>mbk$~K1F-2eE#0-iIvILYN~VJ zOYAt*b7}hNzN}@+R7_E)$ye_=Fmd(c-zs zTk;S72#Qc)J1w^6gZ64oE*~a~L*GTprYzZ1baw9z^(nW64c~q*d%17w)XBRT&Q3oR zY9riWx_tSyUHgxvc`K-nd$t(tgqhJE zh3to;BxY`IlkLrzptBZao}k5?vZYZUxFJ8S0y;k<57;YZWlo)*41WM?RL z%xN#P(B0#j|9l_F{a?3E;a2gXp616ZqIL@Lvn|V9WTabnQM2RL7GL+~)+60|S0)^2 zJ+)GIS&!bLWdRl9Uiq@@Zna|U`v2jMs~&9q zwKX$K_56!3uR0u;KC4<3+}mc4NUfk|qT;pX1#ejx80LyV26A#T^Rf{w#HZojlW$oF z?DN0+r+uDJC{s)0O_{_8lMcsyKQLEl8;@7cN$ryY)4b|_Z&R^Xxm}?!-FA)MwkOxF zuU#Mispj7ggZa!$dg_;dG`n6@cA|Lmvup10$3KKVNk93Gowt6H@?#7Cz?$_BPQQNr zn&;mlqhv3`gO1!C0To=Wi-J$MoDrI%F>9Ga#T$X-Wm{5qI|W~0U*^#1GQVR+U(`plv;uW$!?MX+%+rl&}Siug>H^`2?x+$7L4Ur|3rPh_s; zFFE;nk%y9J9oUvwo_(|SSm?3L@6ET5F5c3ix#w+5K$RTlybXH`Pv814p((3;Mru#v zv&XNJ7T&NgSzVhs>0RrQ#VN1lUJ7f57EcPCD!e2j)#X*Lp2V-i2DOzn2V`d{1+v(F zUv}Qo^wNe%>8uIIo@scqw|zQ0eXZ33`z5iZ5tSRgBe!U%7FJA~{o|(Fq6bwbZs&`Z z8VW73c(`WLz7T!4-l-q19AH`GtE5=2w4N9JvoS~KP@&a^DTh|H zRY&cdAyaL%Pt(G#ep|-rf~^~u*HlMt=lw02F)c)Vl5@w?&V+&`0R`X69dE0AEets% zId?-*`wM4VF0p3Lj=%%Y-35L%oc}nX>jL912dO&V&GNb}^$FE2RT7i8`EUv+Y`hsD zo0q|T@u1k|51YQ3RYgZO)$vSaiEAlmTgL75=7UH8qmQE4G7Z@cGHvg+oto$L`b0FScuf*wDKjGyyX$el7yff_^>m;V=7kZ-VeCwpIe476M z!IaW)smR*k`@U~AKBe$}xKe&|N3)H<&kxnls#8U5!nb&5z1^{psfzWA`F3`D?GH*# zzN^-AvnkrD+&J>>{L<|EWku14+g)#-&CmVHb|$9BOk%ys;j|s5+Vi$cy_uMvxAJY4 zany`|0`uM9{XVnDT=n0h=dV{Rxy3o_qy-Om{I;0#zo*yq{Qmp?C(HY36-mpQn{#;1 z?|3Py8$V^*vmbRUW#o@6ZU1)K`6aJRwC>+)b|vU#bNbYv^4L}pZaeGUE7{id3m0e&$Xyt zx-N+C9vk<%-z6($GkYtVJH^xNz8v#@#`$gEwf!+2n{(C}?_2+E?;7j>4PWhE+}ytW z+47At@85ANt^fIc=e5kLJHP*ZSf}Ck-eiT(>H7>{cIB|f+^RI6wODWZn~vDJht+vO zt@T@{c({GMb@%7;a;w?d&2#x;WgaQrmaJO4K>5o*X{Wo1+FLg4XJXOaCO6$GY*wwF z$EwQ5U$_pGPiI}BPztW~=sn-g zdu$<8%Rixh#TkaZWyf}YNs!-G{Be=>+?(%?K506#`2YjA#1>b}J06SLro5>z-g|%F zau2U*IZrRyE>@3?Sl)HCxXV>mMxge>EwPmMEfX(Bq(0tb@VmUyuRO@*QotG^&n@3) zy?&5Ton8H!VaDFgc5`3WWL|l*Zb7|-<>6$baLG=cMf^shlC>h-nJ?e&F0a4+`{RcX z1@qS}^_;rZD?KD*)}fjQ7rnIEr@ZnwdYUnErV5{G&^CjtAhAhZ)~P37?TAPaYWY1= zFj7(ZRPVgi9OgEMntfkyFp6EVQf1=vAPH|7nFSwXJ$L&rE92a=qNAxh+36`K|EUSzi=sYQ?KJ3#2=SX>{@!ZprVS=j zmkFH6R!dFkw~@N2cQIG%kd~6NR`-;Ni~@qo9yu;e^)l+a8lt#Kb$u_>9u1QilL9?c zo29pOVh;pAG*I)_*}ld}>cPS-=lZuURgqO@)tY^ zRnpo!A{Fl#`EN~Hc|@r2m+WmBRc(E4{WUIJ2GRxmzj z=kVg0FXl|Vxtb$0+N1FN!g)NmlU5nmD?dMF`LE?jQ~STSxAzN8@_v7>@#TlBA-v11 z+x;wlIIP-kf34X*eN}+cO1FUZfttVHe5w{zerQ;`W7jU(-hBJL`z`-l{Hw9tCwI5U zJ~lp?VPDf8fBpoXb7EO1JLCCV#8yk{9}}43;ic zC7)cugO4Xjg*zOWzF2wnKkehLmk*uZntEZAKC=AKtW5FKvmZOo z%&~GcdLzSMx;0&KP3w)eIkL~zpFO%o=v?yFOWKe8TWa6--Kbo<%`;p}R;G+KI@EXB zo{9UXYIL1(f6bi#GVjUiFMFr#l#b8MU2*@$@+&bPmaQn{j(R+G#)4Pxi+7gHUK(-x zo#v%WR!iBpPc2i-5D-c|JauOon*wKt_QjajInw;|qdsiu$d4F*(3<5!;5@v7$3CbDj|WXu|)S*VgQhlcTwjU9xp%UqIJR0i~naoAZxJ znfw$s(vxQqpUt>OG-heVs&oE|ALS(NG^c5(#q0}@JD|9K%G;FOd|S4klf*NweCFD_ zM=E|!e2v9^$^LWt>+0+5t@gjYynp-l8JqV1|M%#@M}PDA=k@LHecS6A=O<)()b00P zpBtL{Z})tgu6RxOcb3cRg-X)Lb9%TWt6yI|b1nSQ4E8I0l{wX?_S(s=z5Rvn_m>~3 z)vr%~T(+u0^ejY+;lWX%`r1~?%RFvU1j7zG)$6~ zf4wSouR`+OpAYhNFJ`I5drUKT>*lBw9QD>Hd!-MIa_?J=+5-?FCL9{ZT`E@U*A ztxqy7SMI))GB-eR$?|8{IbNntNM}l%R`#;i&E%{m6y{?9} z(I9B;)W!EQrWaY+ru=-uzgMP9aY}F8zYFiq1Va-{gMvz5j&&-Jfu-_ITZ|6pj9U1uWk3R|>zLTQBqW)5Wv<*ZfIH_sc4=dKt)W zx0jPQ)4ry54Pzj;U&i&?*24mJ)1S>cdryqOpZ#h0VKOd~|i@~iCCirw=N@}^HD)!3@>-pksSlI_k00L`W3XI9{%=FLa&FtZN9X!yKlA^5{&fHB zjOVs3#!;#H+rwX;$t|zQ;yfofL$@rud+)S<`nNnOQM$V&J#B%7{z-0>Ha6V&PF?KQo~;iT-roBA%5DMHV|p*rC!Q^cJOAtc zg~|K(c!$JR-q1PJ_$I^m%mTA`AKp((*3{X$Ud?Y?e{04nfsKdaWs}19*4$N0JUV^X zkt@3;+b`WUZOUt3*U6x|!NE^1`%Q7EyrofIea>{vTb8la{^!HeAC!kYP4|)w6qvTU zGLK_^)QY-QMju`3EfyTh>~0L1R#2N+s<-@Zv_iKJ&#tOjljA>R3Ymm=N4@!-)HcWO zPj0~7?Z>u$etvB0W;t=Ala(>QFF)Gx&g1E(KTr7A{70Hg?+x8`j~Kj-iuS+lAyVi5$X;gYs%xD0STZz46>S7AhHj0`4PCWw!-=9d zoRY6*+Xx4VJ>CC)=4@NPIRYy(cCVGy?0Y`P^8U{AHwxEp-+T2nWB1=V#fK`)PZ$|0 zxgV6=mN+AAyXD?l1wRh&U&tBfF6g^X;?4Va@5&z9o=iR^;Vb+=ljX#lLsJCBADJvk z-jkrxb->?A)o@AA^AeM%EI(R|5?;0vCxM>2%@^ zktv;ar-R$^$z_QEmRlZ{PClC7-Axw#5j&=F$UjeU_Or-S9^pIlt6xjXwx{sii+}F? z{_@TCx4H}!)1LkdeZxJ4W$p`(`X7rsWDcG_e0}|bUY&-h4>hw`?8N{;?*oJFGz3#l&FAG+(LTJ=Hl)jojHUXOzwlpYTOz zR>T$26^&}E_-`5TTFf~l=yA5c&nr-QzTiVXnZ^Hw`sW|GyC>dn>dQ}osV_{p6xAi< zC(fJECt+fDkmq>Qr+p6|rfMF&axSr_P&6^sKq=5_ve5>K2bTp7P1*3ooKNs?&&<=i znHF;VGTeW*qr+wa@4Our2RVb!$gnPwT^As;VM|+zRQ1ani|?$JPHWkm$`sYll98W( z_vDtXFP#KRAMVoEbezIAzfeR)T#VS^7=kmFHGnBul#~DWY+Psa4_!j$(cb-NlyY2+5j?aZJ=h?k^6Od_aq_z39 zWR=rN{U@g+tD0=n9hY-gWnOtDJ#A+g$Cm389Cw|{{O)~9d1LQ&hTn0A=Bmc#bTB=Q zS{Rcp@-&CBD7H!GfrI4c?(D=xjAbI5ShOOZn=Z@ei`}@MhBQu`yvWH{usWKAtp5*zT-wK}e+)YlL)F!m+mZ|K$EvzT0d6 z`@!7#ybE=w%)Y%gwfgkByvzIMt=i*y;YiTZ=!BcP{r>)4E2MtUio5WoNmb^@$Et(p zFLJ#x3%IFZTdKd|K$maeWx-i}7vAvg%lFQ!98&fN*_?oa1NT;^Ml$?j|2 zAiqeqX7yUfub!TlS!d~8C~1^m$K8>>@cuTz70cKA>NhMCH`&Xu@AYHn-SRD$E55wV z7Zl05%r~p-L&)0$yC(5OoDuve`SaxIn@s=z|2e;$Yt1sX(#)$NkJ(CB>|7}FwsSgb z-O5icpF=Bo#I9D%+9lGO`BO??_0OwYSC$4o{k6;WPrAnIxc6#H7v9^Le9$u2ux$A~ z$D2R=Ztq#nJnwwc4rkeiNB68h?zfOxSzGeDk@OSMlnr7{CXSEYHp$;NJ}R_p)=9Cm z=_{3=gtz2dlui=f^itdc|H};8VfI4m8GGZp z`X#+P%wE`@;V;eq`u}TnQdFv5pX!B0n>)UA*Up;4DYk_3@v~CJJv$ULc>VXf=&Y&U z{p^L<>92>(5?jv3t(&DX{r!@S+#8SGeYrC4Z{^XK4t4LvoekcvZxrd4Z(8Z>@Mxp@ zvaZJt^S|>SseFHRq0LL}vrE{XZkM_h&Asy4T&9Z-k4#uufB*UuG&g?b`UVGia+HaSEQU74rV_v}Ij4R((7bBKc|RQc(fXX*VNm6_4&CN0hLY=xl8lX9&-6VKN6mqx3yJHLDP&Y5LC zQ|0K&j-st?d6I8F)%kI6zu!E8quKPmyG_WBcW=FCh5yg4UGi+(rEMQpU5ZziIT=+K zTJh7N!ucWhqo=}igFZXeeEoUJd8*j#yyz7ZvvQBgKkO2jzJv3lw?9AEf_*E@XMQtW zH*slb-b$`%PnR#OD3)zQz{B2g$^y{rZ97``RRE^p~<~a)<82X-|yKn@`9|xz5Ia`{sgO`dTF`c~46Hi*jH8aDD0h zzkfoPU-=|1mSPzu_)exEy`j3{dHX`{^YN?KD;KnFe>c1M``qex^Y)jfn(p{;aQ@bb zU;b?Po%CkiFSg$-Z|f(8MNW7$J+AbwmrBfTk2_2El)bGfS?ILV?QU$~j$>J=CTiU_ zb)2iuGWQk=EbTc_F+DfNe!YP8pGR&F?E}0SnT)t`ubpLJU|?WmU|`tR2x6hGq(#C+(WWAu_SM*tWgkC-#taJ9r24I_QKp4<2%)pR_H1~k46J#~| z$S*>tsTczT>Nqg6UTlLS2)%yNScXcFwPS1XAhhpLW?(2rZvO;$v$BDt*%{awRx&a$ ISZRZJ0Kbrpg8%>k literal 0 HcmV?d00001 From d3347b6d0832eec766fb70731e9aeb07f31450b0 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 27 Jul 2000 14:27:00 +0000 Subject: [PATCH 004/513] Initial HTML commit [SVN r7640] --- index.htm | 37 ++++ scoped_array.htm | 90 ++++++++ scoped_ptr.htm | 128 +++++++++++ shared_array.htm | 180 ++++++++++++++++ shared_ptr.htm | 206 ++++++++++++++++++ smart_ptr.htm | 138 ++++++++++++ smarttests.htm | 540 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1319 insertions(+) create mode 100644 index.htm create mode 100644 scoped_array.htm create mode 100644 scoped_ptr.htm create mode 100644 shared_array.htm create mode 100644 shared_ptr.htm create mode 100644 smart_ptr.htm create mode 100644 smarttests.htm diff --git a/index.htm b/index.htm new file mode 100644 index 0000000..04643fa --- /dev/null +++ b/index.htm @@ -0,0 +1,37 @@ + + + + +Boost Smart Pointer Library + + + + + + + + + + + + + + +
c++boost.gif (8819 bytes)Home Libraries People FAQ More
+ +

Smart pointer library

+ +

The header smart_ptr.h provides four smart pointer classes.  Smart pointers ease +the management of memory dynamically allocated with C++ new expressions. + +

+ +

Revised July 23, 1999

+ + diff --git a/scoped_array.htm b/scoped_array.htm new file mode 100644 index 0000000..3bf65cd --- /dev/null +++ b/scoped_array.htm @@ -0,0 +1,90 @@ + + + +scoped_array + + + + + + +

c++boost.gif (8819 bytes)Class +scoped_array

+

Class scoped_array stores a pointer to a dynamically +allocated array. (Dynamically allocated arrays are allocated with the C++ new[] +expression.)   The array pointed to is guaranteed to be deleted, +either on destruction of the scoped_array, or via an explicit scoped_array::reset().

+

Class scoped_array is a simple solution for simple +needs.  It cannot be used in C++ Standard Library containers.  See shared_array +if scoped_array does not meet your needs.

+

Class scoped_array cannot correctly hold a pointer to a +single object.  See scoped_ptr +for that usage.

+

Because scoped_array is so simple, in its usual +implementation every operation is as fast as a built-in array pointer and has no +more space overhead that a built-in array pointer.

+

A heavier duty alternative to a scoped_array is a scoped_ptr +to a C++ Standard Library vector.

+

The class is a template parameterized on T, the type of the object +pointed to.   T must meet the smart pointer common +requirements.

+

Class scoped_array Synopsis

+
#include <boost/smart_ptr.hpp>
+namespace boost {
+
+template<typename T> class scoped_array : noncopyable {
+
+ public:
+   typedef T element_type;
+
+   explicit scoped_array( T* p=0 );  // never throws
+   ~scoped_array();
+
+   void reset( T* p=0 );
+
+   T& operator[](std::size_t i) const;  // never throws
+   T* get() const;  // never throws
+   };
+}
+

Class scoped_array Members

+

scoped_array element_type

+
typedef T element_type;
+

Provides the type of the stored pointer.

+

scoped_array constructors

+
explicit scoped_array( T* p=0 );  // never throws
+

Constructs a scoped_array, storing a copy of p, which must +have been allocated via a C++ new[] expression or be 0.

+

scoped_array destructor

+
~scoped_array();
+

Deletes the array pointed to by the stored pointer.  Note that in C++ delete[] +on a pointer with a value of 0 is harmless.

+

Does not throw exceptions.

+

scoped_array reset

+
void reset( T* p=0 )();
+

If p is not equal to the stored pointer, deletes the array pointed to by the +stored pointer and then stores a copy of p, which must have been allocated via a +C++ new[] expression or be 0.

+

Does not throw exceptions.

+

scoped_array operator[]

+

T& operator[](std::size_t i) const; // never throws

+

Returns a reference to element i of the array pointed to by the +stored pointer.

+

Behavior is undefined (and almost certainly undesirable) if get()==0, +or if i is less than 0 or is greater or equal to the number of elements +in the array.

+

scoped_array get

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

Returns the stored pointer.

+

Class scoped_array example

+

[To be supplied. In the meantime, see smart_ptr_test.cpp.]

+
+

Revised  December 8, 1999

+

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

+ + + + diff --git a/scoped_ptr.htm b/scoped_ptr.htm new file mode 100644 index 0000000..3430481 --- /dev/null +++ b/scoped_ptr.htm @@ -0,0 +1,128 @@ + + + +scoped_ptr + + + + + + +

c++boost.gif (8819 bytes)Class +scoped_ptr

+

Class scoped_ptr stores a pointer to a dynamically allocated +object. (Dynamically allocated objects are allocated with the C++ new +expression.)   The object pointed to is guaranteed to be deleted, +either on destruction of the scoped_ptr, or via an explicit scoped_ptr::reset().  +See example.

+

Class scoped_ptr is a simple solution for simple +needs.  It cannot be used in C++ Standard Library containers.  See shared_ptr +or std::auto_ptr if scoped_ptr does not meet your needs.

+

Class scoped_ptr cannot correctly hold a pointer to a +dynamically allocated array.  See scoped_array +for that usage.

+

Because scoped_ptr is so simple, in its usual implementation +every operation is as fast as a built-in pointer and has no more space overhead +that a built-in pointer.

+

The class is a template parameterized on T, the type of the object +pointed to.   T must meet the smart pointer common +requirements.

+

Class scoped_ptr Synopsis

+
#include <boost/smart_ptr.hpp>
+namespace boost {
+
+template<typename T> class scoped_ptr : noncopyable {
+
+ public:
+   typedef T element_type;
+
+   explicit scoped_ptr( T* p=0 );  // never throws
+   ~scoped_ptr();
+
+   void reset( T* p=0 );
+
+   T& operator*() const;  // never throws
+   T* operator->() const;  // never throws
+   T* get() const;  // never throws
+   };
+}
+

Class scoped_ptr Members

+

scoped_ptr element_type

+
typedef T element_type;
+

Provides the type of the stored pointer.

+

scoped_ptr constructors

+
explicit scoped_ptr( T* p=0 );  // never throws
+

Constructs a scoped_ptr, storing a copy of p, which must +have been allocated via a C++ new expression or be 0..

+

scoped_ptr destructor

+
~scoped_ptr();
+

Deletes the object pointed to by the stored pointer.  Note that in C++, delete +on a pointer with a value of 0 is harmless.

+

Does not throw exceptions.

+

scoped_ptr reset

+
void reset( T* p=0 );
+

If p is not equal to the stored pointer, deletes the object pointed to by the +stored pointer and then stores a copy of p, which must have been allocated via a +C++ new expression or be 0.

+

Does not throw exceptions.

+

scoped_ptr operator*

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

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

+

scoped_ptr operator-> and get

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

Both return the stored pointer.

+

Class scoped_ptr examples

+
#include <iostream>
+#include <boost/smart_ptr.h>
+
+struct Shoe { ~Shoe(){ std::cout << "Buckle my shoe" << std::endl; } };
+
+class MyClass {
+    boost::scoped_ptr<int> ptr;
+  public:
+    MyClass() : ptr(new int) { *ptr = 0; }
+    int add_one() { return ++*ptr; }
+    };
+
+void main() {
+    boost::scoped_ptr<Shoe> x(new Shoe);
+    MyClass my_instance;
+    std::cout << my_instance.add_one() << std::endl;
+    std::cout << my_instance.add_one() << std::endl;
+    }
+

The example program produces the beginning of a child's nursery rhyme as +output:

+
+
1
+2
+Buckle my shoe
+
+

Handle/Body Idiom

+

One common usage of shared_pointer is to implement a handle/body +structure which avoids exposing the body (implementation) in the header file:

+
class handle
+{
+public:    // simple forwarding functions to the body class
+    void f();
+    void g(int);
+private:
+    friend class body;  //incomplete class hides implementation
+    boost::scoped_ptr<body> imp;
+};
+

This code requires that class body have a trivial destructor to +avoid undefined behavior.  This is because the definition of class +body is not visible at the time scoped_ptr<> deletes it. See ISO +5.3.5/5.  Note that some compilers will issue a warning even though the +above code is well defined.

+
+

Revised 24 July 2000

+

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

+ + + + diff --git a/shared_array.htm b/shared_array.htm new file mode 100644 index 0000000..eebafdc --- /dev/null +++ b/shared_array.htm @@ -0,0 +1,180 @@ + + + +shared_array + + + + + + +

c++boost.gif (8819 bytes)Class +shared_array

+

Class shared_array stores a pointer to a dynamically +allocated array. (Dynamically allocated arrays are allocated with the C++ new[] +expression.)   The array pointed to is guaranteed to be deleted, +either on destruction of the shared_array, on shared_array::operator=(), +or via an explicit shared_array::reset().  See example.

+

Class shared_array meets the CopyConstuctible +and Assignable requirements of the C++ Standard Library, and so +can be used in C++ Standard Library containers.  A specialization of std:: +less< > for  boost::shared_ptr<Y> is supplied so that  +shared_array works by default for Standard Library's Associative +Container Compare template parameter.  For compilers not supporting partial +specialization, the user must explicitly pass the less<> functor.

+

Class shared_array cannot correctly hold a pointer to a +single object.  See shared_array +for that usage.

+

Class shared_array will not work correctly with cyclic data +structures. For example, if main() holds a shared_array pointing to array A, +which directly or indirectly holds a shared_array pointing back to array A, then +array A's use_count() will be 2, and destruction of the main() shared_array will +leave array A dangling with a use_count() of 1.

+

A heavier duty alternative to a shared_array is a shared_ptr +to a C++ Standard Library vector.

+

The class is a template parameterized on T, the type of the object +pointed to.   T must meet the smart pointer Common +requirements.

+

Class shared_array Synopsis

+
#include <boost/smart_ptr.hpp>
+namespace boost {
+
+template<typename T> class shared_array {
+
+ public:
+   typedef T element_type;
+
+   explicit shared_array( T* p=0 );
+   shared_array( const shared_array& );  // never throws   
+   ~shared_array();
+
+   shared_array& operator=( const shared_array& );  // never throws  
+
+   void reset( T* p=0 );
+
+   T& operator[](std::size_t i) const;  // never throws
+   T* get() const;  // never throws
+
+   long use_count() const;  // never throws
+   bool unique() const;  // never throws
+
+   void swap( shared_array<T>& other ) throw()
+   };
+
+template<typename T>
+  inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
+    { return a.get() == b.get(); }
+
+template<typename T>
+  inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
+    { return a.get() != b.get(); }
+}
+
namespace std {
+
+template<typename T>
+  inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b)
+    { a.swap(b); }
+
+template<typename T>
+  struct less< boost::shared_array<T> >
+    : binary_function<boost::shared_array<T>, boost::shared_array<T>, bool>
+  {
+    bool operator()(const boost::shared_array<T>& a,
+        const boost::shared_array<T>& b) const
+      { return less<T*>()(a.get(),b.get()); }
+  };
+
+} // namespace std 
+

Specialization of std::swap uses the fast, non-throwing swap that's provided +as a member function instead of using the default algorithm which creates a +temporary and uses assignment.
+
+Specialization of std::less allows use of shared arrays as keys in C++ +Standard Library associative collections.
+
+The std::less specializations use std::less<T*> to perform the +comparison.  This insures that pointers are handled correctly, since the +standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] +paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] +paragraph 8).
+
+It's still a controversial question whether supplying only std::less is better +than supplying a full range of comparison operators (<, >, <=, >=).

+

The current implementation does not supply the specializations if the macro +name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.

+

Class shared_array Members

+

shared_array element_type

+
typedef T element_type;
+

Provides the type of the stored pointer.

+

shared_array constructors

+
explicit shared_array( T* p=0 );
+

Constructs a shared_array, storing a copy of p, +which must have been allocated via a C++ new[] expression or be 0. +Afterwards, use_count() is 1 (even if p==0; see ~shared_array).

+

The only exception which may be thrown is std::bad_alloc.  If +an exception is thrown,  delete[] p is called.

+
shared_array( const shared_array& r);  // never throws
+

Constructs a shared_array, as if by storing a copy of the +pointer stored in r. Afterwards, use_count() +for all copies is 1 more than the initial r.use_count().

+

shared_array destructor

+
~shared_array();
+

If use_count() == 1, deletes the array pointed to by the +stored pointer. Otherwise, use_count() for any remaining +copies is decremented by 1. Note that in C++ delete[] on a pointer with +a value of 0 is harmless.

+

Does not throw exceptions.

+

shared_array operator=

+
shared_array& operator=( const shared_array& r);  // never throws
+

First, if use_count() == 1, deletes the array pointed to by +the stored pointer. Otherwise, use_count() for any +remaining copies is decremented by 1. Note that in C++ delete[] on a +pointer with a value of 0 is harmless.

+

Then replaces the contents of this, as if by storing a copy +of the pointer stored in r. Afterwards, use_count() +for all copies is 1 more than the initial r.use_count()

+

shared_array reset

+
void reset( T* p=0 );
+

First, if use_count() == 1, deletes the array pointed to by +the stored pointer. Otherwise, use_count() for any +remaining copies is decremented by 1. Note that in C++  delete[] +on a pointer with a value of 0 is harmless.

+

Then replaces the contents of this, as if by storing a copy +of p, which must have been allocated via a C++ new[] +expression or be 0. Afterwards, use_count() is 1 (even if p==0; +see ~shared_array).

+

The only exception which may be thrown is std::bad_alloc.  If +an exception is thrown,  delete[] p is called.

+

shared_array operator[]

+

T& operator[](std::size_t i) const; // never throws

+

Returns a reference to element i of the array pointed to by the +stored pointer.

+

Behavior is undefined (and almost certainly undesirable) if get()==0, +or if i is less than 0 or is greater or equal to the number of elements +in the array.

+

shared_array get

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

Returns the stored pointer.

+

shared_array use_count

+

long use_count() const; // never throws

+

Returns the number of shared_arrays sharing ownership of the +stored pointer.

+

shared_array unique

+

bool unique() const; // never throws

+

Returns use_count() == 1.

+

shared_array swap

+

void swap( shared_array<T>& other ) throw()

+

Swaps the two smart pointers, as if by std::swap.

+

Class shared_array example

+

[To be supplied. In the meantime, see smart_ptr_test.cpp.]

+
+

Revised December 8, 1999

+

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

+ + + + diff --git a/shared_ptr.htm b/shared_ptr.htm new file mode 100644 index 0000000..3fdca13 --- /dev/null +++ b/shared_ptr.htm @@ -0,0 +1,206 @@ + + + +shared_ptr + + + + + + +

c++boost.gif (8819 bytes)Class +shared_ptr

+

Class shared_ptr stores a pointer to a dynamically allocated +object. (Dynamically allocated objects are allocated with the C++ new +expression.)   The object pointed to is guaranteed to be deleted when +the last shared_ptr pointing to it is deleted or reset.  +See example.

+

Class shared_ptr meets the CopyConstuctible +and Assignable requirements of the C++ Standard Library, and so +can be used in C++ Standard Library containers.  A specialization of std:: +less< > for  boost::shared_ptr<Y> is supplied so that  +shared_ptr works by default for Standard Library's Associative +Container Compare template parameter.  For compilers not supporting partial +specialization, the user must explicitly pass the less<> functor.

+

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

+

Class shared_ptr will not work correctly with cyclic data +structures. For example, if main() holds a shared_ptr to object A, which +directly or indirectly holds a shared_ptr back to object A, then object A's +use_count() will be 2, and destruction of the main() shared_ptr will leave +object A dangling with a use_count() of 1.

+

The class is a template parameterized on T, the type of the object +pointed to.   T must meet the smart pointer Common +requirements.

+

Class shared_ptr Synopsis

+
#include <boost/smart_ptr.hpp>
+namespace boost {
+
+template<typename T> class shared_ptr {
+
+ public:
+   typedef T element_type;
+
+   explicit shared_ptr( T* p=0 );
+   ~shared_ptr();
+
+   shared_ptr( const shared_ptr& );   
+   template<typename Y>
+      shared_ptr(const shared_ptr<Y>& r);  // never throws
+   template<typename Y>
+      shared_ptr(std::auto_ptr<Y>& r);
+
+   shared_ptr& operator=( const shared_ptr& );  // never throws  
+   template<typename Y>
+      shared_ptr& operator=(const shared_ptr<Y>& r);  // never throws
+   template<typename Y>
+      shared_ptr& operator=(std::auto_ptr<Y>& r);
+
+   void reset( T* p=0 );
+
+   T& operator*() const;  // never throws
+   T* operator->() const;  // never throws
+   T* get() const;  // never throws
+
+   long use_count() const;  // never throws
+   bool unique() const;  // never throws
+
+   void swap( shared_ptr<T>& other ) throw()
+   };
+
+template<typename T, typename U>
+  inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b)
+    { return a.get() == b.get(); }
+
+template<typename T, typename U>
+  inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b)
+    { return a.get() != b.get(); }
+}
+
namespace std {
+
+template<typename T>
+  inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b)
+    { a.swap(b); }
+
+template<typename T>
+  struct less< boost::shared_ptr<T> >
+    : binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool>
+  {
+    bool operator()(const boost::shared_ptr<T>& a,
+        const boost::shared_ptr<T>& b) const
+      { return less<T*>()(a.get(),b.get()); }
+  };
+
+} // namespace std 
+

Specialization of std::swap uses the fast, non-throwing swap that's provided +as a member function instead of using the default algorithm which creates a +temporary and uses assignment.
+
+Specialization of std::less allows use of shared pointers as keys in C++ +Standard Library associative collections.
+
+The std::less specializations use std::less<T*> to perform the +comparison.  This insures that pointers are handled correctly, since the +standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] +paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] +paragraph 8).
+
+It's still a controversial question whether supplying only std::less is better +than supplying a full range of comparison operators (<, >, <=, >=).

+

The current implementation does not supply the specializations if the macro +name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.

+

The current implementation does not supply the member template functions if +the macro name BOOST_NO_MEMBER_TEMPLATES is defined.

+

Class shared_ptr Members

+

shared_ptr element_type

+
typedef T element_type;
+

Provides the type of the stored pointer.

+

shared_ptr constructors

+
explicit shared_ptr( T* p=0 );
+

Constructs a shared_ptr, storing a copy of p, which +must have been allocated via a C++ new expression or be 0. Afterwards, use_count() +is 1 (even if p==0; see ~shared_ptr).

+

The only exception which may be thrown by this constructor is std::bad_alloc.   +If an exception is thrown,  delete p is called.

+
shared_ptr( const shared_ptr& r);  // never throws   
+template<typename Y>
+   shared_ptr(const shared_ptr<Y>& r);  // never throws
+template<typename Y>
+   shared_ptr(std::auto_ptr<Y>& r);
+

Constructs a shared_ptr, as if by storing a copy of the +pointer stored in r. Afterwards, use_count() +for all copies is 1 more than the initial r.use_count(), or 1 +in the auto_ptr case. In the auto_ptr case, r.release() +is called.

+

The only exception which may be thrown by the constructor from auto_ptr +is std::bad_alloc.   If an exception is thrown, that +constructor has no effect.

+

shared_ptr destructor

+
~shared_ptr();
+

If use_count() == 1, deletes the object pointed to by the +stored pointer. Otherwise, use_count() for any remaining +copies is decremented by 1. Note that in C++  delete on a pointer +with a value of 0 is harmless.

+

Does not throw exceptions.

+

shared_ptr operator=

+
shared_ptr& operator=( const shared_ptr& r);  
+template<typename Y>
+   shared_ptr& operator=(const shared_ptr<Y>& r);
+template<typename Y>
+   shared_ptr& operator=(std::auto_ptr<Y>& r);
+

First, if use_count() == 1, deletes the object pointed to by +the stored pointer. Otherwise, use_count() for any +remaining copies is decremented by 1. Note that in C++  delete on +a pointer with a value of 0 is harmless.

+

Then replaces the contents of this, as if by storing a copy +of the pointer stored in r. Afterwards, use_count() +for all copies is 1 more than the initial r.use_count(), or 1 +in the auto_ptr case. In the auto_ptr case, r.release() +is called.

+

The first two forms of operator= above do not throw exceptions.

+

The only exception which may be thrown by the auto_ptr form +is std::bad_alloc.   If an exception is thrown, the function +has no effect.

+

shared_ptr reset

+
void reset( T* p=0 );
+

First, if use_count() == 1, deletes the object pointed to by +the stored pointer. Otherwise, use_count() for any +remaining copies is decremented by 1. 

+

Then replaces the contents of this, as if by storing a copy +of p, which must have been allocated via a C++ new +expression or be 0. Afterwards, use_count() is 1 (even if p==0; +see ~shared_ptr). Note that in C++  delete +on a pointer with a value of 0 is harmless.

+

The only exception which may be thrown is std::bad_alloc.  If +an exception is thrown,  delete p is called.

+

shared_ptr operator*

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

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

+

shared_ptr operator-> and get

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

Both return the stored pointer.

+

shared_ptr use_count

+

long use_count() const; // never throws

+

Returns the number of shared_ptrs sharing ownership of the +stored pointer.

+

shared_ptr unique

+

bool unique() const; // never throws

+

Returns use_count() == 1.

+

shared_ptr swap

+

void swap( shared_ptr<T>& other ) throw()

+

Swaps the two smart pointers, as if by std::swap.

+

Class shared_ptr example

+

[To be supplied. In the meantime, see smart_ptr_test.cpp.]

+
+

Revised December 8, 1999

+

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

+ + + + diff --git a/smart_ptr.htm b/smart_ptr.htm new file mode 100644 index 0000000..ab95fc8 --- /dev/null +++ b/smart_ptr.htm @@ -0,0 +1,138 @@ + + + + + + +Smart Pointer Classes + + + + +

c++boost.gif (8819 bytes)Smart +Pointers

+

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

+

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

+

The header boost/smart_ptr.hpp +provides four smart pointer template classes:

+
+ + + + + + + + + + + + + + + + + +
+

scoped_ptr

Simple sole ownership of single objects.
scoped_arraySimple sole ownership of arrays.
shared_ptrObject ownership shared among multiple pointers
shared_arrayArray ownership shared among multiple pointers.
+
+

These classes are designed to complement the C++ Standard Library auto_ptr +class.

+

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

+

A test program (smart_ptr_test.cpp) is +provided to verify correct operation.

+

A page on Smart Pointer Timings will be of +interest to those curious about performance issues.

+

Common requirements

+

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

+

Exception safety

+

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

+

Exception-specifications

+

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

+

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

+

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

+

History and acknowledgements

+

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

+

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

+

May, 1999.  In April and May, 1999, Valentin Bonnard and David Abrahams +made a number of suggestions resulting in numerous improvements.  See the +revision history in smart_ptr.hpp +for the specific changes made as a result of their constructive criticism.

+

Oct, 1998.  In 1994 Greg Colvin proposed to the C++ Standards Committee +classes named auto_ptr and counted_ptr which +were very similar to what we now call scoped_ptr and shared_ptr.  +The committee document was 94-168/N0555, Exception Safe Smart Pointers.  In +one of the very few cases where the Library Working Group's recommendations were +not followed by the full committee, counted_ptr was rejected +and surprising transfer-of-ownership semantics were added to auto-ptr.

+

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

+

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

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

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

+

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

+

See the Revision History section of the header for further contributors.

+
+

Revised  24 Jul 2000

+

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

+ + + + diff --git a/smarttests.htm b/smarttests.htm new file mode 100644 index 0000000..dd976e4 --- /dev/null +++ b/smarttests.htm @@ -0,0 +1,540 @@ + + +boost: smart pointer tests + + + + +

c++boost.gif (8819 bytes)Smart +Pointers Timings

+ +

In late January 2000, Mark Borgerding put forward a suggestion to boost for + a new design of smart pointer whereby an intrusive doubly linked list is used + to join together all instances of smart pointers sharing a given raw pointer. + This allowed avoidance of the costly heap allocation of a reference count that + occurred in the initial construction of the then current version of boost::shared_ptr. + Of course, nothing is for free and the benefit here was gained at the expense + of increased size and more costly copy operations. A debate ensued on the boost + mailing list and the tests which this page describes were performed to provide + a guide for current and future investigations into smart pointer implementation + strategies.

+

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

+

Description

+

Two tests were run: the first aimed to obtain timings for two basic individual + operations:

+
    +
  1. Initial construction from raw pointer.
  2. +
  3. An amortized copy operation consisting of half an assignment and half a + copy construction - designed to reflect average usage.
  4. +
+

The second attempted to gain more insight into normal usage by timing the fill + and sort algorithms for vectors and lists filled with the various smart pointers.

+

Five smart pointer implementation strategies were tested:

+
    +
  1. Counted pointer using a heap allocated reference count, this is referred + to as simple counted.
  2. +
  3. Counted pointer using a special purpose allocator for the reference count + - special counted.
  4. +
  5. Counted pointer using an intrusive reference count - intrusive.
  6. +
  7. Linked pointer as described above - linked.
  8. +
  9. Cyclic pointer, a counted implementation using a std::deque for allocation + with provision for weak pointers and garbage collection of cycles of pointers + - cyclic.
  10. +
+

on two compilers:

+
    +
  1. MSVC 6.0 service pack 3, using default release optimization mode (/O2 - + optimized for speed, no inlining of functions defined outside a class body + unless specified as inline).
  2. +
  3. gcc 2.95.2 using full optimization (-O3 -DNDEBUG).
  4. +
+

Additionally, generated pointer sizes (taking into account struct alignment) + were compared, as were generated code sizes for MSVC mainly by manual inspection + of generated assembly code - a necessity due to function inlining.

+

All tests were run on a PII-200 running Windows NT version 4.0

+

 

+

Operation Timing Test Results

+

The following graphs show the overall time in nanoseconds to acquire a pointer + (default construction) perform n amortized copy operations on it and finally + release it. The initial allocation time for the contained pointer is not included, + although the time for it's deallocation is. The contained pointer pointed to + a trivial class, but for the inclusion of an intrusive reference count for the + benefit of the intrusive counted shared pointer. A dumb pointer (i.e. a smart + pointer that simply acquires and releases its contained pointer with no extra + overhead) and a raw pointer were also included for comparison.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
   
   
   
  
   
+

 

+

Fitting straight lines to the above plots gives the following figures for initialization + and amortized copy operation for the two compilers (times in nanoseconds, errors + at two standard deviations) : -

+

 

+

MSVC

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
initialization
+
copy operation
+
simple counted
+
3000 +/- 170104 +/- 31
+
special counted
+
1330 +/- 5085 +/- 9
+
intrusive
+
1000 +/- 2071 +/- 3
linked970 +/- 60136 +/- 10
cyclic1290 +/- 70112 +/- 12
dumb1020 +/- 2010 +/- 4
+
raw
+
1038 +/- 3010 +/- 5
+

 

+

GCC

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
initialization
+
copy operation
+
simple counted
+
4620 +/- 150301 +/- 28
+
special counted
+
1990 +/- 40264 +/- 7
+
intrusive
+
1590 +/- 70181 +/- 12
linked1470 +/- 140345 +/- 26
cyclic2180 +/- 100330 +/- 18
dumb1590 +/- 7074 +/- 12
+
raw
+
1430 +/- 6027 +/- 11
+

Note that the above times include a certain amount of loop overhead etc. for + each operation. An estimate of the pure smart pointer operation time 'overhead' + can be obtained by subtracting the dumb or raw figure from the smart pointer + time of interest.

+

Detail

+

The test involved iterating a loop which creates raw pointers. These were then + shared among a varying number (set size) of smart pointers. A range of set sizes + was used and then a line fitted to get a linear relation with number of initializations + and copy-operations. A spreadsheet was used for the line fit, and to produce + the performance graphs above.

+

 

+

Container Test Results

+

To gain some insight in to operation within real life programs, this test was + devised. Smart pointers were used to fill standard containers which were then + sorted.

+

In this case, the contained pointer pointed to a class which initializes a + private data member to a random value in its default constructor. This value + is used subsequently for the sort comparison test. The class also contains an + intrusive reference count for the benefit of the intrusive counted pointer.

+

All times are in seconds for 300,000 contained pointers.

+

GCC

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 vectorlist
+
+
+
fill
+
sortfillsort
+
simple counted
+
46.542.4447.093.22
+
special counted
+
14.022.837.283.21
+
intrusive
+
12.151.917.993.08
linked12.462.328.143.27
cyclic22.603.191.633.18
+
raw
+
11.810.2427.510.77
+

 

+

MSVC

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 vectorlist
+
+
+
fill
+
sortfillsort
+
simple counted
+
1.832.371.864.85
+
special counted
+
1.042.351.384.58
+
intrusive
+
1.041.841.164.29
linked1.082.001.214.33
cyclic1.382.841.474.73
+
raw
+
0.670.281.241.81
+

 

+

Code Size

+

The following code sizes were determined by inspection of generated code for + MSVC only. Sizes are given in the form N / M / I where:

+
    +
  • N is the instruction count of the operation
  • +
  • M is the size of the code in bytes
  • +
  • I determines whether generated code was inlined or not I = inline, O = "outline"
  • +
+

 

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
ptr()
+
ptr(p)ptr(ptr)op=() +
~ptr()
+
+
simple counted
+
38/110/O38/110/O9/23/I22/57/I17/40/I
+
special counted
+
50/141/O50/141/O9/23/I23/64/I13/38/I
+
intrusive
+
1/2/I3/6/I3/6/I6/11/I6/11/I
+
linked
+
5/19/I5/15/I10/30/I27/59/I14/38/I
+

During the code inspection, a couple of minor points were noticed: -

+
    +
  • Function inlining was critical to performance.
  • +
  • For MSVC, at least, a "delete 0" caused execution of 11 assembly + instructions, including a function call. So in cases where performance is + at an absolute premium it can be worth inserting the extra manual test.
  • +
+

 

+

Data Size

+

The following smart pointer sizes were obtained in bytes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
MSVC
+
+
GCC
+
+
simple counted
+
+
8
+
+
8
+
+
special counted
+
+
8
+
+
12
+
+
intrusive
+
+
4
+
+
4
+
+
linked
+
+
12
+
+
12
+
+
cyclic
+
+
8
+
+
8
+
+

 

+

Summary

+

The timing results mainly speak for themselves: clearly an intrusive pointer + outperforms all others and a simple heap based counted pointer has poor performance + relative to other implementations. The selection of an optimal non-intrusive + smart pointer implementation is more application dependent, however. Where small + numbers of copies are expected, it is likely that the linked implementation + will be favoured. Conversely, for larger numbers of copies a counted pointer + with some type of special purpose allocator looks like a win. Other factors + to bear in mind are: -

+
    +
  • Deterministic individual, as opposed to amortized, operation time. This + weighs against any implementation depending on an allocator.
  • +
  • Multithreaded synchronization. This weighs against an implementation which + spreads its information as in the case of linked pointer.
  • +
+
+

Revised 21 Feb 2000 +

+

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

+ + From 00c5642eb46d5d2bb06fdd0596b5b5ddb20d5f2b Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 3 Aug 2000 15:26:16 +0000 Subject: [PATCH 005/513] 1.17.0 release candidate runup [SVN r7683] --- index.htm | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/index.htm b/index.htm index 04643fa..4a15b3e 100644 --- a/index.htm +++ b/index.htm @@ -4,34 +4,36 @@ Boost Smart Pointer Library + - - - - - - + + + + + +
c++boost.gif (8819 bytes)Home Libraries People FAQ More c++boost.gif (8819 bytes)HomeLibrariesPeopleFAQMore
-

Smart pointer library

- -

The header smart_ptr.h provides four smart pointer classes.  Smart pointers ease -the management of memory dynamically allocated with C++ new expressions. - +

The header smart_ptr.hpp provides four smart pointer classes.  Smart +pointers ease the management of memory dynamically allocated with C++ new +expressions.

+

Revised 02 Aug 2000 +

-

Revised July 23, 1999

+ From 1412e40490deb3feb9c8603e0a64d466e2309f6f Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 19 Oct 2000 21:16:46 +0000 Subject: [PATCH 006/513] Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts) [SVN r8012] --- include/boost/smart_ptr.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index 353e472..686df8d 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -9,6 +9,7 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 19 Oct 00 Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts) // 24 Jul 00 Change throw() to // never throws. See lib guidelines // Exception-specification rationale. (Beman Dawes) // 22 Jun 00 Remove #if continuations to fix GCC 2.95.2 problem (Beman Dawes) @@ -140,7 +141,7 @@ template class shared_ptr { } template - shared_ptr(std::auto_ptr& r) { + explicit shared_ptr(std::auto_ptr& r) { pn = new long(1); // may throw px = r.release(); // fix: moved here to stop leak if new throws } @@ -164,7 +165,7 @@ template class shared_ptr { return *this; } #else - shared_ptr(std::auto_ptr& r) { + explicit shared_ptr(std::auto_ptr& r) { pn = new long(1); // may throw px = r.release(); // fix: moved here to stop leak if new throws } From db43d160b4a58d1295f95d38e72f2ddf7462ab5c Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 10 Nov 2000 15:39:05 +0000 Subject: [PATCH 007/513] libraries.htm and people.htm moved to sub-directories to make root directory cleaner. [SVN r8166] --- index.htm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.htm b/index.htm index 4a15b3e..da4e16f 100644 --- a/index.htm +++ b/index.htm @@ -13,8 +13,8 @@ c++boost.gif (8819 bytes) Home - Libraries - People + Libraries + People FAQ More @@ -31,7 +31,7 @@ expressions.
  • Submitted by Greg Colvin and Beman Dawes.
  • -

    Revised 02 Aug 2000 +

    Revised 10 Nov 2000

    From 4e832788bfae6fdbfc1aac88c37b6dd47103c2ea Mon Sep 17 00:00:00 2001 From: John Maddock Date: Thu, 16 Nov 2000 11:17:22 +0000 Subject: [PATCH 008/513] Fix for egcs 1.1.1 problems with std::auto_ptr [SVN r8225] --- include/boost/smart_ptr.hpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index 686df8d..59e42a7 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -139,12 +139,13 @@ template class shared_ptr { shared_ptr(const shared_ptr& r) : px(r.px) { // never throws ++*(pn = r.pn); } - +#ifndef BOOST_NO_AUTO_PTR template explicit shared_ptr(std::auto_ptr& r) { pn = new long(1); // may throw px = r.release(); // fix: moved here to stop leak if new throws - } + } +#endif template shared_ptr& operator=(const shared_ptr& r) { @@ -152,6 +153,7 @@ template class shared_ptr { return *this; } +#ifndef BOOST_NO_AUTO_PTR template shared_ptr& operator=(std::auto_ptr& r) { // code choice driven by guarantee of "no effect if new throws" @@ -164,7 +166,9 @@ template class shared_ptr { px = r.release(); // fix: moved here so doesn't leak if new throws return *this; } +#endif #else +#ifndef BOOST_NO_AUTO_PTR explicit shared_ptr(std::auto_ptr& r) { pn = new long(1); // may throw px = r.release(); // fix: moved here to stop leak if new throws @@ -181,6 +185,7 @@ template class shared_ptr { px = r.release(); // fix: moved here so doesn't leak if new throws return *this; } +#endif #endif void reset(T* p=0) { @@ -371,3 +376,4 @@ template #endif // BOOST_SMART_PTR_HPP + From 26fe4c40788dd94f5bf09da8b64748a6c9fe3fdc Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Wed, 6 Dec 2000 14:46:44 +0000 Subject: [PATCH 009/513] Fix typo shared_array should have read shared_ptr in one place (Ed Brey) [SVN r8392] --- shared_array.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared_array.htm b/shared_array.htm index eebafdc..89d9339 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -23,7 +23,7 @@ shared_array works by default for Standard Library's Associative Container Compare template parameter.  For compilers not supporting partial specialization, the user must explicitly pass the less<> functor.

    Class shared_array cannot correctly hold a pointer to a -single object.  See shared_array +single object.  See shared_ptr for that usage.

    Class shared_array will not work correctly with cyclic data structures. For example, if main() holds a shared_array pointing to array A, From cb1b1b7cc09032c588e1842be3e7f813d1a9f2f0 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 22 Jan 2001 04:53:38 +0000 Subject: [PATCH 010/513] Suppress some useless warnings with MSVC [SVN r8704] --- include/boost/smart_ptr.hpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index 59e42a7..162b458 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -9,6 +9,7 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 21 Jan 01 Suppress some useless warnings with MSVC (David Abrahams) // 19 Oct 00 Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts) // 24 Jul 00 Change throw() to // never throws. See lib guidelines // Exception-specification rationale. (Beman Dawes) @@ -75,7 +76,14 @@ template class scoped_ptr : noncopyable { void reset( T* p=0 ) { if ( ptr != p ) { delete ptr; ptr = p; } } T& operator*() const { return *ptr; } // never throws +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4284) // return type for 'identifier::operator->' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation +#endif T* operator->() const { return ptr; } // never throws +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif T* get() const { return ptr; } // never throws #ifdef BOOST_SMART_PTR_CONVERSION // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! @@ -204,7 +212,14 @@ template class shared_ptr { } // reset T& operator*() const { return *px; } // never throws +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4284) // return type for 'identifier::operator->' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation +#endif T* operator->() const { return px; } // never throws +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif T* get() const { return px; } // never throws #ifdef BOOST_SMART_PTR_CONVERSION // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! From 16902b1f4ffb71eb3249a3fe8181e89c79ef18cc Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 9 Feb 2001 14:39:43 +0000 Subject: [PATCH 011/513] Add example [SVN r9054] --- shared_ptr.htm | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 3fdca13..0d489ad 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -192,7 +192,31 @@ stored pointer.

    void swap( shared_ptr<T>& other ) throw()

    Swaps the two smart pointers, as if by std::swap.

    Class shared_ptr example

    -

    [To be supplied. In the meantime, see smart_ptr_test.cpp.]

    +
    //  The application will produce a series of
    +//  objects of type Foo which later must be
    +//  accessed both by occurrence (std::vector)
    +//  and by ordering relationship (std::set).
    +
    +class Foo { ... };
    +
    +typedef boost::shared_ptr<Foo> FooPtr;
    +
    +std::vector<FooPtr> foo_vector;
    +std::set<FooPtr>    foo_set; // NOT multiset!
    +
    +...
    +{ // creation loop
    +  FooPtr foo_ptr ( new Foo( ... ) );
    +  foo_vector.push_back( foo_ptr );
    +  foo_set.insert( foo_ptr );
    +}
    +

    Note that at the termination of the creation loop, some of the FooPtr objects +may have use_count()==1 rather than use_count()==2, since foo_set is a std::set +rather than a std::multiset.  Furthermore, use_count() will be even higher +at various times inside the loop, as container operations are performed.  +More complicated yet, the container operations may throw exceptions under a +variety of circumstances.  Without using a smart pointer, memory and +exception management would be a nightmare.


    Revised December 8, 1999

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, From e57d3f4bc1e77ea51289141f7bccfb2df97cd835 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sat, 10 Feb 2001 12:47:02 +0000 Subject: [PATCH 012/513] Fix revision date [SVN r9069] --- shared_ptr.htm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 0d489ad..b478dc9 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -218,7 +218,8 @@ More complicated yet, the container operations may throw exceptions under a variety of circumstances.  Without using a smart pointer, memory and exception management would be a nightmare.


    -

    Revised December 8, 1999

    +

    Revised 09 February, 2001 +

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" From 6a12efb77bf64e79c232b37057129a603356b327 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Wed, 14 Mar 2001 15:11:55 +0000 Subject: [PATCH 013/513] 1.21.1 run up, including new download instructions and fix broken hyperlinks [SVN r9557] --- index.htm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.htm b/index.htm index da4e16f..9c8e78a 100644 --- a/index.htm +++ b/index.htm @@ -27,11 +27,10 @@ expressions.

  • Documentation (HTML).
  • Header smart_ptr.hpp
  • Test program smart_ptr_test.cpp.
  • -
  • Download all of Boost (ZIP format).
  • Submitted by Greg Colvin and Beman Dawes.
  • -

    Revised 10 Nov 2000 +

    Revised 14 Mar 2001

    From 060ea4a573e1b8841148e3d9cd441a7ccfd2e8ca Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sun, 18 Mar 2001 22:25:51 +0000 Subject: [PATCH 014/513] Add a couple of comments to cut down on FAQ's [SVN r9581] --- include/boost/smart_ptr.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index 162b458..e549f91 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -250,7 +250,7 @@ template class shared_ptr { void dispose() { if (--*pn == 0) { delete px; delete pn; } } void share(T* rpx, long* rpn) { - if (pn != rpn) { + if (pn != rpn) { // assert ((pn==rpn) == (px==rpx)) dispose(); px = rpx; ++*(pn = rpn); @@ -287,7 +287,7 @@ template class shared_array { ~shared_array() { dispose(); } shared_array& operator=(const shared_array& r) { - if (pn != r.pn) { + if (pn != r.pn) { //assert ((pn==r.pn) == (px==r.px)) dispose(); px = r.px; ++*(pn = r.pn); From 2d342f0ddfbe852290b666b812f3acecabd87837 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Mon, 19 Mar 2001 12:34:12 +0000 Subject: [PATCH 015/513] Comment corrected (thanks to Joe Gottman) [SVN r9582] --- include/boost/smart_ptr.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index e549f91..1decce7 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -250,7 +250,7 @@ template class shared_ptr { void dispose() { if (--*pn == 0) { delete px; delete pn; } } void share(T* rpx, long* rpn) { - if (pn != rpn) { // assert ((pn==rpn) == (px==rpx)) + if (pn != rpn) { // Q: why not px != rpx? A: fails when both == 0 dispose(); px = rpx; ++*(pn = rpn); @@ -287,7 +287,7 @@ template class shared_array { ~shared_array() { dispose(); } shared_array& operator=(const shared_array& r) { - if (pn != r.pn) { //assert ((pn==r.pn) == (px==r.px)) + if (pn != r.pn) { // Q: why not px != r.px? A: fails when both px == 0 dispose(); px = r.px; ++*(pn = r.pn); From 55a377b44668366ba02612929f7f3dd743748e7b Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Wed, 25 Apr 2001 00:24:50 +0000 Subject: [PATCH 016/513] Change all eGroups references to YahooGroups [SVN r9979] --- scoped_ptr.htm | 2 +- shared_ptr.htm | 2 +- smart_ptr.htm | 2 +- smarttests.htm | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 3430481..0e47606 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -116,7 +116,7 @@ body is not visible at the time scoped_ptr<> deletes it. See ISO 5.3.5/5.  Note that some compilers will issue a warning even though the above code is well defined.


    -

    Revised 24 July 2000

    +

    Revised 27 July 2000

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" diff --git a/shared_ptr.htm b/shared_ptr.htm index b478dc9..affff12 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -218,7 +218,7 @@ More complicated yet, the container operations may throw exceptions under a variety of circumstances.  Without using a smart pointer, memory and exception management would be a nightmare.


    -

    Revised 09 February, 2001 +

    Revised 10 February, 2001

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright diff --git a/smart_ptr.htm b/smart_ptr.htm index ab95fc8..dc5db1f 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -125,7 +125,7 @@ implementation.

    See the Revision History section of the header for further contributors.


    Revised  24 Jul 200027 Jul 2000

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright diff --git a/smarttests.htm b/smarttests.htm index dd976e4..f78b618 100644 --- a/smarttests.htm +++ b/smarttests.htm @@ -530,7 +530,7 @@ Pointers Timings spreads its information as in the case of linked pointer.


    -

    Revised 21 Feb 2000 +

    Revised 27 Jul 2000

    İ Copyright Gavin Collings 2000. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all From 3b183163c9ab8b5995cd7c3e832b0c79b57dfca9 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 10 May 2001 16:00:49 +0000 Subject: [PATCH 017/513] Clarify rationale for noncopyability [SVN r10085] --- scoped_array.htm | 17 +++++++++++------ scoped_ptr.htm | 17 ++++++++++++----- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/scoped_array.htm b/scoped_array.htm index 3bf65cd..e317e21 100644 --- a/scoped_array.htm +++ b/scoped_array.htm @@ -15,16 +15,21 @@ allocated array. (Dynamically allocated arrays are allocated with the C++ ne expression.)   The array pointed to is guaranteed to be deleted, either on destruction of the scoped_array, or via an explicit scoped_array::reset().

    Class scoped_array is a simple solution for simple -needs.  It cannot be used in C++ Standard Library containers.  See shared_array +needs. It supplies a basic "resource acquisition is +initialization" facility, without shared-ownership or transfer-of-ownership +semantics.  Both its name and enforcement of semantics (by being noncopyable) +signal its intent to retain ownership solely within the current scope.  By +being noncopyable, it is +safer than shared_array for pointers which should not be copied.

    +

    Because scoped_array is so simple, in its usual +implementation every operation is as fast as a built-in array pointer and it has no +more space overhead that a built-in array pointer.

    +

    It cannot be used in C++ Standard Library containers.  See shared_array if scoped_array does not meet your needs.

    Class scoped_array cannot correctly hold a pointer to a single object.  See scoped_ptr for that usage.

    -

    Because scoped_array is so simple, in its usual -implementation every operation is as fast as a built-in array pointer and has no -more space overhead that a built-in array pointer.

    -

    A heavier duty alternative to a scoped_array is a scoped_ptr -to a C++ Standard Library vector.

    +

    A C++ Standard Library vector is a heavier duty alternative to a scoped_array.

    The class is a template parameterized on T, the type of the object pointed to.   T must meet the smart pointer common requirements.

    diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 0e47606..27512d1 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -16,14 +16,21 @@ expression.)   The object pointed to is guaranteed to be deleted, either on destruction of the scoped_ptr, or via an explicit scoped_ptr::reset().  See example.

    Class scoped_ptr is a simple solution for simple -needs.  It cannot be used in C++ Standard Library containers.  See shared_ptr +needs.  It supplies a basic "resource acquisition is +initialization" facility, without shared-ownership or transfer-of-ownership +semantics.  Both its name and enforcement of semantics (by being noncopyable) +signal its intent to retain ownership solely within the current scope.  By +being noncopyable, it is +safer than shared_ptr or std::auto_ptr for pointers which should not be +copied.

    +

    Because scoped_ptr is so simple, in its usual implementation +every operation is as fast as for a built-in pointer and it has no more space overhead +that a built-in pointer.

    +

    Class scoped_ptr cannot be used in C++ Standard Library containers.  See shared_ptr or std::auto_ptr if scoped_ptr does not meet your needs.

    Class scoped_ptr cannot correctly hold a pointer to a dynamically allocated array.  See scoped_array for that usage.

    -

    Because scoped_ptr is so simple, in its usual implementation -every operation is as fast as a built-in pointer and has no more space overhead -that a built-in pointer.

    The class is a template parameterized on T, the type of the object pointed to.   T must meet the smart pointer common requirements.

    @@ -116,7 +123,7 @@ body is not visible at the time scoped_ptr<> deletes it. See ISO 5.3.5/5.  Note that some compilers will issue a warning even though the above code is well defined.


    -

    Revised 27 July 2000

    +

    Revised 10 May 2001

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" From 8f23f07740e3e76ff71b83d1f14fe9727ed0849c Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Mon, 21 May 2001 14:56:51 +0000 Subject: [PATCH 018/513] Fix transitive dependency bug [SVN r10164] --- include/boost/smart_ptr.hpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index 1decce7..2111032 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -9,6 +9,8 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 21 May 01 operator= fails if operand transitively owned by *this, as in a +// linked list (report by Ken Johnson, fix by Beman Dawes) // 21 Jan 01 Suppress some useless warnings with MSVC (David Abrahams) // 19 Oct 00 Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts) // 24 Jul 00 Change throw() to // never throws. See lib guidelines @@ -251,9 +253,11 @@ template class shared_ptr { void share(T* rpx, long* rpn) { if (pn != rpn) { // Q: why not px != rpx? A: fails when both == 0 + ++*rpn; // done before dispose() in case rpn transitively + // dependent on *this (bug reported by Ken Johnson) dispose(); px = rpx; - ++*(pn = rpn); + pn = rpn; } } // share }; // shared_ptr @@ -288,9 +292,11 @@ template class shared_array { shared_array& operator=(const shared_array& r) { if (pn != r.pn) { // Q: why not px != r.px? A: fails when both px == 0 + ++*r.pn; // done before dispose() in case r.pn transitively + // dependent on *this (bug reported by Ken Johnson) dispose(); px = r.px; - ++*(pn = r.pn); + pn = r.pn; } return *this; } // operator= From ac8d0f55053b04d8b0a0632cd4c8b624141abb24 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Mon, 21 May 2001 14:58:07 +0000 Subject: [PATCH 019/513] Fix doc errors, add shared_ptr_example program [SVN r10165] --- scoped_ptr.htm | 4 +- shared_ptr.htm | 30 +++---------- shared_ptr_example.cpp | 96 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 25 deletions(-) create mode 100644 shared_ptr_example.cpp diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 27512d1..277b38e 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -106,7 +106,7 @@ output:

    Buckle my shoe

    Handle/Body Idiom

    -

    One common usage of shared_pointer is to implement a handle/body +

    One common usage of scoped_ptr is to implement a handle/body structure which avoids exposing the body (implementation) in the header file:

    class handle
     {
    @@ -123,7 +123,7 @@ body is not visible at the time scoped_ptr<> deletes it. See ISO
     5.3.5/5.  Note that some compilers will issue a warning even though the
     above code is well defined.


    -

    Revised 10 May 2001

    +

    Revised 21 May 2001

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" diff --git a/shared_ptr.htm b/shared_ptr.htm index affff12..4dd2b87 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -192,33 +192,17 @@ stored pointer.

    void swap( shared_ptr<T>& other ) throw()

    Swaps the two smart pointers, as if by std::swap.

    Class shared_ptr example

    -
    //  The application will produce a series of
    -//  objects of type Foo which later must be
    -//  accessed both by occurrence (std::vector)
    -//  and by ordering relationship (std::set).
    -
    -class Foo { ... };
    -
    -typedef boost::shared_ptr<Foo> FooPtr;
    -
    -std::vector<FooPtr> foo_vector;
    -std::set<FooPtr>    foo_set; // NOT multiset!
    -
    -...
    -{ // creation loop
    -  FooPtr foo_ptr ( new Foo( ... ) );
    -  foo_vector.push_back( foo_ptr );
    -  foo_set.insert( foo_ptr );
    -}
    -

    Note that at the termination of the creation loop, some of the FooPtr objects -may have use_count()==1 rather than use_count()==2, since foo_set is a std::set -rather than a std::multiset.  Furthermore, use_count() will be even higher -at various times inside the loop, as container operations are performed.  +

    See shared_ptr_example.cpp for a complete example program.

    +

    This program builds a std::vector and std::set of FooPtr's.

    +

    Note that after the two containers have been populated, some of the FooPtr objects +will have use_count()==1 rather than use_count()==2, since foo_set is a std::set +rather than a std::multiset.  Furthermore, 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.  Without using a smart pointer, memory and exception management would be a nightmare.


    -

    Revised 10 February, 2001 +

    Revised 21 May, 2001

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright diff --git a/shared_ptr_example.cpp b/shared_ptr_example.cpp new file mode 100644 index 0000000..988efbd --- /dev/null +++ b/shared_ptr_example.cpp @@ -0,0 +1,96 @@ +// Boost shared_ptr_example.cpp --------------------------------------------// + +// (C) Copyright Beman Dawes 2001. Permission to copy, +// use, modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided "as is" +// without express or implied warranty, and with no claim as to its +// suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. + +// Revision History +// 21 May 01 Initial complete version (Beman Dawes) + +// The original code for this example appeared in the shared_ptr documentation. +// Ray Gallimore pointed out that foo_set was missing a Compare template +// argument, so would not work as intended. At that point the code was +// turned into an actual .cpp file so it could be compiled and tested. + +#include +#include +#include +#include +#include + +// The application will produce a series of +// objects of type Foo which later must be +// accessed both by occurrence (std::vector) +// and by ordering relationship (std::set). + +struct Foo +{ + Foo( int _x ) : x(_x) {} + ~Foo() { std::cout << "Destructing a Foo with x=" << x << "\n"; } + int x; + /* ... */ +}; + +typedef boost::shared_ptr FooPtr; + +struct FooPtrOps +{ + bool operator()( const FooPtr & a, const FooPtr & b ) + { return a->x > b->x; } + void operator()( const FooPtr & a ) + { std::cout << a->x << "\n"; } +}; + +int main() +{ + std::vector foo_vector; + std::set foo_set; // NOT multiset! + + FooPtr foo_ptr( new Foo( 2 ) ); + foo_vector.push_back( foo_ptr ); + foo_set.insert( foo_ptr ); + + foo_ptr.reset( new Foo( 1 ) ); + foo_vector.push_back( foo_ptr ); + foo_set.insert( foo_ptr ); + + foo_ptr.reset( new Foo( 3 ) ); + foo_vector.push_back( foo_ptr ); + foo_set.insert( foo_ptr ); + + foo_ptr.reset ( new Foo( 2 ) ); + foo_vector.push_back( foo_ptr ); + foo_set.insert( foo_ptr ); + + std::cout << "foo_vector:\n"; + std::for_each( foo_vector.begin(), foo_vector.end(), FooPtrOps() ); + + std::cout << "\nfoo_set:\n"; + std::for_each( foo_set.begin(), foo_set.end(), FooPtrOps() ); + std::cout << "\n"; + +// Expected output: +// +// foo_vector: +// 2 +// 1 +// 3 +// 2 +// +// foo_set: +// 3 +// 2 +// 1 +// +// Destructing a Foo with x=2 +// Destructing a Foo with x=1 +// Destructing a Foo with x=3 +// Destructing a Foo with x=2 + + return 0; +} + From a90a157ea60dba8286401e4c300ef3182f9cd0a0 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Tue, 22 May 2001 18:58:21 +0000 Subject: [PATCH 020/513] Smart pointer and utility changes related to adding checked_delere and checked_array_delete [SVN r10189] --- include/boost/smart_ptr.hpp | 34 +++++++++++++++--------------- scoped_array.htm | 10 +++++++++ scoped_ptr.htm | 41 +++++++++++++++++++++---------------- scoped_ptr_example.cpp | 16 +++++++++++++++ scoped_ptr_example.hpp | 21 +++++++++++++++++++ scoped_ptr_example_test.cpp | 10 +++++++++ shared_array.htm | 20 ++++++++++++++++++ shared_ptr.htm | 27 ++++++++++++++++++++++-- smart_ptr.htm | 29 +++++++++++++++++++++----- 9 files changed, 167 insertions(+), 41 deletions(-) create mode 100644 scoped_ptr_example.cpp create mode 100644 scoped_ptr_example.hpp create mode 100644 scoped_ptr_example_test.cpp diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index 2111032..3dea3f9 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -9,6 +9,7 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 21 May 01 Require complete type on delete (suggested by Vladimir Prus) // 21 May 01 operator= fails if operand transitively owned by *this, as in a // linked list (report by Ken Johnson, fix by Beman Dawes) // 21 Jan 01 Suppress some useless warnings with MSVC (David Abrahams) @@ -54,8 +55,9 @@ #include // for std::size_t #include // for std::auto_ptr #include // for std::swap -#include // for boost::noncopyable +#include // for boost::noncopyable, checked_delete, checked_array_delete #include // for std::less +#include // for BOOST_STATIC_ASSERT namespace boost { @@ -74,9 +76,8 @@ template class scoped_ptr : noncopyable { typedef T element_type; explicit scoped_ptr( T* p=0 ) : ptr(p) {} // never throws - ~scoped_ptr() { delete ptr; } - - void reset( T* p=0 ) { if ( ptr != p ) { delete ptr; ptr = p; } } + ~scoped_ptr() { checked_delete(ptr); } + void reset( T* p=0 ) { if ( ptr != p ) { checked_delete(ptr); ptr = p; } } T& operator*() const { return *ptr; } // never throws #ifdef BOOST_MSVC # pragma warning(push) @@ -107,9 +108,10 @@ template class scoped_array : noncopyable { typedef T element_type; explicit scoped_array( T* p=0 ) : ptr(p) {} // never throws - ~scoped_array() { delete [] ptr; } + ~scoped_array() { checked_array_delete(ptr); } - void reset( T* p=0 ) { if ( ptr != p ) {delete [] ptr; ptr=p;} } + void reset( T* p=0 ) { if ( ptr != p ) + {checked_array_delete(ptr); ptr=p;} } T* get() const { return ptr; } // never throws #ifdef BOOST_SMART_PTR_CONVERSION @@ -132,7 +134,7 @@ template class shared_ptr { explicit shared_ptr(T* p =0) : px(p) { try { pn = new long(1); } // fix: prevent leak if new throws - catch (...) { delete p; throw; } + catch (...) { checked_delete(p); throw; } } shared_ptr(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); } // never throws @@ -167,7 +169,7 @@ template class shared_ptr { template shared_ptr& operator=(std::auto_ptr& r) { // code choice driven by guarantee of "no effect if new throws" - if (*pn == 1) { delete px; } + if (*pn == 1) { checked_delete(px); } else { // allocate new reference counter long * tmp = new long(1); // may throw --*pn; // only decrement once danger of new throwing is past @@ -186,7 +188,7 @@ template class shared_ptr { shared_ptr& operator=(std::auto_ptr& r) { // code choice driven by guarantee of "no effect if new throws" - if (*pn == 1) { delete px; } + if (*pn == 1) { checked_delete(px); } else { // allocate new reference counter long * tmp = new long(1); // may throw --*pn; // only decrement once danger of new throwing is past @@ -200,12 +202,12 @@ template class shared_ptr { void reset(T* p=0) { if ( px == p ) return; // fix: self-assignment safe - if (--*pn == 0) { delete px; } + if (--*pn == 0) { checked_delete(px); } else { // allocate new reference counter try { pn = new long; } // fix: prevent leak if new throws catch (...) { ++*pn; // undo effect of --*pn above to meet effects guarantee - delete p; + checked_delete(p); throw; } // catch } // allocate new reference counter @@ -249,7 +251,7 @@ template class shared_ptr { template friend class shared_ptr; #endif - void dispose() { if (--*pn == 0) { delete px; delete pn; } } + void dispose() { if (--*pn == 0) { checked_delete(px); delete pn; } } void share(T* rpx, long* rpn) { if (pn != rpn) { // Q: why not px != rpx? A: fails when both == 0 @@ -282,7 +284,7 @@ template class shared_array { explicit shared_array(T* p =0) : px(p) { try { pn = new long(1); } // fix: prevent leak if new throws - catch (...) { delete [] p; throw; } + catch (...) { checked_array_delete(p); throw; } } shared_array(const shared_array& r) : px(r.px) // never throws @@ -303,12 +305,12 @@ template class shared_array { void reset(T* p=0) { if ( px == p ) return; // fix: self-assignment safe - if (--*pn == 0) { delete [] px; } + if (--*pn == 0) { checked_array_delete(px); } else { // allocate new reference counter try { pn = new long; } // fix: prevent leak if new throws catch (...) { ++*pn; // undo effect of --*pn above to meet effects guarantee - delete [] p; + checked_array_delete(p); throw; } // catch } // allocate new reference counter @@ -335,7 +337,7 @@ template class shared_array { T* px; // contained pointer long* pn; // ptr to reference counter - void dispose() { if (--*pn == 0) { delete [] px; delete pn; } } + void dispose() { if (--*pn == 0) { checked_array_delete(px); delete pn; } } }; // shared_array diff --git a/scoped_array.htm b/scoped_array.htm index e317e21..f146ee2 100644 --- a/scoped_array.htm +++ b/scoped_array.htm @@ -59,19 +59,27 @@ template<typename T> class scoped_array : Common Requirements.

    scoped_array destructor

    ~scoped_array();
    +

    T is required be a complete type at point of instantiation.  See Common +Requirements.

    Deletes the array pointed to by the stored pointer.  Note that in C++ delete[] on a pointer with a value of 0 is harmless.

    Does not throw exceptions.

    scoped_array reset

    void reset( T* p=0 )();
    +

    T is required be a complete type at point of instantiation.  See Common +Requirements.

    If p is not equal to the stored pointer, deletes the array pointed to by the stored pointer and then stores a copy of p, which must have been allocated via a C++ new[] expression or be 0.

    Does not throw exceptions.

    scoped_array operator[]

    T& operator[](std::size_t i) const; // never throws

    +

    T is required be a complete type at point of instantiation.  See Common +Requirements.

    Returns a reference to element i of the array pointed to by the stored pointer.

    Behavior is undefined (and almost certainly undesirable) if get()==0, @@ -79,6 +87,8 @@ or if i is less than 0 or is greater or equal to the number of elements in the array.

    scoped_array get

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

    T is not required be a complete type at point of instantiation.  +See Common Requirements.

    Returns the stored pointer.

    Class scoped_array example

    [To be supplied. In the meantime, see smart_ptr_test.cpp.]

    diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 277b38e..4945084 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -59,25 +59,38 @@ template<typename T> class scoped_ptr : scoped_ptr constructors
    explicit scoped_ptr( T* p=0 );  // never throws
    +

    T is not required be a complete type at point of instantiation.  +See Common Requirements.

    Constructs a scoped_ptr, storing a copy of p, which must -have been allocated via a C++ new expression or be 0..

    +have been allocated via a C++ new expression or be 0.

    scoped_ptr destructor

    ~scoped_ptr();
    +

    T is required be a complete type at point of instantiation.  See Common +Requirements.

    Deletes the object pointed to by the stored pointer.  Note that in C++, delete on a pointer with a value of 0 is harmless.

    Does not throw exceptions.

    scoped_ptr reset

    void reset( T* p=0 );
    +

    T is required be a complete type at point of instantiation.  See Common +Requirements.

    If p is not equal to the stored pointer, deletes the object pointed to by the stored pointer and then stores a copy of p, which must have been allocated via a C++ new expression or be 0.

    Does not throw exceptions.

    scoped_ptr operator*

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

    T is required be a complete type at point of instantiation.  See Common +Requirements.

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

    scoped_ptr operator-> and get

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

    T is required be a complete type at point of instantiation of +operator->().  See Common +Requirements.

    +

    T is not required be a complete type at point of instantiation of +get().  See Common Requirements.

    Both return the stored pointer.

    Class scoped_ptr examples

    #include <iostream>
    @@ -106,24 +119,16 @@ output:

    Buckle my shoe

    Handle/Body Idiom

    -

    One common usage of scoped_ptr is to implement a handle/body -structure which avoids exposing the body (implementation) in the header file:

    -
    class handle
    -{
    -public:    // simple forwarding functions to the body class
    -    void f();
    -    void g(int);
    -private:
    -    friend class body;  //incomplete class hides implementation
    -    boost::scoped_ptr<body> imp;
    -};
    -

    This code requires that class body have a trivial destructor to -avoid undefined behavior.  This is because the definition of class -body is not visible at the time scoped_ptr<> deletes it. See ISO -5.3.5/5.  Note that some compilers will issue a warning even though the -above code is well defined.

    +

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

    +

    The scoped_ptr_example_test.cpp +sample program includes a header file, scoped_ptr_example.hpp, +which uses a scoped_ptr<> to an incomplete type to hide the +implementation.   The +instantiation of member functions which require a complete type occurs in the scoped_ptr_example.cpp +implementation file. 


    -

    Revised 21 May 2001

    +

    Revised 22 May 2001

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" diff --git a/scoped_ptr_example.cpp b/scoped_ptr_example.cpp new file mode 100644 index 0000000..3e2e511 --- /dev/null +++ b/scoped_ptr_example.cpp @@ -0,0 +1,16 @@ +// Boost scoped_ptr_example implementation file -----------------------------// + +#include "scoped_ptr_example.hpp" +#include + +class example::implementation +{ + public: + ~implementation() { std::cout << "destroying implementation\n"; } +}; + +example::example() : _imp( new implementation ) {} + +void example::do_something() { std::cout << "did something\n"; } + +example::~example() {} diff --git a/scoped_ptr_example.hpp b/scoped_ptr_example.hpp new file mode 100644 index 0000000..97c8bff --- /dev/null +++ b/scoped_ptr_example.hpp @@ -0,0 +1,21 @@ +// Boost scoped_ptr_example header file ------------------------------------// + +#include + +// The point of this example is to prove that even though +// example::implementation is an incomplete type in translation units using +// this header, scoped_ptr< implementation > is still valid because the type +// is complete where it counts - in the inplementation translation unit where +// destruction is actually instantiated. + +class example : boost::noncopyable +{ + public: + example(); + ~example(); + void do_something(); + private: + class implementation; + boost::scoped_ptr< implementation > _imp; // hide implementation details +}; + diff --git a/scoped_ptr_example_test.cpp b/scoped_ptr_example_test.cpp new file mode 100644 index 0000000..3629ec8 --- /dev/null +++ b/scoped_ptr_example_test.cpp @@ -0,0 +1,10 @@ +// Boost scoped_ptr_example_test main program -------------------------------// + +#include "scoped_ptr_example.hpp" + +int main() +{ + example my_example; + my_example.do_something(); + return 0; +} \ No newline at end of file diff --git a/shared_array.htm b/shared_array.htm index 89d9339..24842d1 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -108,17 +108,23 @@ name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.

    Provides the type of the stored pointer.

    shared_array constructors

    explicit shared_array( T* p=0 );
    +

    T is required be a complete type at point of instantiation.  See Common +Requirements.

    Constructs a shared_array, storing a copy of p, which must have been allocated via a C++ new[] expression or be 0. Afterwards, use_count() is 1 (even if p==0; see ~shared_array).

    The only exception which may be thrown is std::bad_alloc.  If an exception is thrown,  delete[] p is called.

    shared_array( const shared_array& r);  // never throws
    +

    T is not required be a complete type at point of instantiation.  +See Common Requirements.

    Constructs a shared_array, as if by storing a copy of the pointer stored in r. Afterwards, use_count() for all copies is 1 more than the initial r.use_count().

    shared_array destructor

    ~shared_array();
    +

    T is required be a complete type at point of instantiation.  See Common +Requirements.

    If use_count() == 1, deletes the array pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++ delete[] on a pointer with @@ -126,6 +132,8 @@ a value of 0 is harmless.

    Does not throw exceptions.

    shared_array operator=

    shared_array& operator=( const shared_array& r);  // never throws
    +

    T is required be a complete type at point of instantiation.  See Common +Requirements.

    First, if use_count() == 1, deletes the array pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++ delete[] on a @@ -135,6 +143,8 @@ of the pointer stored in r. Afterwards, use_count()r.use_count()

    shared_array reset

    void reset( T* p=0 );
    +

    T is required be a complete type at point of instantiation.  See Common +Requirements.

    First, if use_count() == 1, deletes the array pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++  delete[] @@ -147,6 +157,8 @@ see ~shared_array).

    an exception is thrown,  delete[] p is called.

    shared_array operator[]

    T& operator[](std::size_t i) const; // never throws

    +

    T is required be a complete type at point of instantiation.  See Common +Requirements.

    Returns a reference to element i of the array pointed to by the stored pointer.

    Behavior is undefined (and almost certainly undesirable) if get()==0, @@ -154,16 +166,24 @@ or if i is less than 0 or is greater or equal to the number of elements in the array.

    shared_array get

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

    T is not required be a complete type at point of instantiation.  +See Common Requirements.

    Returns the stored pointer.

    shared_array use_count

    long use_count() const; // never throws

    +

    T is not required be a complete type at point of instantiation.  +See Common Requirements.

    Returns the number of shared_arrays sharing ownership of the stored pointer.

    shared_array unique

    bool unique() const; // never throws

    +

    T is not required be a complete type at point of instantiation.  +See Common Requirements.

    Returns use_count() == 1.

    shared_array swap

    void swap( shared_array<T>& other ) throw()

    +

    T is not required be a complete type at point of instantiation.  +See Common Requirements.

    Swaps the two smart pointers, as if by std::swap.

    Class shared_array example

    [To be supplied. In the meantime, see smart_ptr_test.cpp.]

    diff --git a/shared_ptr.htm b/shared_ptr.htm index 4dd2b87..78ed702 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -118,6 +118,8 @@ the macro name BOOST_NO_MEMBER_TEMPLATES is defined.

    Provides the type of the stored pointer.

    shared_ptr constructors

    explicit shared_ptr( T* p=0 );
    +

    T is required be a complete type at point of instantiation.  See Common +Requirements.

    Constructs a shared_ptr, storing a copy of p, which must have been allocated via a C++ new expression or be 0. Afterwards, use_count() is 1 (even if p==0; see ~shared_ptr).

    @@ -128,6 +130,8 @@ template<typename Y> shared_ptr(const shared_ptr<Y>& r); // never throws template<typename Y> shared_ptr(std::auto_ptr<Y>& r);
    +

    T is not required be a complete type at point of instantiation.  +See Common Requirements.

    Constructs a shared_ptr, as if by storing a copy of the pointer stored in r. Afterwards, use_count() for all copies is 1 more than the initial r.use_count(), or 1 @@ -138,6 +142,8 @@ is std::bad_alloc.   If an exception is thrown, that constructor has no effect.

    shared_ptr destructor

    ~shared_ptr();
    +

    T is required be a complete type at point of instantiation.  See Common +Requirements.

    If use_count() == 1, deletes the object pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++  delete on a pointer @@ -149,6 +155,8 @@ template<typename Y> shared_ptr& operator=(const shared_ptr<Y>& r); template<typename Y> shared_ptr& operator=(std::auto_ptr<Y>& r); +

    T is required be a complete type at point of instantiation.  See Common +Requirements.

    First, if use_count() == 1, deletes the object pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++  delete on @@ -164,6 +172,8 @@ is std::bad_alloc.   If an exception is thrown, the function has no effect.

    shared_ptr reset

    void reset( T* p=0 );
    +

    T is required be a complete type at point of instantiation.  See Common +Requirements.

    First, if use_count() == 1, deletes the object pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. 

    @@ -176,33 +186,46 @@ on a pointer with a value of 0 is harmless.

    an exception is thrown,  delete p is called.

    shared_ptr operator*

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

    T is required be a complete type at point of instantiation.  See Common +Requirements.

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

    shared_ptr operator-> and get

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

    T is required be a complete type at point of instantiation of +operator->().  See Common +Requirements.

    +

    T is not required be a complete type at point of instantiation of +get().  See Common Requirements.

    Both return the stored pointer.

    shared_ptr use_count

    long use_count() const; // never throws

    +

    T is not required be a complete type at point of instantiation.  +See Common Requirements.

    Returns the number of shared_ptrs sharing ownership of the stored pointer.

    shared_ptr unique

    bool unique() const; // never throws

    +

    T is not required be a complete type at point of instantiation.  +See Common Requirements.

    Returns use_count() == 1.

    shared_ptr swap

    void swap( shared_ptr<T>& other ) throw()

    +

    T is not required be a complete type at point of instantiation.  +See Common Requirements.

    Swaps the two smart pointers, as if by std::swap.

    Class shared_ptr example

    See shared_ptr_example.cpp for a complete example program.

    This program builds a std::vector and std::set of FooPtr's.

    Note that after the two containers have been populated, some of the FooPtr objects will have use_count()==1 rather than use_count()==2, since foo_set is a std::set -rather than a std::multiset.  Furthermore, use_count() may be even higher +rather than a std::multiset, and thus does not contain duplicate entries.  Furthermore, 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.  Without using a smart pointer, memory and exception management would be a nightmare.


    -

    Revised 21 May, 2001 +

    Revised 22 May, 2001

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright diff --git a/smart_ptr.htm b/smart_ptr.htm index dc5db1f..b7bcf04 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -27,11 +27,11 @@ provides four smart pointer template classes:

    scoped_ptr - Simple sole ownership of single objects. + Simple sole ownership of single objects. Noncopyable. scoped_array - Simple sole ownership of arrays. + Simple sole ownership of arrays. Noncopyable. shared_ptr @@ -53,10 +53,25 @@ provided to verify correct operation.

    A page on Smart Pointer Timings will be of interest to those curious about performance issues.

    Common requirements

    -

    These smart pointer classes have a template parameter, T, which +

    These smart pointer classes have a template parameter, T, which specifies the type of the object pointed to by the smart pointer.  The behavior of all four classes is undefined if the destructor or operator delete -for objects of type T throws exceptions.

    +for objects of type T throws exceptions.

    +

    T may be an incomplete type at the point of smart pointer +declaration.  Unless otherwise specified, it is required that T +be a complete type at point of instantiation of all member functions.

    +

    Rationale

    +

    The requirements on T are carefully crafted to ensure safety +yet allow handle-body (aka pimpl) and similar idioms.  In these idioms a +smart pointer may appear in translation units where T is an +incomplete type.  This separates interface from implementation and hides +implementation from translation units which merely use the interface.

    +

    Example

    +

    The scoped_ptr_example_test.cpp +sample program includes a header file, scoped_ptr_example.hpp, +which uses a scoped_ptr<> to an incomplete type.   The +instantiation of member functions which require a complete type occurs in the scoped_ptr_example.cpp +implementation file. 

    Exception safety

    Several functions in these smart pointer classes are specified as having "no effect" or "no effect except such-and-such" if an @@ -78,6 +93,10 @@ never throws.

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

    History and acknowledgements

    +

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

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

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

    @@ -125,7 +144,7 @@ implementation.

    See the Revision History section of the header for further contributors.


    Revised  27 Jul 200022 May 2001

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright From 7c09884eacafeb8c83b4ec2b2a7d98764dd5d86a Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Wed, 23 May 2001 20:14:15 +0000 Subject: [PATCH 021/513] Move MS VC++ pragmas to workaround compiler crash reported by several people with SP4 and SP5. [SVN r10204] --- include/boost/smart_ptr.hpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index 3dea3f9..0ec807b 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -9,7 +9,8 @@ // See http://www.boost.org for most recent version including documentation. // Revision History -// 21 May 01 Require complete type on delete (suggested by Vladimir Prus) +// 21 May 01 Require complete type where incomplete type is unsafe. +// (suggested by Vladimir Prus) // 21 May 01 operator= fails if operand transitively owned by *this, as in a // linked list (report by Ken Johnson, fix by Beman Dawes) // 21 Jan 01 Suppress some useless warnings with MSVC (David Abrahams) @@ -59,6 +60,11 @@ #include // for std::less #include // for BOOST_STATIC_ASSERT +#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash +# pragma warning(push) +# pragma warning(disable:4284) // return type for 'identifier::operator->' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation +#endif + namespace boost { // scoped_ptr --------------------------------------------------------------// @@ -80,13 +86,7 @@ template class scoped_ptr : noncopyable { void reset( T* p=0 ) { if ( ptr != p ) { checked_delete(ptr); ptr = p; } } T& operator*() const { return *ptr; } // never throws #ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable:4284) // return type for 'identifier::operator->' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation -#endif T* operator->() const { return ptr; } // never throws -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif T* get() const { return ptr; } // never throws #ifdef BOOST_SMART_PTR_CONVERSION // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! @@ -216,14 +216,7 @@ template class shared_ptr { } // reset T& operator*() const { return *px; } // never throws -#ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable:4284) // return type for 'identifier::operator->' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation -#endif T* operator->() const { return px; } // never throws -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif T* get() const { return px; } // never throws #ifdef BOOST_SMART_PTR_CONVERSION // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! @@ -397,6 +390,10 @@ template #endif // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + #endif // BOOST_SMART_PTR_HPP From 94287044ba41125fe689417a65a35a1d03859e5a Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 24 May 2001 01:32:07 +0000 Subject: [PATCH 022/513] Oops! Fix boo boo from prior fix [SVN r10206] --- include/boost/smart_ptr.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index 0ec807b..442598b 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -85,7 +85,6 @@ template class scoped_ptr : noncopyable { ~scoped_ptr() { checked_delete(ptr); } void reset( T* p=0 ) { if ( ptr != p ) { checked_delete(ptr); ptr = p; } } T& operator*() const { return *ptr; } // never throws -#ifdef BOOST_MSVC T* operator->() const { return ptr; } // never throws T* get() const { return ptr; } // never throws #ifdef BOOST_SMART_PTR_CONVERSION From c17921c417413ac11041b04f7ed23a5d435ce09a Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 24 May 2001 18:42:25 +0000 Subject: [PATCH 023/513] Documentation and example program improvements [SVN r10220] --- scoped_array.htm | 17 ++-- scoped_ptr.htm | 55 ++++++----- shared_array.htm | 29 ++---- shared_ptr.htm | 49 +++++----- smart_ptr.htm | 22 ++--- smart_ptr_test.cpp | 228 +++++++++++++++++++++++++-------------------- 6 files changed, 214 insertions(+), 186 deletions(-) diff --git a/scoped_array.htm b/scoped_array.htm index f146ee2..518b4cb 100644 --- a/scoped_array.htm +++ b/scoped_array.htm @@ -34,7 +34,7 @@ for that usage.

    pointed to.   T must meet the smart pointer common requirements.

    Class scoped_array Synopsis

    -
    #include <boost/smart_ptr.hpp>
    +
    #include <boost/smart_ptr.hpp>
     namespace boost {
     
     template<typename T> class scoped_array : noncopyable {
    @@ -59,27 +59,21 @@ template<typename T> class scoped_array : Common Requirements.

    scoped_array destructor

    ~scoped_array();
    -

    T is required be a complete type at point of instantiation.  See Common -Requirements.

    Deletes the array pointed to by the stored pointer.  Note that in C++ delete[] on a pointer with a value of 0 is harmless.

    Does not throw exceptions.

    scoped_array reset

    void reset( T* p=0 )();
    -

    T is required be a complete type at point of instantiation.  See Common -Requirements.

    If p is not equal to the stored pointer, deletes the array pointed to by the stored pointer and then stores a copy of p, which must have been allocated via a C++ new[] expression or be 0.

    Does not throw exceptions.

    scoped_array operator[]

    T& operator[](std::size_t i) const; // never throws

    -

    T is required be a complete type at point of instantiation.  See Common -Requirements.

    Returns a reference to element i of the array pointed to by the stored pointer.

    Behavior is undefined (and almost certainly undesirable) if get()==0, @@ -87,13 +81,16 @@ or if i is less than 0 or is greater or equal to the number of elements in the array.

    scoped_array get

    T* get() const;  // never throws
    -

    T is not required be a complete type at point of instantiation.  +

    T is not required be a complete type.  See Common Requirements.

    Returns the stored pointer.

    Class scoped_array example

    [To be supplied. In the meantime, see smart_ptr_test.cpp.]


    -

    Revised  December 8, 1999

    +

    Revised  24 May, 2001 +

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 4945084..652d1bb 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -19,13 +19,16 @@ See example.

    needs.  It supplies a basic "resource acquisition is initialization" facility, without shared-ownership or transfer-of-ownership semantics.  Both its name and enforcement of semantics (by being noncopyable) -signal its intent to retain ownership solely within the current scope.  By -being noncopyable, it is -safer than shared_ptr or std::auto_ptr for pointers which should not be +signal its intent to retain ownership solely within the current scope.  +Because it is noncopyable, it is +safer than shared_ptr or std::auto_ptr for pointers which should not be copied.

    Because scoped_ptr is so simple, in its usual implementation every operation is as fast as for a built-in pointer and it has no more space overhead -that a built-in pointer.

    +that a built-in pointer.  (Because of the "complete type" +requirement for delete and reset members, they may have one additional function +call overhead in certain idioms.  See Handle/Body +Idiom.)   

    Class scoped_ptr cannot be used in C++ Standard Library containers.  See shared_ptr or std::auto_ptr if scoped_ptr does not meet your needs.

    Class scoped_ptr cannot correctly hold a pointer to a @@ -35,7 +38,7 @@ for that usage.

    pointed to.   T must meet the smart pointer common requirements.

    Class scoped_ptr Synopsis

    -
    #include <boost/smart_ptr.hpp>
    +
    #include <boost/smart_ptr.hpp>
     namespace boost {
     
     template<typename T> class scoped_ptr : noncopyable {
    @@ -59,38 +62,28 @@ template<typename T> class scoped_ptr : scoped_ptr constructors
     
    explicit scoped_ptr( T* p=0 );  // never throws
    -

    T is not required be a complete type at point of instantiation.  +

    T is not required be a complete type.  See Common Requirements.

    Constructs a scoped_ptr, storing a copy of p, which must have been allocated via a C++ new expression or be 0.

    scoped_ptr destructor

    ~scoped_ptr();
    -

    T is required be a complete type at point of instantiation.  See Common -Requirements.

    Deletes the object pointed to by the stored pointer.  Note that in C++, delete on a pointer with a value of 0 is harmless.

    Does not throw exceptions.

    scoped_ptr reset

    void reset( T* p=0 );
    -

    T is required be a complete type at point of instantiation.  See Common -Requirements.

    If p is not equal to the stored pointer, deletes the object pointed to by the stored pointer and then stores a copy of p, which must have been allocated via a C++ new expression or be 0.

    Does not throw exceptions.

    scoped_ptr operator*

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

    T is required be a complete type at point of instantiation.  See Common -Requirements.

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

    scoped_ptr operator-> and get

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

    T is required be a complete type at point of instantiation of -operator->().  See Common -Requirements.

    -

    T is not required be a complete type at point of instantiation of -get().  See Common Requirements.

    +

    T is not required by get() be a complete type.  See Common Requirements.

    Both return the stored pointer.

    Class scoped_ptr examples

    #include <iostream>
    @@ -118,17 +111,37 @@ output:

    2 Buckle my shoe
    -

    Handle/Body Idiom

    -

    One common usage of scoped_ptr is to implement a handle/body idiom which avoids exposing the body (implementation) in the header +

    Rationale

    +

    The primary reason to use scoped_ptr rather than auto_ptr is to let readers +of your code know that you intend "resource acquisition is initialization" to be applied only for the current scope, and have no intent to transfer +ownership.

    +

    A secondary reason to use scoped_ptr is to prevent a later maintenance programmer from adding a function that actually transfers +ownership by returning the auto_ptr (because the maintenance programmer saw +auto_ptr, and assumed ownership could safely be transferred.) 

    +

    Think of bool vs int. We all know that under the covers bool is usually +just an int. Indeed, some argued against including bool in the +C++ standard because of that. But by coding bool rather than int, you tell your readers +what your intent is. Same with scoped_ptr - you are signaling intent.

    +

    It has been suggested that boost::scoped_ptr<T> is equivalent to +std::auto_ptr<T> const.  Ed Brey pointed out, however, that +reset() will not work on a std::auto_ptr<T> const.

    +

    Handle/Body Idiom

    +

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

    The scoped_ptr_example_test.cpp sample program includes a header file, scoped_ptr_example.hpp, which uses a scoped_ptr<> to an incomplete type to hide the implementation.   The instantiation of member functions which require a complete type occurs in the scoped_ptr_example.cpp -implementation file. 

    +implementation file.

    +

    FAQ

    +

    Q. Why doesn't scoped_ptr have a release() member?
    +A. Because the whole point of scoped_ptr is to signal intent not +to transfer ownership.  Use std::auto_ptr if ownership transfer is +required.


    -

    Revised 22 May 2001

    +

    Revised 24 May 2001

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" diff --git a/shared_array.htm b/shared_array.htm index 24842d1..6de8704 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -30,13 +30,13 @@ structures. For example, if main() holds a shared_array pointing to array A, which directly or indirectly holds a shared_array pointing back to array A, then array A's use_count() will be 2, and destruction of the main() shared_array will leave array A dangling with a use_count() of 1.

    -

    A heavier duty alternative to a shared_array is a shared_ptr -to a C++ Standard Library vector.

    +

    A C++ Standard Library vector is a +heavier duty alternative to a shared_array.

    The class is a template parameterized on T, the type of the object pointed to.   T must meet the smart pointer Common requirements.

    Class shared_array Synopsis

    -
    #include <boost/smart_ptr.hpp>
    +
    #include <boost/smart_ptr.hpp>
     namespace boost {
     
     template<typename T> class shared_array {
    @@ -108,23 +108,17 @@ name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.

    Provides the type of the stored pointer.

    shared_array constructors

    explicit shared_array( T* p=0 );
    -

    T is required be a complete type at point of instantiation.  See Common -Requirements.

    Constructs a shared_array, storing a copy of p, which must have been allocated via a C++ new[] expression or be 0. Afterwards, use_count() is 1 (even if p==0; see ~shared_array).

    The only exception which may be thrown is std::bad_alloc.  If an exception is thrown,  delete[] p is called.

    shared_array( const shared_array& r);  // never throws
    -

    T is not required be a complete type at point of instantiation.  -See Common Requirements.

    Constructs a shared_array, as if by storing a copy of the pointer stored in r. Afterwards, use_count() for all copies is 1 more than the initial r.use_count().

    shared_array destructor

    ~shared_array();
    -

    T is required be a complete type at point of instantiation.  See Common -Requirements.

    If use_count() == 1, deletes the array pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++ delete[] on a pointer with @@ -132,8 +126,6 @@ a value of 0 is harmless.

    Does not throw exceptions.

    shared_array operator=

    shared_array& operator=( const shared_array& r);  // never throws
    -

    T is required be a complete type at point of instantiation.  See Common -Requirements.

    First, if use_count() == 1, deletes the array pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++ delete[] on a @@ -143,8 +135,6 @@ of the pointer stored in r. Afterwards, use_count()r.use_count()

    shared_array reset

    void reset( T* p=0 );
    -

    T is required be a complete type at point of instantiation.  See Common -Requirements.

    First, if use_count() == 1, deletes the array pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++  delete[] @@ -157,8 +147,6 @@ see ~shared_array).

    an exception is thrown,  delete[] p is called.

    shared_array operator[]

    T& operator[](std::size_t i) const; // never throws

    -

    T is required be a complete type at point of instantiation.  See Common -Requirements.

    Returns a reference to element i of the array pointed to by the stored pointer.

    Behavior is undefined (and almost certainly undesirable) if get()==0, @@ -166,29 +154,30 @@ or if i is less than 0 or is greater or equal to the number of elements in the array.

    shared_array get

    T* get() const;  // never throws
    -

    T is not required be a complete type at point of instantiation.  +

    T is not required be a complete type.  See Common Requirements.

    Returns the stored pointer.

    shared_array use_count

    long use_count() const; // never throws

    -

    T is not required be a complete type at point of instantiation.  +

    T is not required be a complete type.  See Common Requirements.

    Returns the number of shared_arrays sharing ownership of the stored pointer.

    shared_array unique

    bool unique() const; // never throws

    -

    T is not required be a complete type at point of instantiation.  +

    T is not required be a complete type.  See Common Requirements.

    Returns use_count() == 1.

    shared_array swap

    void swap( shared_array<T>& other ) throw()

    -

    T is not required be a complete type at point of instantiation.  +

    T is not required be a complete type.  See Common Requirements.

    Swaps the two smart pointers, as if by std::swap.

    Class shared_array example

    [To be supplied. In the meantime, see smart_ptr_test.cpp.]


    -

    Revised December 8, 1999

    +

    Revised 24 May, 2001 +

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" diff --git a/shared_ptr.htm b/shared_ptr.htm index 78ed702..cdf2b93 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -34,7 +34,7 @@ object A dangling with a use_count() of 1.

    pointed to.   T must meet the smart pointer Common requirements.

    Class shared_ptr Synopsis

    -
    #include <boost/smart_ptr.hpp>
    +
    #include <boost/smart_ptr.hpp>
     namespace boost {
     
     template<typename T> class shared_ptr {
    @@ -118,8 +118,6 @@ the macro name BOOST_NO_MEMBER_TEMPLATES is defined.

    Provides the type of the stored pointer.

    shared_ptr constructors

    explicit shared_ptr( T* p=0 );
    -

    T is required be a complete type at point of instantiation.  See Common -Requirements.

    Constructs a shared_ptr, storing a copy of p, which must have been allocated via a C++ new expression or be 0. Afterwards, use_count() is 1 (even if p==0; see ~shared_ptr).

    @@ -130,8 +128,6 @@ template<typename Y> shared_ptr(const shared_ptr<Y>& r); // never throws template<typename Y> shared_ptr(std::auto_ptr<Y>& r);
    -

    T is not required be a complete type at point of instantiation.  -See Common Requirements.

    Constructs a shared_ptr, as if by storing a copy of the pointer stored in r. Afterwards, use_count() for all copies is 1 more than the initial r.use_count(), or 1 @@ -142,8 +138,6 @@ is std::bad_alloc.   If an exception is thrown, that constructor has no effect.

    shared_ptr destructor

    ~shared_ptr();
    -

    T is required be a complete type at point of instantiation.  See Common -Requirements.

    If use_count() == 1, deletes the object pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++  delete on a pointer @@ -155,8 +149,6 @@ template<typename Y> shared_ptr& operator=(const shared_ptr<Y>& r); template<typename Y> shared_ptr& operator=(std::auto_ptr<Y>& r);

    -

    T is required be a complete type at point of instantiation.  See Common -Requirements.

    First, if use_count() == 1, deletes the object pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++  delete on @@ -172,8 +164,6 @@ is std::bad_alloc.   If an exception is thrown, the function has no effect.

    shared_ptr reset

    void reset( T* p=0 );
    -

    T is required be a complete type at point of instantiation.  See Common -Requirements.

    First, if use_count() == 1, deletes the object pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. 

    @@ -186,32 +176,26 @@ on a pointer with a value of 0 is harmless.

    an exception is thrown,  delete p is called.

    shared_ptr operator*

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

    T is required be a complete type at point of instantiation.  See Common -Requirements.

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

    shared_ptr operator-> and get

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

    T is required be a complete type at point of instantiation of -operator->().  See Common -Requirements.

    -

    T is not required be a complete type at point of instantiation of -get().  See Common Requirements.

    +

    T is not required by get() to be a complete type .  See Common Requirements.

    Both return the stored pointer.

    shared_ptr use_count

    long use_count() const; // never throws

    -

    T is not required be a complete type at point of instantiation.  +

    T is not required be a complete type.  See Common Requirements.

    Returns the number of shared_ptrs sharing ownership of the stored pointer.

    shared_ptr unique

    bool unique() const; // never throws

    -

    T is not required be a complete type at point of instantiation.  +

    T is not required be a complete type.  See Common Requirements.

    Returns use_count() == 1.

    shared_ptr swap

    void swap( shared_ptr<T>& other ) throw()

    -

    T is not required be a complete type at point of instantiation.  +

    T is not required be a complete type.  See Common Requirements.

    Swaps the two smart pointers, as if by std::swap.

    Class shared_ptr example

    @@ -224,8 +208,29 @@ at various times while push_back() and insert() container operations are perform More complicated yet, the container operations may throw exceptions under a variety of circumstances.  Without using a smart pointer, memory and exception management would be a nightmare.

    +

    Handle/Body Idiom

    +

    One common usage of shared_ptr is to implement a handle/body (also +called pimpl) idiom which avoids exposing the body (implementation) in the header +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 type occurs in the shared_ptr_example2.cpp +implementation file.

    +

    FAQ

    +

    Q. Why doesn't shared_ptr have template parameters supplying +traits or policies to allow extensive user customization?
    +A. Parameterization discourages users.  Shared_ptr is +carefully crafted to meet common needs without extensive parameterization. +Someday 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.

    +

    Q. Why don't shared_ptr (and the other Boost smart pointers) +supply an automatic conversion to T*?
    +A. Automatic conversion is believed to be too error prone.


    -

    Revised 22 May, 2001 +

    Revised 24 May, 2001

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright diff --git a/smart_ptr.htm b/smart_ptr.htm index b7bcf04..07538e4 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -56,22 +56,20 @@ interest to those curious about performance issues.

    These smart pointer classes have a template parameter, T, which specifies the type of the object pointed to by the smart pointer.  The behavior of all four classes is undefined if the destructor or operator delete -for objects of type T throws exceptions.

    +for objects of type T throw exceptions.

    T may be an incomplete type at the point of smart pointer declaration.  Unless otherwise specified, it is required that T -be a complete type at point of instantiation of all member functions.

    +be a complete type at points of smart pointer instantiation. Implementations are +required to diagnose (treat as an error) all violations of this requirement, +including deletion of an incomplete type. See checked_delete().

    Rationale

    -

    The requirements on T are carefully crafted to ensure safety -yet allow handle-body (aka pimpl) and similar idioms.  In these idioms a +

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

    -

    Example

    -

    The scoped_ptr_example_test.cpp -sample program includes a header file, scoped_ptr_example.hpp, -which uses a scoped_ptr<> to an incomplete type.   The -instantiation of member functions which require a complete type occurs in the scoped_ptr_example.cpp -implementation file. 

    +implementation from translation units which merely use the interface.  +Examples described in the documentation for specific smart pointers illustrate +use of smart pointers in these idioms.

    Exception safety

    Several functions in these smart pointer classes are specified as having "no effect" or "no effect except such-and-such" if an @@ -144,7 +142,7 @@ implementation.

    See the Revision History section of the header for further contributors.


    Revised  22 May 200124 May 2001

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright diff --git a/smart_ptr_test.cpp b/smart_ptr_test.cpp index cd4d61b..62c97ca 100644 --- a/smart_ptr_test.cpp +++ b/smart_ptr_test.cpp @@ -6,20 +6,26 @@ // implied warranty, and with no claim as to its suitability for any purpose. // Revision History +// 24 May 01 use Boost test library for error detection, reporting, add tests +// for operations on incomplete types (Beman Dawes) // 29 Nov 99 added std::swap and associative container tests (Darin Adler) // 25 Sep 99 added swap tests // 20 Jul 99 header name changed to .hpp // 20 Apr 99 additional error tests added. +#define BOOST_INCLUDE_MAIN +#include #include -#include #include #include #include -#ifdef NDEBUG -#error This test program makes no sense if NDEBUG is defined -#endif +class Incomplete; + +Incomplete * get_ptr( boost::shared_ptr& incomplete ) +{ + return incomplete.get(); +} using namespace std; using boost::scoped_ptr; @@ -28,7 +34,7 @@ using boost::shared_ptr; using boost::shared_array; template -void ck( const T* v1, T v2 ) { assert( *v1 == v2 ); } +void ck( const T* v1, T v2 ) { BOOST_TEST( *v1 == v2 ); } namespace { int UDT_use_count; // independent of pointer maintained counts @@ -48,169 +54,189 @@ class UDT { void value( long v ) { value_ = v;; } }; // UDT +// tests on incomplete types -----------------------------------------------// + +// Certain smart pointer operations are specified to work on incomplete types, +// and some uses depend upon this feature. These tests verify compilation +// only - the functions aren't actually invoked. + +class Incomplete; + +Incomplete * check_incomplete( scoped_ptr& incomplete ) +{ + return incomplete.get(); +} + +Incomplete * check_incomplete( shared_ptr& incomplete, + shared_ptr& i2 ) +{ + incomplete.swap(i2); + cout << incomplete.use_count() << " " << incomplete.unique() << endl; + return incomplete.get(); +} // main --------------------------------------------------------------------// // This isn't a very systematic test; it just hits some of the basics. -int main() { +int test_main( int, char ** ) { - assert( UDT_use_count == 0 ); // reality check + BOOST_TEST( UDT_use_count == 0 ); // reality check // test scoped_ptr with a built-in type long * lp = new long; scoped_ptr sp ( lp ); - assert( sp.get() == lp ); - assert( lp == sp.get() ); - assert( &*sp == lp ); + BOOST_TEST( sp.get() == lp ); + BOOST_TEST( lp == sp.get() ); + BOOST_TEST( &*sp == lp ); *sp = 1234568901L; - assert( *sp == 1234568901L ); - assert( *lp == 1234568901L ); + BOOST_TEST( *sp == 1234568901L ); + BOOST_TEST( *lp == 1234568901L ); ck( static_cast(sp.get()), 1234568901L ); ck( lp, *sp ); sp.reset(); - assert( sp.get() == 0 ); + BOOST_TEST( sp.get() == 0 ); // test scoped_ptr with a user defined type scoped_ptr udt_sp ( new UDT( 999888777 ) ); - assert( udt_sp->value() == 999888777 ); + BOOST_TEST( udt_sp->value() == 999888777 ); udt_sp.reset(); udt_sp.reset( new UDT( 111222333 ) ); - assert( udt_sp->value() == 111222333 ); + BOOST_TEST( udt_sp->value() == 111222333 ); udt_sp.reset( new UDT( 333222111 ) ); - assert( udt_sp->value() == 333222111 ); + BOOST_TEST( udt_sp->value() == 333222111 ); // test scoped_array with a build-in type char * sap = new char [ 100 ]; scoped_array sa ( sap ); - assert( sa.get() == sap ); - assert( sap == sa.get() ); + BOOST_TEST( sa.get() == sap ); + BOOST_TEST( sap == sa.get() ); strcpy( sa.get(), "Hot Dog with mustard and relish" ); - assert( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 ); - assert( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 ); - assert( sa[0] == 'H' ); - assert( sa[30] == 'h' ); + BOOST_TEST( sa[0] == 'H' ); + BOOST_TEST( sa[30] == 'h' ); sa[0] = 'N'; sa[4] = 'd'; - assert( strcmp( sap, "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( sap, "Not dog with mustard and relish" ) == 0 ); sa.reset(); - assert( sa.get() == 0 ); + BOOST_TEST( sa.get() == 0 ); // test shared_ptr with a built-in type int * ip = new int; shared_ptr cp ( ip ); - assert( ip == cp.get() ); - assert( cp.use_count() == 1 ); + BOOST_TEST( ip == cp.get() ); + BOOST_TEST( cp.use_count() == 1 ); *cp = 54321; - assert( *cp == 54321 ); - assert( *ip == 54321 ); + BOOST_TEST( *cp == 54321 ); + BOOST_TEST( *ip == 54321 ); ck( static_cast(cp.get()), 54321 ); ck( static_cast(ip), *cp ); shared_ptr cp2 ( cp ); - assert( ip == cp2.get() ); - assert( cp.use_count() == 2 ); - assert( cp2.use_count() == 2 ); + BOOST_TEST( ip == cp2.get() ); + BOOST_TEST( cp.use_count() == 2 ); + BOOST_TEST( cp2.use_count() == 2 ); - assert( *cp == 54321 ); - assert( *cp2 == 54321 ); + BOOST_TEST( *cp == 54321 ); + BOOST_TEST( *cp2 == 54321 ); ck( static_cast(cp2.get()), 54321 ); ck( static_cast(ip), *cp2 ); shared_ptr cp3 ( cp ); - assert( cp.use_count() == 3 ); - assert( cp2.use_count() == 3 ); - assert( cp3.use_count() == 3 ); + BOOST_TEST( cp.use_count() == 3 ); + BOOST_TEST( cp2.use_count() == 3 ); + BOOST_TEST( cp3.use_count() == 3 ); cp.reset(); - assert( cp2.use_count() == 2 ); - assert( cp3.use_count() == 2 ); - assert( cp.use_count() == 1 ); + BOOST_TEST( cp2.use_count() == 2 ); + BOOST_TEST( cp3.use_count() == 2 ); + BOOST_TEST( cp.use_count() == 1 ); cp.reset( new int ); *cp = 98765; - assert( *cp == 98765 ); + BOOST_TEST( *cp == 98765 ); *cp3 = 87654; - assert( *cp3 == 87654 ); - assert( *cp2 == 87654 ); + BOOST_TEST( *cp3 == 87654 ); + BOOST_TEST( *cp2 == 87654 ); cp.swap( cp3 ); - assert( *cp == 87654 ); - assert( *cp2 == 87654 ); - assert( *cp3 == 98765 ); + BOOST_TEST( *cp == 87654 ); + BOOST_TEST( *cp2 == 87654 ); + BOOST_TEST( *cp3 == 98765 ); cp.swap( cp3 ); - assert( *cp == 98765 ); - assert( *cp2 == 87654 ); - assert( *cp3 == 87654 ); + BOOST_TEST( *cp == 98765 ); + BOOST_TEST( *cp2 == 87654 ); + BOOST_TEST( *cp3 == 87654 ); cp2 = cp2; - assert( cp2.use_count() == 2 ); - assert( *cp2 == 87654 ); + BOOST_TEST( cp2.use_count() == 2 ); + BOOST_TEST( *cp2 == 87654 ); cp = cp2; - assert( cp2.use_count() == 3 ); - assert( *cp2 == 87654 ); - assert( cp.use_count() == 3 ); - assert( *cp == 87654 ); + BOOST_TEST( cp2.use_count() == 3 ); + BOOST_TEST( *cp2 == 87654 ); + BOOST_TEST( cp.use_count() == 3 ); + BOOST_TEST( *cp == 87654 ); shared_ptr cp4; swap( cp2, cp4 ); - assert( cp4.use_count() == 3 ); - assert( *cp4 == 87654 ); - assert( cp2.get() == 0 ); + BOOST_TEST( cp4.use_count() == 3 ); + BOOST_TEST( *cp4 == 87654 ); + BOOST_TEST( cp2.get() == 0 ); #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION set< shared_ptr > scp; scp.insert(cp4); - assert( scp.find(cp4) != scp.end() ); - assert( scp.find(cp4) == scp.find( shared_ptr(cp4) ) ); + BOOST_TEST( scp.find(cp4) != scp.end() ); + BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr(cp4) ) ); #endif // test shared_array with a built-in type char * cap = new char [ 100 ]; shared_array ca ( cap ); - assert( ca.get() == cap ); - assert( cap == ca.get() ); - assert( &ca[0] == cap ); + BOOST_TEST( ca.get() == cap ); + BOOST_TEST( cap == ca.get() ); + BOOST_TEST( &ca[0] == cap ); strcpy( ca.get(), "Hot Dog with mustard and relish" ); - assert( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 ); - assert( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 ); - assert( ca[0] == 'H' ); - assert( ca[30] == 'h' ); + BOOST_TEST( ca[0] == 'H' ); + BOOST_TEST( ca[30] == 'h' ); shared_array ca2 ( ca ); shared_array ca3 ( ca2 ); ca[0] = 'N'; ca[4] = 'd'; - assert( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 ); - assert( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 ); - assert( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 ); - assert( ca.use_count() == 3 ); - assert( ca2.use_count() == 3 ); - assert( ca3.use_count() == 3 ); + BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( ca.use_count() == 3 ); + BOOST_TEST( ca2.use_count() == 3 ); + BOOST_TEST( ca3.use_count() == 3 ); ca2.reset(); - assert( ca.use_count() == 2 ); - assert( ca3.use_count() == 2 ); - assert( ca2.use_count() == 1 ); + BOOST_TEST( ca.use_count() == 2 ); + BOOST_TEST( ca3.use_count() == 2 ); + BOOST_TEST( ca2.use_count() == 1 ); ca.reset(); - assert( ca.get() == 0 ); + BOOST_TEST( ca.get() == 0 ); shared_array ca4; swap( ca3, ca4 ); - assert( ca4.use_count() == 1 ); - assert( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); - assert( ca3.get() == 0 ); + BOOST_TEST( ca4.use_count() == 1 ); + BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( ca3.get() == 0 ); #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION set< shared_array > sca; sca.insert(ca4); - assert( sca.find(ca4) != sca.end() ); - assert( sca.find(ca4) == sca.find( shared_array(ca4) ) ); + BOOST_TEST( sca.find(ca4) != sca.end() ); + BOOST_TEST( sca.find(ca4) == sca.find( shared_array(ca4) ) ); #endif // test shared_array with user defined type @@ -221,38 +247,38 @@ int main() { udta[2].value( 333 ); shared_array udta2 ( udta ); - assert( udta[0].value() == 111 ); - assert( udta[1].value() == 222 ); - assert( udta[2].value() == 333 ); - assert( udta2[0].value() == 111 ); - assert( udta2[1].value() == 222 ); - assert( udta2[2].value() == 333 ); + BOOST_TEST( udta[0].value() == 111 ); + BOOST_TEST( udta[1].value() == 222 ); + BOOST_TEST( udta[2].value() == 333 ); + BOOST_TEST( udta2[0].value() == 111 ); + BOOST_TEST( udta2[1].value() == 222 ); + BOOST_TEST( udta2[2].value() == 333 ); udta2.reset(); - assert( udta2.get() == 0 ); - assert( udta.use_count() == 1 ); - assert( udta2.use_count() == 1 ); + BOOST_TEST( udta2.get() == 0 ); + BOOST_TEST( udta.use_count() == 1 ); + BOOST_TEST( udta2.use_count() == 1 ); - assert( UDT_use_count == 4 ); // reality check + BOOST_TEST( UDT_use_count == 4 ); // reality check // test shared_ptr with a user defined type UDT * up = new UDT; shared_ptr sup ( up ); - assert( up == sup.get() ); - assert( sup.use_count() == 1 ); + BOOST_TEST( up == sup.get() ); + BOOST_TEST( sup.use_count() == 1 ); sup->value( 54321 ) ; - assert( sup->value() == 54321 ); - assert( up->value() == 54321 ); + BOOST_TEST( sup->value() == 54321 ); + BOOST_TEST( up->value() == 54321 ); shared_ptr sup2; sup2 = sup; - assert( sup2->value() == 54321 ); - assert( sup.use_count() == 2 ); - assert( sup2.use_count() == 2 ); + BOOST_TEST( sup2->value() == 54321 ); + BOOST_TEST( sup.use_count() == 2 ); + BOOST_TEST( sup2.use_count() == 2 ); sup2 = sup2; - assert( sup2->value() == 54321 ); - assert( sup.use_count() == 2 ); - assert( sup2.use_count() == 2 ); + BOOST_TEST( sup2->value() == 54321 ); + BOOST_TEST( sup.use_count() == 2 ); + BOOST_TEST( sup2.use_count() == 2 ); cout << "OK" << endl; From c41b060618df4e3e51075b4f9690fd721d31cef6 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 24 May 2001 18:43:24 +0000 Subject: [PATCH 024/513] Initial checkin [SVN r10221] --- shared_ptr_example2.cpp | 21 +++++++++++++++++++++ shared_ptr_example2.hpp | 27 +++++++++++++++++++++++++++ shared_ptr_example2_test.cpp | 15 +++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 shared_ptr_example2.cpp create mode 100644 shared_ptr_example2.hpp create mode 100644 shared_ptr_example2_test.cpp diff --git a/shared_ptr_example2.cpp b/shared_ptr_example2.cpp new file mode 100644 index 0000000..eddc806 --- /dev/null +++ b/shared_ptr_example2.cpp @@ -0,0 +1,21 @@ +// Boost shared_ptr_example2 implementation file -----------------------------// + +#include "shared_ptr_example2.hpp" +#include + +class example::implementation +{ + public: + ~implementation() { std::cout << "destroying implementation\n"; } +}; + +example::example() : _imp( new implementation ) {} +example::example( const example & s ) : _imp( s._imp ) {} + +example & example::operator=( const example & s ) + { _imp = s._imp; return *this; } + +void example::do_something() + { std::cout << "use_count() is " << _imp.use_count() << "\n"; } + +example::~example() {} diff --git a/shared_ptr_example2.hpp b/shared_ptr_example2.hpp new file mode 100644 index 0000000..fea810b --- /dev/null +++ b/shared_ptr_example2.hpp @@ -0,0 +1,27 @@ +// Boost shared_ptr_example2 header file -----------------------------------// + +#include + +// This example demonstrates the handle/body idiom (also called pimpl and +// several other names). It separates the interface (in this header file) +// from the implementation (in shared_ptr_example2.cpp). + +// Note that even though example::implementation is an incomplete type in +// some translation units using this header, shared_ptr< implementation > +// is still valid because the type is complete where it counts - in the +// shared_ptr_example2.cpp translation unit where functions requiring a +// complete type are actually instantiated. + +class example +{ + public: + example(); + ~example(); + example( const example & ); + example & operator=( const example & ); + void do_something(); + private: + class implementation; + boost::shared_ptr< implementation > _imp; // hide implementation details +}; + diff --git a/shared_ptr_example2_test.cpp b/shared_ptr_example2_test.cpp new file mode 100644 index 0000000..1e9886b --- /dev/null +++ b/shared_ptr_example2_test.cpp @@ -0,0 +1,15 @@ +// Boost shared_ptr_example2_test main program ------------------------------// + +#include "shared_ptr_example2.hpp" + +int main() +{ + example a; + a.do_something(); + example b(a); + b.do_something(); + example c; + c = a; + c.do_something(); + return 0; +} \ No newline at end of file From 5fbc553611676fb063334774f134511cec1d1725 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 6 Jul 2001 13:23:07 +0000 Subject: [PATCH 025/513] Reorder shared_ptr code so VC++ 6 member templates work, allowing polymorphic pointers to now work with that compiler (Gary Powell) [SVN r10548] --- include/boost/smart_ptr.hpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index 442598b..d9c0aa5 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -9,6 +9,8 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 6 Jul 01 Reorder shared_ptr code so VC++ 6 member templates work, allowing +// polymorphic pointers to now work with that compiler (Gary Powell) // 21 May 01 Require complete type where incomplete type is unsafe. // (suggested by Vladimir Prus) // 21 May 01 operator= fails if operand transitively owned by *this, as in a @@ -136,16 +138,9 @@ template class shared_ptr { catch (...) { checked_delete(p); throw; } } - shared_ptr(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); } // never throws - ~shared_ptr() { dispose(); } - shared_ptr& operator=(const shared_ptr& r) { - share(r.px,r.pn); - return *this; - } - -#if !defined( BOOST_NO_MEMBER_TEMPLATES ) +#if !defined( BOOST_NO_MEMBER_TEMPLATES ) || defined (BOOST_MSVC6_MEMBER_TEMPLATES) template shared_ptr(const shared_ptr& r) : px(r.px) { // never throws ++*(pn = r.pn); @@ -199,6 +194,15 @@ template class shared_ptr { #endif #endif + // The assignment operator and the copy constructor must come after + // the templated versions for MSVC6 to work. (Gary Powell) + shared_ptr(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); } // never throws + + shared_ptr& operator=(const shared_ptr& r) { + share(r.px,r.pn); + return *this; + } + void reset(T* p=0) { if ( px == p ) return; // fix: self-assignment safe if (--*pn == 0) { checked_delete(px); } @@ -231,7 +235,7 @@ template class shared_ptr { // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) // Don't split this line into two; that causes problems for some GCC 2.95.2 builds -#if defined(BOOST_NO_MEMBER_TEMPLATES) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) +#if ( defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) ) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) private: #endif From 65c3f2dc859669732b03f0e93f7c660876642440 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 12 Jul 2001 19:51:53 +0000 Subject: [PATCH 026/513] Add table of contents, improve the FAQ [SVN r10599] --- shared_ptr.htm | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index cdf2b93..33db24b 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -10,6 +10,14 @@

    c++boost.gif (8819 bytes)Class shared_ptr

    +

    Introduction
    +Synopsis

    +Members
    +Example
    +Handle/Body Idiom
    +Frequently Asked Questions
    +Smart Pointer Timings

    +

    Introduction

    Class shared_ptr stores a pointer to a dynamically allocated object. (Dynamically allocated objects are allocated with the C++ new expression.)   The object pointed to is guaranteed to be deleted when @@ -33,7 +41,7 @@ object A dangling with a use_count() of 1.

    The class is a template parameterized on T, the type of the object pointed to.   T must meet the smart pointer Common requirements.

    -

    Class shared_ptr Synopsis

    +

    Class shared_ptr Synopsis

    #include <boost/smart_ptr.hpp>
     namespace boost {
     
    @@ -112,7 +120,7 @@ than supplying a full range of comparison operators (<, >, <=, >=).<
     name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.

    The current implementation does not supply the member template functions if the macro name BOOST_NO_MEMBER_TEMPLATES is defined.

    -

    Class shared_ptr Members

    +

    Class shared_ptr Members

    shared_ptr element_type

    typedef T element_type;

    Provides the type of the stored pointer.

    @@ -218,19 +226,25 @@ 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.

    -

    FAQ

    +

    Frequently Asked Questions

    Q. Why doesn't shared_ptr have template parameters supplying traits or policies to allow extensive user customization?
    A. Parameterization discourages users.  Shared_ptr is carefully crafted to meet common needs without extensive parameterization. Someday 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.

    +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. Why doesn't shared_ptr use a linked list implementation?
    +A. A linked list implementation does not offer enough advantages to +offset the added cost of an extra pointer.  See timings +page.

    Q. Why don't shared_ptr (and the other Boost smart pointers) supply an automatic conversion to T*?
    A. Automatic conversion is believed to be too error prone.


    -

    Revised 24 May, 2001 +

    Revised 12 July, 2001

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright From aea7d0c9c8ffe5763148bc30ea1ed7ed984505a3 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 13 Jul 2001 14:07:08 +0000 Subject: [PATCH 027/513] Add FAQ why use_count()? [SVN r10604] --- shared_ptr.htm | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 33db24b..3f6c7df 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -227,24 +227,28 @@ implementation.   The instantiation of member functions which require a complete type occurs in the shared_ptr_example2.cpp implementation file.

    Frequently Asked Questions

    -

    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.  Shared_ptr is +A. Parameterization discourages users.  Shared_ptr is carefully crafted to meet common needs without extensive parameterization. Someday 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. Why doesn't shared_ptr use a linked list implementation?
    -A. A linked list implementation does not offer enough advantages to +

    Q. Why doesn't shared_ptr use a linked list implementation?
    +A. A linked list implementation does not offer enough advantages to offset the added cost of an extra pointer.  See timings page.

    -

    Q. Why don't shared_ptr (and the other Boost smart pointers) +

    Q. Why don't shared_ptr (and the other Boost smart pointers) supply an automatic conversion to T*?
    -A. Automatic conversion is believed to be too error prone.

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

    +

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


    -

    Revised 12 July, 2001 +

    Revised 13 July, 2001

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright From c5846378ab2789f82510bbc80ac5a1a8dacddb6e Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 13 Jul 2001 16:32:34 +0000 Subject: [PATCH 028/513] More FAQ entries added. [SVN r10605] --- shared_ptr.htm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/shared_ptr.htm b/shared_ptr.htm index 3f6c7df..c9fe1e6 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -247,6 +247,14 @@ supply an automatic conversion to T*?
    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 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 (your pet feature here)?
    +A. Because (your pet feature here) would mandate a reference counted (or a link-list, or ...) implementation. This is not the intent. +[Provided by Peter Dimov]
    +


    Revised 13 July, 2001

    From a93dfc1837480fab88c646b7d4f5d403ba26188a Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sun, 19 Aug 2001 15:08:33 +0000 Subject: [PATCH 029/513] Fix broken hyperlink [SVN r10896] --- smarttests.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smarttests.htm b/smarttests.htm index f78b618..ad0fbb1 100644 --- a/smarttests.htm +++ b/smarttests.htm @@ -530,7 +530,7 @@ Pointers Timings spreads its information as in the case of linked pointer.
    -

    Revised 27 Jul 2000 +

    Revised 17 Aug 2001

    İ Copyright Gavin Collings 2000. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all From 1a9b1dd123abc92a0ba534f8e457bd94045a3f74 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Mon, 1 Oct 2001 15:54:23 +0000 Subject: [PATCH 030/513] 1.25.0 Final runup [SVN r11315] --- smarttests.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smarttests.htm b/smarttests.htm index ad0fbb1..dcd8fda 100644 --- a/smarttests.htm +++ b/smarttests.htm @@ -530,7 +530,7 @@ Pointers Timings spreads its information as in the case of linked pointer.


    -

    Revised 17 Aug 2001 +

    Revised 19 Aug 2001

    İ Copyright Gavin Collings 2000. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all From 11ec5153783df16d216450fbdc8edd8bd0862d7f Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 11 Jan 2002 16:15:09 +0000 Subject: [PATCH 031/513] Fix broken link [SVN r12285] --- shared_ptr.htm | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index c9fe1e6..2108b43 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -2,21 +2,22 @@ shared_ptr - + -

    c++boost.gif (8819 bytes)Class +

    +c++boost.gif (8819 bytes)Class shared_ptr

    Introduction
    Synopsis

    Members
    Example
    Handle/Body Idiom
    -Frequently Asked Questions
    -Smart Pointer Timings

    +Frequently Asked Questions
    +Smart Pointer Timings

    Introduction

    Class shared_ptr stores a pointer to a dynamically allocated object. (Dynamically allocated objects are allocated with the C++ new @@ -256,7 +257,7 @@ had to meet stringent complexity requirements.

    [Provided by Peter Dimov]


    -

    Revised 13 July, 2001 +

    Revised 11 January, 2002

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright @@ -266,4 +267,4 @@ any purpose.

    - + \ No newline at end of file From 4f964ce6ada8f1585828f1320511acc9892b94fa Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 11 Jan 2002 20:20:07 +0000 Subject: [PATCH 032/513] Add FAQ: why no release() [SVN r12286] --- shared_ptr.htm | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 2108b43..4913f65 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -252,9 +252,23 @@ complex project that turned out to have cyclic-dependencies.

    A. Because complexity 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() +because the other copy will still destroy the object.

    +

    Consider:

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

    [Provided by Peter Dimov]

    Q. Why doesn't shared_ptr provide (your pet feature here)?
    A. Because (your pet feature here) would mandate a reference counted (or a link-list, or ...) implementation. This is not the intent. -[Provided by Peter Dimov]
    +[Provided by Peter Dimov]

    +



    Revised 11 January, 2002 From b104e9ae7843821f98efdbbe1ae0ea903240fb58 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 17 Jan 2002 12:46:45 +0000 Subject: [PATCH 033/513] smart_ptr.hpp less<> fixed, partial specialization enabled on Sun 5.3 [SVN r12334] --- include/boost/smart_ptr.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index d9c0aa5..dbcb787 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -377,7 +377,7 @@ template { bool operator()(const boost::shared_ptr& a, const boost::shared_ptr& b) const - { return less()(a.get(),b.get()); } + { return std::less()(a.get(),b.get()); } }; template @@ -386,7 +386,7 @@ template { bool operator()(const boost::shared_array& a, const boost::shared_array& b) const - { return less()(a.get(),b.get()); } + { return std::less()(a.get(),b.get()); } }; } // namespace std From f255439ece0687eb61b8bcae576faf9b2521912f Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sat, 19 Jan 2002 15:54:28 +0000 Subject: [PATCH 034/513] add eof newline [SVN r12358] --- scoped_ptr_example_test.cpp | 2 +- shared_ptr_example2_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scoped_ptr_example_test.cpp b/scoped_ptr_example_test.cpp index 3629ec8..1b77af2 100644 --- a/scoped_ptr_example_test.cpp +++ b/scoped_ptr_example_test.cpp @@ -7,4 +7,4 @@ int main() example my_example; my_example.do_something(); return 0; -} \ No newline at end of file +} diff --git a/shared_ptr_example2_test.cpp b/shared_ptr_example2_test.cpp index 1e9886b..3a2cf53 100644 --- a/shared_ptr_example2_test.cpp +++ b/shared_ptr_example2_test.cpp @@ -12,4 +12,4 @@ int main() c = a; c.do_something(); return 0; -} \ No newline at end of file +} From 09c14760632986e4068a059411cae9c89cb84f46 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 22 Jan 2002 13:38:52 +0000 Subject: [PATCH 035/513] Smart pointer enhancements, initial commit [SVN r12439] --- include/boost/detail/atomic_count.hpp | 122 +++++++++ include/boost/detail/atomic_count_linux.hpp | 64 +++++ .../boost/detail/atomic_count_pthreads.hpp | 99 +++++++ include/boost/detail/atomic_count_win32.hpp | 68 +++++ include/boost/detail/shared_array_nmt.hpp | 135 ++++++++++ include/boost/detail/shared_count.hpp | 250 ++++++++++++++++++ include/boost/detail/shared_ptr_nmt.hpp | 165 ++++++++++++ include/boost/scoped_array.hpp | 87 ++++++ include/boost/scoped_ptr.hpp | 90 +++++++ include/boost/shared_array.hpp | 136 ++++++++++ include/boost/shared_ptr.hpp | 246 +++++++++++++++++ include/boost/weak_ptr.hpp | 175 ++++++++++++ 12 files changed, 1637 insertions(+) create mode 100644 include/boost/detail/atomic_count.hpp create mode 100644 include/boost/detail/atomic_count_linux.hpp create mode 100644 include/boost/detail/atomic_count_pthreads.hpp create mode 100644 include/boost/detail/atomic_count_win32.hpp create mode 100644 include/boost/detail/shared_array_nmt.hpp create mode 100644 include/boost/detail/shared_count.hpp create mode 100644 include/boost/detail/shared_ptr_nmt.hpp create mode 100644 include/boost/scoped_array.hpp create mode 100644 include/boost/scoped_ptr.hpp create mode 100644 include/boost/shared_array.hpp create mode 100644 include/boost/shared_ptr.hpp create mode 100644 include/boost/weak_ptr.hpp diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp new file mode 100644 index 0000000..0a22e64 --- /dev/null +++ b/include/boost/detail/atomic_count.hpp @@ -0,0 +1,122 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/atomic_count.hpp - thread/SMP safe reference counter +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// typedef boost::detail::atomic_count; +// +// atomic_count a(n); +// +// (n is convertible to long) +// +// Effects: Constructs an atomic_count with an initial value of n +// +// a; +// +// Returns: (long) the current value of a +// +// ++a; +// +// Effects: Atomically increments the value of a +// Returns: nothing +// +// --a; +// +// Effects: Atomically decrements the value of a +// Returns: (long) zero if the new value of a is zero, +// unspecified non-zero value otherwise (usually the new value) +// +// Important note: when --a returns zero, it must act as a +// read memory barrier (RMB); i.e. the calling thread must +// have a synchronized view of the memory +// +// On Intel IA-32 (x86) memory is always synchronized, so this +// is not a problem. +// +// On many architectures the atomic instructions already act as +// a memory barrier. +// +// This property is necessary for proper reference counting, since +// a thread can update the contents of a shared object, then +// release its reference, and another thread may immediately +// release the last reference causing object destruction. +// +// The destructor needs to have a synchronized view of the +// object to perform proper cleanup. +// +// Original example by Alexander Terekhov: +// +// Given: +// +// - a mutable shared object OBJ; +// - two threads THREAD1 and THREAD2 each holding +// a private smart_ptr object pointing to that OBJ. +// +// t1: THREAD1 updates OBJ (thread-safe via some synchronization) +// and a few cycles later (after "unlock") destroys smart_ptr; +// +// t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization +// with respect to shared mutable object OBJ; OBJ destructors +// are called driven by smart_ptr interface... +// + + +#include + +#ifndef BOOST_HAS_THREADS + +namespace boost +{ + +namespace detail +{ + +typedef long atomic_count; + +} + +} + +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) + +#include "atomic_count_win32.hpp" + +#elif defined(linux) || defined(__linux) || defined(__linux__) + +#include "atomic_count_linux.hpp" + +#elif defined(BOOST_HAS_PTHREADS) + +#include "atomic_count_pthreads.hpp" + +#else + +// #warning Unrecognized platform, detail::atomic_count will not be thread safe + +namespace boost +{ + +namespace detail +{ + +typedef long atomic_counter; + +} + +} + +#endif + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_linux.hpp b/include/boost/detail/atomic_count_linux.hpp new file mode 100644 index 0000000..8fd5346 --- /dev/null +++ b/include/boost/detail/atomic_count_linux.hpp @@ -0,0 +1,64 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED + +// +// boost/detail/atomic_count_linux.hpp +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +// +// On Linux, atomic.h is usually located in /usr/include/asm +// + +#include + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count(long v) + { + atomic_t init = ATOMIC_INIT(v); + value_ = init; + } + + void operator++() + { + atomic_inc(&value_); + } + + long operator--() + { + return !atomic_dec_and_test(&value_); + } + + operator long() const + { + return atomic_read(&value_); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + atomic_t value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_pthreads.hpp b/include/boost/detail/atomic_count_pthreads.hpp new file mode 100644 index 0000000..eb1dd97 --- /dev/null +++ b/include/boost/detail/atomic_count_pthreads.hpp @@ -0,0 +1,99 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED + +// +// boost/detail/atomic_count_pthreads.hpp +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include + +// +// The generic pthread_mutex-based implementation sometimes leads to +// inefficiencies. Example: a class with two atomic_count members +// can get away with a single mutex. +// +// Define a macro so that users can detect the situation and optimize. +// + +#define BOOST_ATOMIC_COUNT_USES_PTHREADS + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +private: + + class scoped_lock + { + public: + + scoped_lock(pthread_mutex_t & m): m_(m) + { + pthread_mutex_lock(&m_); + } + + ~scoped_lock() + { + pthread_mutex_unlock(&m_); + } + + private: + + pthread_mutex_t & m_; + }; + +public: + + explicit atomic_count(long v): value_(v) + { + pthread_mutex_init(&mutex_, 0); + } + + ~atomic_count() + { + pthread_mutex_destroy(&mutex_); + } + + void operator++() + { + scoped_lock lock(mutex_); + ++value_; + } + + long operator--() + { + scoped_lock lock(mutex_); + return --value_; + } + + operator long() const + { + scoped_lock lock(mutex_); + return value_; + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + mutable pthread_mutex_t mutex_; + long value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_win32.hpp b/include/boost/detail/atomic_count_win32.hpp new file mode 100644 index 0000000..163a26d --- /dev/null +++ b/include/boost/detail/atomic_count_win32.hpp @@ -0,0 +1,68 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/atomic_count_win32.hpp +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +namespace boost +{ + +namespace detail +{ + +// Avoid #including + +namespace win32 +{ +extern "C" __declspec(dllimport) long __stdcall InterlockedIncrement(long volatile *); +extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement(long volatile *); +} + +class atomic_count +{ +public: + + explicit atomic_count(long v): value_(v) + { + } + + long operator++() + { + return win32::InterlockedIncrement(&value_); + } + + long operator--() + { + return win32::InterlockedDecrement(&value_); + } + + operator long() const + { + return value_; + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + volatile long value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED diff --git a/include/boost/detail/shared_array_nmt.hpp b/include/boost/detail/shared_array_nmt.hpp new file mode 100644 index 0000000..e5137a3 --- /dev/null +++ b/include/boost/detail/shared_array_nmt.hpp @@ -0,0 +1,135 @@ +#ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED +#define BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED + +// +// detail/shared_array_nmt.hpp - shared_array.hpp without member templates +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// + +#include +#include +#include + +#include // for std::ptrdiff_t +#include // for std::swap +#include // for std::less + +namespace boost +{ + +template class shared_array +{ +private: + + typedef detail::atomic_count count_type; + +public: + + typedef T element_type; + + explicit shared_array(T * p = 0): px(p) + { + try // prevent leak if new throws + { + pn = new count_type(1); + } + catch(...) + { + checked_array_delete(p); + throw; + } + } + + ~shared_array() + { + if(--*pn == 0) + { + checked_array_delete(px); + delete pn; + } + } + + shared_array(shared_array const & r) : px(r.px) // never throws + { + pn = r.pn; + ++*pn; + } + + shared_array & operator=(shared_array const & r) + { + shared_array(r).swap(*this); + return *this; + } + + void reset(T * p = 0) + { + shared_array(p).swap(*this); + } + + T * get() const // never throws + { + return px; + } + + T & operator[](std::ptrdiff_t i) const // never throws + { + BOOST_ASSERT(px != 0); + BOOST_ASSERT(i >= 0); + return px[i]; + } + + long use_count() const // never throws + { + return *pn; + } + + bool unique() const // never throws + { + return *pn == 1; + } + + void swap(shared_array & other) // never throws + { + std::swap(px, other.px); + std::swap(pn, other.pn); + } + +private: + + T * px; // contained pointer + count_type * pn; // ptr to reference counter + +}; // shared_array + +template inline bool operator==(shared_array const & a, shared_array const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(shared_array const & a, shared_array const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator<(shared_array const & a, shared_array const & b) +{ + return std::less()(a.get(), b.get()); +} + +template void swap(shared_array & a, shared_array & b) +{ + a.swap(b); +} + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp new file mode 100644 index 0000000..46ceaf5 --- /dev/null +++ b/include/boost/detail/shared_count.hpp @@ -0,0 +1,250 @@ +#ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED +#define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// detail/shared_count.hpp +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include + +namespace boost +{ + +namespace detail +{ + +class counted_base +{ +public: + + typedef atomic_count count_type; + + explicit counted_base(long initial_use_count, long initial_weak_count): + use_count_(initial_use_count), weak_count_(initial_weak_count), self_deleter_(&self_delete) + { + } + + virtual ~counted_base() + { + } + + virtual void dispose() + { + } + + void add_ref() + { + ++use_count_; + ++weak_count_; + } + + void release() + { + if(--use_count_ == 0) + { + dispose(); + } + + if(--weak_count_ == 0) + { + // not a direct 'delete this', because the inlined + // release() may use a different heap manager + self_deleter_(this); + } + } + + void weak_add_ref() + { + ++weak_count_; + } + + void weak_release() + { + if(--weak_count_ == 0) + { + self_deleter_(this); + } + } + + long use_count() const + { + return use_count_; + } + +private: + + counted_base(counted_base const &); + counted_base & operator= (counted_base const &); + + static void self_delete(counted_base * p) + { + delete p; + } + + count_type use_count_; + count_type weak_count_; + + void (*self_deleter_) (counted_base *); +}; + +template class counted_base_impl: public counted_base +{ +private: + + P ptr; // copy constructor must not throw + D del; // copy constructor must not throw + + counted_base_impl(counted_base_impl const &); + counted_base_impl & operator= (counted_base_impl const &); + +public: + + counted_base_impl(P p, D d, long initial_use_count, long initial_weak_count): + counted_base(initial_use_count, initial_weak_count), ptr(p), del(d) + { + } + + virtual void dispose() + { + del(ptr); + } +}; + + +class shared_count +{ +private: + + counted_base * pi_; + + friend class weak_count; + +public: + + template shared_count(P p, D d): pi_(0) + { + try + { + pi_ = new counted_base_impl(p, d, 1, 1); + } + catch(...) + { + d(p); // delete p + throw; + } + } + + ~shared_count() // nothrow + { + pi_->release(); + } + + shared_count(shared_count const & r): pi_(r.pi_) // nothrow + { + pi_->add_ref(); + } + + shared_count & operator= (shared_count const & r) // nothrow + { + counted_base * tmp = r.pi_; + tmp->add_ref(); + pi_->release(); + pi_ = tmp; + + return *this; + } + + void swap(shared_count & r) // nothrow + { + counted_base * tmp = r.pi_; + r.pi_ = pi_; + pi_ = tmp; + } + + long use_count() const // nothrow + { + return pi_->use_count(); + } + + bool unique() const // nothrow + { + return pi_->use_count() == 1; + } +}; + +class weak_count +{ +private: + + counted_base * pi_; + +public: + + weak_count(): pi_(new counted_base(0, 1)) // can throw + { + } + + weak_count(shared_count const & r): pi_(r.pi_) // nothrow + { + pi_->weak_add_ref(); + } + + weak_count(weak_count const & r): pi_(r.pi_) // nothrow + { + pi_->weak_add_ref(); + } + + ~weak_count() // nothrow + { + pi_->weak_release(); + } + + weak_count & operator= (shared_count const & r) // nothrow + { + counted_base * tmp = r.pi_; + tmp->weak_add_ref(); + pi_->weak_release(); + pi_ = tmp; + + return *this; + } + + weak_count & operator= (weak_count const & r) // nothrow + { + counted_base * tmp = r.pi_; + tmp->weak_add_ref(); + pi_->weak_release(); + pi_ = tmp; + + return *this; + } + + void swap(weak_count & r) // nothrow + { + counted_base * tmp = r.pi_; + r.pi_ = pi_; + pi_ = tmp; + } + + long use_count() const // nothrow + { + return pi_->use_count(); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED diff --git a/include/boost/detail/shared_ptr_nmt.hpp b/include/boost/detail/shared_ptr_nmt.hpp new file mode 100644 index 0000000..8b268a2 --- /dev/null +++ b/include/boost/detail/shared_ptr_nmt.hpp @@ -0,0 +1,165 @@ +#ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED +#define BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED + +// +// detail/shared_ptr_nmt.hpp - shared_ptr.hpp without member templates +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// + +#include +#include +#include + +#ifndef BOOST_NO_AUTO_PTR +#include // for std::auto_ptr +#endif + +#include // for std::swap +#include // for std::less + +namespace boost +{ + +template class shared_ptr +{ +private: + + typedef detail::atomic_count count_type; + +public: + + typedef T element_type; + + explicit shared_ptr(T * p = 0): px(p) + { + try // prevent leak if new throws + { + pn = new count_type(1); + } + catch(...) + { + checked_delete(p); + throw; + } + } + + ~shared_ptr() + { + if(--*pn == 0) + { + checked_delete(px); + delete pn; + } + } + + shared_ptr(shared_ptr const & r): px(r.px) // never throws + { + pn = r.pn; + ++*pn; + } + + shared_ptr & operator=(shared_ptr const & r) + { + shared_ptr(r).swap(*this); + return *this; + } + +#ifndef BOOST_NO_AUTO_PTR + + explicit shared_ptr(std::auto_ptr & r) + { + pn = new count_type(1); // may throw + px = r.release(); // fix: moved here to stop leak if new throws + } + + shared_ptr & operator=(std::auto_ptr & r) + { + shared_ptr(r).swap(*this); + return *this; + } + +#endif + + void reset(T * p = 0) + { + shared_ptr(p).swap(*this); + } + + T & operator*() const // never throws + { + BOOST_ASSERT(px != 0); + return *px; + } + + T * operator->() const // never throws + { + BOOST_ASSERT(px != 0); + return px; + } + + T * get() const // never throws + { + return px; + } + + long use_count() const // never throws + { + return *pn; + } + + bool unique() const // never throws + { + return *pn == 1; + } + + void swap(shared_ptr & other) // never throws + { + std::swap(px, other.px); + std::swap(pn, other.pn); + } + +private: + + T * px; // contained pointer + count_type * pn; // ptr to reference counter +}; + +template inline bool operator==(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator<(shared_ptr const & a, shared_ptr const & b) +{ + return std::less()(a.get(), b.get()); +} + +template void swap(shared_ptr & a, shared_ptr & b) +{ + a.swap(b); +} + +// get_pointer() enables boost::mem_fn to recognize shared_ptr + +template inline T * get_pointer(shared_ptr const & p) +{ + return p.get(); +} + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp new file mode 100644 index 0000000..3fcce8d --- /dev/null +++ b/include/boost/scoped_array.hpp @@ -0,0 +1,87 @@ +#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED +#define BOOST_SCOPED_ARRAY_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. + +#include +#include // in case ptrdiff_t not in std +#include // for std::ptrdiff_t + +namespace boost +{ + +// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to +// is guaranteed, either on destruction of the scoped_array or via an explicit +// reset(). Use shared_array or std::vector if your needs are more complex. + +template class scoped_array // noncopyable +{ +private: + + T* ptr; + + scoped_array(scoped_array const &); + scoped_array & operator=(scoped_array const &); + +public: + + typedef T element_type; + + explicit scoped_array( T* p = 0 ): ptr(p) // never throws + { + } + + ~scoped_array() + { + typedef char type_must_be_complete[sizeof(T)]; + delete [] ptr; + } + + void reset( T* p = 0 ) + { + typedef char type_must_be_complete[sizeof(T)]; + + if ( ptr != p ) + { + delete [] ptr; + ptr = p; + } + } + + T& operator[](std::ptrdiff_t i) const // never throws + { + BOOST_ASSERT(ptr != 0); + BOOST_ASSERT(i >= 0); + return ptr[i]; + } + + T* get() const // never throws + { + return ptr; + } + + void swap(scoped_array & rhs) + { + T * tmp = rhs.ptr; + rhs.ptr = ptr; + ptr = tmp; + } + +}; + +template inline void swap(scoped_array & a, scoped_array & b) +{ + a.swap(b); +} + +} // namespace boost + +#endif // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp new file mode 100644 index 0000000..b920a72 --- /dev/null +++ b/include/boost/scoped_ptr.hpp @@ -0,0 +1,90 @@ +#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED +#define BOOST_SCOPED_PTR_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. + +#include + +namespace boost +{ + +// scoped_ptr mimics a built-in pointer except that it guarantees deletion +// of the object pointed to, either on destruction of the scoped_ptr or via +// an explicit reset(). scoped_ptr is a simple solution for simple needs; +// use shared_ptr or std::auto_ptr if your needs are more complex. + +template class scoped_ptr // noncopyable +{ +private: + + T* ptr; + + scoped_ptr(scoped_ptr const &); + scoped_ptr & operator=(scoped_ptr const &); + +public: + + typedef T element_type; + + explicit scoped_ptr( T* p = 0 ): ptr(p) // never throws + { + } + + ~scoped_ptr() + { + typedef char type_must_be_complete[sizeof(T)]; + delete ptr; + } + + void reset( T* p = 0 ) + { + typedef char type_must_be_complete[sizeof(T)]; + + if ( ptr != p ) + { + delete ptr; + ptr = p; + } + } + + T& operator*() const // never throws + { + BOOST_ASSERT(ptr != 0); + return *ptr; + } + + T* operator->() const // never throws + { + BOOST_ASSERT(ptr != 0); + return ptr; + } + + T* get() const // never throws + { + return ptr; + } + + void swap(scoped_ptr & rhs) + { + T * tmp = rhs.ptr; + rhs.ptr = ptr; + ptr = tmp; + } +}; + +template inline void swap(scoped_ptr & a, scoped_ptr & b) +{ + a.swap(b); +} + +} // namespace boost + +#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp new file mode 100644 index 0000000..85741b2 --- /dev/null +++ b/include/boost/shared_array.hpp @@ -0,0 +1,136 @@ +#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED +#define BOOST_SHARED_ARRAY_HPP_INCLUDED + +// +// shared_array.hpp +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// + +#include // for broken compiler workarounds + +#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#include +#else + +#include +#include + +#include + +#include // for std::ptrdiff_t +#include // for std::swap +#include // for std::less + +namespace boost +{ + +// +// shared_array +// +// shared_array extends shared_ptr to arrays. +// The array pointed to is deleted when the last shared_array pointing to it +// is destroyed or reset. +// + +template class shared_array +{ +private: + + // Borland 5.5.1 specific workarounds + typedef checked_array_deleter deleter; + typedef shared_array this_type; + +public: + + typedef T element_type; + + explicit shared_array(T * p = 0): px(p), pn(p, deleter()) + { + } + + // + // Requirements: D's copy constructor must not throw + // + // shared_array will release p by calling d(p) + // + + template shared_array(T * p, D d): px(p), pn(p, d) + { + } + +// generated copy constructor, assignment, destructor are fine + + void reset(T * p = 0) + { + this_type(p).swap(*this); + } + + T & operator[] (std::ptrdiff_t i) const // never throws + { + BOOST_ASSERT(px != 0); + BOOST_ASSERT(i >= 0); + return px[i]; + } + + T * get() const // never throws + { + return px; + } + + long use_count() const // never throws + { + return pn.use_count(); + } + + bool unique() const // never throws + { + return pn.unique(); + } + + void swap(shared_array & other) // never throws + { + std::swap(px, other.px); + pn.swap(other.pn); + } + +private: + + T * px; // contained pointer + detail::shared_count pn; // reference counter + +}; // shared_array + +template inline bool operator==(shared_array const & a, shared_array const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(shared_array const & a, shared_array const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator<(shared_array const & a, shared_array const & b) +{ + return std::less()(a.get(), b.get()); +} + +template void swap(shared_array & a, shared_array & b) +{ + a.swap(b); +} + +} // namespace boost + +#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC_MEMBER_TEMPLATES) + +#endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp new file mode 100644 index 0000000..996a1b5 --- /dev/null +++ b/include/boost/shared_ptr.hpp @@ -0,0 +1,246 @@ +#ifndef BOOST_SHARED_PTR_HPP_INCLUDED +#define BOOST_SHARED_PTR_HPP_INCLUDED + +// +// shared_ptr.hpp +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// + +#include // for broken compiler workarounds + +#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#include +#else + +#include +#include + +#include + +#include // for std::auto_ptr +#include // for std::swap +#include // for std::less + +#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash +# pragma warning(push) +# pragma warning(disable:4284) // odd return type for operator-> +#endif + +namespace boost +{ + +namespace detail +{ + +struct static_cast_tag {}; +struct dynamic_cast_tag {}; + +template struct shared_ptr_traits +{ + typedef T & reference; +}; + +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + +} // namespace detail + + +// +// shared_ptr +// +// An enhanced relative of scoped_ptr with reference counted copy semantics. +// The object pointed to is deleted when the last shared_ptr pointing to it +// is destroyed or reset. +// + +template class weak_ptr; + +template class shared_ptr +{ +private: + + // Borland 5.5.1 specific workarounds + typedef checked_deleter deleter; + typedef shared_ptr this_type; + +public: + + typedef T element_type; + + explicit shared_ptr(T * p = 0): px(p), pn(p, deleter()) + { + } + + // + // Requirements: D's copy constructor must not throw + // + // shared_ptr will release p by calling d(p) + // + + template shared_ptr(T * p, D d): px(p), pn(p, d) + { + } + +// generated copy constructor, assignment, destructor are fine + + template + shared_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws + { + } + + template + shared_ptr(shared_ptr const & r, detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) + { + } + + template + shared_ptr(shared_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) + { + if(px == 0) // need to allocate new counter -- the cast failed + { + pn = detail::shared_count(static_cast(0), deleter()); + } + } + +#ifndef BOOST_NO_AUTO_PTR + + template + explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn(r.release(), checked_deleter()) + { + } + +#endif + + template + shared_ptr & operator=(shared_ptr const & r) // nothrow? + { + px = r.px; + pn = r.pn; // shared_count::op= doesn't throw + return *this; + } + +#ifndef BOOST_NO_AUTO_PTR + + template + shared_ptr & operator=(std::auto_ptr & r) + { + this_type(r).swap(*this); + return *this; + } + +#endif + + void reset(T * p = 0) + { + this_type(p).swap(*this); + } + + typename detail::shared_ptr_traits::reference operator* () const // never throws + { + BOOST_ASSERT(px != 0); + return *px; + } + + T * operator-> () const // never throws + { + BOOST_ASSERT(px != 0); + return px; + } + + T * get() const // never throws + { + return px; + } + + long use_count() const // never throws + { + return pn.use_count(); + } + + bool unique() const // never throws + { + return pn.unique(); + } + + void swap(shared_ptr & other) // never throws + { + std::swap(px, other.px); + pn.swap(other.pn); + } + +// Tasteless as this may seem, making all members public allows member templates +// to work in the absence of member template friends. (Matthew Langston) + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + +private: + + template friend class shared_ptr; + template friend class weak_ptr; + + +#endif + + T * px; // contained pointer + detail::shared_count pn; // reference counter + +}; // shared_ptr + +template inline bool operator==(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator<(shared_ptr const & a, shared_ptr const & b) +{ + return std::less()(a.get(), b.get()); +} + +template shared_ptr shared_static_cast(shared_ptr const & r) +{ + return shared_ptr(r, detail::static_cast_tag()); +} + +template shared_ptr shared_dynamic_cast(shared_ptr const & r) +{ + return shared_ptr(r, detail::dynamic_cast_tag()); +} + +template void swap(shared_ptr & a, shared_ptr & b) +{ + a.swap(b); +} + +// get_pointer() enables boost::mem_fn to recognize shared_ptr + +template inline T * get_pointer(shared_ptr const & p) +{ + return p.get(); +} + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC_MEMBER_TEMPLATES) + +#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp new file mode 100644 index 0000000..87231c3 --- /dev/null +++ b/include/boost/weak_ptr.hpp @@ -0,0 +1,175 @@ +#ifndef BOOST_WEAK_PTR_HPP_INCLUDED +#define BOOST_WEAK_PTR_HPP_INCLUDED + +// +// weak_ptr.hpp +// +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// + +#include + +#include // for broken compiler workarounds +#include + +#include + +#include // for std::swap +#include // for std::less + +#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash +# pragma warning(push) +# pragma warning(disable:4284) // odd return type for operator-> +#endif + +namespace boost +{ + +template class weak_ptr +{ +private: + + // Borland 5.5.1 specific workarounds + typedef weak_ptr this_type; + +public: + + typedef T element_type; + + weak_ptr(): px(0), pn() + { + } + +// generated copy constructor, assignment, destructor are fine + + template + weak_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws + { + } + + template + weak_ptr(weak_ptr const & r, detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) + { + } + + template + weak_ptr(weak_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) + { + if(px == 0) // need to allocate new counter -- the cast failed + { + pn = detail::weak_count(); + } + } + + template + weak_ptr & operator=(weak_ptr const & r) // nothrow? + { + px = r.px; + pn = r.pn; + return *this; + } + + void reset() + { + this_type().swap(*this); + } + + long use_count() const // never throws + { + return pn.use_count(); + } + + T * get() const // never throws + { + return use_count() == 0? 0: px; + } + + typename detail::shared_ptr_traits::reference operator* () const // never throws + { + T * p = get(); + + BOOST_ASSERT(p != 0); + return *p; + } + + T * operator-> () const // never throws + { + T * p = get(); + + BOOST_ASSERT(p != 0); + return p; + } + + void swap(weak_ptr & other) // never throws + { + std::swap(px, other.px); + pn.swap(other.pn); + } + +// Tasteless as this may seem, making all members public allows member templates +// to work in the absence of member template friends. (Matthew Langston) + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + +private: + + template friend class weak_ptr; + +#endif + + T * px; // contained pointer + detail::weak_count pn; // reference counter + +}; // weak_ptr + +template inline bool operator==(weak_ptr const & a, weak_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(weak_ptr const & a, weak_ptr const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator<(weak_ptr const & a, weak_ptr const & b) +{ + return std::less()(a.get(), b.get()); +} + +template weak_ptr shared_static_cast(weak_ptr const & r) +{ + return weak_ptr(r, detail::static_cast_tag()); +} + +template weak_ptr shared_dynamic_cast(weak_ptr const & r) +{ + return weak_ptr(r, detail::dynamic_cast_tag()); +} + +template void swap(weak_ptr & a, weak_ptr & b) +{ + a.swap(b); +} + +// get_pointer() enables boost::mem_fn to recognize weak_ptr + +template inline T * get_pointer(weak_ptr const & p) +{ + return p.get(); +} + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_WEAK_PTR_HPP_INCLUDED From 5d564a2f01f0caf9e11261b988dbef1abaf91392 Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Thu, 24 Jan 2002 19:16:12 +0000 Subject: [PATCH 036/513] Add a self-assignment assert to reset(). Also add an overload of reset to allow resetting to a new pointer with a new deletion function. [SVN r12491] --- include/boost/detail/shared_array_nmt.hpp | 1 + include/boost/detail/shared_ptr_nmt.hpp | 1 + include/boost/shared_array.hpp | 1 + include/boost/shared_ptr.hpp | 8 +++++++- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/boost/detail/shared_array_nmt.hpp b/include/boost/detail/shared_array_nmt.hpp index e5137a3..570af13 100644 --- a/include/boost/detail/shared_array_nmt.hpp +++ b/include/boost/detail/shared_array_nmt.hpp @@ -72,6 +72,7 @@ public: void reset(T * p = 0) { + BOOST_ASSERT(p == 0 || p != px); shared_array(p).swap(*this); } diff --git a/include/boost/detail/shared_ptr_nmt.hpp b/include/boost/detail/shared_ptr_nmt.hpp index 8b268a2..5364e77 100644 --- a/include/boost/detail/shared_ptr_nmt.hpp +++ b/include/boost/detail/shared_ptr_nmt.hpp @@ -91,6 +91,7 @@ public: void reset(T * p = 0) { + BOOST_ASSERT(p == 0 || p != px); shared_ptr(p).swap(*this); } diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index 85741b2..5098dee 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -71,6 +71,7 @@ public: void reset(T * p = 0) { + BOOST_ASSERT(p == 0 || p != px); this_type(p).swap(*this); } diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 996a1b5..db75b9e 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -33,7 +33,7 @@ #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash # pragma warning(push) # pragma warning(disable:4284) // odd return type for operator-> -#endif +#endif namespace boost { @@ -144,9 +144,15 @@ public: void reset(T * p = 0) { + BOOST_ASSERT(p == 0 || p != px); this_type(p).swap(*this); } + template void reset(T * p, D d) + { + this_type(p, d).swap(*this); + } + typename detail::shared_ptr_traits::reference operator* () const // never throws { BOOST_ASSERT(px != 0); From 58c5711b47153d50a914c5e86090517b9c35e83f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 25 Jan 2002 13:54:30 +0000 Subject: [PATCH 037/513] Added tests for the new smart pointers. [SVN r12500] --- shared_ptr_test.cpp | 157 +++++++++++++++++++++++ smart_ptr_test2.cpp | 295 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 452 insertions(+) create mode 100644 shared_ptr_test.cpp create mode 100644 smart_ptr_test2.cpp diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp new file mode 100644 index 0000000..3dd5e98 --- /dev/null +++ b/shared_ptr_test.cpp @@ -0,0 +1,157 @@ +#if defined(_MSC_VER) && !defined(__ICL) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// shared_ptr_test.cpp - a test for shared_ptr.hpp and weak_ptr.hpp +// +// Copyright (c) 2001 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#define BOOST_INCLUDE_MAIN +#include + +#include +#include + +bool boost_error(char const *, char const *, char const *, long) +{ + return true; +} + +namespace +{ + int cnt = 0; +} + +struct X +{ + X() + { + ++cnt; + std::cout << "X(" << this << ")::X()\n"; + } + + virtual ~X() + { + --cnt; + std::cout << "X(" << this << ")::~X()\n"; + } + +private: + + X(X const &); + X & operator= (X const &); +}; + +struct Y: public X +{ + Y() + { + ++cnt; + std::cout << "Y(" << this << ")::Y()\n"; + } + + ~Y() + { + --cnt; + std::cout << "Y(" << this << ")::~Y()\n"; + } + +private: + + Y(Y const &); + Y & operator= (Y const &); +}; + +int * get_object() +{ + ++cnt; + std::cout << "get_object()\n"; + return &cnt; +} + +void release_object(int * p) +{ + BOOST_TEST(p == &cnt); + --cnt; + std::cout << "release_object()\n"; +} + +int test_main(int, char * []) +{ + using namespace boost; + + { + shared_ptr p(new Y); + shared_ptr p2(new X); + + shared_ptr p3 = shared_dynamic_cast(p); + shared_ptr p4 = shared_dynamic_cast(p2); + + BOOST_TEST(p.use_count() == 2); + BOOST_TEST(p2.use_count() == 1); + BOOST_TEST(p3.use_count() == 2); + BOOST_TEST(p4.use_count() == 1); + + shared_ptr p5(p); + + std::cout << "--\n"; + + p.reset(); + p2.reset(); + p3.reset(); + p4.reset(); + + std::cout << "--\n"; + + BOOST_TEST(p5.use_count() == 1); + + weak_ptr wp1; + + BOOST_TEST(wp1.use_count() == 0); + BOOST_TEST(wp1.get() == 0); + + weak_ptr wp2 = shared_static_cast(p5); + + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(wp2.get() != 0); + + weak_ptr wp3 = shared_dynamic_cast(wp2); + + BOOST_TEST(wp3.use_count() == 1); + BOOST_TEST(wp3.get() != 0); + BOOST_TEST(wp2 == wp3); + + wp1 = wp2; + + BOOST_TEST(wp1.use_count() == 1); + BOOST_TEST(wp1.get() != 0); + BOOST_TEST(wp1 == wp2); + + p5.reset(); + + BOOST_TEST(wp1.use_count() == 0); + BOOST_TEST(wp1.get() == 0); + + BOOST_TEST(wp2.use_count() == 0); + BOOST_TEST(wp2.get() == 0); + + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(wp3.get() == 0); + + shared_ptr p6(get_object(), release_object); + } + + BOOST_TEST(cnt == 0); + + return 0; +} diff --git a/smart_ptr_test2.cpp b/smart_ptr_test2.cpp new file mode 100644 index 0000000..4ea305e --- /dev/null +++ b/smart_ptr_test2.cpp @@ -0,0 +1,295 @@ +// smart pointer test program ----------------------------------------------// + +// (C) Copyright Beman Dawes 1998, 1999. Permission to copy, use, modify, sell +// and distribute this software is granted provided this copyright notice +// appears in all copies. This software is provided "as is" without express or +// implied warranty, and with no claim as to its suitability for any purpose. + +// Revision History +// 24 May 01 use Boost test library for error detection, reporting, add tests +// for operations on incomplete types (Beman Dawes) +// 29 Nov 99 added std::swap and associative container tests (Darin Adler) +// 25 Sep 99 added swap tests +// 20 Jul 99 header name changed to .hpp +// 20 Apr 99 additional error tests added. + +#include +#include +#include +#include + +#define BOOST_INCLUDE_MAIN +#include + +#include +#include +#include + +bool boost_error(char const *, char const *, char const *, long) +{ + return true; // fail with assert() +} + +class Incomplete; + +Incomplete * get_ptr( boost::shared_ptr& incomplete ) +{ + return incomplete.get(); +} + +using namespace std; +using boost::scoped_ptr; +using boost::scoped_array; +using boost::shared_ptr; +using boost::shared_array; + +template +void ck( const T* v1, T v2 ) { BOOST_TEST( *v1 == v2 ); } + +namespace { + int UDT_use_count; // independent of pointer maintained counts + } + +// user defined type -------------------------------------------------------// + +class UDT { + long value_; + public: + explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; } + ~UDT() { + --UDT_use_count; + cout << "UDT with value " << value_ << " being destroyed" << endl; + } + long value() const { return value_; } + void value( long v ) { value_ = v;; } + }; // UDT + +// tests on incomplete types -----------------------------------------------// + +// Certain smart pointer operations are specified to work on incomplete types, +// and some uses depend upon this feature. These tests verify compilation +// only - the functions aren't actually invoked. + +class Incomplete; + +Incomplete * check_incomplete( scoped_ptr& incomplete ) +{ + return incomplete.get(); +} + +Incomplete * check_incomplete( shared_ptr& incomplete, + shared_ptr& i2 ) +{ + incomplete.swap(i2); + cout << incomplete.use_count() << " " << incomplete.unique() << endl; + return incomplete.get(); +} +// main --------------------------------------------------------------------// + +// This isn't a very systematic test; it just hits some of the basics. + +int test_main( int, char ** ) { + + BOOST_TEST( UDT_use_count == 0 ); // reality check + + // test scoped_ptr with a built-in type + long * lp = new long; + scoped_ptr sp ( lp ); + BOOST_TEST( sp.get() == lp ); + BOOST_TEST( lp == sp.get() ); + BOOST_TEST( &*sp == lp ); + + *sp = 1234568901L; + BOOST_TEST( *sp == 1234568901L ); + BOOST_TEST( *lp == 1234568901L ); + ck( static_cast(sp.get()), 1234568901L ); + ck( lp, *sp ); + + sp.reset(); + BOOST_TEST( sp.get() == 0 ); + + // test scoped_ptr with a user defined type + scoped_ptr udt_sp ( new UDT( 999888777 ) ); + BOOST_TEST( udt_sp->value() == 999888777 ); + udt_sp.reset(); + udt_sp.reset( new UDT( 111222333 ) ); + BOOST_TEST( udt_sp->value() == 111222333 ); + udt_sp.reset( new UDT( 333222111 ) ); + BOOST_TEST( udt_sp->value() == 333222111 ); + + // test scoped_array with a build-in type + char * sap = new char [ 100 ]; + scoped_array sa ( sap ); + BOOST_TEST( sa.get() == sap ); + BOOST_TEST( sap == sa.get() ); + + strcpy( sa.get(), "Hot Dog with mustard and relish" ); + BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 ); + + BOOST_TEST( sa[0] == 'H' ); + BOOST_TEST( sa[30] == 'h' ); + + sa[0] = 'N'; + sa[4] = 'd'; + BOOST_TEST( strcmp( sap, "Not dog with mustard and relish" ) == 0 ); + + sa.reset(); + BOOST_TEST( sa.get() == 0 ); + + // test shared_ptr with a built-in type + int * ip = new int; + shared_ptr cp ( ip ); + BOOST_TEST( ip == cp.get() ); + BOOST_TEST( cp.use_count() == 1 ); + + *cp = 54321; + BOOST_TEST( *cp == 54321 ); + BOOST_TEST( *ip == 54321 ); + ck( static_cast(cp.get()), 54321 ); + ck( static_cast(ip), *cp ); + + shared_ptr cp2 ( cp ); + BOOST_TEST( ip == cp2.get() ); + BOOST_TEST( cp.use_count() == 2 ); + BOOST_TEST( cp2.use_count() == 2 ); + + BOOST_TEST( *cp == 54321 ); + BOOST_TEST( *cp2 == 54321 ); + ck( static_cast(cp2.get()), 54321 ); + ck( static_cast(ip), *cp2 ); + + shared_ptr cp3 ( cp ); + BOOST_TEST( cp.use_count() == 3 ); + BOOST_TEST( cp2.use_count() == 3 ); + BOOST_TEST( cp3.use_count() == 3 ); + cp.reset(); + BOOST_TEST( cp2.use_count() == 2 ); + BOOST_TEST( cp3.use_count() == 2 ); + BOOST_TEST( cp.use_count() == 1 ); + cp.reset( new int ); + *cp = 98765; + BOOST_TEST( *cp == 98765 ); + *cp3 = 87654; + BOOST_TEST( *cp3 == 87654 ); + BOOST_TEST( *cp2 == 87654 ); + cp.swap( cp3 ); + BOOST_TEST( *cp == 87654 ); + BOOST_TEST( *cp2 == 87654 ); + BOOST_TEST( *cp3 == 98765 ); + cp.swap( cp3 ); + BOOST_TEST( *cp == 98765 ); + BOOST_TEST( *cp2 == 87654 ); + BOOST_TEST( *cp3 == 87654 ); + cp2 = cp2; + BOOST_TEST( cp2.use_count() == 2 ); + BOOST_TEST( *cp2 == 87654 ); + cp = cp2; + BOOST_TEST( cp2.use_count() == 3 ); + BOOST_TEST( *cp2 == 87654 ); + BOOST_TEST( cp.use_count() == 3 ); + BOOST_TEST( *cp == 87654 ); + + shared_ptr cp4; + swap( cp2, cp4 ); + BOOST_TEST( cp4.use_count() == 3 ); + BOOST_TEST( *cp4 == 87654 ); + BOOST_TEST( cp2.get() == 0 ); + + set< shared_ptr > scp; + scp.insert(cp4); + BOOST_TEST( scp.find(cp4) != scp.end() ); + BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr(cp4) ) ); + + // test shared_array with a built-in type + char * cap = new char [ 100 ]; + shared_array ca ( cap ); + BOOST_TEST( ca.get() == cap ); + BOOST_TEST( cap == ca.get() ); + BOOST_TEST( &ca[0] == cap ); + + strcpy( ca.get(), "Hot Dog with mustard and relish" ); + BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 ); + + BOOST_TEST( ca[0] == 'H' ); + BOOST_TEST( ca[30] == 'h' ); + + shared_array ca2 ( ca ); + shared_array ca3 ( ca2 ); + + ca[0] = 'N'; + ca[4] = 'd'; + BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( ca.use_count() == 3 ); + BOOST_TEST( ca2.use_count() == 3 ); + BOOST_TEST( ca3.use_count() == 3 ); + ca2.reset(); + BOOST_TEST( ca.use_count() == 2 ); + BOOST_TEST( ca3.use_count() == 2 ); + BOOST_TEST( ca2.use_count() == 1 ); + + ca.reset(); + BOOST_TEST( ca.get() == 0 ); + + shared_array ca4; + swap( ca3, ca4 ); + BOOST_TEST( ca4.use_count() == 1 ); + BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( ca3.get() == 0 ); + + set< shared_array > sca; + sca.insert(ca4); + BOOST_TEST( sca.find(ca4) != sca.end() ); + BOOST_TEST( sca.find(ca4) == sca.find( shared_array(ca4) ) ); + + // test shared_array with user defined type + shared_array udta ( new UDT[3] ); + + udta[0].value( 111 ); + udta[1].value( 222 ); + udta[2].value( 333 ); + shared_array udta2 ( udta ); + + BOOST_TEST( udta[0].value() == 111 ); + BOOST_TEST( udta[1].value() == 222 ); + BOOST_TEST( udta[2].value() == 333 ); + BOOST_TEST( udta2[0].value() == 111 ); + BOOST_TEST( udta2[1].value() == 222 ); + BOOST_TEST( udta2[2].value() == 333 ); + udta2.reset(); + BOOST_TEST( udta2.get() == 0 ); + BOOST_TEST( udta.use_count() == 1 ); + BOOST_TEST( udta2.use_count() == 1 ); + + BOOST_TEST( UDT_use_count == 4 ); // reality check + + // test shared_ptr with a user defined type + UDT * up = new UDT; + shared_ptr sup ( up ); + BOOST_TEST( up == sup.get() ); + BOOST_TEST( sup.use_count() == 1 ); + + sup->value( 54321 ) ; + BOOST_TEST( sup->value() == 54321 ); + BOOST_TEST( up->value() == 54321 ); + + shared_ptr sup2; + sup2 = sup; + BOOST_TEST( sup2->value() == 54321 ); + BOOST_TEST( sup.use_count() == 2 ); + BOOST_TEST( sup2.use_count() == 2 ); + sup2 = sup2; + BOOST_TEST( sup2->value() == 54321 ); + BOOST_TEST( sup.use_count() == 2 ); + BOOST_TEST( sup2.use_count() == 2 ); + + cout << "OK" << endl; + + new char[12345]; // deliberate memory leak to verify leaks detected + + return 0; + } // main + From a8efe20862a99d8c59953dcd49ca87bc574aae4c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 25 Jan 2002 16:10:26 +0000 Subject: [PATCH 038/513] Comments added. [SVN r12510] --- include/boost/detail/shared_count.hpp | 31 ++++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 46ceaf5..cf8f8ee 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -30,26 +30,37 @@ public: typedef atomic_count count_type; + // pre: initial_use_count <= initial_weak_count + explicit counted_base(long initial_use_count, long initial_weak_count): use_count_(initial_use_count), weak_count_(initial_weak_count), self_deleter_(&self_delete) { } - virtual ~counted_base() + virtual ~counted_base() // nothrow { } - virtual void dispose() + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + // + // counted_base doesn't manage any resources except itself, and + // the default implementation is a no-op. + // + // dispose() is not pure virtual since weak_ptr instantiates a + // counted_base in its default constructor. + + virtual void dispose() // nothrow { } - void add_ref() + void add_ref() // nothrow { ++use_count_; ++weak_count_; } - void release() + void release() // nothrow { if(--use_count_ == 0) { @@ -64,12 +75,12 @@ public: } } - void weak_add_ref() + void weak_add_ref() // nothrow { ++weak_count_; } - void weak_release() + void weak_release() // nothrow { if(--weak_count_ == 0) { @@ -77,7 +88,7 @@ public: } } - long use_count() const + long use_count() const // nothrow { return use_count_; } @@ -92,6 +103,8 @@ private: delete p; } + // inv: use_count_ <= weak_count_ + count_type use_count_; count_type weak_count_; @@ -110,12 +123,14 @@ private: public: + // pre: initial_use_count <= initial_weak_count, d(p) must not throw + counted_base_impl(P p, D d, long initial_use_count, long initial_weak_count): counted_base(initial_use_count, initial_weak_count), ptr(p), del(d) { } - virtual void dispose() + virtual void dispose() // nothrow { del(ptr); } From 4fdc84f29eeb7b19e1cb731d55f6ab29cb458350 Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Thu, 31 Jan 2002 06:52:58 +0000 Subject: [PATCH 039/513] Make the non-threads version work. [SVN r12597] --- include/boost/detail/atomic_count.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 0a22e64..0f33ac4 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -111,7 +111,7 @@ namespace boost namespace detail { -typedef long atomic_counter; +typedef long atomic_count; } From 39c10f739d8a809a1d86b3e0bc8174fd00040b0d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 1 Feb 2002 18:40:35 +0000 Subject: [PATCH 040/513] added an auto_ptr & constructor to shared_count [SVN r12623] --- include/boost/detail/shared_count.hpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index cf8f8ee..8756294 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -16,6 +16,13 @@ // warranty, and with no claim as to its suitability for any purpose. // +#include + +#ifndef BOOST_NO_AUTO_PTR +# include +#endif + +#include #include namespace boost @@ -160,6 +167,18 @@ public: } } +#ifndef BOOST_NO_AUTO_PTR + + // auto_ptr is special cased to provide the strong guarantee + + template + explicit shared_count(std::auto_ptr & r): pi_(new counted_base_impl< Y *, checked_deleter >(r.get(), checked_deleter(), 1, 1)) + { + r.release(); + } + +#endif + ~shared_count() // nothrow { pi_->release(); From 8b5b780c2c4f6251370d3cac8cc721ae5b8b18d5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 1 Feb 2002 19:34:31 +0000 Subject: [PATCH 041/513] better weak_ptr coverage [SVN r12624] --- shared_ptr_test.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 3dd5e98..7387cc8 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -131,6 +131,11 @@ int test_main(int, char * []) BOOST_TEST(wp3.get() != 0); BOOST_TEST(wp2 == wp3); + weak_ptr wp4(wp3); + + wp1 = p2; + wp1 = p4; + wp1 = wp3; wp1 = wp2; BOOST_TEST(wp1.use_count() == 1); From b224270cc0d70243af4455b62867c781c6d3e72f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 2 Feb 2002 16:18:04 +0000 Subject: [PATCH 042/513] auto_ptr& constructor now has no effects when exception is thrown [SVN r12643] --- include/boost/shared_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index db75b9e..eb4d662 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -117,7 +117,7 @@ public: #ifndef BOOST_NO_AUTO_PTR template - explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn(r.release(), checked_deleter()) + explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn(r) { } From d3c76575f945d225d690d1134005a4594aa7dccd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 2 Feb 2002 16:19:45 +0000 Subject: [PATCH 043/513] templated copy constructor added. [SVN r12644] --- include/boost/weak_ptr.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 87231c3..d73c5f3 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -49,6 +49,11 @@ public: // generated copy constructor, assignment, destructor are fine + template + weak_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // never throws + { + } + template weak_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws { From 1a7cd887e4ee658f763d88590a2a05b9ad76ac7b Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Sat, 2 Feb 2002 18:36:12 +0000 Subject: [PATCH 044/513] New smart pointer documentation. Related clean-up of the smart pointer library. Changing includes to include the new individual smart pointer headers. Replacing old smart pointer library with an include of the new smart pointer headers. Simplify ifdefs that involve the member templates macros now that BOOST_MSVC6_MEMBER_TEMPLATES is also guaranteed to bet set for platforms that have full member templates. [SVN r12647] --- compatibility.htm | 105 +++++++ include/boost/scoped_array.hpp | 20 +- include/boost/scoped_ptr.hpp | 26 +- include/boost/shared_array.hpp | 27 +- include/boost/shared_ptr.hpp | 52 ++-- include/boost/smart_ptr.hpp | 405 +------------------------- include/boost/weak_ptr.hpp | 36 +-- index.htm | 31 +- scoped_array.htm | 191 ++++++++----- scoped_ptr.htm | 262 ++++++++++------- scoped_ptr_example.hpp | 2 +- shared_array.htm | 351 +++++++++++++---------- shared_ptr.htm | 506 +++++++++++++++++++-------------- shared_ptr_example.cpp | 2 +- shared_ptr_example2.cpp | 2 - shared_ptr_example2.hpp | 3 +- smart_ptr.htm | 196 ++++++++----- smart_ptr_test.cpp | 22 +- smart_ptr_test2.cpp | 295 ------------------- smarttests.htm | 25 +- weak_ptr.htm | 233 +++++++++++++++ 21 files changed, 1367 insertions(+), 1425 deletions(-) create mode 100644 compatibility.htm delete mode 100644 smart_ptr_test2.cpp create mode 100644 weak_ptr.htm diff --git a/compatibility.htm b/compatibility.htm new file mode 100644 index 0000000..65acfd7 --- /dev/null +++ b/compatibility.htm @@ -0,0 +1,105 @@ + + + + + + +Smart Pointer Changes + + + + +

    c++boost.gif (8819 bytes)Smart +Pointer Changes

    + +

    The February 2002 change to the Boost smart pointers introduced a number +of changes. Since the previous version of the smart pointers was in use for +a long time, it's useful to have a detailed list of what changed from a library +user's point of view.

    + +

    Note that for compilers that don't support member templates well enough, +a separate implementation is used that lacks many of the new features and is +more like the old version.

    + +

    Features Requiring Code Changes to Take Advantage

    + +
      + +
    • The smart pointer class templates now each have their own header file. +For compatibility, the +<boost/smart_ptr.hpp> +header now includes the headers for the four classic smart pointer class templates.
    • + +
    • The weak_ptr template was added.
    • + +
    • The new shared_ptr and shared_array relax the requirement that the pointed-to object's +destructor must be visible when instantiating the shared_ptr destructor. +This makes it easier to have shared_ptr members in classes without explicit destructors.
    • + +
    • A custom deallocator can be passed in when creating a shared_ptr or shared_array.
    • + +
    • shared_static_cast and shared_dynamic_cast function templates are +provided which work for shared_ptr and weak_ptr as static_cast and +dynamic_cast do for pointers.
    • + +
    • The self-assignment misfeature has been removed from shared_ptr::reset, +although it is still present in scoped_ptr, and in std::auto_ptr. +Calling reset with a pointer to the object that's already owned by the +shared_ptr results in undefined behavior +(an assertion, or eventually a double-delete if assertions are off).
    • + +
    • The BOOST_SMART_PTR_CONVERSION feature has been removed.
    • + +
    • shared_ptr<void> is now allowed.
    • + +
    + +

    Features That Improve Robustness

    + +
      + +
    • The manipulation of use counts is now thread safe on Windows, Linux, and platforms +that support pthreads. See the +<boost/detail/atomic_count.hpp> +file for details
    • + +
    • The new shared_ptr will always delete the object using the pointer it was originally constructed with. +This prevents subtle problems that could happen if the last shared_ptr was a pointer to a sub-object +of a class that did not have a virtual destructor.
    • + +
    + +

    Implementation Details

    + +
      + +
    • Some bugs in the assignment operator implementations and in reset +have been fixed by using the "copy and swap" idiom.
    • + +
    • Assertions have been added to check preconditions of various functions; +however, since these use the new +<boost/assert.hpp> +header, the assertions are disabled by default.
    • + +
    • The partial specialization of std::less has been replaced by operator< +overloads which accomplish the same thing without relying on undefined behavior.
    • + +
    • The incorrect overload of std::swap has been replaced by boost::swap, which +has many of the same advantages for generic programming but does not violate the C++ standard.
    • + +
    + +
    + +

    Revised 1 February 2002

    + +

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

    + + + + diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index 3fcce8d..74ecebe 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -35,49 +35,49 @@ public: typedef T element_type; - explicit scoped_array( T* p = 0 ): ptr(p) // never throws + explicit scoped_array(T * p = 0) : ptr(p) // never throws { } - ~scoped_array() + ~scoped_array() // never throws { typedef char type_must_be_complete[sizeof(T)]; delete [] ptr; } - void reset( T* p = 0 ) + void reset(T * p = 0) // never throws { typedef char type_must_be_complete[sizeof(T)]; - if ( ptr != p ) + if (ptr != p) { delete [] ptr; ptr = p; } } - T& operator[](std::ptrdiff_t i) const // never throws + T& operator[](std::ptrdiff_t i) const // never throws { BOOST_ASSERT(ptr != 0); BOOST_ASSERT(i >= 0); return ptr[i]; } - T* get() const // never throws + T* get() const // never throws { return ptr; } - void swap(scoped_array & rhs) + void swap(scoped_array & b) // never throws { - T * tmp = rhs.ptr; - rhs.ptr = ptr; + T * tmp = b.ptr; + b.ptr = ptr; ptr = tmp; } }; -template inline void swap(scoped_array & a, scoped_array & b) +template inline void swap(scoped_array & a, scoped_array & b) // never throws { a.swap(b); } diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index b920a72..6648f09 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -18,7 +18,7 @@ namespace boost // scoped_ptr mimics a built-in pointer except that it guarantees deletion // of the object pointed to, either on destruction of the scoped_ptr or via -// an explicit reset(). scoped_ptr is a simple solution for simple needs; +// an explicit reset(). scoped_ptr is a simple solution for simple needs; // use shared_ptr or std::auto_ptr if your needs are more complex. template class scoped_ptr // noncopyable @@ -34,57 +34,57 @@ public: typedef T element_type; - explicit scoped_ptr( T* p = 0 ): ptr(p) // never throws + explicit scoped_ptr(T * p = 0): ptr(p) // never throws { } - ~scoped_ptr() + ~scoped_ptr() // never throws { typedef char type_must_be_complete[sizeof(T)]; delete ptr; } - void reset( T* p = 0 ) + void reset(T * p = 0) // never throws { typedef char type_must_be_complete[sizeof(T)]; - if ( ptr != p ) + if (ptr != p) { delete ptr; ptr = p; } } - T& operator*() const // never throws + T & operator*() const // never throws { BOOST_ASSERT(ptr != 0); return *ptr; } - T* operator->() const // never throws + T * operator->() const // never throws { BOOST_ASSERT(ptr != 0); return ptr; } - T* get() const // never throws + T * get() const // never throws { return ptr; } - void swap(scoped_ptr & rhs) + void swap(scoped_ptr & b) // never throws { - T * tmp = rhs.ptr; - rhs.ptr = ptr; + T * tmp = b.ptr; + b.ptr = ptr; ptr = tmp; } }; -template inline void swap(scoped_ptr & a, scoped_ptr & b) +template inline void swap(scoped_ptr & a, scoped_ptr & b) // never throws { a.swap(b); } } // namespace boost -#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED +#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index 5098dee..4d400dc 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -17,7 +17,7 @@ #include // for broken compiler workarounds -#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#ifndef BOOST_MSVC6_MEMBER_TEMPLATES #include #else @@ -75,6 +75,11 @@ public: this_type(p).swap(*this); } + template void reset(T * p = 0, D d) + { + this_type(p, d).swap(*this); + } + T & operator[] (std::ptrdiff_t i) const // never throws { BOOST_ASSERT(px != 0); @@ -87,16 +92,16 @@ public: return px; } - long use_count() const // never throws - { - return pn.use_count(); - } - bool unique() const // never throws { return pn.unique(); } + long use_count() const // never throws + { + return pn.use_count(); + } + void swap(shared_array & other) // never throws { std::swap(px, other.px); @@ -110,28 +115,28 @@ private: }; // shared_array -template inline bool operator==(shared_array const & a, shared_array const & b) +template inline bool operator==(shared_array const & a, shared_array const & b) // never throws { return a.get() == b.get(); } -template inline bool operator!=(shared_array const & a, shared_array const & b) +template inline bool operator!=(shared_array const & a, shared_array const & b) // never throws { return a.get() != b.get(); } -template inline bool operator<(shared_array const & a, shared_array const & b) +template inline bool operator<(shared_array const & a, shared_array const & b) // never throws { return std::less()(a.get(), b.get()); } -template void swap(shared_array & a, shared_array & b) +template void swap(shared_array & a, shared_array & b) // never throws { a.swap(b); } } // namespace boost -#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC_MEMBER_TEMPLATES) +#endif // #ifndef BOOST_MSVC6_MEMBER_TEMPLATES #endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index eb4d662..d601bab 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -17,7 +17,7 @@ #include // for broken compiler workarounds -#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#ifndef BOOST_MSVC6_MEMBER_TEMPLATES #include #else @@ -44,7 +44,7 @@ namespace detail struct static_cast_tag {}; struct dynamic_cast_tag {}; -template struct shared_ptr_traits +template struct shared_ptr_traits { typedef T & reference; }; @@ -108,10 +108,8 @@ public: template shared_ptr(shared_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) { - if(px == 0) // need to allocate new counter -- the cast failed - { + if (px == 0) // need to allocate new counter -- the cast failed pn = detail::shared_count(static_cast(0), deleter()); - } } #ifndef BOOST_NO_AUTO_PTR @@ -124,7 +122,7 @@ public: #endif template - shared_ptr & operator=(shared_ptr const & r) // nothrow? + shared_ptr & operator=(shared_ptr const & r) // never throws { px = r.px; pn = r.pn; // shared_count::op= doesn't throw @@ -170,16 +168,16 @@ public: return px; } - long use_count() const // never throws - { - return pn.use_count(); - } - bool unique() const // never throws { return pn.unique(); } + long use_count() const // never throws + { + return pn.use_count(); + } + void swap(shared_ptr & other) // never throws { std::swap(px, other.px); @@ -204,39 +202,39 @@ private: }; // shared_ptr -template inline bool operator==(shared_ptr const & a, shared_ptr const & b) +template inline bool operator==(shared_ptr const & a, shared_ptr const & b) { return a.get() == b.get(); } -template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) +template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) { return a.get() != b.get(); } -template inline bool operator<(shared_ptr const & a, shared_ptr const & b) +template inline bool operator<(shared_ptr const & a, shared_ptr const & b) { return std::less()(a.get(), b.get()); } -template shared_ptr shared_static_cast(shared_ptr const & r) -{ - return shared_ptr(r, detail::static_cast_tag()); -} - -template shared_ptr shared_dynamic_cast(shared_ptr const & r) -{ - return shared_ptr(r, detail::dynamic_cast_tag()); -} - -template void swap(shared_ptr & a, shared_ptr & b) +template void swap(shared_ptr & a, shared_ptr & b) { a.swap(b); } +template shared_ptr shared_static_cast(shared_ptr const & r) +{ + return shared_ptr(r, detail::static_cast_tag()); +} + +template shared_ptr shared_dynamic_cast(shared_ptr const & r) +{ + return shared_ptr(r, detail::dynamic_cast_tag()); +} + // get_pointer() enables boost::mem_fn to recognize shared_ptr -template inline T * get_pointer(shared_ptr const & p) +template inline T * get_pointer(shared_ptr const & p) { return p.get(); } @@ -247,6 +245,6 @@ template inline T * get_pointer(shared_ptr const & p) # pragma warning(pop) #endif -#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC_MEMBER_TEMPLATES) +#endif // #ifndef BOOST_MSVC6_MEMBER_TEMPLATES #endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index dbcb787..da28e87 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -1,402 +1,9 @@ // Boost smart_ptr.hpp header file -----------------------------------------// -// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. Permission to copy, -// use, modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided "as is" -// without express or implied warranty, and with no claim as to its -// suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 6 Jul 01 Reorder shared_ptr code so VC++ 6 member templates work, allowing -// polymorphic pointers to now work with that compiler (Gary Powell) -// 21 May 01 Require complete type where incomplete type is unsafe. -// (suggested by Vladimir Prus) -// 21 May 01 operator= fails if operand transitively owned by *this, as in a -// linked list (report by Ken Johnson, fix by Beman Dawes) -// 21 Jan 01 Suppress some useless warnings with MSVC (David Abrahams) -// 19 Oct 00 Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts) -// 24 Jul 00 Change throw() to // never throws. See lib guidelines -// Exception-specification rationale. (Beman Dawes) -// 22 Jun 00 Remove #if continuations to fix GCC 2.95.2 problem (Beman Dawes) -// 1 Feb 00 Additional shared_ptr BOOST_NO_MEMBER_TEMPLATES workarounds -// (Dave Abrahams) -// 31 Dec 99 Condition tightened for no member template friend workaround -// (Dave Abrahams) -// 30 Dec 99 Moved BOOST_NMEMBER_TEMPLATES compatibility code to config.hpp -// (Dave Abrahams) -// 30 Nov 99 added operator ==, operator !=, and std::swap and std::less -// specializations for shared types (Darin Adler) -// 11 Oct 99 replaced op[](int) with op[](std::size_t) (Ed Brey, Valentin -// Bonnard), added shared_ptr workaround for no member template -// friends (Matthew Langston) -// 25 Sep 99 added shared_ptr::swap and shared_array::swap (Luis Coelho). -// 20 Jul 99 changed name to smart_ptr.hpp, #include , -// #include and use boost::noncopyable -// 17 May 99 remove scoped_array and shared_array operator*() as -// unnecessary (Beman Dawes) -// 14 May 99 reorder code so no effects when bad_alloc thrown (Abrahams/Dawes) -// 13 May 99 remove certain throw() specifiers to avoid generated try/catch -// code cost (Beman Dawes) -// 11 May 99 get() added, conversion to T* placed in macro guard (Valentin -// Bonnard, Dave Abrahams, and others argued for elimination -// of the automatic conversion) -// 28 Apr 99 #include fix (Valentin Bonnard) -// 28 Apr 99 rename transfer() to share() for clarity (Dave Abrahams) -// 28 Apr 99 remove unsafe shared_array template conversions(Valentin Bonnard) -// 28 Apr 99 p(r) changed to p(r.px) for clarity (Dave Abrahams) -// 21 Apr 99 reset() self assignment fix (Valentin Bonnard) -// 21 Apr 99 dispose() provided to improve clarity (Valentin Bonnard) -// 27 Apr 99 leak when new throws fixes (Dave Abrahams) -// 21 Oct 98 initial Version (Greg Colvin/Beman Dawes) - -#ifndef BOOST_SMART_PTR_HPP -#define BOOST_SMART_PTR_HPP - -#include // for broken compiler workarounds -#include // for std::size_t -#include // for std::auto_ptr -#include // for std::swap -#include // for boost::noncopyable, checked_delete, checked_array_delete -#include // for std::less -#include // for BOOST_STATIC_ASSERT - -#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash -# pragma warning(push) -# pragma warning(disable:4284) // return type for 'identifier::operator->' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation -#endif - -namespace boost { - -// scoped_ptr --------------------------------------------------------------// - -// scoped_ptr mimics a built-in pointer except that it guarantees deletion -// of the object pointed to, either on destruction of the scoped_ptr or via -// an explicit reset(). scoped_ptr is a simple solution for simple needs; -// see shared_ptr (below) or std::auto_ptr if your needs are more complex. - -template class scoped_ptr : noncopyable { - - T* ptr; - - public: - typedef T element_type; - - explicit scoped_ptr( T* p=0 ) : ptr(p) {} // never throws - ~scoped_ptr() { checked_delete(ptr); } - void reset( T* p=0 ) { if ( ptr != p ) { checked_delete(ptr); ptr = p; } } - T& operator*() const { return *ptr; } // never throws - T* operator->() const { return ptr; } // never throws - T* get() const { return ptr; } // never throws -#ifdef BOOST_SMART_PTR_CONVERSION - // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! - operator T*() const { return ptr; } // never throws -#endif - }; // scoped_ptr - -// scoped_array ------------------------------------------------------------// - -// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to -// is guaranteed, either on destruction of the scoped_array or via an explicit -// reset(). See shared_array or std::vector if your needs are more complex. - -template class scoped_array : noncopyable { - - T* ptr; - - public: - typedef T element_type; - - explicit scoped_array( T* p=0 ) : ptr(p) {} // never throws - ~scoped_array() { checked_array_delete(ptr); } - - void reset( T* p=0 ) { if ( ptr != p ) - {checked_array_delete(ptr); ptr=p;} } - - T* get() const { return ptr; } // never throws -#ifdef BOOST_SMART_PTR_CONVERSION - // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! - operator T*() const { return ptr; } // never throws -#else - T& operator[](std::size_t i) const { return ptr[i]; } // never throws -#endif - }; // scoped_array - -// shared_ptr --------------------------------------------------------------// - -// An enhanced relative of scoped_ptr with reference counted copy semantics. -// The object pointed to is deleted when the last shared_ptr pointing to it -// is destroyed or reset. - -template class shared_ptr { - public: - typedef T element_type; - - explicit shared_ptr(T* p =0) : px(p) { - try { pn = new long(1); } // fix: prevent leak if new throws - catch (...) { checked_delete(p); throw; } - } - - ~shared_ptr() { dispose(); } - -#if !defined( BOOST_NO_MEMBER_TEMPLATES ) || defined (BOOST_MSVC6_MEMBER_TEMPLATES) - template - shared_ptr(const shared_ptr& r) : px(r.px) { // never throws - ++*(pn = r.pn); - } -#ifndef BOOST_NO_AUTO_PTR - template - explicit shared_ptr(std::auto_ptr& r) { - pn = new long(1); // may throw - px = r.release(); // fix: moved here to stop leak if new throws - } -#endif - - template - shared_ptr& operator=(const shared_ptr& r) { - share(r.px,r.pn); - return *this; - } - -#ifndef BOOST_NO_AUTO_PTR - template - shared_ptr& operator=(std::auto_ptr& r) { - // code choice driven by guarantee of "no effect if new throws" - if (*pn == 1) { checked_delete(px); } - else { // allocate new reference counter - long * tmp = new long(1); // may throw - --*pn; // only decrement once danger of new throwing is past - pn = tmp; - } // allocate new reference counter - px = r.release(); // fix: moved here so doesn't leak if new throws - return *this; - } -#endif -#else -#ifndef BOOST_NO_AUTO_PTR - explicit shared_ptr(std::auto_ptr& r) { - pn = new long(1); // may throw - px = r.release(); // fix: moved here to stop leak if new throws - } - - shared_ptr& operator=(std::auto_ptr& r) { - // code choice driven by guarantee of "no effect if new throws" - if (*pn == 1) { checked_delete(px); } - else { // allocate new reference counter - long * tmp = new long(1); // may throw - --*pn; // only decrement once danger of new throwing is past - pn = tmp; - } // allocate new reference counter - px = r.release(); // fix: moved here so doesn't leak if new throws - return *this; - } -#endif -#endif - - // The assignment operator and the copy constructor must come after - // the templated versions for MSVC6 to work. (Gary Powell) - shared_ptr(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); } // never throws - - shared_ptr& operator=(const shared_ptr& r) { - share(r.px,r.pn); - return *this; - } - - void reset(T* p=0) { - if ( px == p ) return; // fix: self-assignment safe - if (--*pn == 0) { checked_delete(px); } - else { // allocate new reference counter - try { pn = new long; } // fix: prevent leak if new throws - catch (...) { - ++*pn; // undo effect of --*pn above to meet effects guarantee - checked_delete(p); - throw; - } // catch - } // allocate new reference counter - *pn = 1; - px = p; - } // reset - - T& operator*() const { return *px; } // never throws - T* operator->() const { return px; } // never throws - T* get() const { return px; } // never throws - #ifdef BOOST_SMART_PTR_CONVERSION - // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! - operator T*() const { return px; } // never throws - #endif - - long use_count() const { return *pn; } // never throws - bool unique() const { return *pn == 1; } // never throws - - void swap(shared_ptr& other) // never throws - { std::swap(px,other.px); std::swap(pn,other.pn); } - -// Tasteless as this may seem, making all members public allows member templates -// to work in the absence of member template friends. (Matthew Langston) -// Don't split this line into two; that causes problems for some GCC 2.95.2 builds -#if ( defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) ) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) - private: -#endif - - T* px; // contained pointer - long* pn; // ptr to reference counter - -// Don't split this line into two; that causes problems for some GCC 2.95.2 builds -#if !defined( BOOST_NO_MEMBER_TEMPLATES ) && !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) - template friend class shared_ptr; -#endif - - void dispose() { if (--*pn == 0) { checked_delete(px); delete pn; } } - - void share(T* rpx, long* rpn) { - if (pn != rpn) { // Q: why not px != rpx? A: fails when both == 0 - ++*rpn; // done before dispose() in case rpn transitively - // dependent on *this (bug reported by Ken Johnson) - dispose(); - px = rpx; - pn = rpn; - } - } // share -}; // shared_ptr - -template - inline bool operator==(const shared_ptr& a, const shared_ptr& b) - { return a.get() == b.get(); } - -template - inline bool operator!=(const shared_ptr& a, const shared_ptr& b) - { return a.get() != b.get(); } - -// shared_array ------------------------------------------------------------// - -// shared_array extends shared_ptr to arrays. -// The array pointed to is deleted when the last shared_array pointing to it -// is destroyed or reset. - -template class shared_array { - public: - typedef T element_type; - - explicit shared_array(T* p =0) : px(p) { - try { pn = new long(1); } // fix: prevent leak if new throws - catch (...) { checked_array_delete(p); throw; } - } - - shared_array(const shared_array& r) : px(r.px) // never throws - { ++*(pn = r.pn); } - - ~shared_array() { dispose(); } - - shared_array& operator=(const shared_array& r) { - if (pn != r.pn) { // Q: why not px != r.px? A: fails when both px == 0 - ++*r.pn; // done before dispose() in case r.pn transitively - // dependent on *this (bug reported by Ken Johnson) - dispose(); - px = r.px; - pn = r.pn; - } - return *this; - } // operator= - - void reset(T* p=0) { - if ( px == p ) return; // fix: self-assignment safe - if (--*pn == 0) { checked_array_delete(px); } - else { // allocate new reference counter - try { pn = new long; } // fix: prevent leak if new throws - catch (...) { - ++*pn; // undo effect of --*pn above to meet effects guarantee - checked_array_delete(p); - throw; - } // catch - } // allocate new reference counter - *pn = 1; - px = p; - } // reset - - T* get() const { return px; } // never throws - #ifdef BOOST_SMART_PTR_CONVERSION - // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk! - operator T*() const { return px; } // never throws - #else - T& operator[](std::size_t i) const { return px[i]; } // never throws - #endif - - long use_count() const { return *pn; } // never throws - bool unique() const { return *pn == 1; } // never throws - - void swap(shared_array& other) // never throws - { std::swap(px,other.px); std::swap(pn,other.pn); } - - private: - - T* px; // contained pointer - long* pn; // ptr to reference counter - - void dispose() { if (--*pn == 0) { checked_array_delete(px); delete pn; } } - -}; // shared_array - -template - inline bool operator==(const shared_array& a, const shared_array& b) - { return a.get() == b.get(); } - -template - inline bool operator!=(const shared_array& a, const shared_array& b) - { return a.get() != b.get(); } - -} // namespace boost - -// specializations for things in namespace std -----------------------------// - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -namespace std { - -// Specialize std::swap to use the fast, non-throwing swap that's provided -// as a member function instead of using the default algorithm which creates -// a temporary and uses assignment. - -template - inline void swap(boost::shared_ptr& a, boost::shared_ptr& b) - { a.swap(b); } - -template - inline void swap(boost::shared_array& a, boost::shared_array& b) - { a.swap(b); } - -// Specialize std::less so we can use shared pointers and arrays as keys in -// associative collections. - -// It's still a controversial question whether this is better than supplying -// a full range of comparison operators (<, >, <=, >=). - -template - struct less< boost::shared_ptr > - : binary_function, boost::shared_ptr, bool> - { - bool operator()(const boost::shared_ptr& a, - const boost::shared_ptr& b) const - { return std::less()(a.get(),b.get()); } - }; - -template - struct less< boost::shared_array > - : binary_function, boost::shared_array, bool> - { - bool operator()(const boost::shared_array& a, - const boost::shared_array& b) const - { return std::less()(a.get(),b.get()); } - }; - -} // namespace std - -#endif // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif - -#endif // BOOST_SMART_PTR_HPP - +// For compatibility, this header includes the header for the four "classic" +// smart pointer class templates. +#include +#include +#include +#include diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index d73c5f3..087ab12 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -67,14 +67,20 @@ public: template weak_ptr(weak_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) { - if(px == 0) // need to allocate new counter -- the cast failed - { + if (px == 0) // need to allocate new counter -- the cast failed pn = detail::weak_count(); - } } template - weak_ptr & operator=(weak_ptr const & r) // nothrow? + weak_ptr & operator=(weak_ptr const & r) // never throws + { + px = r.px; + pn = r.pn; + return *this; + } + + template + weak_ptr & operator=(shared_ptr const & r) // never throws { px = r.px; pn = r.pn; @@ -86,11 +92,6 @@ public: this_type().swap(*this); } - long use_count() const // never throws - { - return pn.use_count(); - } - T * get() const // never throws { return use_count() == 0? 0: px; @@ -99,7 +100,6 @@ public: typename detail::shared_ptr_traits::reference operator* () const // never throws { T * p = get(); - BOOST_ASSERT(p != 0); return *p; } @@ -107,11 +107,15 @@ public: T * operator-> () const // never throws { T * p = get(); - BOOST_ASSERT(p != 0); return p; } + long use_count() const // never throws + { + return pn.use_count(); + } + void swap(weak_ptr & other) // never throws { std::swap(px, other.px); @@ -149,6 +153,11 @@ template inline bool operator<(weak_ptr const & a, weak_ptr const return std::less()(a.get(), b.get()); } +template void swap(weak_ptr & a, weak_ptr & b) +{ + a.swap(b); +} + template weak_ptr shared_static_cast(weak_ptr const & r) { return weak_ptr(r, detail::static_cast_tag()); @@ -159,11 +168,6 @@ template weak_ptr shared_dynamic_cast(weak_ptr const & r return weak_ptr(r, detail::dynamic_cast_tag()); } -template void swap(weak_ptr & a, weak_ptr & b) -{ - a.swap(b); -} - // get_pointer() enables boost::mem_fn to recognize weak_ptr template inline T * get_pointer(weak_ptr const & p) diff --git a/index.htm b/index.htm index 9c8e78a..676c78c 100644 --- a/index.htm +++ b/index.htm @@ -1,10 +1,10 @@ + + Boost Smart Pointer Library - - @@ -19,19 +19,28 @@ More -

    Smart pointer library

    -

    The header smart_ptr.hpp provides four smart pointer classes.  Smart -pointers ease the management of memory dynamically allocated with C++ new -expressions. +

    Smart Pointer Library

    +

    The smart pointer library includes five smart pointer class templates. Smart +pointers ease the management of memory dynamically allocated with C++ new +expressions. In addition, scoped_ptr can ease the management of memory +dynamically allocated in other ways.

    -

    Revised 14 Mar 2001 -

    + +

    Revised 1 February 2002.

    diff --git a/scoped_array.htm b/scoped_array.htm index 518b4cb..4df98a9 100644 --- a/scoped_array.htm +++ b/scoped_array.htm @@ -1,101 +1,144 @@ + + + scoped_array - - -

    c++boost.gif (8819 bytes)Class -scoped_array

    -

    Class scoped_array stores a pointer to a dynamically -allocated array. (Dynamically allocated arrays are allocated with the C++ new[] -expression.)   The array pointed to is guaranteed to be deleted, -either on destruction of the scoped_array, or via an explicit scoped_array::reset().

    -

    Class scoped_array is a simple solution for simple -needs. It supplies a basic "resource acquisition is +

    c++boost.gif (8819 bytes)scoped_array class template

    + +

    The scoped_array class template stores a pointer to a dynamically allocated +array. (Dynamically allocated arrays are allocated with the C++ new[] +expression.) The array pointed to is guaranteed to be deleted, +either on destruction of the scoped_array, or via an explicit reset.

    + +

    The scoped_array template is a simple solution for simple +needs. It supplies a basic "resource acquisition is initialization" facility, without shared-ownership or transfer-of-ownership -semantics.  Both its name and enforcement of semantics (by being noncopyable) -signal its intent to retain ownership solely within the current scope.  By -being noncopyable, it is +semantics. Both its name and enforcement of semantics (by being +noncopyable) +signal its intent to retain ownership solely within the current scope. +Because it is noncopyable, it is safer than shared_array for pointers which should not be copied.

    -

    Because scoped_array is so simple, in its usual -implementation every operation is as fast as a built-in array pointer and it has no + +

    Because scoped_array is so simple, in its usual implementation +every operation is as fast as a built-in array pointer and it has no more space overhead that a built-in array pointer.

    -

    It cannot be used in C++ Standard Library containers.  See shared_array -if scoped_array does not meet your needs.

    -

    Class scoped_array cannot correctly hold a pointer to a -single object.  See scoped_ptr + +

    It cannot be used in C++ standard library containers. +See shared_array +if scoped_array does not meet your needs.

    + +

    It cannot correctly hold a pointer to a single object. +See scoped_ptr for that usage.

    -

    A C++ Standard Library vector is a heavier duty alternative to a scoped_array.

    -

    The class is a template parameterized on T, the type of the object -pointed to.   T must meet the smart pointer common -requirements.

    -

    Class scoped_array Synopsis

    -
    #include <boost/smart_ptr.hpp>
    -namespace boost {
     
    -template<typename T> class scoped_array : noncopyable {
    +

    A std::vector is an alternative to a scoped_array that is +a bit heavier duty but far more flexible. +A boost::array is an alternative that does not use dynamic allocation.

    - public: - typedef T element_type; +

    The class template is parameterized on T, the type of the object +pointed to. T must meet the smart pointer +common requirements.

    - explicit scoped_array( T* p=0 ); // never throws - ~scoped_array(); +

    Synopsis

    - void reset( T* p=0 ); +
    namespace boost {
    +
    +  template<typename T> class scoped_array : noncopyable {
    +
    +    public:
    +      typedef T element_type;
    +
    +      explicit scoped_array(T * p = 0); // never throws
    +      ~scoped_array(); // never throws
    +
    +      void reset(T * p = 0); // never throws
    +
    +      T & operator[](std::size_t i) const; // never throws
    +      T * get() const; // never throws
    +     
    +      void swap(scoped_array & b); // never throws
    +  };
    +
    +  template<typename T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws
     
    -   T& operator[](std::size_t i) const;  // never throws
    -   T* get() const;  // never throws
    -   };
     }
    -

    Class scoped_array Members

    -

    scoped_array element_type

    + +

    Members

    + +

    +element_type

    typedef T element_type;

    Provides the type of the stored pointer.

    -

    scoped_array constructors

    -
    explicit scoped_array( T* p=0 );  // never throws
    -

    Constructs a scoped_array, storing a copy of p, which must -have been allocated via a C++ new[] expression or be 0.

    -

    T is not required be a complete type.  -See Common Requirements.

    -

    scoped_array destructor

    -
    ~scoped_array();
    -

    Deletes the array pointed to by the stored pointer.  Note that in C++ delete[] -on a pointer with a value of 0 is harmless.

    -

    Does not throw exceptions.

    -

    scoped_array reset

    -
    void reset( T* p=0 )();
    + +

    constructors

    +
    explicit scoped_array(T * p = 0); // never throws
    +

    Constructs a scoped_array, storing a copy of p, which must +have been allocated via a C++ new[] expression or be 0. +T is not required be a complete type. +See the smart pointer +common requirements.

    + +

    destructor

    +
    ~scoped_array(); // never throws
    +

    Deletes the array pointed to by the stored pointer. +Note that delete[] on a pointer with a value of 0 is harmless. +The guarantee that this does not throw exceptions depends on the requirement that the +deleted array's objects' destructors do not throw exceptions. +See the smart pointer common requirements.

    + +

    reset

    +
    void reset(T * p = 0); // never throws

    If p is not equal to the stored pointer, deletes the array pointed to by the stored pointer and then stores a copy of p, which must have been allocated via a -C++ new[] expression or be 0.

    -

    Does not throw exceptions.

    -

    scoped_array operator[]

    -

    T& operator[](std::size_t i) const; // never throws

    -

    Returns a reference to element i of the array pointed to by the -stored pointer.

    -

    Behavior is undefined (and almost certainly undesirable) if get()==0, -or if i is less than 0 or is greater or equal to the number of elements +C++ new[] expression or be 0. +The guarantee that this does not throw exceptions depends on the requirement that the +deleted array's objects' destructors do not throw exceptions. +See the smart pointer common requirements.

    + +

    subscripting

    +
    T & operator[](std::size_t i) const; // never throws
    +

    Returns a reference to element i of the array pointed to by the +stored pointer. +Behavior is undefined and almost certainly undesirable if the stored pointer is 0, +or if i is less than 0 or is greater than or equal to the number of elements in the array.

    -

    scoped_array get

    -
    T* get() const;  // never throws
    -

    T is not required be a complete type.  -See Common Requirements.

    -

    Returns the stored pointer.

    -

    Class scoped_array example

    -

    [To be supplied. In the meantime, see smart_ptr_test.cpp.]

    + +

    get

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

    Returns the stored pointer. +T need not be a complete type. +See the smart pointer +common requirements.

    + +

    swap

    +
    void swap(scoped_array & b); // never throws
    +

    Exchanges the contents of the two smart pointers. +T need not be a complete type. +See the smart pointer +common requirements.

    + +

    Free Functions

    + +

    swap

    +
    template<typename T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws
    +

    Equivalent to a.swap(b). Matches the interface of std::swap. +Provided as an aid to generic programming.

    +
    -

    Revised  24 May, 2001 -

    -

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

    + +

    Revised 1 February 2002

    + +

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

    diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 652d1bb..ec0057d 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -1,152 +1,216 @@ + + + scoped_ptr - - -

    c++boost.gif (8819 bytes)Class -scoped_ptr

    -

    Class scoped_ptr stores a pointer to a dynamically allocated -object. (Dynamically allocated objects are allocated with the C++ new -expression.)   The object pointed to is guaranteed to be deleted, -either on destruction of the scoped_ptr, or via an explicit scoped_ptr::reset().  -See example.

    -

    Class scoped_ptr is a simple solution for simple -needs.  It supplies a basic "resource acquisition is +

    c++boost.gif (8819 bytes)scoped_ptr class template

    + +

    The scoped_ptr class template stores a pointer to a dynamically allocated +object. (Dynamically allocated objects are allocated with the C++ new +expression.) The object pointed to is guaranteed to be deleted, +either on destruction of the scoped_ptr, or via an explicit reset. +See the example.

    + +

    The scoped_ptr template is a simple solution for simple +needs. It supplies a basic "resource acquisition is initialization" facility, without shared-ownership or transfer-of-ownership -semantics.  Both its name and enforcement of semantics (by being noncopyable) -signal its intent to retain ownership solely within the current scope.  +semantics. Both its name and enforcement of semantics (by being +noncopyable) +signal its intent to retain ownership solely within the current scope. Because it is noncopyable, it is -safer than shared_ptr or std::auto_ptr for pointers which should not be +safer than shared_ptr or std::auto_ptr for pointers which should not be copied.

    -

    Because scoped_ptr is so simple, in its usual implementation + +

    Because scoped_ptr is simple, in its usual implementation every operation is as fast as for a built-in pointer and it has no more space overhead -that a built-in pointer.  (Because of the "complete type" -requirement for delete and reset members, they may have one additional function -call overhead in certain idioms.  See Handle/Body -Idiom.)   

    -

    Class scoped_ptr cannot be used in C++ Standard Library containers.  See shared_ptr -or std::auto_ptr if scoped_ptr does not meet your needs.

    -

    Class scoped_ptr cannot correctly hold a pointer to a -dynamically allocated array.  See scoped_array +that a built-in pointer.

    + +

    It cannot be used in C++ Standard Library containers. +See shared_ptr +or std::auto_ptr if scoped_ptr does not meet your needs.

    + +

    It cannot correctly hold a pointer to a +dynamically allocated array. See scoped_array for that usage.

    -

    The class is a template parameterized on T, the type of the object -pointed to.   T must meet the smart pointer common -requirements.

    -

    Class scoped_ptr Synopsis

    -
    #include <boost/smart_ptr.hpp>
    -namespace boost {
     
    -template<typename T> class scoped_ptr : noncopyable {
    +

    The class template is parameterized on T, the type of the object +pointed to. T must meet the smart pointer +common requirements.

    - public: - typedef T element_type; +

    Synopsis

    - explicit scoped_ptr( T* p=0 ); // never throws - ~scoped_ptr(); +
    namespace boost {
     
    -   void reset( T* p=0 );
    +  template<typename T> class scoped_ptr : noncopyable {
    +
    +   public:
    +     typedef T element_type;
    +
    +     explicit scoped_ptr(T * p = 0); // never throws
    +     ~scoped_ptr(); // never throws
    +
    +     void reset(T * p = 0); // never throws
    +
    +     T & operator*() const; // never throws
    +     T * operator->() const; // never throws
    +     T * get() const; // never throws
    +     
    +     void swap(scoped_ptr & b); // never throws
    +  };
    +
    +  template<typename T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
     
    -   T& operator*() const;  // never throws
    -   T* operator->() const;  // never throws
    -   T* get() const;  // never throws
    -   };
     }
    -

    Class scoped_ptr Members

    -

    scoped_ptr element_type

    + +

    Members

    + +

    element_type

    typedef T element_type;

    Provides the type of the stored pointer.

    -

    scoped_ptr constructors

    -
    explicit scoped_ptr( T* p=0 );  // never throws
    -

    T is not required be a complete type.  -See Common Requirements.

    -

    Constructs a scoped_ptr, storing a copy of p, which must -have been allocated via a C++ new expression or be 0.

    -

    scoped_ptr destructor

    -
    ~scoped_ptr();
    -

    Deletes the object pointed to by the stored pointer.  Note that in C++, delete -on a pointer with a value of 0 is harmless.

    -

    Does not throw exceptions.

    -

    scoped_ptr reset

    -
    void reset( T* p=0 );
    + +

    constructors

    +
    explicit scoped_ptr(T * p = 0); // never throws
    +

    Constructs a scoped_ptr, storing a copy of p, which must +have been allocated via a C++ new expression or be 0. +T is not required be a complete type. +See the smart pointer +common requirements.

    + +

    destructor

    +
    ~scoped_ptr(); // never throws
    +

    Deletes the object pointed to by the stored pointer. +Note that delete on a pointer with a value of 0 is harmless. +The guarantee that this does not throw exceptions depends on the requirement that the +deleted object's destructor does not throw exceptions. +See the smart pointer common requirements.

    + +

    reset

    +
    void reset(T * p = 0); // never throws

    If p is not equal to the stored pointer, deletes the object pointed to by the stored pointer and then stores a copy of p, which must have been allocated via a -C++ new expression or be 0.

    -

    Does not throw exceptions.

    -

    scoped_ptr operator*

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

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

    -

    scoped_ptr operator-> and get

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

    T is not required by get() be a complete type.  See Common Requirements.

    -

    Both return the stored pointer.

    -

    Class scoped_ptr examples

    -
    #include <iostream>
    -#include <boost/smart_ptr.h>
    +C++ new expression or be 0.
    +The guarantee that this does not throw exceptions depends on the requirement that the
    +deleted object's destructor does not throw exceptions.
    +See the smart pointer common requirements.

    -struct Shoe { ~Shoe(){ std::cout << "Buckle my shoe" << std::endl; } }; +

    indirection

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

    Returns a reference to the object pointed to by the stored pointer. +Behavior is undefined if the stored pointer is 0.

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

    Returns the stored pointer. Behavior is undefined if the stored pointer is 0.

    + +

    get

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

    Returns the stored pointer. +T need not be a complete type. +See the smart pointer +common requirements.

    + +

    swap

    +
    void swap(scoped_ptr & b); // never throws
    +

    Exchanges the contents of the two smart pointers. +T need not be a complete type. +See the smart pointer +common requirements.

    + +

    Free Functions

    + +

    swap

    +
    template<typename T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
    +

    Equivalent to a.swap(b). Matches the interface of std::swap. +Provided as an aid to generic programming.

    + +

    Example

    + +

    Here's an example that uses scoped_ptr.

    + +
    +
    #include <boost/scoped_ptr.hpp>
    +#include <iostream>
    +
    +struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } };
     
     class MyClass {
         boost::scoped_ptr<int> ptr;
       public:
         MyClass() : ptr(new int) { *ptr = 0; }
         int add_one() { return ++*ptr; }
    -    };
    +};
     
    -void main() {
    +void main()
    +{
         boost::scoped_ptr<Shoe> x(new Shoe);
         MyClass my_instance;
    -    std::cout << my_instance.add_one() << std::endl;
    -    std::cout << my_instance.add_one() << std::endl;
    -    }
    -

    The example program produces the beginning of a child's nursery rhyme as -output:

    + std::cout << my_instance.add_one() << '\n'; + std::cout << my_instance.add_one() << '\n'; +}
    + + +

    The example program produces the beginning of a child's nursery rhyme:

    +
    1
     2
     Buckle my shoe
    +

    Rationale

    -

    The primary reason to use scoped_ptr rather than auto_ptr is to let readers -of your code know that you intend "resource acquisition is initialization" to be applied only for the current scope, and have no intent to transfer -ownership.

    -

    A secondary reason to use scoped_ptr is to prevent a later maintenance programmer from adding a function that actually transfers -ownership by returning the auto_ptr (because the maintenance programmer saw -auto_ptr, and assumed ownership could safely be transferred.) 

    -

    Think of bool vs int. We all know that under the covers bool is usually -just an int. Indeed, some argued against including bool in the -C++ standard because of that. But by coding bool rather than int, you tell your readers -what your intent is. Same with scoped_ptr - you are signaling intent.

    -

    It has been suggested that boost::scoped_ptr<T> is equivalent to -std::auto_ptr<T> const.  Ed Brey pointed out, however, that -reset() will not work on a std::auto_ptr<T> const.

    + +

    The primary reason to use scoped_ptr rather than auto_ptr is to let readers +of your code know that you intend "resource acquisition is initialization" to be applied only +for the current scope, and have no intent to transfer ownership.

    + +

    A secondary reason to use scoped_ptr is to prevent a later maintenance programmer +from adding a function that transfers ownership by returning the auto_ptr, +because the maintenance programmer saw auto_ptr, and assumed ownership could safely +be transferred.

    + +

    Think of bool vs int. We all know that under the covers bool is usually +just an int. Indeed, some argued against including bool in the +C++ standard because of that. But by coding bool rather than int, you tell your readers +what your intent is. Same with scoped_ptr; by using it you are signaling intent.

    + +

    It has been suggested that scoped_ptr<T> is equivalent to +std::auto_ptr<T> const. Ed Brey pointed out, however, that +reset will not work on a std::auto_ptr<T> const.

    +

    Handle/Body Idiom

    +

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

    +

    The scoped_ptr_example_test.cpp sample program includes a header file, scoped_ptr_example.hpp, which uses a scoped_ptr<> to an incomplete type to hide the -implementation.   The -instantiation of member functions which require a complete type occurs in the scoped_ptr_example.cpp +implementation. The +instantiation of member functions which require a complete type occurs in +the scoped_ptr_example.cpp implementation file.

    -

    FAQ

    + +

    Frequently Asked Questions

    +

    Q. Why doesn't scoped_ptr have a release() member?
    -A. Because the whole point of scoped_ptr is to signal intent not -to transfer ownership.  Use std::auto_ptr if ownership transfer is +A. Because the point of scoped_ptr is to signal intent, not +to transfer ownership. Use std::auto_ptr if ownership transfer is required.

    +
    -

    Revised 24 May 2001

    -

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

    + +

    Revised 1 February 2002

    + +

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

    diff --git a/scoped_ptr_example.hpp b/scoped_ptr_example.hpp index 97c8bff..ae1fb8d 100644 --- a/scoped_ptr_example.hpp +++ b/scoped_ptr_example.hpp @@ -1,6 +1,6 @@ // Boost scoped_ptr_example header file ------------------------------------// -#include +#include // The point of this example is to prove that even though // example::implementation is an incomplete type in translation units using diff --git a/shared_array.htm b/shared_array.htm index 6de8704..8d21823 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -1,188 +1,223 @@ + + + shared_array - - -

    c++boost.gif (8819 bytes)Class -shared_array

    -

    Class shared_array stores a pointer to a dynamically -allocated array. (Dynamically allocated arrays are allocated with the C++ new[] -expression.)   The array pointed to is guaranteed to be deleted, -either on destruction of the shared_array, on shared_array::operator=(), -or via an explicit shared_array::reset().  See example.

    -

    Class shared_array meets the CopyConstuctible -and Assignable requirements of the C++ Standard Library, and so -can be used in C++ Standard Library containers.  A specialization of std:: -less< > for  boost::shared_ptr<Y> is supplied so that  -shared_array works by default for Standard Library's Associative -Container Compare template parameter.  For compilers not supporting partial -specialization, the user must explicitly pass the less<> functor.

    -

    Class shared_array cannot correctly hold a pointer to a -single object.  See shared_ptr +

    c++boost.gif (8819 bytes)shared_array class template

    + +

    The shared_array class template stores a pointer to a dynamically allocated +array. (Dynamically allocated array are allocated with the C++ new[] +expression.) The object pointed to is guaranteed to be deleted when +the last shared_array pointing to it is destroyed or reset.

    + +

    Every shared_array 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_array works with +the standard library's associative containers.

    + +

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

    -

    Class shared_array will not work correctly with cyclic data -structures. For example, if main() holds a shared_array pointing to array A, -which directly or indirectly holds a shared_array pointing back to array A, then -array A's use_count() will be 2, and destruction of the main() shared_array will -leave array A dangling with a use_count() of 1.

    -

    A C++ Standard Library vector is a -heavier duty alternative to a shared_array.

    -

    The class is a template parameterized on T, the type of the object -pointed to.   T must meet the smart pointer Common -requirements.

    -

    Class shared_array Synopsis

    -
    #include <boost/smart_ptr.hpp>
    -namespace boost {
     
    -template<typename T> class shared_array {
    +

    Because the implementation uses reference counting, shared_array will not work +correctly with cyclic data structures. For example, if main() holds a shared_array +to A, which directly or indirectly holds a shared_array back to A, +A's use count will be 2. Destruction of the original shared_array +will leave A dangling with a use count of 1.

    - public: - typedef T element_type; +

    A shared_ptr to a std::vector is an alternative to a shared_array that is +a bit heavier duty but far more flexible.

    - explicit shared_array( T* p=0 ); - shared_array( const shared_array& ); // never throws - ~shared_array(); +

    The class template is parameterized on T, the type of the object +pointed to. T must meet the smart pointer +common requirements.

    - shared_array& operator=( const shared_array& ); // never throws +

    Synopsis

    - void reset( T* p=0 ); +
    namespace boost {
     
    -   T& operator[](std::size_t i) const;  // never throws
    -   T* get() const;  // never throws
    +  template<typename T> class shared_array {
     
    -   long use_count() const;  // never throws
    -   bool unique() const;  // never throws
    +    public:
    +      typedef T element_type;
     
    -   void swap( shared_array<T>& other ) throw()
    -   };
    +      explicit shared_array(T * p = 0);
    +      template<typename D> shared_array(T * p, D d);
    +      ~shared_array(); // never throws
     
    -template<typename T>
    -  inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
    -    { return a.get() == b.get(); }
    +      shared_array(shared_array const & r); // never throws
     
    -template<typename T>
    -  inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
    -    { return a.get() != b.get(); }
    -}
    -
    namespace std {
    +      shared_array & operator=(shared_array const & r); // never throws  
     
    -template<typename T>
    -  inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b)
    -    { a.swap(b); }
    +      void reset(T * p = 0); // never throws
    +      template<typename D> void reset(T * p, D d); // never throws
     
    -template<typename T>
    -  struct less< boost::shared_array<T> >
    -    : binary_function<boost::shared_array<T>, boost::shared_array<T>, bool>
    -  {
    -    bool operator()(const boost::shared_array<T>& a,
    -        const boost::shared_array<T>& b) const
    -      { return less<T*>()(a.get(),b.get()); }
    +      T & operator[](std::ptrdiff_t i) const() const; // never throws
    +      T * get() const; // never throws
    +
    +      bool unique() const; // never throws
    +      long use_count() const; // never throws
    +
    +      void swap(shared_array<T> & b); // never throws
       };
     
    -} // namespace std 
    -

    Specialization of std::swap uses the fast, non-throwing swap that's provided -as a member function instead of using the default algorithm which creates a -temporary and uses assignment.
    -
    -Specialization of std::less allows use of shared arrays as keys in C++ -Standard Library associative collections.
    -
    -The std::less specializations use std::less<T*> to perform the -comparison.  This insures that pointers are handled correctly, since the -standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] -paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] -paragraph 8).
    -
    -It's still a controversial question whether supplying only std::less is better -than supplying a full range of comparison operators (<, >, <=, >=).

    -

    The current implementation does not supply the specializations if the macro -name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.

    -

    Class shared_array Members

    -

    shared_array element_type

    + template<typename T> + bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws + template<typename T> + bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws + template<typename T> + bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws + + template<typename T> void swap(shared_array<T> & a, shared_array<T> & b); // never throws + +}
    + +

    Members

    + +

    element_type

    typedef T element_type;

    Provides the type of the stored pointer.

    -

    shared_array constructors

    -
    explicit shared_array( T* p=0 );
    -

    Constructs a shared_array, storing a copy of p, -which must have been allocated via a C++ new[] expression or be 0. -Afterwards, use_count() is 1 (even if p==0; see ~shared_array).

    -

    The only exception which may be thrown is std::bad_alloc.  If -an exception is thrown,  delete[] p is called.

    -
    shared_array( const shared_array& r);  // never throws
    -

    Constructs a shared_array, as if by storing a copy of the -pointer stored in r. Afterwards, use_count() -for all copies is 1 more than the initial r.use_count().

    -

    shared_array destructor

    -
    ~shared_array();
    -

    If use_count() == 1, deletes the array pointed to by the -stored pointer. Otherwise, use_count() for any remaining -copies is decremented by 1. Note that in C++ delete[] on a pointer with -a value of 0 is harmless.

    -

    Does not throw exceptions.

    -

    shared_array operator=

    -
    shared_array& operator=( const shared_array& r);  // never throws
    -

    First, if use_count() == 1, deletes the array pointed to by -the stored pointer. Otherwise, use_count() for any -remaining copies is decremented by 1. Note that in C++ delete[] on a -pointer with a value of 0 is harmless.

    -

    Then replaces the contents of this, as if by storing a copy -of the pointer stored in r. Afterwards, use_count() -for all copies is 1 more than the initial r.use_count()

    -

    shared_array reset

    -
    void reset( T* p=0 );
    -

    First, if use_count() == 1, deletes the array pointed to by -the stored pointer. Otherwise, use_count() for any -remaining copies is decremented by 1. Note that in C++  delete[] -on a pointer with a value of 0 is harmless.

    -

    Then replaces the contents of this, as if by storing a copy -of p, which must have been allocated via a C++ new[] -expression or be 0. Afterwards, use_count() is 1 (even if p==0; -see ~shared_array).

    -

    The only exception which may be thrown is std::bad_alloc.  If -an exception is thrown,  delete[] p is called.

    -

    shared_array operator[]

    -

    T& operator[](std::size_t i) const; // never throws

    -

    Returns a reference to element i of the array pointed to by the -stored pointer.

    -

    Behavior is undefined (and almost certainly undesirable) if get()==0, -or if i is less than 0 or is greater or equal to the number of elements + +

    constructors

    + +
    explicit shared_array(T * p = 0);
    +

    Constructs a shared_array, storing a copy of p, which +must be a pointer to an array that was allocated via a C++ new[] expression or be 0. +Afterwards, the use count is 1 (even if p == 0; see ~shared_array). +The only exception which may be thrown by this constructor is std::bad_alloc. +If an exception is thrown, delete[] p is called.

    + +
    template<typename D> shared_array(T * p, D d);
    +

    Constructs a shared_array, storing a copy of p and of d. +Afterwards, the use count is 1. +D's copy constructor must not throw. +When the the time comes to delete the array pointed to by p, the object +d is used in the statement d(p). Invoking the object d with +parameter p in this way must not throw. +The only exception which may be thrown by this constructor is std::bad_alloc. +If an exception is thrown, d(p) is called.

    + +
    shared_array(shared_array const & r); // never throws
    +

    Constructs a shared_array, as if by storing a copy of the +pointer stored in r. Afterwards, the use count +for all copies is 1 more than the initial use count.

    + +

    destructor

    + +
    ~shared_array(); // never throws
    +

    Decrements the use count. Then, if the use count is 0, +deletes the array pointed to by the stored pointer. +Note that delete[] on a pointer with a value of 0 is harmless. +T need not be a complete type. +The guarantee that this does not throw exceptions depends on the requirement that the +deleted object's destructor does not throw exceptions. +See the smart pointer common requirements.

    + +

    assignment

    + +
    shared_array & operator=(shared_array const & r); // never throws
    +

    Constructs a new shared_array as described above, +then replaces this shared_array with the new one, destroying the replaced object.

    + +

    reset

    + +
    void reset(T * p = 0);
    +

    Constructs a new shared_array as described above, +then replaces this shared_array with the new one, destroying the replaced object. +The only exception which may be thrown is std::bad_alloc. If +an exception is thrown, delete[] p is called.

    + +
    template<typename D> void reset(T * p, D d);
    +

    Constructs a new shared_array as described above, +then replaces this shared_array with the new one, destroying the replaced object. +D's copy constructor must not throw. +The only exception which may be thrown is std::bad_alloc. If +an exception is thrown, d(p) is called.

    + +

    indexing

    +
    T & operator[](std::size_t i) const; // never throws
    +

    Returns a reference to element i of the array pointed to by the stored pointer. +Behavior is undefined and almost certainly undesirable if the stored pointer is 0, +or if i is less than 0 or is greater than or equal to the number of elements in the array.

    -

    shared_array get

    -
    T* get() const;  // never throws
    -

    T is not required be a complete type.  -See Common Requirements.

    -

    Returns the stored pointer.

    -

    shared_array use_count

    -

    long use_count() const; // never throws

    -

    T is not required be a complete type.  -See Common Requirements.

    -

    Returns the number of shared_arrays sharing ownership of the -stored pointer.

    -

    shared_array unique

    -

    bool unique() const; // never throws

    -

    T is not required be a complete type.  -See Common Requirements.

    -

    Returns use_count() == 1.

    -

    shared_array swap

    -

    void swap( shared_array<T>& other ) throw()

    -

    T is not required be a complete type.  -See Common Requirements.

    -

    Swaps the two smart pointers, as if by std::swap.

    -

    Class shared_array example

    -

    [To be supplied. In the meantime, see smart_ptr_test.cpp.]

    + +

    get

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

    Returns the stored pointer. +T need not be a complete type. +See the smart pointer +common requirements.

    + +

    unique

    +
    bool unique() const; // never throws
    +

    Returns true if no other shared_array is sharing ownership of +the stored pointer, false otherwise. +T need not be a complete type. +See the smart pointer +common requirements.

    + +

    use_count

    +
    long use_count() const; // never throws
    +

    Returns the number of shared_array objects sharing ownership of the +stored pointer. +T need not be a complete type. +See the smart pointer +common requirements.

    +

    Because use_count is not necessarily efficient to implement for +implementations of shared_array that do not use an explicit reference +count, it might be removed from some future version. Thus it should +be used for debugging purposes only, and not production code.

    + +

    swap

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

    Exchanges the contents of the two smart pointers. +T need not be a complete type. +See the smart pointer +common requirements.

    + +

    Free Functions

    + +

    comparison

    +
    template<typename T>
    +  bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws
    +template<typename T>
    +  bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws
    +template<typename T>
    +  bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws
    +

    Compares the stored pointers of the two smart pointers. +T need not be a complete type. +See the smart pointer +common requirements.

    +

    The operator< overload is provided to define an ordering so that shared_array +objects can be used in associative containers such as std::map. +The implementation uses std::less<T*> to perform the +comparison. This ensures that the comparison is handled correctly, since the +standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] +paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] +paragraph 8).

    + +

    swap

    +
    template<typename T>
    +  void swap(shared_array<T> & a, shared_array<T> & b) // never throws
    +

    Equivalent to a.swap(b). Matches the interface of std::swap. +Provided as an aid to generic programming.

    +
    -

    Revised 24 May, 2001 -

    -

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

    + +

    Revised 1 February 2002

    + +

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

    diff --git a/shared_ptr.htm b/shared_ptr.htm index 4913f65..fc6d0d6 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -1,284 +1,356 @@ + + + shared_ptr - - -

    -c++boost.gif (8819 bytes)Class -shared_ptr

    -

    Introduction
    -Synopsis

    +

    c++boost.gif (8819 bytes)shared_ptr class template

    + +

    Introduction
    +Synopsis
    Members
    -Example
    +Free Functions
    +Example
    Handle/Body Idiom
    Frequently Asked Questions
    Smart Pointer Timings

    +

    Introduction

    -

    Class shared_ptr stores a pointer to a dynamically allocated -object. (Dynamically allocated objects are allocated with the C++ new -expression.)   The object pointed to is guaranteed to be deleted when -the last shared_ptr pointing to it is deleted or reset.  -See example.

    -

    Class shared_ptr meets the CopyConstuctible -and Assignable requirements of the C++ Standard Library, and so -can be used in C++ Standard Library containers.  A specialization of std:: -less< > for  boost::shared_ptr<Y> is supplied so that  -shared_ptr works by default for Standard Library's Associative -Container Compare template parameter.  For compilers not supporting partial -specialization, the user must explicitly pass the less<> functor.

    -

    Class shared_ptr cannot correctly hold a pointer to a -dynamically allocated array.  See shared_array + +

    The shared_ptr class template stores a pointer to a dynamically allocated +object. (Dynamically allocated objects are allocated with the 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 works with +the standard library's associative containers.

    + +

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

    -

    Class shared_ptr will not work correctly with cyclic data -structures. For example, if main() holds a shared_ptr to object A, which -directly or indirectly holds a shared_ptr back to object A, then object A's -use_count() will be 2, and destruction of the main() shared_ptr will leave -object A dangling with a use_count() of 1.

    -

    The class is a template parameterized on T, the type of the object -pointed to.   T must meet the smart pointer Common -requirements.

    -

    Class shared_ptr Synopsis

    -
    #include <boost/smart_ptr.hpp>
    -namespace boost {
     
    -template<typename T> class shared_ptr {
    +

    Because the implementation uses reference counting, shared_ptr will not work +correctly with cyclic data structures. For example, if main() holds a shared_ptr +to A, which directly or indirectly holds a shared_ptr back to A, +A's use count will be 2. Destruction of the original shared_ptr +will leave A dangling with a use count of 1.

    - public: - typedef T element_type; +

    The class template is parameterized on T, the type of the object +pointed to. T must meet the smart pointer +common requirements. +T may be void, but in that case, either an explicit delete +function must be passed in, or the pointed-to object must have a trivial destructor.

    - explicit shared_ptr( T* p=0 ); - ~shared_ptr(); +

    Synopsis

    - shared_ptr( const shared_ptr& ); - template<typename Y> - shared_ptr(const shared_ptr<Y>& r); // never throws - template<typename Y> - shared_ptr(std::auto_ptr<Y>& r); +
    namespace boost {
     
    -   shared_ptr& operator=( const shared_ptr& );  // never throws  
    -   template<typename Y>
    -      shared_ptr& operator=(const shared_ptr<Y>& r);  // never throws
    -   template<typename Y>
    -      shared_ptr& operator=(std::auto_ptr<Y>& r);
    +  template<typename T> class shared_ptr {
     
    -   void reset( T* p=0 );
    +    public:
    +      typedef T element_type;
     
    -   T& operator*() const;  // never throws
    -   T* operator->() const;  // never throws
    -   T* get() const;  // never throws
    +      explicit shared_ptr(T * p = 0);
    +      template<typename D> shared_ptr(T * p, D d);
    +      ~shared_ptr(); // never throws
     
    -   long use_count() const;  // never throws
    -   bool unique() const;  // never throws
    +      shared_ptr(shared_ptr const & r); // never throws
    +      template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws
    +      template<typename Y> shared_ptr(std::auto_ptr<Y> & r);
     
    -   void swap( shared_ptr<T>& other ) throw()
    -   };
    +      shared_ptr & operator=(shared_ptr const & r); // never throws  
    +      template<typename Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
    +      template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
     
    -template<typename T, typename U>
    -  inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b)
    -    { return a.get() == b.get(); }
    +      void reset(T * p = 0); // never throws
    +      template<typename D> void reset(T * p, D d); // never throws
     
    -template<typename T, typename U>
    -  inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b)
    -    { return a.get() != b.get(); }
    -}
    -
    namespace std {
    +      T & operator*() const; // never throws
    +      T * operator->() const; // never throws
    +      T * get() const; // never throws
     
    -template<typename T>
    -  inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b)
    -    { a.swap(b); }
    +      bool unique() const; // never throws
    +      long use_count() const; // never throws
     
    -template<typename T>
    -  struct less< boost::shared_ptr<T> >
    -    : binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool>
    -  {
    -    bool operator()(const boost::shared_ptr<T>& a,
    -        const boost::shared_ptr<T>& b) const
    -      { return less<T*>()(a.get(),b.get()); }
    +      void swap(shared_ptr<T> & b); // never throws
       };
     
    -} // namespace std 
    -

    Specialization of std::swap uses the fast, non-throwing swap that's provided -as a member function instead of using the default algorithm which creates a -temporary and uses assignment.
    -
    -Specialization of std::less allows use of shared pointers as keys in C++ -Standard Library associative collections.
    -
    -The std::less specializations use std::less<T*> to perform the -comparison.  This insures that pointers are handled correctly, since the -standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] -paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] -paragraph 8).
    -
    -It's still a controversial question whether supplying only std::less is better -than supplying a full range of comparison operators (<, >, <=, >=).

    -

    The current implementation does not supply the specializations if the macro -name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.

    -

    The current implementation does not supply the member template functions if -the macro name BOOST_NO_MEMBER_TEMPLATES is defined.

    -

    Class shared_ptr Members

    -

    shared_ptr element_type

    + template<typename T, typename U> + bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws + template<typename T, typename U> + bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws + template<typename T, typename U> + bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws + + template<typename T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws + + template<typename T, typename U> + shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws + template<typename T, typename U> + shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r); + +}
    + +

    Members

    + +

    element_type

    typedef T element_type;

    Provides the type of the stored pointer.

    -

    shared_ptr constructors

    -
    explicit shared_ptr( T* p=0 );
    -

    Constructs a shared_ptr, storing a copy of p, which -must have been allocated via a C++ new expression or be 0. Afterwards, use_count() -is 1 (even if p==0; see ~shared_ptr).

    -

    The only exception which may be thrown by this constructor is std::bad_alloc.   -If an exception is thrown,  delete p is called.

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

    Constructs a shared_ptr, as if by storing a copy of the -pointer stored in r. Afterwards, use_count() -for all copies is 1 more than the initial r.use_count(), or 1 -in the auto_ptr case. In the auto_ptr case, r.release() -is called.

    -

    The only exception which may be thrown by the constructor from auto_ptr -is std::bad_alloc.   If an exception is thrown, that -constructor has no effect.

    -

    shared_ptr destructor

    -
    ~shared_ptr();
    -

    If use_count() == 1, deletes the object pointed to by the -stored pointer. Otherwise, use_count() for any remaining -copies is decremented by 1. Note that in C++  delete on a pointer -with a value of 0 is harmless.

    -

    Does not throw exceptions.

    -

    shared_ptr operator=

    -
    shared_ptr& operator=( const shared_ptr& r);  
    -template<typename Y>
    -   shared_ptr& operator=(const shared_ptr<Y>& r);
    -template<typename Y>
    -   shared_ptr& operator=(std::auto_ptr<Y>& r);
    -

    First, if use_count() == 1, deletes the object pointed to by -the stored pointer. Otherwise, use_count() for any -remaining copies is decremented by 1. Note that in C++  delete on -a pointer with a value of 0 is harmless.

    -

    Then replaces the contents of this, as if by storing a copy -of the pointer stored in r. Afterwards, use_count() -for all copies is 1 more than the initial r.use_count(), or 1 -in the auto_ptr case. In the auto_ptr case, r.release() -is called.

    -

    The first two forms of operator= above do not throw exceptions.

    -

    The only exception which may be thrown by the auto_ptr form -is std::bad_alloc.   If an exception is thrown, the function -has no effect.

    -

    shared_ptr reset

    -
    void reset( T* p=0 );
    -

    First, if use_count() == 1, deletes the object pointed to by -the stored pointer. Otherwise, use_count() for any -remaining copies is decremented by 1. 

    -

    Then replaces the contents of this, as if by storing a copy -of p, which must have been allocated via a C++ new -expression or be 0. Afterwards, use_count() is 1 (even if p==0; -see ~shared_ptr). Note that in C++  delete -on a pointer with a value of 0 is harmless.

    -

    The only exception which may be thrown is std::bad_alloc.  If -an exception is thrown,  delete p is called.

    -

    shared_ptr operator*

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

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

    -

    shared_ptr operator-> and get

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

    T is not required by get() to be a complete type .  See Common Requirements.

    -

    Both return the stored pointer.

    -

    shared_ptr use_count

    -

    long use_count() const; // never throws

    -

    T is not required be a complete type.  -See Common Requirements.

    -

    Returns the number of shared_ptrs sharing ownership of the -stored pointer.

    -

    shared_ptr unique

    -

    bool unique() const; // never throws

    -

    T is not required be a complete type.  -See Common Requirements.

    -

    Returns use_count() == 1.

    -

    shared_ptr swap

    -

    void swap( shared_ptr<T>& other ) throw()

    -

    T is not required be a complete type.  -See Common Requirements.

    -

    Swaps the two smart pointers, as if by std::swap.

    -

    Class shared_ptr example

    -

    See shared_ptr_example.cpp for a complete example program.

    -

    This program builds a std::vector and std::set of FooPtr's.

    -

    Note that after the two containers have been populated, some of the FooPtr objects -will have use_count()==1 rather than use_count()==2, since foo_set is a std::set -rather than a std::multiset, and thus does not contain duplicate entries.  Furthermore, use_count() may be even higher -at various times while push_back() and insert() container operations are performed.  + +

    constructors

    + +
    explicit shared_ptr(T * p = 0);
    +

    Constructs a shared_ptr, storing a copy of p, which +must be a pointer to an object that was allocated via a C++ new expression or be 0. +Afterwards, the use count is 1 (even if p == 0; see ~shared_ptr). +The only exception which may be thrown by this constructor is std::bad_alloc. +If an exception is thrown, delete p is called.

    + +
    template<typename D> shared_ptr(T * p, D d);
    +

    Constructs a shared_ptr, storing a copy of p and of d. +Afterwards, the use count is 1. +D's copy constructor must not throw. +When the the time comes to delete the object pointed to by p, the object +d is used in the statement d(p). Invoking the object d with +parameter p in this way must not throw. +The only exception which may be thrown by this constructor is std::bad_alloc. +If an exception is thrown, d(p) is called.

    + +
    shared_ptr(shared_ptr const & r); // never throws
    +template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws
    +template<typename Y> shared_ptr(std::auto_ptr<Y> & r);
    +

    Constructs a shared_ptr, as if by storing a copy of the +pointer stored in r. Afterwards, the use count +for all copies is 1 more than the initial use count, or 1 +in the auto_ptr case. In the auto_ptr case, r.release() +is called. +The only exception which may be thrown is std::bad_alloc, +which may be thrown during construction from auto_ptr. +If an exception is thrown, the constructor has no effect.

    + +

    destructor

    + +
    ~shared_ptr(); // never throws
    +

    Decrements the use count. Then, if the use count is 0, +deletes the object pointed to by the stored pointer. +Note that delete on a pointer with a value of 0 is harmless. +T need not be a complete type. +The guarantee that this does not throw exceptions depends on the requirement that the +deleted object's destructor does not throw exceptions. +See the smart pointer common requirements.

    + +

    assignment

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

    Constructs a new shared_ptr as described above, +then replaces this shared_ptr with the new one, destroying the replaced object. +The only exception which may be thrown is std::bad_alloc, +which may be thrown during assignment from auto_ptr. +If an exception is thrown, the assignment has no effect.

    + +

    reset

    + +
    void reset(T * p = 0);
    +

    Constructs a new shared_ptr as described above, +then replaces this shared_ptr with the new one, destroying the replaced object. +The only exception which may be thrown is std::bad_alloc. If +an exception is thrown, delete p is called.

    + +
    template<typename D> void reset(T * p, D d);
    +

    Constructs a new shared_ptr as described above, +then replaces this shared_ptr with the new one, destroying the replaced object. +D's copy constructor must not throw. +The only exception which may be thrown is std::bad_alloc. If +an exception is thrown, d(p) is called.

    + +

    indirection

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

    Returns a reference to the object pointed to by the stored pointer. +Behavior is undefined if the stored pointer is 0.

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

    Returns the stored pointer. Behavior is undefined if the stored pointer is 0.

    + +

    get

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

    Returns the stored pointer. +T need not be a complete type. +See the smart pointer +common requirements.

    + +

    unique

    +
    bool unique() const; // never throws
    +

    Returns true if no other shared_ptr is sharing ownership of +the stored pointer, false otherwise. +T need not be a complete type. +See the smart pointer +common requirements.

    + +

    use_count

    +
    long use_count() const; // never throws
    +

    Returns the number of shared_ptr objects sharing ownership of the +stored pointer. +T need not be a complete type. +See the smart pointer +common requirements.

    +

    Because use_count is not necessarily efficient to implement for +implementations of shared_ptr that do not use an explicit reference +count, it might be removed from some future version. Thus it should +be used for debugging purposes only, and not production code.

    + +

    swap

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

    Exchanges the contents of the two smart pointers. +T need not be a complete type. +See the smart pointer +common requirements.

    + +

    Free Functions

    + +

    comparison

    +
    template<typename T, typename U>
    +  bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
    +template<typename T, typename U>
    +  bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
    +template<typename T, typename U>
    +  bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
    +

    Compares the stored pointers of the two smart pointers. +T need not be a complete type. +See the smart pointer +common requirements.

    +

    The operator< overload is provided to define an ordering so that shared_ptr +objects can be used in associative containers such as std::map. +The implementation uses std::less<T*> to perform the +comparison. This ensures that the comparison is handled correctly, since the +standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] +paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] +paragraph 8).

    + +

    swap

    +
    template<typename T>
    +  void swap(shared_ptr<T> & a, shared_ptr<T> & b) // never throws
    +

    Equivalent to a.swap(b). Matches the interface of std::swap. +Provided as an aid to generic programming.

    + +

    shared_static_cast

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

    Perform a static_cast on the stored pointer, returning another shared_ptr. +The resulting smart pointer will share its use count with the original pointer.

    +

    Note that the seemingly equivalent expression

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

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

    + +

    shared_dynamic_cast

    +
    template<typename T, typename U>
    +  shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r);
    +

    Perform a dynamic_cast on the stored pointer, returning another shared_ptr. +The resulting smart pointer will share its use count with the original pointer unless the result of the +cast is 0. The only exception which may be thrown is std::bad_alloc, which may be thrown during the +construction of the new shared_ptr if the result of the cast is 0. If an exception is thrown, the +cast has no effect.

    +

    Note that the seemingly equivalent expression

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

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

    + +

    Example

    + +

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

    + +

    Note that after the containers have been populated, some of the shared_ptr objects +will have a use count of 1 rather than a use count of 2, since the set is a std::set +rather than a std::multiset, and thus does not 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.  Without using a smart pointer, memory and -exception management would be a nightmare.

    +variety of circumstances. Getting the memory management and exception handling in this +example right without a smart pointer would be a nightmare.

    +

    Handle/Body Idiom

    +

    One common usage of shared_ptr is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) in the header 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 type occurs in the shared_ptr_example2.cpp -implementation file.

    +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 type.

    +

    Frequently Asked Questions

    +

    Q. Why doesn't shared_ptr have template parameters supplying traits or policies to allow extensive user customization?
    -A. Parameterization discourages users.  Shared_ptr is +A. Parameterization discourages users. The shared_ptr template is carefully crafted to meet common needs without extensive parameterization. -Someday 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.)

    +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. Why doesn't shared_ptr use a linked list implementation?
    A. A linked list implementation does not offer enough advantages to -offset the added cost of an extra pointer.  See timings +offset the added cost of an extra pointer. See timings page.

    -

    Q. Why don't shared_ptr (and the other Boost smart pointers) + +

    Q. Why doesn't shared_ptr (or any of the other Boost smart pointers) supply an automatic conversion to T*?
    A. Automatic conversion is believed to be too error prone.

    +

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

    +

    Q. Why doesn't shared_ptr specify complexity requirements?
    -A. Because complexity limit implementors and complicate the specification without apparent benefit to -shared_ptr users. For example, error-checking implementations might become non-conforming if they +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() because the other copy will still destroy the object.

    Consider:

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

    [Provided by Peter Dimov]

    +// Who owns p now? b will still call delete on it in its destructor.
    +

    Q. Why doesn't shared_ptr provide (your pet feature here)?
    -A. Because (your pet feature here) would mandate a reference counted (or a link-list, or ...) implementation. This is not the intent. -[Provided by Peter Dimov]

    -


    -

    +A. Because (your pet feature here) would mandate a reference counted +implementation or a linked list implementation, or some other specific implementation. +This is not the intent.

    +
    -

    Revised 11 January, 2002 -

    -

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

    + +

    Revised 1 February 2002

    + +

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

    - \ No newline at end of file + diff --git a/shared_ptr_example.cpp b/shared_ptr_example.cpp index 988efbd..4db8fc6 100644 --- a/shared_ptr_example.cpp +++ b/shared_ptr_example.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include // The application will produce a series of // objects of type Foo which later must be diff --git a/shared_ptr_example2.cpp b/shared_ptr_example2.cpp index eddc806..746dd48 100644 --- a/shared_ptr_example2.cpp +++ b/shared_ptr_example2.cpp @@ -17,5 +17,3 @@ example & example::operator=( const example & s ) void example::do_something() { std::cout << "use_count() is " << _imp.use_count() << "\n"; } - -example::~example() {} diff --git a/shared_ptr_example2.hpp b/shared_ptr_example2.hpp index fea810b..93b77e5 100644 --- a/shared_ptr_example2.hpp +++ b/shared_ptr_example2.hpp @@ -1,6 +1,6 @@ // Boost shared_ptr_example2 header file -----------------------------------// -#include +#include // This example demonstrates the handle/body idiom (also called pimpl and // several other names). It separates the interface (in this header file) @@ -16,7 +16,6 @@ class example { public: example(); - ~example(); example( const example & ); example & operator=( const example & ); void do_something(); diff --git a/smart_ptr.htm b/smart_ptr.htm index 07538e4..0f5246d 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -1,126 +1,175 @@ + + - - -Smart Pointer Classes +Smart Pointers -

    c++boost.gif (8819 bytes)Smart +

    c++boost.gif (8819 bytes)Smart Pointers

    -

    Smart pointers are classes which store pointers to dynamically allocated -(heap) objects.  They behave much like built-in C++ pointers except that + +

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

    +

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

    -

    The header boost/smart_ptr.hpp -provides four smart pointer template classes:

    + +

    The smart pointer library provides five smart pointer class templates:

    +
    - + + - - + + + - + + - + + + + + + +
    -

    scoped_ptr

    scoped_ptr<boost/scoped_ptr.hpp> Simple sole ownership of single objects. Noncopyable.
    scoped_arraySimple sole ownership of arrays. Noncopyable.scoped_array<boost/scoped_array.hpp>Simple sole ownership of arrays. Noncopyable.
    shared_ptrshared_ptr<boost/shared_ptr.hpp> Object ownership shared among multiple pointers
    shared_arrayshared_array<boost/shared_array.hpp> Array ownership shared among multiple pointers.
    weak_ptr<boost/weak_ptr.hpp>Non-owning observers of an object owned by shared_ptr.
    -

    These classes are designed to complement the C++ Standard Library auto_ptr -class.

    + +

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

    +

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

    -

    A test program (smart_ptr_test.cpp) is + +

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

    -

    A page on Smart Pointer Timings will be of + +

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

    + +

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

    -

    Common requirements

    -

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

    -

    T may be an incomplete type at the point of smart pointer -declaration.  Unless otherwise specified, it is required that T + +

    Common Requirements

    + +

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

    + +

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

    +including deletion of an incomplete type. +See the description of the checked_delete +function template.

    +

    Rationale

    -

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

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

    -

    Exception safety

    + +

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

    + +

    Exception Safety

    +

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

    +thrown. This amounts to a guarantee that there are no detectable side +effects. Other functions never throw exceptions. The only exception +ever thrown by functions which do throw (assuming T meets the +common requirements) is std::bad_alloc, +and that is thrown only by functions which are explicitly documented as possibly +throwing std::bad_alloc.

    +

    Exception-specifications

    -

    Exception-specifications are not used; see exception-specification + +

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

    -

    All four classes contain member functions which can never throw exceptions, + +

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

    +may throw exceptions. These members are indicated by a comment: +// never throws.

    +

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

    -

    History and acknowledgements

    -

    May, 2001. Vladimir Prus suggested requiring a complete type on -destruction.  Refinement evolved in discussions including Dave Abrahams, +throwing exceptions by the common requirements.

    + +

    History and Acknowledgements

    + +

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

    + +

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

    -

    November, 1999. Darin Adler provided operator ==, operator !=, and std::swap + +

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

    -

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

    -

    May, 1999.  In April and May, 1999, Valentin Bonnard and David Abrahams -made a number of suggestions resulting in numerous improvements.  See the -revision history in smart_ptr.hpp + +

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

    + +

    May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams +made a number of suggestions resulting in numerous improvements. See the +revision history in smart_ptr.hpp for the specific changes made as a result of their constructive criticism.

    -

    Oct, 1998.  In 1994 Greg Colvin proposed to the C++ Standards Committee -classes named auto_ptr and counted_ptr which -were very similar to what we now call scoped_ptr and shared_ptr.  -The committee document was 94-168/N0555, Exception Safe Smart Pointers.  In + +

    October 1998. In 1994 Greg Colvin proposed to the C++ Standards Committee +classes named auto_ptr and counted_ptr which +were very similar to what we now call scoped_ptr and shared_ptr. +The committee document was 94-168/N0555, Exception Safe Smart Pointers. In one of the very few cases where the Library Working Group's recommendations were -not followed by the full committee, counted_ptr was rejected -and surprising transfer-of-ownership semantics were added to auto-ptr.

    -

    Beman Dawes proposed reviving the original semantics under the names safe_ptr -and counted_ptr at an October, 1998, meeting of Per Andersson, +not followed by the full committee, counted_ptr was rejected +and surprising transfer-of-ownership semantics were added to auto_ptr.

    + +

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

    -

    Over the next three months, several implementations were considered for shared_ptr, + +

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

    • Direct detached: the shared_ptr contains a pointer to the object, and a pointer to the count.
    • @@ -129,22 +178,29 @@ elsewhere. Each of those variants have themselves two major variants:
    • Embedded attached: the count is a member of the object pointed to.
    • Placement attached: the count is attached via operator new manipulations.
    -

    Each implementation technique has advantages and disadvantages.  We went + +

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

    +

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

    +

    See the Revision History section of the header for further contributors.

    +
    -

    Revised  24 May 20011 February 2002

    -

    İ Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, + +

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. +Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for diff --git a/smart_ptr_test.cpp b/smart_ptr_test.cpp index 62c97ca..8d41070 100644 --- a/smart_ptr_test.cpp +++ b/smart_ptr_test.cpp @@ -13,13 +13,23 @@ // 20 Jul 99 header name changed to .hpp // 20 Apr 99 additional error tests added. +#include +#include +#include +#include + #define BOOST_INCLUDE_MAIN #include -#include + #include #include #include +bool boost_error(char const *, char const *, char const *, long) +{ + return true; // fail with assert() +} + class Incomplete; Incomplete * get_ptr( boost::shared_ptr& incomplete ) @@ -48,7 +58,7 @@ class UDT { explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; } ~UDT() { --UDT_use_count; - cout << "UDT with value " << value_ << " being destroyed" << endl; + cout << "UDT with value " << value_ << " being destroyed\n"; } long value() const { return value_; } void value( long v ) { value_ = v;; } @@ -71,7 +81,7 @@ Incomplete * check_incomplete( shared_ptr& incomplete, shared_ptr& i2 ) { incomplete.swap(i2); - cout << incomplete.use_count() << " " << incomplete.unique() << endl; + cout << incomplete.use_count() << ' ' << incomplete.unique() << '\n'; return incomplete.get(); } // main --------------------------------------------------------------------// @@ -186,12 +196,10 @@ int test_main( int, char ** ) { BOOST_TEST( *cp4 == 87654 ); BOOST_TEST( cp2.get() == 0 ); -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION set< shared_ptr > scp; scp.insert(cp4); BOOST_TEST( scp.find(cp4) != scp.end() ); BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr(cp4) ) ); -#endif // test shared_array with a built-in type char * cap = new char [ 100 ]; @@ -232,12 +240,10 @@ int test_main( int, char ** ) { BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); BOOST_TEST( ca3.get() == 0 ); -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION set< shared_array > sca; sca.insert(ca4); BOOST_TEST( sca.find(ca4) != sca.end() ); BOOST_TEST( sca.find(ca4) == sca.find( shared_array(ca4) ) ); -#endif // test shared_array with user defined type shared_array udta ( new UDT[3] ); @@ -280,7 +286,7 @@ int test_main( int, char ** ) { BOOST_TEST( sup.use_count() == 2 ); BOOST_TEST( sup2.use_count() == 2 ); - cout << "OK" << endl; + cout << "OK\n"; new char[12345]; // deliberate memory leak to verify leaks detected diff --git a/smart_ptr_test2.cpp b/smart_ptr_test2.cpp deleted file mode 100644 index 4ea305e..0000000 --- a/smart_ptr_test2.cpp +++ /dev/null @@ -1,295 +0,0 @@ -// smart pointer test program ----------------------------------------------// - -// (C) Copyright Beman Dawes 1998, 1999. Permission to copy, use, modify, sell -// and distribute this software is granted provided this copyright notice -// appears in all copies. This software is provided "as is" without express or -// implied warranty, and with no claim as to its suitability for any purpose. - -// Revision History -// 24 May 01 use Boost test library for error detection, reporting, add tests -// for operations on incomplete types (Beman Dawes) -// 29 Nov 99 added std::swap and associative container tests (Darin Adler) -// 25 Sep 99 added swap tests -// 20 Jul 99 header name changed to .hpp -// 20 Apr 99 additional error tests added. - -#include -#include -#include -#include - -#define BOOST_INCLUDE_MAIN -#include - -#include -#include -#include - -bool boost_error(char const *, char const *, char const *, long) -{ - return true; // fail with assert() -} - -class Incomplete; - -Incomplete * get_ptr( boost::shared_ptr& incomplete ) -{ - return incomplete.get(); -} - -using namespace std; -using boost::scoped_ptr; -using boost::scoped_array; -using boost::shared_ptr; -using boost::shared_array; - -template -void ck( const T* v1, T v2 ) { BOOST_TEST( *v1 == v2 ); } - -namespace { - int UDT_use_count; // independent of pointer maintained counts - } - -// user defined type -------------------------------------------------------// - -class UDT { - long value_; - public: - explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; } - ~UDT() { - --UDT_use_count; - cout << "UDT with value " << value_ << " being destroyed" << endl; - } - long value() const { return value_; } - void value( long v ) { value_ = v;; } - }; // UDT - -// tests on incomplete types -----------------------------------------------// - -// Certain smart pointer operations are specified to work on incomplete types, -// and some uses depend upon this feature. These tests verify compilation -// only - the functions aren't actually invoked. - -class Incomplete; - -Incomplete * check_incomplete( scoped_ptr& incomplete ) -{ - return incomplete.get(); -} - -Incomplete * check_incomplete( shared_ptr& incomplete, - shared_ptr& i2 ) -{ - incomplete.swap(i2); - cout << incomplete.use_count() << " " << incomplete.unique() << endl; - return incomplete.get(); -} -// main --------------------------------------------------------------------// - -// This isn't a very systematic test; it just hits some of the basics. - -int test_main( int, char ** ) { - - BOOST_TEST( UDT_use_count == 0 ); // reality check - - // test scoped_ptr with a built-in type - long * lp = new long; - scoped_ptr sp ( lp ); - BOOST_TEST( sp.get() == lp ); - BOOST_TEST( lp == sp.get() ); - BOOST_TEST( &*sp == lp ); - - *sp = 1234568901L; - BOOST_TEST( *sp == 1234568901L ); - BOOST_TEST( *lp == 1234568901L ); - ck( static_cast(sp.get()), 1234568901L ); - ck( lp, *sp ); - - sp.reset(); - BOOST_TEST( sp.get() == 0 ); - - // test scoped_ptr with a user defined type - scoped_ptr udt_sp ( new UDT( 999888777 ) ); - BOOST_TEST( udt_sp->value() == 999888777 ); - udt_sp.reset(); - udt_sp.reset( new UDT( 111222333 ) ); - BOOST_TEST( udt_sp->value() == 111222333 ); - udt_sp.reset( new UDT( 333222111 ) ); - BOOST_TEST( udt_sp->value() == 333222111 ); - - // test scoped_array with a build-in type - char * sap = new char [ 100 ]; - scoped_array sa ( sap ); - BOOST_TEST( sa.get() == sap ); - BOOST_TEST( sap == sa.get() ); - - strcpy( sa.get(), "Hot Dog with mustard and relish" ); - BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 ); - BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 ); - - BOOST_TEST( sa[0] == 'H' ); - BOOST_TEST( sa[30] == 'h' ); - - sa[0] = 'N'; - sa[4] = 'd'; - BOOST_TEST( strcmp( sap, "Not dog with mustard and relish" ) == 0 ); - - sa.reset(); - BOOST_TEST( sa.get() == 0 ); - - // test shared_ptr with a built-in type - int * ip = new int; - shared_ptr cp ( ip ); - BOOST_TEST( ip == cp.get() ); - BOOST_TEST( cp.use_count() == 1 ); - - *cp = 54321; - BOOST_TEST( *cp == 54321 ); - BOOST_TEST( *ip == 54321 ); - ck( static_cast(cp.get()), 54321 ); - ck( static_cast(ip), *cp ); - - shared_ptr cp2 ( cp ); - BOOST_TEST( ip == cp2.get() ); - BOOST_TEST( cp.use_count() == 2 ); - BOOST_TEST( cp2.use_count() == 2 ); - - BOOST_TEST( *cp == 54321 ); - BOOST_TEST( *cp2 == 54321 ); - ck( static_cast(cp2.get()), 54321 ); - ck( static_cast(ip), *cp2 ); - - shared_ptr cp3 ( cp ); - BOOST_TEST( cp.use_count() == 3 ); - BOOST_TEST( cp2.use_count() == 3 ); - BOOST_TEST( cp3.use_count() == 3 ); - cp.reset(); - BOOST_TEST( cp2.use_count() == 2 ); - BOOST_TEST( cp3.use_count() == 2 ); - BOOST_TEST( cp.use_count() == 1 ); - cp.reset( new int ); - *cp = 98765; - BOOST_TEST( *cp == 98765 ); - *cp3 = 87654; - BOOST_TEST( *cp3 == 87654 ); - BOOST_TEST( *cp2 == 87654 ); - cp.swap( cp3 ); - BOOST_TEST( *cp == 87654 ); - BOOST_TEST( *cp2 == 87654 ); - BOOST_TEST( *cp3 == 98765 ); - cp.swap( cp3 ); - BOOST_TEST( *cp == 98765 ); - BOOST_TEST( *cp2 == 87654 ); - BOOST_TEST( *cp3 == 87654 ); - cp2 = cp2; - BOOST_TEST( cp2.use_count() == 2 ); - BOOST_TEST( *cp2 == 87654 ); - cp = cp2; - BOOST_TEST( cp2.use_count() == 3 ); - BOOST_TEST( *cp2 == 87654 ); - BOOST_TEST( cp.use_count() == 3 ); - BOOST_TEST( *cp == 87654 ); - - shared_ptr cp4; - swap( cp2, cp4 ); - BOOST_TEST( cp4.use_count() == 3 ); - BOOST_TEST( *cp4 == 87654 ); - BOOST_TEST( cp2.get() == 0 ); - - set< shared_ptr > scp; - scp.insert(cp4); - BOOST_TEST( scp.find(cp4) != scp.end() ); - BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr(cp4) ) ); - - // test shared_array with a built-in type - char * cap = new char [ 100 ]; - shared_array ca ( cap ); - BOOST_TEST( ca.get() == cap ); - BOOST_TEST( cap == ca.get() ); - BOOST_TEST( &ca[0] == cap ); - - strcpy( ca.get(), "Hot Dog with mustard and relish" ); - BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 ); - BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 ); - - BOOST_TEST( ca[0] == 'H' ); - BOOST_TEST( ca[30] == 'h' ); - - shared_array ca2 ( ca ); - shared_array ca3 ( ca2 ); - - ca[0] = 'N'; - ca[4] = 'd'; - BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 ); - BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 ); - BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 ); - BOOST_TEST( ca.use_count() == 3 ); - BOOST_TEST( ca2.use_count() == 3 ); - BOOST_TEST( ca3.use_count() == 3 ); - ca2.reset(); - BOOST_TEST( ca.use_count() == 2 ); - BOOST_TEST( ca3.use_count() == 2 ); - BOOST_TEST( ca2.use_count() == 1 ); - - ca.reset(); - BOOST_TEST( ca.get() == 0 ); - - shared_array ca4; - swap( ca3, ca4 ); - BOOST_TEST( ca4.use_count() == 1 ); - BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); - BOOST_TEST( ca3.get() == 0 ); - - set< shared_array > sca; - sca.insert(ca4); - BOOST_TEST( sca.find(ca4) != sca.end() ); - BOOST_TEST( sca.find(ca4) == sca.find( shared_array(ca4) ) ); - - // test shared_array with user defined type - shared_array udta ( new UDT[3] ); - - udta[0].value( 111 ); - udta[1].value( 222 ); - udta[2].value( 333 ); - shared_array udta2 ( udta ); - - BOOST_TEST( udta[0].value() == 111 ); - BOOST_TEST( udta[1].value() == 222 ); - BOOST_TEST( udta[2].value() == 333 ); - BOOST_TEST( udta2[0].value() == 111 ); - BOOST_TEST( udta2[1].value() == 222 ); - BOOST_TEST( udta2[2].value() == 333 ); - udta2.reset(); - BOOST_TEST( udta2.get() == 0 ); - BOOST_TEST( udta.use_count() == 1 ); - BOOST_TEST( udta2.use_count() == 1 ); - - BOOST_TEST( UDT_use_count == 4 ); // reality check - - // test shared_ptr with a user defined type - UDT * up = new UDT; - shared_ptr sup ( up ); - BOOST_TEST( up == sup.get() ); - BOOST_TEST( sup.use_count() == 1 ); - - sup->value( 54321 ) ; - BOOST_TEST( sup->value() == 54321 ); - BOOST_TEST( up->value() == 54321 ); - - shared_ptr sup2; - sup2 = sup; - BOOST_TEST( sup2->value() == 54321 ); - BOOST_TEST( sup.use_count() == 2 ); - BOOST_TEST( sup2.use_count() == 2 ); - sup2 = sup2; - BOOST_TEST( sup2->value() == 54321 ); - BOOST_TEST( sup.use_count() == 2 ); - BOOST_TEST( sup2.use_count() == 2 ); - - cout << "OK" << endl; - - new char[12345]; // deliberate memory leak to verify leaks detected - - return 0; - } // main - diff --git a/smarttests.htm b/smarttests.htm index dcd8fda..84fd16e 100644 --- a/smarttests.htm +++ b/smarttests.htm @@ -1,13 +1,15 @@ + + + -boost: smart pointer tests +Smart Pointer Timings - + + -

    c++boost.gif (8819 bytes)Smart -Pointers Timings

    +

    c++boost.gif (8819 bytes)Smart Pointer Timings

    In late January 2000, Mark Borgerding put forward a suggestion to boost for a new design of smart pointer whereby an intrusive doubly linked list is used @@ -19,9 +21,10 @@ Pointers Timings mailing list and the tests which this page describes were performed to provide a guide for current and future investigations into smart pointer implementation strategies.

    -

    Thanks are due to Dave Abrahams, - Gavin Collings, Greg Colvin and - Beman Dawes +

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

    Description

    @@ -75,7 +78,7 @@ Pointers Timings   - + MSVC speed graph   @@ -85,7 +88,7 @@ Pointers Timings   - + GCC speed graph   @@ -530,7 +533,7 @@ Pointers Timings spreads its information as in the case of linked pointer.
    -

    Revised 19 Aug 2001 +

    Revised 19 August 2001

    İ Copyright Gavin Collings 2000. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all diff --git a/weak_ptr.htm b/weak_ptr.htm new file mode 100644 index 0000000..fb97eac --- /dev/null +++ b/weak_ptr.htm @@ -0,0 +1,233 @@ + + + + + + +weak_ptr + + + + +

    c++boost.gif (8819 bytes)weak_ptr class template

    + +

    Introduction
    +Synopsis
    +Members
    +Free Functions
    +Example
    +Handle/Body Idiom
    +Frequently Asked Questions
    +Smart Pointer Timings

    + +

    Introduction

    + +

    The weak_ptr class template stores a pointer to an +object that's already managed by a shared_ptr. When the +object last shared_ptr to the object goes away and the object +is deleted, all weak_ptr objects have their stored pointers +set to 0.

    + +

    Every weak_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 weak_ptr works with +the standard library's associative containers.

    + +

    The class template is parameterized on T, the type of the object +pointed to. T must meet the smart pointer +common requirements.

    + +

    Synopsis

    + +
    namespace boost {
    +
    +  template<typename T> class weak_ptr {
    +
    +    public:
    +      typedef T element_type;
    +
    +      explicit weak_ptr();
    +      template<typename Y> weak_ptr(shared_ptr<Y> const & r); // never throws
    +      ~weak_ptr(); // never throws
    +
    +      weak_ptr(weak_ptr const & r); // never throws
    +      template<typename Y> weak_ptr(weak_ptr<Y> const & r); // never throws
    +
    +      weak_ptr & operator=(weak_ptr const & r); // never throws  
    +      template<typename Y> weak_ptr & operator=(weak_ptr<Y> const & r); // never throws
    +      template<typename Y> weak_ptr & operator=(shared_ptr<Y> const & r); // never throws
    +
    +      void reset(); // never throws
    +
    +      T & operator*() const; // never throws
    +      T * operator->() const; // never throws
    +      T * get() const; // never throws
    +
    +      long use_count() const; // never throws
    +
    +      void swap(weak_ptr<T> & b); // never throws
    +  };
    +
    +  template<typename T, typename U>
    +    bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    +  template<typename T, typename U>
    +    bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    +  template<typename T, typename U>
    +    bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    +
    +  template<typename T> void swap(weak_ptr<T> & a, weak_ptr<T> & b); // never throws
    +
    +  template<typename T, typename U>
    +    weak_ptr<T> shared_static_cast(weak_ptr<U> const & r); // never throws
    +  template<typename T, typename U>
    +    weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r);
    +
    +}
    + +

    Members

    + +

    element_type

    +
    typedef T element_type;
    +

    Provides the type of the stored pointer.

    + +

    constructors

    + +
    explicit weak_ptr();
    +

    Constructs a weak_ptr, with 0 as its stored pointer. +The only exception which may be thrown by this constructor is std::bad_alloc. +If an exception is thrown, the constructor has no effect.

    + +
    template<typename Y> weak_ptr(shared_ptr<Y> const & r); // never throws
    +

    Constructs a weak_ptr, as if by storing a copy of the pointer stored in r. +Afterwards, the use count for all copies is unchanged. +When the last shared_ptr is destroyed, the use count and stored pointer become 0. +The only exception which may be thrown by this constructor is std::bad_alloc. +If an exception is thrown, the constructor has no effect.

    + +
    weak_ptr(weak_ptr const & r); // never throws
    +template<typename Y> weak_ptr(weak_ptr<Y> const & r); // never throws
    +

    Constructs a weak_ptr, as if by storing a copy of the +pointer stored in r.

    + +

    destructor

    + +
    ~weak_ptr(); // never throws
    +

    Destroys this weak_ptr but has no effect on the object its stored pointer points to. +T need not be a complete type. +See the smart pointer common requirements.

    + +

    assignment

    + +
    weak_ptr & operator=(weak_ptr const & r); // never throws
    +template<typename Y> weak_ptr & operator=(weak_ptr<Y> const & r); // never throws
    +template<typename Y> weak_ptr & operator=(shared_ptr<Y> const & r); // never throws
    +

    Constructs a new weak_ptr as described above, +then replaces this weak_ptr with the new one, destroying the replaced object.

    + +

    reset

    + +
    void reset();
    +

    Constructs a new weak_ptr as described above, +then replaces this weak_ptr with the new one, destroying the replaced object. +The only exception which may be thrown is std::bad_alloc. If +an exception is thrown, the reset has no effect.

    + +

    indirection

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

    Returns a reference to the object pointed to by the stored pointer. +Behavior is undefined if the stored pointer is 0. +Note that the stored pointer becomes 0 if all shared_ptr objects for that +pointer are destroyed.

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

    Returns the stored pointer. +Behavior is undefined if the stored pointer is 0. +Note that the stored pointer becomes 0 if all shared_ptr objects for that +pointer are destroyed.

    + +

    get

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

    Returns the stored pointer. +Note that the stored pointer becomes 0 if all shared_ptr objects for that +pointer are destroyed. +T need not be a complete type. +See the smart pointer +common requirements.

    + +

    use_count

    +
    long use_count() const; // never throws
    +

    Returns the number of shared_ptr objects sharing ownership of the +stored pointer. +T need not be a complete type. +See the smart pointer +common requirements.

    +

    Because use_count is not necessarily efficient to implement for +implementations of weak_ptr that do not use an explicit reference +count, it might be removed from some future version. Thus it should +be used for debugging purposes only, and get should be used for +production code.

    + +

    swap

    +
    void swap(weak_ptr & b); // never throws
    +

    Exchanges the contents of the two smart pointers. +T need not be a complete type. +See the smart pointer +common requirements.

    + +

    Free Functions

    + +

    comparison

    +
    template<typename T, typename U>
    +  bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    +template<typename T, typename U>
    +  bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    +template<typename T, typename U>
    +  bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    +

    Compares the stored pointers of the two smart pointers. +T need not be a complete type. +See the smart pointer +common requirements.

    +

    The operator< overload is provided to define an ordering so that weak_ptr +objects can be used in associative containers such as std::map. +The implementation uses std::less<T*> to perform the +comparison. This ensures that the comparison is handled correctly, since the +standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] +paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] +paragraph 8).

    + +

    swap

    +
    template<typename T>
    +  void swap(weak_ptr<T> & a, weak_ptr<T> & b) // never throws
    +

    Equivalent to a.swap(b). Matches the interface of std::swap. +Provided as an aid to generic programming.

    + +

    shared_static_cast

    +
    template<typename T, typename U>
    +  weak_ptr<T> shared_static_cast(weak_ptr<U> const & r); // never throws
    +

    Perform a static_cast on the stored pointer, returning another weak_ptr. +The resulting smart pointer will share its use count with the original pointer.

    + +

    shared_dynamic_cast

    +
    template<typename T, typename U>
    +  weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r);
    +

    Perform a dynamic_cast on the stored pointer, returning another weak_ptr. +The resulting smart pointer will share its use count with the original pointer unless the result of the +cast is 0. The only exception which may be thrown is std::bad_alloc, which may be thrown during the +construction of the new weak_ptr if the result of the cast is 0. If an exception is thrown, the +cast has no effect.

    + +
    + +

    Revised 1 February 2002

    + +

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

    + + + + From ddd6d5442637e1f47f5b8eeb3c995d13f9d7b8e3 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sun, 3 Feb 2002 15:19:04 +0000 Subject: [PATCH 045/513] Need to include utility.hpp to get noncopyable [SVN r12669] --- scoped_ptr_example.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/scoped_ptr_example.hpp b/scoped_ptr_example.hpp index ae1fb8d..c4b6bf5 100644 --- a/scoped_ptr_example.hpp +++ b/scoped_ptr_example.hpp @@ -1,5 +1,6 @@ // Boost scoped_ptr_example header file ------------------------------------// +#include #include // The point of this example is to prove that even though From 590757e2b22b9a014ce37bc4d4902d8447115ed0 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sun, 3 Feb 2002 15:21:41 +0000 Subject: [PATCH 046/513] Don't give default arguments to function parameters what subsequent parameters do not have default arguments [SVN r12670] --- include/boost/shared_array.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index 4d400dc..3c8775f 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -75,7 +75,7 @@ public: this_type(p).swap(*this); } - template void reset(T * p = 0, D d) + template void reset(T * p, D d) { this_type(p, d).swap(*this); } From 758954a93f0ac047907ac58c4d3ea0a5df2580b1 Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Sun, 3 Feb 2002 17:46:08 +0000 Subject: [PATCH 047/513] Documentation updates. [SVN r12675] --- shared_array.htm | 2 +- shared_ptr.htm | 2 +- weak_ptr.htm | 11 ----------- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/shared_array.htm b/shared_array.htm index 8d21823..2b818e7 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -97,7 +97,7 @@ If an exception is thrown, delete[] p is called.

    template<typename D> shared_array(T * p, D d);

    Constructs a shared_array, storing a copy of p and of d. Afterwards, the use count is 1. -D's copy constructor must not throw. +D's copy constructor and destructor must not throw. When the the time comes to delete the array pointed to by p, the object d is used in the statement d(p). Invoking the object d with parameter p in this way must not throw. diff --git a/shared_ptr.htm b/shared_ptr.htm index fc6d0d6..7773c2b 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -118,7 +118,7 @@ If an exception is thrown, delete p is called.

    template<typename D> shared_ptr(T * p, D d);

    Constructs a shared_ptr, storing a copy of p and of d. Afterwards, the use count is 1. -D's copy constructor must not throw. +D's copy constructor and destructor must not throw. When the the time comes to delete the object pointed to by p, the object d is used in the statement d(p). Invoking the object d with parameter p in this way must not throw. diff --git a/weak_ptr.htm b/weak_ptr.htm index fb97eac..545195f 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -11,17 +11,6 @@

    c++boost.gif (8819 bytes)weak_ptr class template

    -

    Introduction
    -Synopsis
    -Members
    -Free Functions
    -Example
    -Handle/Body Idiom
    -Frequently Asked Questions
    -Smart Pointer Timings

    - -

    Introduction

    -

    The weak_ptr class template stores a pointer to an object that's already managed by a shared_ptr. When the object last shared_ptr to the object goes away and the object From ee3d3bd1e199033c4ee55030aed6aa069ef86e01 Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Sun, 3 Feb 2002 17:50:11 +0000 Subject: [PATCH 048/513] Mention thread safety feature. [SVN r12676] --- compatibility.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compatibility.htm b/compatibility.htm index 65acfd7..fb4d0a5 100644 --- a/compatibility.htm +++ b/compatibility.htm @@ -58,7 +58,7 @@ Calling reset with a pointer to the object that's already owned by the

      -
    • The manipulation of use counts is now thread safe on Windows, Linux, and platforms +
    • The manipulation of use counts is now thread safe on Windows, Linux, and platforms that support pthreads. See the <boost/detail/atomic_count.hpp> file for details
    • From 6ed07733cba5f13abf631642a171aa9b3209a098 Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Mon, 4 Feb 2002 08:00:20 +0000 Subject: [PATCH 049/513] Fix atomic_count.hpp includes, convert Macintosh newlines to Unix ones, since Metrowerks supports either and the rest of Boost uses Unix ones. [SVN r12683] --- include/boost/detail/atomic_count.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 0f33ac4..6486755 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -91,15 +91,15 @@ typedef long atomic_count; #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -#include "atomic_count_win32.hpp" +#include #elif defined(linux) || defined(__linux) || defined(__linux__) -#include "atomic_count_linux.hpp" +#include #elif defined(BOOST_HAS_PTHREADS) -#include "atomic_count_pthreads.hpp" +#include #else From c29cc62d66616ef76e70f6d7250d868c4fcf1e78 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Feb 2002 11:15:40 +0000 Subject: [PATCH 050/513] Minor tweaks. [SVN r12684] --- include/boost/detail/shared_array_nmt.hpp | 2 +- include/boost/detail/shared_ptr_nmt.hpp | 2 +- include/boost/scoped_array.hpp | 3 ++- include/boost/scoped_ptr.hpp | 3 ++- include/boost/shared_array.hpp | 2 +- include/boost/shared_ptr.hpp | 4 +++- include/boost/weak_ptr.hpp | 4 +++- weak_ptr.htm | 4 +--- 8 files changed, 14 insertions(+), 10 deletions(-) diff --git a/include/boost/detail/shared_array_nmt.hpp b/include/boost/detail/shared_array_nmt.hpp index 570af13..3ff1954 100644 --- a/include/boost/detail/shared_array_nmt.hpp +++ b/include/boost/detail/shared_array_nmt.hpp @@ -12,7 +12,7 @@ // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation. // #include diff --git a/include/boost/detail/shared_ptr_nmt.hpp b/include/boost/detail/shared_ptr_nmt.hpp index 5364e77..79d5b5d 100644 --- a/include/boost/detail/shared_ptr_nmt.hpp +++ b/include/boost/detail/shared_ptr_nmt.hpp @@ -12,7 +12,7 @@ // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. // #include diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index 74ecebe..c4fa3d0 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -9,7 +9,8 @@ // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/smart_ptr/scoped_array.htm for documentation. +// #include #include // in case ptrdiff_t not in std diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 6648f09..e2a3ddf 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -9,7 +9,8 @@ // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation. +// #include diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index 3c8775f..a820abc 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -12,7 +12,7 @@ // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation. // #include // for broken compiler workarounds diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index d601bab..e6411c3 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -12,7 +12,7 @@ // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. // #include // for broken compiler workarounds @@ -109,7 +109,9 @@ public: shared_ptr(shared_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) { if (px == 0) // need to allocate new counter -- the cast failed + { pn = detail::shared_count(static_cast(0), deleter()); + } } #ifndef BOOST_NO_AUTO_PTR diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 087ab12..f96856a 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -11,7 +11,7 @@ // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation. // #include @@ -68,7 +68,9 @@ public: weak_ptr(weak_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) { if (px == 0) // need to allocate new counter -- the cast failed + { pn = detail::weak_count(); + } } template diff --git a/weak_ptr.htm b/weak_ptr.htm index 545195f..10a0c2c 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -90,9 +90,7 @@ If an exception is thrown, the constructor has no effect.

      template<typename Y> weak_ptr(shared_ptr<Y> const & r); // never throws

      Constructs a weak_ptr, as if by storing a copy of the pointer stored in r. Afterwards, the use count for all copies is unchanged. -When the last shared_ptr is destroyed, the use count and stored pointer become 0. -The only exception which may be thrown by this constructor is std::bad_alloc. -If an exception is thrown, the constructor has no effect.

      +When the last shared_ptr is destroyed, the use count and stored pointer become 0.

      weak_ptr(weak_ptr const & r); // never throws
       template<typename Y> weak_ptr(weak_ptr<Y> const & r); // never throws
      From 08df55159baad83c9ccfa9166bac4bd78d0d3383 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Mon, 4 Feb 2002 18:51:16 +0000 Subject: [PATCH 051/513] Fix broken links [SVN r12697] --- smart_ptr.htm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/smart_ptr.htm b/smart_ptr.htm index 0f5246d..682a675 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -29,27 +29,27 @@ thus responsible for deletion of the object when it is no longer needed.

      - + - + - + - + - +
      scoped_ptr<boost/scoped_ptr.hpp><boost/scoped_ptr.hpp> Simple sole ownership of single objects. Noncopyable.
      scoped_array<boost/scoped_array.hpp><boost/scoped_array.hpp> Simple sole ownership of arrays. Noncopyable.
      shared_ptr<boost/shared_ptr.hpp><boost/shared_ptr.hpp> Object ownership shared among multiple pointers
      shared_array<boost/shared_array.hpp><boost/shared_array.hpp> Array ownership shared among multiple pointers.
      weak_ptr<boost/weak_ptr.hpp><boost/weak_ptr.hpp> Non-owning observers of an object owned by shared_ptr.
      @@ -196,7 +196,7 @@ implementation.


      Revised 1 February 200204 February 2002

      Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. From e1567707b1f6921cd796236b08bac52dcdd259f4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Feb 2002 19:45:11 +0000 Subject: [PATCH 052/513] Tab removed :-) [SVN r12701] --- smart_ptr_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smart_ptr_test.cpp b/smart_ptr_test.cpp index 8d41070..baee93d 100644 --- a/smart_ptr_test.cpp +++ b/smart_ptr_test.cpp @@ -27,7 +27,7 @@ bool boost_error(char const *, char const *, char const *, long) { - return true; // fail with assert() + return true; // fail with assert() } class Incomplete; From f9782387d9524b91092a7df63f4e8ccf4524c3e3 Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Mon, 4 Feb 2002 22:52:48 +0000 Subject: [PATCH 053/513] Tweaks. [SVN r12715] --- include/boost/scoped_array.hpp | 6 +++--- shared_array.htm | 4 ++-- shared_ptr.htm | 4 ++-- smart_ptr.htm | 2 +- weak_ptr.htm | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index c4fa3d0..6734c5e 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -27,7 +27,7 @@ template class scoped_array // noncopyable { private: - T* ptr; + T * ptr; scoped_array(scoped_array const &); scoped_array & operator=(scoped_array const &); @@ -57,14 +57,14 @@ public: } } - T& operator[](std::ptrdiff_t i) const // never throws + T & operator[](std::ptrdiff_t i) const // never throws { BOOST_ASSERT(ptr != 0); BOOST_ASSERT(i >= 0); return ptr[i]; } - T* get() const // never throws + T * get() const // never throws { return ptr; } diff --git a/shared_array.htm b/shared_array.htm index 2b818e7..12c353e 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -197,10 +197,10 @@ See the smart pointer common requirements.

      The operator< overload is provided to define an ordering so that shared_array objects can be used in associative containers such as std::map. -The implementation uses std::less<T*> to perform the +The implementation uses std::less<T *> to perform the comparison. This ensures that the comparison is handled correctly, since the standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] -paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] +paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] paragraph 8).

      swap

      diff --git a/shared_ptr.htm b/shared_ptr.htm index 7773c2b..42e23fe 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -230,10 +230,10 @@ See the smart pointer common requirements.

      The operator< overload is provided to define an ordering so that shared_ptr objects can be used in associative containers such as std::map. -The implementation uses std::less<T*> to perform the +The implementation uses std::less<T *> to perform the comparison. This ensures that the comparison is handled correctly, since the standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] -paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] +paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] paragraph 8).

      swap

      diff --git a/smart_ptr.htm b/smart_ptr.htm index 682a675..c6782a4 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -196,7 +196,7 @@ implementation.


      Revised 04 February 20024 February 2002

      Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. diff --git a/weak_ptr.htm b/weak_ptr.htm index 10a0c2c..a28232b 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -178,10 +178,10 @@ See the smart pointer common requirements.

      The operator< overload is provided to define an ordering so that weak_ptr objects can be used in associative containers such as std::map. -The implementation uses std::less<T*> to perform the +The implementation uses std::less<T *> to perform the comparison. This ensures that the comparison is handled correctly, since the standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] -paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] +paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] paragraph 8).

      swap

      From 0dd3285d5668ca25da0858ca9cce80a972a5d6dd Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Wed, 6 Feb 2002 19:42:04 +0000 Subject: [PATCH 054/513] New casts for smart pointers. [SVN r12743] --- include/boost/shared_ptr.hpp | 23 ++++++++++++++++++++++- include/boost/weak_ptr.hpp | 20 ++++++++++++++++++++ shared_ptr.htm | 24 ++++++++++++++++++++++-- weak_ptr.htm | 24 ++++++++++++++++++++++-- 4 files changed, 86 insertions(+), 5 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index e6411c3..c13c3a8 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -43,6 +43,7 @@ namespace detail struct static_cast_tag {}; struct dynamic_cast_tag {}; +struct polymorphic_cast_tag {}; template struct shared_ptr_traits { @@ -114,6 +115,15 @@ public: } } + template + shared_ptr(shared_ptr const & r, detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) + { + if (px == 0) + { + throw std::bad_cast(); + } + } + #ifndef BOOST_NO_AUTO_PTR template @@ -219,7 +229,7 @@ template inline bool operator<(shared_ptr const & a, shared_ptr()(a.get(), b.get()); } -template void swap(shared_ptr & a, shared_ptr & b) +template inline void swap(shared_ptr & a, shared_ptr & b) { a.swap(b); } @@ -234,6 +244,17 @@ template shared_ptr shared_dynamic_cast(shared_ptr return shared_ptr(r, detail::dynamic_cast_tag()); } +template shared_ptr shared_polymorphic_cast(shared_ptr const & r) +{ + return shared_ptr(r, detail::polymorphic_cast_tag()); +} + +template shared_ptr shared_polymorphic_downcast(shared_ptr const & r) +{ + BOOST_ASSERT(dynamic_cast(r.get()) == r.get()); + return shared_static_cast(r); +} + // get_pointer() enables boost::mem_fn to recognize shared_ptr template inline T * get_pointer(shared_ptr const & p) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index f96856a..c96d097 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -73,6 +73,15 @@ public: } } + template + weak_ptr(weak_ptr const & r, detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) + { + if (px == 0) + { + throw std::bad_cast(); + } + } + template weak_ptr & operator=(weak_ptr const & r) // never throws { @@ -170,6 +179,17 @@ template weak_ptr shared_dynamic_cast(weak_ptr const & r return weak_ptr(r, detail::dynamic_cast_tag()); } +template weak_ptr shared_polymorphic_cast(weak_ptr const & r) +{ + return weak_ptr(r, detail::polymorphic_cast_tag()); +} + +template weak_ptr shared_polymorphic_downcast(weak_ptr const & r) +{ + BOOST_ASSERT(dynamic_cast(r.get()) == r.get()); + return shared_static_cast(r); +} + // get_pointer() enables boost::mem_fn to recognize weak_ptr template inline T * get_pointer(weak_ptr const & p) diff --git a/shared_ptr.htm b/shared_ptr.htm index 42e23fe..0e9d426 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -97,6 +97,10 @@ function must be passed in, or the pointed-to object must have a trivial destruc shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws template<typename T, typename U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r); + template<typename T, typename U> + shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r); + template<typename T, typename U> + shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws }
    @@ -244,7 +248,7 @@ Provided as an aid to generic programming.

    shared_static_cast

    template<typename T, typename U>
    -  shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws
    + shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws

    Perform a static_cast on the stored pointer, returning another shared_ptr. The resulting smart pointer will share its use count with the original pointer.

    Note that the seemingly equivalent expression

    @@ -253,7 +257,7 @@ The resulting smart pointer will share its use count with the original pointer.<

    shared_dynamic_cast

    template<typename T, typename U>
    -  shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r);
    + shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r);

    Perform a dynamic_cast on the stored pointer, returning another shared_ptr. The resulting smart pointer will share its use count with the original pointer unless the result of the cast is 0. The only exception which may be thrown is std::bad_alloc, which may be thrown during the @@ -263,6 +267,22 @@ cast has no effect.

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

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

    +

    shared_polymorphic_cast

    +
    template<typename T, typename U>
    +  shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r);
    +

    Perform a polymorphic_cast on the stored pointer, +returning another shared_ptr. +The resulting smart pointer will share its use count with the original pointer. +The only exception which may be thrown is std::bad_cast, if the pointer type can not be converted. +If an exception is thrown, the cast has no effect.

    + +

    shared_polymorphic_downcast

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

    Perform a polymorphic_downcast on the stored pointer, +returning another shared_ptr. +The resulting smart pointer will share its use count with the original pointer.

    +

    Example

    See shared_ptr_example.cpp for a complete example program. diff --git a/weak_ptr.htm b/weak_ptr.htm index a28232b..ccedf19 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -71,6 +71,10 @@ pointed to. T must meet the smart pointer weak_ptr<T> shared_static_cast(weak_ptr<U> const & r); // never throws template<typename T, typename U> weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r); + template<typename T, typename U> + weak_ptr<T> shared_polymorphic_cast(weak_ptr<U> const & r); + template<typename T, typename U> + weak_ptr<T> shared_polymorphic_downcast(weak_ptr<U> const & r); // never throws }

    @@ -192,19 +196,35 @@ Provided as an aid to generic programming.

    shared_static_cast

    template<typename T, typename U>
    -  weak_ptr<T> shared_static_cast(weak_ptr<U> const & r); // never throws
    + weak_ptr<T> shared_static_cast(weak_ptr<U> const & r); // never throws

    Perform a static_cast on the stored pointer, returning another weak_ptr. The resulting smart pointer will share its use count with the original pointer.

    shared_dynamic_cast

    template<typename T, typename U>
    -  weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r);
    + weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r);

    Perform a dynamic_cast on the stored pointer, returning another weak_ptr. The resulting smart pointer will share its use count with the original pointer unless the result of the cast is 0. The only exception which may be thrown is std::bad_alloc, which may be thrown during the construction of the new weak_ptr if the result of the cast is 0. If an exception is thrown, the cast has no effect.

    +

    shared_polymorphic_cast

    +
    template<typename T, typename U>
    +  weak_ptr<T> shared_polymorphic_cast(weak_ptr<U> const & r);
    +

    Perform a polymorphic_cast on the stored pointer, +returning another weak_ptr. +The resulting smart pointer will share its use count with the original pointer. +The only exception which may be thrown is std::bad_cast, if the pointer type can not be converted. +If an exception is thrown, the cast has no effect.

    + +

    shared_polymorphic_downcast

    +
    template<typename T, typename U>
    +  weak_ptr<T> shared_polymorphic_downcast(weak_ptr<U> const & r); // never throws
    +

    Perform a polymorphic_downcast on the stored pointer, +returning another weak_ptr. +The resulting smart pointer will share its use count with the original pointer.

    +

    Revised 1 February 2002

    From 2a2f10fddda938029638387dc5ff1e4c52ba590e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Feb 2002 18:40:49 +0000 Subject: [PATCH 055/513] Borland 5.5.1 fix [SVN r12761] --- include/boost/weak_ptr.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index c96d097..170359d 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -110,14 +110,14 @@ public: typename detail::shared_ptr_traits::reference operator* () const // never throws { - T * p = get(); + element_type * p = get(); BOOST_ASSERT(p != 0); return *p; } T * operator-> () const // never throws { - T * p = get(); + element_type * p = get(); BOOST_ASSERT(p != 0); return p; } From 7add76dae81b8430d3f21d426b708ed29ee5ea99 Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Fri, 8 Feb 2002 20:08:15 +0000 Subject: [PATCH 056/513] Always say "private noncopyable" to avoid warnings. [SVN r12762] --- scoped_ptr_example.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scoped_ptr_example.hpp b/scoped_ptr_example.hpp index c4b6bf5..d3009f7 100644 --- a/scoped_ptr_example.hpp +++ b/scoped_ptr_example.hpp @@ -9,7 +9,7 @@ // is complete where it counts - in the inplementation translation unit where // destruction is actually instantiated. -class example : boost::noncopyable +class example : private boost::noncopyable { public: example(); From 87f0accb23348282619dea861c8d354e5720ed69 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Feb 2002 20:45:04 +0000 Subject: [PATCH 057/513] Minor fixes. [SVN r12763] --- shared_array.htm | 6 +++--- shared_ptr.htm | 12 ++++++------ weak_ptr.htm | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/shared_array.htm b/shared_array.htm index 12c353e..6ecc911 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -54,10 +54,10 @@ pointed to. T must meet the smart pointer
    shared_array(shared_array const & r); // never throws - shared_array & operator=(shared_array const & r); // never throws + shared_array & operator=(shared_array const & r); // never throws - void reset(T * p = 0); // never throws - template<typename D> void reset(T * p, D d); // never throws + void reset(T * p = 0); + template<typename D> void reset(T * p, D d); T & operator[](std::ptrdiff_t i) const() const; // never throws T * get() const; // never throws diff --git a/shared_ptr.htm b/shared_ptr.htm index 0e9d426..3f4c366 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -71,8 +71,8 @@ function must be passed in, or the pointed-to object must have a trivial destruc template<typename Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r); - void reset(T * p = 0); // never throws - template<typename D> void reset(T * p, D d); // never throws + void reset(T * p = 0); + template<typename D> void reset(T * p, D d); T & operator*() const; // never throws T * operator->() const; // never throws @@ -88,8 +88,8 @@ function must be passed in, or the pointed-to object must have a trivial destruc bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws template<typename T, typename U> bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws - template<typename T, typename U> - bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws + template<typename T> + bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws template<typename T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws @@ -226,8 +226,8 @@ See the smart pointer bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws template<typename T, typename U> bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws -template<typename T, typename U> - bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
    +template<typename T> + bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws

    Compares the stored pointers of the two smart pointers. T need not be a complete type. See the smart pointer diff --git a/weak_ptr.htm b/weak_ptr.htm index ccedf19..25ae561 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -47,7 +47,7 @@ pointed to. T must meet the smart pointer template<typename Y> weak_ptr & operator=(weak_ptr<Y> const & r); // never throws template<typename Y> weak_ptr & operator=(shared_ptr<Y> const & r); // never throws - void reset(); // never throws + void reset(); T & operator*() const; // never throws T * operator->() const; // never throws @@ -62,8 +62,8 @@ pointed to. T must meet the smart pointer bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws template<typename T, typename U> bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws - template<typename T, typename U> - bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws + template<typename T> + bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws template<typename T> void swap(weak_ptr<T> & a, weak_ptr<T> & b); // never throws @@ -174,8 +174,8 @@ See the smart pointer bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws template<typename T, typename U> bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws -template<typename T, typename U> - bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws

    +template<typename T> + bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws

    Compares the stored pointers of the two smart pointers. T need not be a complete type. See the smart pointer From a6126b137029205c49e5598ce1767d6f402e1875 Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Sat, 9 Feb 2002 01:18:00 +0000 Subject: [PATCH 058/513] Fixed some broken internal links. [SVN r12766] --- shared_array.htm | 16 ++++++++-------- shared_ptr.htm | 14 +++++++------- weak_ptr.htm | 16 ++++++++-------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/shared_array.htm b/shared_array.htm index 6ecc911..3319553 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -23,7 +23,7 @@ are supplied so that shared_array works with the standard library's associative containers.

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

    Because the implementation uses reference counting, shared_array will not work @@ -69,11 +69,11 @@ pointed to. T must meet the smart pointer }; template<typename T> - bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws + bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws template<typename T> - bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws + bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws template<typename T> - bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws + bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws template<typename T> void swap(shared_array<T> & a, shared_array<T> & b); // never throws @@ -186,11 +186,11 @@ See the smart pointer

    comparison

    template<typename T>
    -  bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws
    +  bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws
     template<typename T>
    -  bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws
    +  bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws
     template<typename T>
    -  bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws
    + bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws

    Compares the stored pointers of the two smart pointers. T need not be a complete type. See the smart pointer @@ -211,7 +211,7 @@ Provided as an aid to generic programming.


    -

    Revised 1 February 2002

    +

    Revised 8 February 2002

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Permission to copy, use, modify, sell and distribute this document is granted diff --git a/shared_ptr.htm b/shared_ptr.htm index 3f4c366..0cc96f1 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -85,11 +85,11 @@ function must be passed in, or the pointed-to object must have a trivial destruc }; template<typename T, typename U> - bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws + bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws template<typename T, typename U> - bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws + bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws template<typename T> - bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws + bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws template<typename T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws @@ -223,11 +223,11 @@ See the smart pointer

    comparison

    template<typename T, typename U>
    -  bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
    +  bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
     template<typename T, typename U>
    -  bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
    +  bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
     template<typename T>
    -  bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws
    + bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws

    Compares the stored pointers of the two smart pointers. T need not be a complete type. See the smart pointer @@ -363,7 +363,7 @@ This is not the intent.


    -

    Revised 1 February 2002

    +

    Revised 8 February 2002

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Permission to copy, use, modify, sell and distribute this document is granted diff --git a/weak_ptr.htm b/weak_ptr.htm index 25ae561..9ef44d4 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -36,7 +36,7 @@ pointed to. T must meet the smart pointer public: typedef T element_type; - explicit weak_ptr(); + weak_ptr(); template<typename Y> weak_ptr(shared_ptr<Y> const & r); // never throws ~weak_ptr(); // never throws @@ -59,11 +59,11 @@ pointed to. T must meet the smart pointer }; template<typename T, typename U> - bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws + bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws template<typename T, typename U> - bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws + bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws template<typename T> - bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws + bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws template<typename T> void swap(weak_ptr<T> & a, weak_ptr<T> & b); // never throws @@ -171,11 +171,11 @@ See the smart pointer

    comparison

    template<typename T, typename U>
    -  bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    +  bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
     template<typename T, typename U>
    -  bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    +  bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
     template<typename T>
    -  bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws
    + bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws

    Compares the stored pointers of the two smart pointers. T need not be a complete type. See the smart pointer @@ -227,7 +227,7 @@ The resulting smart pointer will share its use count with the original pointer.<


    -

    Revised 1 February 2002

    +

    Revised 8 February 2002

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Permission to copy, use, modify, sell and distribute this document is granted From d2e20cf56cdaf6d41e071b67a8cbd7fa66cfdf68 Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Sat, 9 Feb 2002 02:54:00 +0000 Subject: [PATCH 059/513] Remove obsolete paragraph [SVN r12767] --- smart_ptr.htm | 2 -- 1 file changed, 2 deletions(-) diff --git a/smart_ptr.htm b/smart_ptr.htm index c6782a4..ce7e38e 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -191,8 +191,6 @@ preferred, and that was also experimented with.

    discourage users", and in the end we choose to supply only the direct implementation.

    -

    See the Revision History section of the header for further contributors.

    -

    Revised 8 February 2002

    - -

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

    - - - +// Who owns p now? b will still call delete on it in its destructor. + +

    Q. Why doesn't shared_ptr provide (your pet feature here)?
    + A. Because (your pet feature here) would mandate a reference counted + implementation or a linked list implementation, or some other specific + implementation. This is not the intent.

    +
    +

    Revised  + 14 February 2002

    +

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

    + From 5e2f514140fe9c9d9e2809714bb3cc4ff59960a3 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 14 Feb 2002 23:08:30 +0000 Subject: [PATCH 067/513] Added forward declaration of 'weak_count' class, which is referenced in shared_count; the friend declaration does not suffice to forward-declare the name. [SVN r12813] --- include/boost/detail/shared_count.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 120fd47..2e0dc47 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -174,6 +174,7 @@ public: } }; +class weak_count; class shared_count { From 5a6cd1cf3ee66077dc14ca17a421f6869859197d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 15 Feb 2002 13:31:58 +0000 Subject: [PATCH 068/513] Added a default constructor to shared_count and shared_ptr for incomplete types (void). [SVN r12815] --- include/boost/detail/shared_count.hpp | 6 +++- include/boost/shared_ptr.hpp | 15 ++++++-- shared_ptr.htm | 50 +++++++++++++++++++++------ 3 files changed, 57 insertions(+), 14 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 2e0dc47..d513329 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -186,6 +186,10 @@ private: public: + shared_count(): pi_(new counted_base(1, 1)) + { + } + template shared_count(P p, D d): pi_(0) { try @@ -221,7 +225,7 @@ public: pi_->add_ref(); } - explicit shared_count(weak_count const & r); // throws bad_weak_to_shared_cast when r.use_count() == 0 + explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0 shared_count & operator= (shared_count const & r) // nothrow { diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index bd0fcff..e2ddb94 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -81,7 +81,11 @@ public: typedef T element_type; - explicit shared_ptr(T * p = 0): px(p), pn(p, deleter()) + shared_ptr(): px(0), pn() + { + } + + explicit shared_ptr(T * p): px(p), pn(p, deleter()) // requires complete type { } @@ -157,9 +161,14 @@ public: #endif - void reset(T * p = 0) + void reset() { - BOOST_ASSERT(p == 0 || p != px); + this_type().swap(*this); + } + + void reset(T * p) // requires complete type + { + BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors this_type(p).swap(*this); } diff --git a/shared_ptr.htm b/shared_ptr.htm index be3b1c5..ae1c36d 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -40,6 +40,8 @@

    Synopsis

    namespace boost {
     
    +  class use_count_is_zero: public std::exception;
    +
       template<typename T> class weak_ptr;
     
       template<typename T> class shared_ptr {
    @@ -47,20 +49,22 @@
         public:
           typedef T element_type;
     
    -      explicit shared_ptr(T * p = 0);
    +      shared_ptr ();
    +      explicit shared_ptr (T * p); // requires complete type
           template<typename D> shared_ptr(T * p, D d);
           ~shared_ptr(); // never throws
     
           shared_ptr(shared_ptr const & r); // never throws
           template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws
    -      shared_ptr(weak_ptr const & r);
    +      explicit shared_ptr(weak_ptr const & r);
           template<typename Y> shared_ptr(std::auto_ptr<Y> & r);
     
           shared_ptr & operator=(shared_ptr const & r); // never throws  
           template<typename Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
           template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
     
    -      void reset(T * p = 0);
    +      void reset ();
    +      void reset (T * p); // requires complete type
           template<typename D> void reset(T * p, D d);
     
           T & operator*() const; // never throws
    @@ -99,7 +103,18 @@
     			

    Provides the type of the template parameter T.

    constructors

    -
    explicit shared_ptr(T * p = 0);
    +
    shared_ptr();
    +
    +

    Effects: Constructs a shared_ptr.

    +

    Postconditions: use count is 1; the stored + pointer is 0.

    +

    Throws: std::bad_alloc.

    +

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

    +

    Notes: T need not be a complete type. See the smart pointer + common requirements.

    +
    +
    explicit shared_ptr(T * p);

    Requirements: The expression delete p must be well-formed and must not invoke undefined behavior. @@ -136,7 +151,7 @@ template<typename Y> shared_ptr(shared_ptr<Y> const & r); // nev increased by one.

    Throws: nothing.

    -
    shared_ptr(weak_ptr const & r);
    +
    explicit shared_ptr(weak_ptr const & r);

    Effects: Constructs a shared_ptr, as if by storing a copy of the pointer stored in r.

    @@ -174,11 +189,26 @@ template<typename Y> shared_ptr & operator=(shared_ptr<Y> const template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r);

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

    +

    Notes: 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);
    +p = p;
    +q = p;
    +
    +

    both assignments may be no-ops.

    reset

    -
    void reset(T * p = 0);
    +
    void reset();
    +
    +

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

    +
    +
    void reset(T * p);

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

    +

    Notes: Note the implied requirement that T is a complete type.

    template<typename D> void reset(T * p, D d);
    @@ -312,8 +342,8 @@ template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> &am shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r);

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

    + polymorphic_cast<T*>(r.get()) must be well-formed and + its behavior defined.

    Returns: A shared_ptr<T> object that stores a copy of polymorphic_cast<T*>(r.get()) and shares ownership with r.

    @@ -325,8 +355,8 @@ template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> &am shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws

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

    + polymorphic_downcast<T*>(r.get()) must be well-formed + and its behavior defined.

    Returns: A shared_ptr<T> object that stores a copy of polymorphic_downcast<T*>(r.get()) and shares ownership with r.

    From adc3ec3851eb3d86b99a55db8cee7783f195f194 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 15 Feb 2002 14:19:30 +0000 Subject: [PATCH 069/513] Fixes. [SVN r12816] --- include/boost/shared_ptr.hpp | 2 +- shared_ptr.htm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index e2ddb94..0c00e9a 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -120,7 +120,7 @@ public: { if (px == 0) // need to allocate new counter -- the cast failed { - pn = detail::shared_count(static_cast(0), deleter()); + pn = detail::shared_count(); } } diff --git a/shared_ptr.htm b/shared_ptr.htm index ae1c36d..ff3e5aa 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -347,7 +347,7 @@ q = p;

    Returns: A shared_ptr<T> object that stores a copy of polymorphic_cast<T*>(r.get()) and shares ownership with r.

    -

    Throws: std::bad_cast.

    +

    Throws: std::bad_cast when the pointer cannot be converted.

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

    shared_polymorphic_downcast

    From 862dc0001fb6baa0dad292986a7b6369b1fc3564 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 15 Feb 2002 14:46:53 +0000 Subject: [PATCH 070/513] Documented the bool conversion. [SVN r12817] --- shared_ptr.htm | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index ff3e5aa..8dbd3a1 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -74,6 +74,8 @@ bool unique() const; // never throws long use_count() const; // never throws + operator implementation-defined-type () const; // never throws + void swap(shared_ptr<T> & b); // never throws }; @@ -255,6 +257,17 @@ q = p; be a complete type. See the smart pointer common requirements.

    +

    conversions

    +
    operator implementation-defined-type () const; // never throws
    +
    +

    Returns: an implementation defined 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, avloiding many + of the implicit conversion pitfalls.

    +

    swap

    void swap(shared_ptr & b); // never throws
    @@ -284,7 +297,7 @@ q = p;
    template<typename T>
       bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws
    -

    Returns: An implementation-defined value such that operator< +

    Returns: an implementation-defined value such that operator< is a strict weak ordering as described in section 25.3 [lib.alg.sorting] of the C++ standard.

    Throws: nothing.

    @@ -347,7 +360,8 @@ q = p;

    Returns: A shared_ptr<T> object that stores a copy of polymorphic_cast<T*>(r.get()) and shares ownership with r.

    -

    Throws: std::bad_cast when the pointer cannot be converted.

    +

    Throws: std::bad_cast when the pointer cannot be + converted.

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

    shared_polymorphic_downcast

    From 875bab352c9582f8699591a55cc7c2e479e4ba0c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 15 Feb 2002 18:06:17 +0000 Subject: [PATCH 071/513] Added a timing test for the single/multi threaded perf ratio (~2:1) [SVN r12821] --- shared_ptr_timing_test.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 shared_ptr_timing_test.cpp diff --git a/shared_ptr_timing_test.cpp b/shared_ptr_timing_test.cpp new file mode 100644 index 0000000..d456eaf --- /dev/null +++ b/shared_ptr_timing_test.cpp @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +int const n = 8 * 1024 * 1024; + +int main() +{ + std::vector< boost::shared_ptr > v; + boost::shared_ptr pi(new int); + + std::clock_t t = std::clock(); + + for(int i = 0; i < n; ++i) + { + v.push_back(pi); + } + + t = std::clock() - t; + + std::cout << static_cast(t) / CLOCKS_PER_SEC << '\n'; +} From 7981b647c31310cbc23d417d752a62ee7986478f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 15 Feb 2002 18:07:42 +0000 Subject: [PATCH 072/513] lwm_nop fixed to not emit warnings on g++; locking code #ifdef'ed since compilers sometimes have trouble removing it. [SVN r12822] --- include/boost/detail/lwm_nop.hpp | 23 +---------------------- include/boost/detail/shared_count.hpp | 12 ++++++++++++ 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/include/boost/detail/lwm_nop.hpp b/include/boost/detail/lwm_nop.hpp index 1d798e0..671a5b0 100644 --- a/include/boost/detail/lwm_nop.hpp +++ b/include/boost/detail/lwm_nop.hpp @@ -24,30 +24,9 @@ namespace detail class lightweight_mutex { -private: - - lightweight_mutex(lightweight_mutex const &); - lightweight_mutex & operator=(lightweight_mutex const &); - public: - lightweight_mutex() - { - } - - class scoped_lock - { - private: - - scoped_lock(scoped_lock const &); - scoped_lock & operator=(scoped_lock const &); - - public: - - explicit scoped_lock(lightweight_mutex &) - { - } - }; + typedef lightweight_mutex scoped_lock; }; } // namespace detail diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index d513329..9dfed4f 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -74,7 +74,9 @@ public: void add_ref() { +#ifdef BOOST_HAS_THREADS lightweight_mutex::scoped_lock lock(mtx_); +#endif if(use_count_ == 0) throw use_count_is_zero(); ++use_count_; ++weak_count_; @@ -86,7 +88,9 @@ public: long new_weak_count; { +#ifdef BOOST_HAS_THREADS lightweight_mutex::scoped_lock lock(mtx_); +#endif new_use_count = --use_count_; new_weak_count = --weak_count_; } @@ -106,7 +110,9 @@ public: void weak_add_ref() // nothrow { +#ifdef BOOST_HAS_THREADS lightweight_mutex::scoped_lock lock(mtx_); +#endif ++weak_count_; } @@ -115,7 +121,9 @@ public: long new_weak_count; { +#ifdef BOOST_HAS_THREADS lightweight_mutex::scoped_lock lock(mtx_); +#endif new_weak_count = --weak_count_; } @@ -127,7 +135,9 @@ public: long use_count() const // nothrow { +#ifdef BOOST_HAS_THREADS lightweight_mutex::scoped_lock lock(mtx_); +#endif return use_count_; } @@ -145,7 +155,9 @@ private: long use_count_; long weak_count_; +#ifdef BOOST_HAS_THREADS mutable lightweight_mutex mtx_; +#endif void (*self_deleter_) (counted_base *); }; From 2482e00224cf678e4e8363523bebbc53b56d7201 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 16 Feb 2002 13:23:01 +0000 Subject: [PATCH 073/513] Modified scoped_* to use checked_delete; HP aCC doesn't like the inline assertions. [SVN r12832] --- include/boost/scoped_array.hpp | 8 +++----- include/boost/scoped_ptr.hpp | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index 6734c5e..070925c 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -13,6 +13,7 @@ // #include +#include #include // in case ptrdiff_t not in std #include // for std::ptrdiff_t @@ -42,17 +43,14 @@ public: ~scoped_array() // never throws { - typedef char type_must_be_complete[sizeof(T)]; - delete [] ptr; + checked_array_delete(ptr); } void reset(T * p = 0) // never throws { - typedef char type_must_be_complete[sizeof(T)]; - if (ptr != p) { - delete [] ptr; + checked_array_delete(ptr); ptr = p; } } diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index e2a3ddf..f452f7a 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -13,6 +13,7 @@ // #include +#include namespace boost { @@ -41,17 +42,14 @@ public: ~scoped_ptr() // never throws { - typedef char type_must_be_complete[sizeof(T)]; - delete ptr; + checked_delete(ptr); } void reset(T * p = 0) // never throws { - typedef char type_must_be_complete[sizeof(T)]; - if (ptr != p) { - delete ptr; + checked_delete(ptr); ptr = p; } } From 6e6a2a013afeee29f7c5f3de6d73686c13b8da6a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 16 Feb 2002 14:34:34 +0000 Subject: [PATCH 074/513] Added lwm_linux.hpp [SVN r12833] --- include/boost/detail/lwm_linux.hpp | 78 ++++++++++++++++++++++++++++++ include/boost/detail/lwm_win32.hpp | 11 ++--- 2 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 include/boost/detail/lwm_linux.hpp diff --git a/include/boost/detail/lwm_linux.hpp b/include/boost/detail/lwm_linux.hpp new file mode 100644 index 0000000..c2ef69a --- /dev/null +++ b/include/boost/detail/lwm_linux.hpp @@ -0,0 +1,78 @@ +#ifndef BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED +#define BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/lwm_linux.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include + +namespace boost +{ + +namespace detail +{ + +class lightweight_mutex +{ +private: + + atomic_t a_; + + lightweight_mutex(lightweight_mutex const &); + lightweight_mutex & operator=(lightweight_mutex const &); + +public: + + lightweight_mutex() + { + atomic_t a = ATOMIC_INIT(1); + a_ = a; + } + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock + { + private: + + lightweight_mutex & m_; + + scoped_lock(scoped_lock const &); + scoped_lock & operator=(scoped_lock const &); + + public: + + explicit scoped_lock(lightweight_mutex & m): m_(m) + { + while( !atomic_dec_and_test(&m_.a_) ) + { + atomic_inc(&m_.a_); + // sched_yield(); + } + } + + ~scoped_lock() + { + atomic_inc(&m_.a_); + } + }; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED diff --git a/include/boost/detail/lwm_win32.hpp b/include/boost/detail/lwm_win32.hpp index 2a29c3d..60388d5 100644 --- a/include/boost/detail/lwm_win32.hpp +++ b/include/boost/detail/lwm_win32.hpp @@ -22,13 +22,10 @@ namespace boost namespace detail { -// Avoid #including +// avoid including -namespace win32 -{ extern "C" __declspec(dllimport) long __stdcall InterlockedExchange(long volatile *, long); extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long); -} class lightweight_mutex { @@ -61,14 +58,14 @@ public: explicit scoped_lock(lightweight_mutex & m): m_(m) { - while( win32::InterlockedExchange(&m_.l_, 1) ) win32::Sleep(0); + while( InterlockedExchange(&m_.l_, 1) ) Sleep(0); } ~scoped_lock() { - win32::InterlockedExchange(&m_.l_, 0); + InterlockedExchange(&m_.l_, 0); - // Note: adding a win32::Sleep(0) here will make + // Note: adding a Sleep(0) here will make // the mutex more fair and will increase the overall // performance of the application substantially in // high contention situations, but will penalize the From 76c19e6111d197fb7fdd09aa2d2623f1b3667c17 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 16 Feb 2002 15:00:55 +0000 Subject: [PATCH 075/513] Enabled lwm_linux.hpp in lightweight_mutex.hpp. [SVN r12834] --- include/boost/detail/lightweight_mutex.hpp | 4 ++-- include/boost/detail/lwm_linux.hpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index 9f80b00..d4ef1c1 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -38,8 +38,8 @@ # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) # include -//#elif defined(linux) || defined(__linux) || defined(__linux__) -//# include +#elif defined(linux) || defined(__linux) || defined(__linux__) +# include #elif defined(BOOST_HAS_PTHREADS) # include #else diff --git a/include/boost/detail/lwm_linux.hpp b/include/boost/detail/lwm_linux.hpp index c2ef69a..f502d60 100644 --- a/include/boost/detail/lwm_linux.hpp +++ b/include/boost/detail/lwm_linux.hpp @@ -17,6 +17,7 @@ // #include +#include namespace boost { @@ -60,7 +61,7 @@ public: while( !atomic_dec_and_test(&m_.a_) ) { atomic_inc(&m_.a_); - // sched_yield(); + sched_yield(); } } From 9f295cbb48b76d2464c40adc5b1478d4351e4e69 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 16 Feb 2002 16:09:08 +0000 Subject: [PATCH 076/513] Threaded test added. [SVN r12837] --- shared_ptr_mt_test.cpp | 161 +++++++++++++++++++++++++++++++++++++ shared_ptr_test.cpp | 2 +- shared_ptr_timing_test.cpp | 18 +++++ 3 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 shared_ptr_mt_test.cpp diff --git a/shared_ptr_mt_test.cpp b/shared_ptr_mt_test.cpp new file mode 100644 index 0000000..ac1dac1 --- /dev/null +++ b/shared_ptr_mt_test.cpp @@ -0,0 +1,161 @@ +#if defined(_MSC_VER) && !defined(__ICL) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// shared_ptr_mt_test.cpp - tests shared_ptr with multiple threads +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include +#include + +#include +#include +#include + +#include + +// 'portable' thread framework + +class abstract_thread +{ +public: + + virtual ~abstract_thread() {} + virtual void run() = 0; +}; + +#if !defined(BOOST_HAS_PTHREADS) && defined(BOOST_HAS_WINTHREADS) + +char const * title = "Using Windows threads."; + +#include +#include + +typedef HANDLE pthread_t; + +unsigned __stdcall common_thread_routine(void * pv) +{ + abstract_thread * pt = static_cast(pv); + pt->run(); + delete pt; + return 0; +} + +int pthread_create(pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg) +{ + HANDLE h = (HANDLE)_beginthreadex(0, 0, start_routine, arg, 0, 0); + + if(h != 0) + { + *thread = h; + return 0; + } + else + { + return 1; // return errno; + } +} + +int pthread_join(pthread_t thread, void ** /*value_ptr*/) +{ + ::WaitForSingleObject(thread, INFINITE); + ::CloseHandle(thread); + return 0; +} + +#else + +char const * title = "Using POSIX threads."; + +#include + +extern "C" void* common_thread_routine(void * pv) +{ + abstract_thread * pt = static_cast(pv); + pt->run(); + delete pt; + return 0; +} + +#endif + +// + +template class thread: public abstract_thread +{ +public: + + explicit thread(F f): f_(f) + { + } + + void run() + { + f_(); + } + +private: + + F f_; +}; + +template pthread_t createThread(F f) +{ + std::auto_ptr p(new thread(f)); + + pthread_t r; + + if(pthread_create(&r, 0, common_thread_routine, p.get()) == 0) + { + p.release(); + return r; + } + + throw std::runtime_error("createThread failed."); +} + +// + +int const n = 1024 * 1024; + +void test(boost::shared_ptr const & pi) +{ + std::vector< boost::shared_ptr > v; + + for(int i = 0; i < n; ++i) + { + v.push_back(pi); + } +} + +int const m = 16; // threads + +int main() +{ + std::puts(title); + + boost::shared_ptr pi(new int); + + pthread_t a[m]; + + for(int i = 0; i < m; ++i) + { + a[i] = createThread( boost::bind(test, pi) ); + } + + for(int i = 0; i < m; ++i) + { + pthread_join(a[i], 0); + } +} diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 5039e65..0e4e86b 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -8,7 +8,7 @@ // // shared_ptr_test.cpp - a test for shared_ptr.hpp and weak_ptr.hpp // -// Copyright (c) 2001 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. diff --git a/shared_ptr_timing_test.cpp b/shared_ptr_timing_test.cpp index d456eaf..53fa314 100644 --- a/shared_ptr_timing_test.cpp +++ b/shared_ptr_timing_test.cpp @@ -1,3 +1,21 @@ +#if defined(_MSC_VER) && !defined(__ICL) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// shared_ptr_timing_test.cpp - use to evaluate the impact of thread safety +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + #include #include #include From 6dfe0896e3a5e2345dc55b978338416767915f13 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 16 Feb 2002 16:14:16 +0000 Subject: [PATCH 077/513] Untabified. [SVN r12838] --- shared_ptr_mt_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared_ptr_mt_test.cpp b/shared_ptr_mt_test.cpp index ac1dac1..af48918 100644 --- a/shared_ptr_mt_test.cpp +++ b/shared_ptr_mt_test.cpp @@ -143,9 +143,9 @@ int const m = 16; // threads int main() { - std::puts(title); + std::puts(title); - boost::shared_ptr pi(new int); + boost::shared_ptr pi(new int); pthread_t a[m]; From e6605637f8c22aac4155f83c1fac5de3b49a751d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 16 Feb 2002 18:45:20 +0000 Subject: [PATCH 078/513] BOOST_LWM_WIN32_USE_CRITICAL_SECTION option. [SVN r12842] --- include/boost/detail/lwm_win32.hpp | 59 +++++++++++++++++++++++++++++- shared_ptr_mt_test.cpp | 9 ++++- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/include/boost/detail/lwm_win32.hpp b/include/boost/detail/lwm_win32.hpp index 60388d5..8bcd469 100644 --- a/include/boost/detail/lwm_win32.hpp +++ b/include/boost/detail/lwm_win32.hpp @@ -16,12 +16,18 @@ // warranty, and with no claim as to its suitability for any purpose. // +#ifndef BOOST_LWM_WIN32_USE_CRITICAL_SECTION +# include +#endif + namespace boost { namespace detail { +#ifndef BOOST_LWM_WIN32_USE_CRITICAL_SECTION + // avoid including extern "C" __declspec(dllimport) long __stdcall InterlockedExchange(long volatile *, long); @@ -67,13 +73,64 @@ public: // Note: adding a Sleep(0) here will make // the mutex more fair and will increase the overall - // performance of the application substantially in + // performance of some applications substantially in // high contention situations, but will penalize the // low contention / single thread case up to 5x } }; }; +#else + +class lightweight_mutex +{ +private: + + CRITICAL_SECTION cs_; + + lightweight_mutex(lightweight_mutex const &); + lightweight_mutex & operator=(lightweight_mutex const &); + +public: + + lightweight_mutex() + { + ::InitializeCriticalSection(&cs_); + } + + ~lightweight_mutex() + { + ::DeleteCriticalSection(&cs_); + } + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock + { + private: + + lightweight_mutex & m_; + + scoped_lock(scoped_lock const &); + scoped_lock & operator=(scoped_lock const &); + + public: + + explicit scoped_lock(lightweight_mutex & m): m_(m) + { + ::EnterCriticalSection(&m_.cs_); + } + + ~scoped_lock() + { + ::LeaveCriticalSection(&m_.cs_); + } + }; +}; + +#endif + } // namespace detail } // namespace boost diff --git a/shared_ptr_mt_test.cpp b/shared_ptr_mt_test.cpp index af48918..2511716 100644 --- a/shared_ptr_mt_test.cpp +++ b/shared_ptr_mt_test.cpp @@ -19,6 +19,9 @@ #include #include +#define BOOST_INCLUDE_MAIN +#include + #include #include #include @@ -141,11 +144,11 @@ void test(boost::shared_ptr const & pi) int const m = 16; // threads -int main() +int test_main( int, char ** ) { std::puts(title); - boost::shared_ptr pi(new int); + boost::shared_ptr pi(new int(42)); pthread_t a[m]; @@ -158,4 +161,6 @@ int main() { pthread_join(a[i], 0); } + + return 0; } From 7b53c0040c0b73cc6cd4dd4b14f9d2c1fd77c222 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 18 Feb 2002 12:39:32 +0000 Subject: [PATCH 079/513] More output. [SVN r12852] --- shared_ptr_mt_test.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/shared_ptr_mt_test.cpp b/shared_ptr_mt_test.cpp index 2511716..831be86 100644 --- a/shared_ptr_mt_test.cpp +++ b/shared_ptr_mt_test.cpp @@ -27,6 +27,7 @@ #include #include +#include // 'portable' thread framework @@ -40,7 +41,7 @@ public: #if !defined(BOOST_HAS_PTHREADS) && defined(BOOST_HAS_WINTHREADS) -char const * title = "Using Windows threads."; +char const * title = "Using Windows threads"; #include #include @@ -79,7 +80,7 @@ int pthread_join(pthread_t thread, void ** /*value_ptr*/) #else -char const * title = "Using POSIX threads."; +char const * title = "Using POSIX threads"; #include @@ -146,10 +147,12 @@ int const m = 16; // threads int test_main( int, char ** ) { - std::puts(title); + std::printf("%s: %d threads, %d iterations, ", title, m, n); boost::shared_ptr pi(new int(42)); + std::clock_t t = std::clock(); + pthread_t a[m]; for(int i = 0; i < m; ++i) @@ -162,5 +165,9 @@ int test_main( int, char ** ) pthread_join(a[i], 0); } + t = std::clock() - t; + + std::printf("%.4f seconds.\n", static_cast(t) / CLOCKS_PER_SEC); + return 0; } From aa98e2b37ee1b0a4c4470816cf0817056db66a9d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 27 Feb 2002 16:35:15 +0000 Subject: [PATCH 080/513] Added lwm_irix.hpp (contributed by Dan Gohman) [SVN r12955] --- include/boost/detail/lightweight_mutex.hpp | 2 + include/boost/detail/lwm_irix.hpp | 78 ++++++++++++++++++++++ include/boost/detail/lwm_win32.hpp | 57 ---------------- 3 files changed, 80 insertions(+), 57 deletions(-) create mode 100644 include/boost/detail/lwm_irix.hpp diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index d4ef1c1..69a3a6c 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -40,6 +40,8 @@ # include #elif defined(linux) || defined(__linux) || defined(__linux__) # include +#elif defined(__sgi) +# include #elif defined(BOOST_HAS_PTHREADS) # include #else diff --git a/include/boost/detail/lwm_irix.hpp b/include/boost/detail/lwm_irix.hpp new file mode 100644 index 0000000..2a55161 --- /dev/null +++ b/include/boost/detail/lwm_irix.hpp @@ -0,0 +1,78 @@ +#ifndef BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED +#define BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/lwm_irix.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2002 Dan Gohman +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include +#include +#include + +namespace boost +{ + +namespace detail +{ + +class lightweight_mutex +{ +private: + + __uint32_t l_; + + lightweight_mutex(lightweight_mutex const &); + lightweight_mutex & operator=(lightweight_mutex const &); + +public: + + lightweight_mutex(): l_(0) + { + } + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock + { + private: + + lightweight_mutex & m_; + + scoped_lock(scoped_lock const &); + scoped_lock & operator=(scoped_lock const &); + + public: + + explicit scoped_lock(lightweight_mutex & m): m_(m) + { + while( test_and_set32(&m_.l_, 1) ) + { + sched_yield(); + } + } + + ~scoped_lock() + { + m_.l_ = 0; + } + }; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED diff --git a/include/boost/detail/lwm_win32.hpp b/include/boost/detail/lwm_win32.hpp index 8bcd469..3e79198 100644 --- a/include/boost/detail/lwm_win32.hpp +++ b/include/boost/detail/lwm_win32.hpp @@ -16,18 +16,12 @@ // warranty, and with no claim as to its suitability for any purpose. // -#ifndef BOOST_LWM_WIN32_USE_CRITICAL_SECTION -# include -#endif - namespace boost { namespace detail { -#ifndef BOOST_LWM_WIN32_USE_CRITICAL_SECTION - // avoid including extern "C" __declspec(dllimport) long __stdcall InterlockedExchange(long volatile *, long); @@ -80,57 +74,6 @@ public: }; }; -#else - -class lightweight_mutex -{ -private: - - CRITICAL_SECTION cs_; - - lightweight_mutex(lightweight_mutex const &); - lightweight_mutex & operator=(lightweight_mutex const &); - -public: - - lightweight_mutex() - { - ::InitializeCriticalSection(&cs_); - } - - ~lightweight_mutex() - { - ::DeleteCriticalSection(&cs_); - } - - class scoped_lock; - friend class scoped_lock; - - class scoped_lock - { - private: - - lightweight_mutex & m_; - - scoped_lock(scoped_lock const &); - scoped_lock & operator=(scoped_lock const &); - - public: - - explicit scoped_lock(lightweight_mutex & m): m_(m) - { - ::EnterCriticalSection(&m_.cs_); - } - - ~scoped_lock() - { - ::LeaveCriticalSection(&m_.cs_); - } - }; -}; - -#endif - } // namespace detail } // namespace boost From 3e0233a26cd4f920ad4482ce53651ab7790f67b6 Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Wed, 27 Feb 2002 17:03:30 +0000 Subject: [PATCH 081/513] Minor text updates in history section. [SVN r12956] --- smart_ptr.htm | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/smart_ptr.htm b/smart_ptr.htm index ce7e38e..1e045f1 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -138,15 +138,13 @@ destruction. Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and others.

    -

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

    +

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

    -

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

    +

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

    May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams -made a number of suggestions resulting in numerous improvements. See the -revision history in smart_ptr.hpp -for the specific changes made as a result of their constructive criticism.

    +made a number of suggestions resulting in numerous improvements.

    October 1998. In 1994 Greg Colvin proposed to the C++ Standards Committee classes named auto_ptr and counted_ptr which From 8e604a9da9f7e4c90c14a532f72aa47fddd6e349 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 1 Mar 2002 16:17:08 +0000 Subject: [PATCH 082/513] Disabled the linux-specific versions since using kernel headers is problematic. #define BOOST_USE_ASM_ATOMIC_H to get them back. [SVN r12995] --- include/boost/detail/atomic_count.hpp | 17 +++++++---------- include/boost/detail/atomic_count_linux.hpp | 8 +++++++- include/boost/detail/lightweight_mutex.hpp | 6 +++++- include/boost/detail/lwm_linux.hpp | 10 ++++++++++ 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 6486755..d97fafa 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -72,6 +72,8 @@ // are called driven by smart_ptr interface... // +// Note: atomic_count_linux.hpp has been disabled by default; see the +// comments inside for more info. #include @@ -90,17 +92,12 @@ typedef long atomic_count; } #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) - -#include - -#elif defined(linux) || defined(__linux) || defined(__linux__) - -#include - +# include +//#elif defined(linux) || defined(__linux) || defined(__linux__) +#elif defined(BOOST_USE_ASM_ATOMIC_H) +# include #elif defined(BOOST_HAS_PTHREADS) - -#include - +# include #else // #warning Unrecognized platform, detail::atomic_count will not be thread safe diff --git a/include/boost/detail/atomic_count_linux.hpp b/include/boost/detail/atomic_count_linux.hpp index 8fd5346..1a69cec 100644 --- a/include/boost/detail/atomic_count_linux.hpp +++ b/include/boost/detail/atomic_count_linux.hpp @@ -13,7 +13,13 @@ // // -// On Linux, atomic.h is usually located in /usr/include/asm +// This implementation uses . This is a kernel header; +// using kernel headers in a user program may cause a number of problems, +// and not all flavors of Linux provide the atomic instructions. +// +// This file is only provided because the performance of this implementation +// is significantly higher than the pthreads version. Use at your own risk +// (by defining BOOST_USE_ASM_ATOMIC_H.) // #include diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index 69a3a6c..d199114 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -31,6 +31,9 @@ // * Never keep a lightweight_mutex locked for long periods. // +// Note: lwm_linux.hpp has been disabled by default; see the comments +// inside for more info. + #include @@ -38,7 +41,8 @@ # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) # include -#elif defined(linux) || defined(__linux) || defined(__linux__) +//#elif defined(linux) || defined(__linux) || defined(__linux__) +#elif defined(BOOST_USE_ASM_ATOMIC_H) # include #elif defined(__sgi) # include diff --git a/include/boost/detail/lwm_linux.hpp b/include/boost/detail/lwm_linux.hpp index f502d60..c4b3b1d 100644 --- a/include/boost/detail/lwm_linux.hpp +++ b/include/boost/detail/lwm_linux.hpp @@ -16,6 +16,16 @@ // warranty, and with no claim as to its suitability for any purpose. // +// +// This implementation uses . This is a kernel header; +// using kernel headers in a user program may cause a number of problems, +// and not all flavors of Linux provide the atomic instructions. +// +// This file is only provided because the performance of this implementation +// is about 3.5 times higher than the pthreads version. Use at your own risk +// (by defining BOOST_USE_ASM_ATOMIC_H.) +// + #include #include From c17f8c36c12246d0beb0ddee4742a898dd74907c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Mar 2002 16:56:16 +0000 Subject: [PATCH 083/513] weak_ptr::expired() added; weak_ptr documentation updated. [SVN r13141] --- include/boost/weak_ptr.hpp | 7 +- shared_ptr.htm | 4 +- weak_ptr.htm | 416 ++++++++++++++++++++----------------- 3 files changed, 232 insertions(+), 195 deletions(-) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 9e9f1a2..33d762d 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -97,7 +97,7 @@ public: T * get() const // never throws; unsafe in multithreaded programs! { - return use_count() == 0? 0: px; + return pn.use_count() == 0? 0: px; } long use_count() const // never throws @@ -105,6 +105,11 @@ public: return pn.use_count(); } + bool expired() const // never throws + { + return pn.use_count() == 0; + } + void swap(this_type & other) // never throws { std::swap(px, other.px); diff --git a/shared_ptr.htm b/shared_ptr.htm index 8dbd3a1..49649e2 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -297,7 +297,7 @@ q = p;

    template<typename T>
       bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws
    -

    Returns: an implementation-defined value such that operator< +

    Returns: an implementation-defined value such that operator< is a strict weak ordering as described in section 25.3 [lib.alg.sorting] of the C++ standard.

    Throws: nothing.

    @@ -343,7 +343,7 @@ q = p;
  • Otherwise, a default-constructed shared_ptr<T> object.
  • Throws: std::bad_alloc.

    -

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

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

    Notes: the seemingly equivalent expression

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

    diff --git a/weak_ptr.htm b/weak_ptr.htm index 9ef44d4..6c1d5dd 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -1,35 +1,25 @@ - - - - -weak_ptr - - - - -

    c++boost.gif (8819 bytes)weak_ptr class template

    - -

    The weak_ptr class template stores a pointer to an -object that's already managed by a shared_ptr. When the -object last shared_ptr to the object goes away and the object -is deleted, all weak_ptr objects have their stored pointers -set to 0.

    - -

    Every weak_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 weak_ptr works with -the standard library's associative containers.

    - -

    The class template is parameterized on T, the type of the object -pointed to. T must meet the smart pointer -common requirements.

    - -

    Synopsis

    - -
    namespace boost {
    +	
    +		weak_ptr
    +		
    +	
    +	
    +		

    c++boost.gif (8819 bytes)weak_ptr + class template

    +

    The weak_ptr class template stores a pointer to an object that's already + managed by a shared_ptr. When the object last shared_ptr to the + object goes away and the object is deleted, all weak_ptr objects have + their stored pointers set to 0.

    +

    Every weak_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 weak_ptr works with the + standard library's associative containers.

    +

    The class template is parameterized on T, the type of the object pointed + to. T must meet the smart pointer + common requirements.

    +

    Synopsis

    +
    namespace boost {
     
       template<typename T> class weak_ptr {
     
    @@ -48,12 +38,10 @@ pointed to. T must meet the smart pointer
           template<typename Y> weak_ptr & operator=(shared_ptr<Y> const & r); // never throws
     
           void reset();
    -
    -      T & operator*() const; // never throws
    -      T * operator->() const; // never throws
    -      T * get() const; // never throws
    +      T * get() const; // never throws; unsafe in multithreaded code!
     
           long use_count() const; // never throws
    +      bool expired() const; // never throws
     
           void swap(weak_ptr<T> & b); // never throws
       };
    @@ -67,174 +55,218 @@ pointed to. T must meet the smart pointer
     
       template<typename T> void swap(weak_ptr<T> & a, weak_ptr<T> & b); // never throws
     
    +  template<typename T>
    +    shared_ptr<T> make_shared(weak_ptr<T> const & r); // never throws
    +
       template<typename T, typename U>
    -    weak_ptr<T> shared_static_cast(weak_ptr<U> const & r); // never throws
    +    weak_ptr<T> shared_static_cast(weak_ptr<U> const & r); // never throws
       template<typename T, typename U>
    -    weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r);
    +    weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r);
       template<typename T, typename U>
    -    weak_ptr<T> shared_polymorphic_cast(weak_ptr<U> const & r);
    +    weak_ptr<T> shared_polymorphic_cast(weak_ptr<U> const & r);
       template<typename T, typename U>
    -    weak_ptr<T> shared_polymorphic_downcast(weak_ptr<U> const & r); // never throws
    +    weak_ptr<T> shared_polymorphic_downcast(weak_ptr<U> const & r); // never throws
     
    -}
    - -

    Members

    - -

    element_type

    -
    typedef T element_type;
    -

    Provides the type of the stored pointer.

    - -

    constructors

    - -
    explicit weak_ptr();
    -

    Constructs a weak_ptr, with 0 as its stored pointer. -The only exception which may be thrown by this constructor is std::bad_alloc. -If an exception is thrown, the constructor has no effect.

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

    Constructs a weak_ptr, as if by storing a copy of the pointer stored in r. -Afterwards, the use count for all copies is unchanged. -When the last shared_ptr is destroyed, the use count and stored pointer become 0.

    - -
    weak_ptr(weak_ptr const & r); // never throws
    +}
    +
    +

    Members

    +

    element_type

    +
    typedef T element_type;
    +
    +

    Provides the type of the template parameter T.

    +
    +

    constructors

    +
    explicit weak_ptr();
    +
    +

    Effects: Constructs a weak_ptr.

    +

    Postconditions: use count is 0; the stored + pointer is 0.

    +

    Throws: std::bad_alloc.

    +

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

    +

    Notes: T need not be a complete type. See the smart pointer + common requirements.

    +
    +
    template<typename Y> weak_ptr(shared_ptr<Y> const & r); // never throws
    +
    +

    Effects: Constructs a weak_ptr, as if by storing a copy of the + pointer stored in r.

    +

    Throws: nothing.

    +

    Notes: The use count for all copies is + unchanged. When the last shared_ptr is destroyed, the use count and + stored pointer become 0.

    +
    +
    weak_ptr(weak_ptr const & r); // never throws
     template<typename Y> weak_ptr(weak_ptr<Y> const & r); // never throws
    -

    Constructs a weak_ptr, as if by storing a copy of the -pointer stored in r.

    - -

    destructor

    - -
    ~weak_ptr(); // never throws
    -

    Destroys this weak_ptr but has no effect on the object its stored pointer points to. -T need not be a complete type. -See the smart pointer common requirements.

    - -

    assignment

    - -
    weak_ptr & operator=(weak_ptr const & r); // never throws
    +		
    +

    Effects: Constructs a weak_ptr, as if by storing a copy of the + pointer stored in r.

    +

    Throws: nothing.

    +

    Notes: The use count for all copies is + unchanged.

    +
    +

    destructor

    +
    ~weak_ptr(); // never throws
    +
    +

    Effects: Destroys this weak_ptr but has no effect on the object + its stored pointer points to.

    +

    Throws: nothing.

    +

    Notes: T need not be a complete type. See the smart pointer + common requirements.

    +
    +

    assignment

    +
    weak_ptr & operator=(weak_ptr const & r); // never throws
     template<typename Y> weak_ptr & operator=(weak_ptr<Y> const & r); // never throws
     template<typename Y> weak_ptr & operator=(shared_ptr<Y> const & r); // never throws
    -

    Constructs a new weak_ptr as described above, -then replaces this weak_ptr with the new one, destroying the replaced object.

    - -

    reset

    - -
    void reset();
    -

    Constructs a new weak_ptr as described above, -then replaces this weak_ptr with the new one, destroying the replaced object. -The only exception which may be thrown is std::bad_alloc. If -an exception is thrown, the reset has no effect.

    - -

    indirection

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

    Returns a reference to the object pointed to by the stored pointer. -Behavior is undefined if the stored pointer is 0. -Note that the stored pointer becomes 0 if all shared_ptr objects for that -pointer are destroyed.

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

    Returns the stored pointer. -Behavior is undefined if the stored pointer is 0. -Note that the stored pointer becomes 0 if all shared_ptr objects for that -pointer are destroyed.

    - -

    get

    -
    T * get() const; // never throws
    -

    Returns the stored pointer. -Note that the stored pointer becomes 0 if all shared_ptr objects for that -pointer are destroyed. -T need not be a complete type. -See the smart pointer -common requirements.

    - -

    use_count

    -
    long use_count() const; // never throws
    -

    Returns the number of shared_ptr objects sharing ownership of the -stored pointer. -T need not be a complete type. -See the smart pointer -common requirements.

    -

    Because use_count is not necessarily efficient to implement for -implementations of weak_ptr that do not use an explicit reference -count, it might be removed from some future version. Thus it should -be used for debugging purposes only, and get should be used for -production code.

    - -

    swap

    -
    void swap(weak_ptr & b); // never throws
    -

    Exchanges the contents of the two smart pointers. -T need not be a complete type. -See the smart pointer -common requirements.

    - -

    Free Functions

    - -

    comparison

    -
    template<typename T, typename U>
    +		
    +

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

    +

    Throws: nothing.

    +

    Notes: The implementation is free to meet the effects (and the implied + guarantees) via different means, without creating a temporary.

    +
    +

    reset

    +
    void reset();
    +
    +

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

    +
    +

    get

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

    Returns: the stored pointer (0 if all shared_ptr objects for that + pointer are destroyed.)

    +

    Throws: nothing.

    +

    Notes: Using get in multithreaded code is dangerous. After the + function returns, the pointed-to object may be destroyed by a different thread, + since the weak_ptr doesn't affect its use_count.

    +
    +

    use_count

    +
    long use_count() const; // never throws
    +
    +

    Returns: the number of shared_ptr objects sharing ownership of the + stored pointer.

    +

    Throws: nothing.

    +

    Notes: use_count() is not necessarily efficient. Use only + for debugging and testing purposes, not for production code. T need not + be a complete type. See the smart pointer + common requirements.

    +
    +

    expired

    +
    bool expired() const; // never throws
    +
    +

    Returns: use_count() == 0.

    +

    Throws: nothing.

    +

    Notes: expired() may be faster than use_count(). + T need not be a complete type. See the smart pointer + common requirements.

    +
    +

    swap

    +
    void swap(weak_ptr & b); // never throws
    +
    +

    Effects: Exchanges the contents of the two smart pointers.

    +

    Throws: nothing.

    +

    Notes: T need not be a complete type. See the smart pointer + common requirements.

    +
    +

    Free Functions

    +

    comparison

    +
    template<typename T, typename U>
       bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
     template<typename T, typename U>
    -  bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    -template<typename T>
    +  bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    +
    +

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

    +

    Throws: nothing.

    +

    Notes: T need not be a complete type. See the smart pointer + common requirements.

    +
    +
    template<typename T>
       bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws
    -

    Compares the stored pointers of the two smart pointers. -T need not be a complete type. -See the smart pointer -common requirements.

    -

    The operator< overload is provided to define an ordering so that weak_ptr -objects can be used in associative containers such as std::map. -The implementation uses std::less<T *> to perform the -comparison. This ensures that the comparison is handled correctly, since the -standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] -paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] -paragraph 8).

    - -

    swap

    -
    template<typename T>
    +		
    +

    Returns: an implementation-defined value such that operator< is + a strict weak ordering as described in section 25.3 [lib.alg.sorting] + of the C++ standard.

    +

    Throws: nothing.

    +

    Notes: Allows weak_ptr objects to be used as keys in + associative containers. T need not be a complete type. See the smart + pointer common requirements.

    +
    +

    swap

    +
    template<typename T>
       void swap(weak_ptr<T> & a, weak_ptr<T> & b) // never throws
    -

    Equivalent to a.swap(b). Matches the interface of std::swap. -Provided as an aid to generic programming.

    - -

    shared_static_cast

    -
    template<typename T, typename U>
    -  weak_ptr<T> shared_static_cast(weak_ptr<U> const & r); // never throws
    -

    Perform a static_cast on the stored pointer, returning another weak_ptr. -The resulting smart pointer will share its use count with the original pointer.

    - -

    shared_dynamic_cast

    -
    template<typename T, typename U>
    -  weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r);
    -

    Perform a dynamic_cast on the stored pointer, returning another weak_ptr. -The resulting smart pointer will share its use count with the original pointer unless the result of the -cast is 0. The only exception which may be thrown is std::bad_alloc, which may be thrown during the -construction of the new weak_ptr if the result of the cast is 0. If an exception is thrown, the -cast has no effect.

    - -

    shared_polymorphic_cast

    -
    template<typename T, typename U>
    -  weak_ptr<T> shared_polymorphic_cast(weak_ptr<U> const & r);
    -

    Perform a polymorphic_cast on the stored pointer, -returning another weak_ptr. -The resulting smart pointer will share its use count with the original pointer. -The only exception which may be thrown is std::bad_cast, if the pointer type can not be converted. -If an exception is thrown, the cast has no effect.

    - -

    shared_polymorphic_downcast

    -
    template<typename T, typename U>
    -  weak_ptr<T> shared_polymorphic_downcast(weak_ptr<U> const & r); // never throws
    -

    Perform a polymorphic_downcast on the stored pointer, -returning another weak_ptr. -The resulting smart pointer will share its use count with the original pointer.

    - -
    - -

    Revised 8 February 2002

    - -

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

    - - - +
    +

    Effects: Equivalent to a.swap(b).

    +

    Throws: nothing.

    +

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

    +
    +

    make_shared

    +
    template<typename T>
    +  shared_ptr<T> make_shared(weak_ptr<T> & const r) // never throws
    +
    +

    Returns: r.expired()? shared_ptr<T>(): shared_ptr<T>(r).

    +

    Throws: nothing.

    +
    +

    shared_static_cast

    +
    template<typename T, typename U>
    +  weak_ptr<T> shared_static_cast(weak_ptr<U> const & r); // never throws
    +
    +

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

    +

    Returns: A weak_ptr<T> object that stores a copy + of static_cast<T*>(r.get()) and shares ownership with r.

    +

    Throws: nothing.

    +
    +

    shared_dynamic_cast

    +
    template<typename T, typename U>
    +  weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r);
    +
    +

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

    +

    Returns:

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

    Throws: std::bad_alloc.

    +

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

    +
    +

    shared_polymorphic_cast

    +
    template<typename T, typename U>
    +  weak_ptr<T> shared_polymorphic_cast(weak_ptr<U> const & r);
    +
    +

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

    +

    Returns: A weak_ptr<T> object that stores a copy + of polymorphic_cast<T*>(r.get()) + and shares ownership with r.

    +

    Throws: std::bad_cast when the pointer cannot be + converted.

    +

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

    +
    +

    shared_polymorphic_downcast

    +
    template<typename T, typename U>
    +  weak_ptr<T> shared_polymorphic_downcast(weak_ptr<U> const & r); // never throws
    +
    +

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

    +

    Returns: A weak_ptr<T> object that stores a copy + of polymorphic_downcast<T*>(r.get()) + and shares ownership with r.

    +

    Throws: nothing.

    +
    +
    +

    Revised + 8 March 2002

    +

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

    + + From 72f83165e025fa0a688be66fc89c7a09a334e6ee Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 12 Mar 2002 14:02:38 +0000 Subject: [PATCH 084/513] Removed casts as unsafe. [SVN r13179] --- include/boost/weak_ptr.hpp | 44 -------------------------------------- shared_ptr_test.cpp | 2 +- 2 files changed, 1 insertion(+), 45 deletions(-) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 33d762d..356ab60 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -51,29 +51,6 @@ public: { } - template - weak_ptr(weak_ptr const & r, detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) - { - } - - template - weak_ptr(weak_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) - { - if (px == 0) // need to allocate new counter -- the cast failed - { - pn = detail::weak_count(); - } - } - - template - weak_ptr(weak_ptr const & r, detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) - { - if (px == 0) - { - throw std::bad_cast(); - } - } - template weak_ptr & operator=(weak_ptr const & r) // never throws { @@ -187,27 +164,6 @@ template shared_ptr make_shared(weak_ptr const & r) // never thro } } -template weak_ptr shared_static_cast(weak_ptr const & r) -{ - return weak_ptr(r, detail::static_cast_tag()); -} - -template weak_ptr shared_dynamic_cast(weak_ptr const & r) -{ - return weak_ptr(r, detail::dynamic_cast_tag()); -} - -template weak_ptr shared_polymorphic_cast(weak_ptr const & r) -{ - return weak_ptr(r, detail::polymorphic_cast_tag()); -} - -template weak_ptr shared_polymorphic_downcast(weak_ptr const & r) -{ - BOOST_ASSERT(dynamic_cast(r.get()) == r.get()); - return shared_static_cast(r); -} - } // namespace boost #ifdef BOOST_MSVC diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 0e4e86b..7b1b960 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -244,7 +244,7 @@ int test_main(int, char * []) test_is_nonzero(boost::make_shared(wp2)); } - weak_ptr wp3 = shared_dynamic_cast(wp2); + weak_ptr wp3 = shared_dynamic_cast(boost::make_shared(wp2)); BOOST_TEST(wp3.use_count() == 1); BOOST_TEST(wp3.get() != 0); From 220f35a0f15f43c9afff6420b9f7fb71c7a6f3c6 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 12 Mar 2002 14:39:22 +0000 Subject: [PATCH 085/513] Casts removed as unsafe, added intro paragraph about make_shared. [SVN r13180] --- weak_ptr.htm | 99 +++++++++++++++++++--------------------------------- 1 file changed, 35 insertions(+), 64 deletions(-) diff --git a/weak_ptr.htm b/weak_ptr.htm index 6c1d5dd..72104fb 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -18,6 +18,40 @@

    The class template is parameterized on T, the type of the object pointed to. T must meet the smart pointer common requirements.

    +

    Compared to shared_ptr, weak_ptr provides + a very limited subset of operations since accessing its stored pointer is + unsafe in multithreaded programs (that is, it may invoke undefined + behavior.) Consider, for example, this innocent piece of code:

    +
    +shared_ptr<int> p(new int(5));
    +weak_ptr<int> q(p);
    +
    +// some time later
    +
    +if(int * r = q.get())
    +{
    +	// use *r
    +}
    +
    +

    Imagine that after the if, but immediately before r + is used, another thread executes the statement p.reset(). Now r + is a dangling pointer.

    +

    The solution to this problem is to create a temporary shared_ptr + from q:

    +
    +shared_ptr<int> p(new int(5));
    +weak_ptr<int> q(p);
    +
    +// some time later
    +
    +if(shared_ptr<int> r = make_shared(q))
    +{
    +	// use *r
    +}
    +
    +

    Now r holds a reference to the object that was pointed by q. + Even if p.reset() is executed in another thread, the object will + stay alive until r goes out of scope (or is reset.)

    Synopsis

    namespace boost {
     
    @@ -58,15 +92,6 @@
       template<typename T>
         shared_ptr<T> make_shared(weak_ptr<T> const & r); // never throws
     
    -  template<typename T, typename U>
    -    weak_ptr<T> shared_static_cast(weak_ptr<U> const & r); // never throws
    -  template<typename T, typename U>
    -    weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r);
    -  template<typename T, typename U>
    -    weak_ptr<T> shared_polymorphic_cast(weak_ptr<U> const & r);
    -  template<typename T, typename U>
    -    weak_ptr<T> shared_polymorphic_downcast(weak_ptr<U> const & r); // never throws
    -
     }
     

    Members

    @@ -206,62 +231,8 @@ template<typename T, typename U>

    Returns: r.expired()? shared_ptr<T>(): shared_ptr<T>(r).

    Throws: nothing.

    -

    shared_static_cast

    -
    template<typename T, typename U>
    -  weak_ptr<T> shared_static_cast(weak_ptr<U> const & r); // never throws
    -
    -

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

    -

    Returns: A weak_ptr<T> object that stores a copy - of static_cast<T*>(r.get()) and shares ownership with r.

    -

    Throws: nothing.

    -
    -

    shared_dynamic_cast

    -
    template<typename T, typename U>
    -  weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r);
    -
    -

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

    -

    Returns:

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

    Throws: std::bad_alloc.

    -

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

    -
    -

    shared_polymorphic_cast

    -
    template<typename T, typename U>
    -  weak_ptr<T> shared_polymorphic_cast(weak_ptr<U> const & r);
    -
    -

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

    -

    Returns: A weak_ptr<T> object that stores a copy - of polymorphic_cast<T*>(r.get()) - and shares ownership with r.

    -

    Throws: std::bad_cast when the pointer cannot be - converted.

    -

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

    -
    -

    shared_polymorphic_downcast

    -
    template<typename T, typename U>
    -  weak_ptr<T> shared_polymorphic_downcast(weak_ptr<U> const & r); // never throws
    -
    -

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

    -

    Returns: A weak_ptr<T> object that stores a copy - of polymorphic_downcast<T*>(r.get()) - and shares ownership with r.

    -

    Throws: nothing.

    -

    -

    Revised - 8 March 2002

    +

    Revised 12 March 2002

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in From b89945d36a7ba6fe88deac7ac0a11c1e75501fef Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 15 Mar 2002 22:00:10 +0000 Subject: [PATCH 086/513] Added winapi.hpp and a CRITICAL_SECTION lightweight_mutex variant. [SVN r13211] --- include/boost/detail/atomic_count.hpp | 8 +- .../boost/detail/atomic_count_pthreads.hpp | 4 +- include/boost/detail/atomic_count_win32.hpp | 14 +--- include/boost/detail/lightweight_mutex.hpp | 18 ++++- include/boost/detail/lwm_win32.hpp | 14 ++-- include/boost/detail/lwm_win32_cs.hpp | 78 +++++++++++++++++++ include/boost/detail/winapi.hpp | 75 ++++++++++++++++++ 7 files changed, 185 insertions(+), 26 deletions(-) create mode 100644 include/boost/detail/lwm_win32_cs.hpp create mode 100644 include/boost/detail/winapi.hpp diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index d97fafa..2adb57e 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -91,12 +91,14 @@ typedef long atomic_count; } -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -# include -//#elif defined(linux) || defined(__linux) || defined(__linux__) #elif defined(BOOST_USE_ASM_ATOMIC_H) # include +#elif defined(BOOST_AC_USE_PTHREADS) +# include +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# include #elif defined(BOOST_HAS_PTHREADS) +# define BOOST_AC_USE_PTHREADS # include #else diff --git a/include/boost/detail/atomic_count_pthreads.hpp b/include/boost/detail/atomic_count_pthreads.hpp index eb1dd97..0f8c663 100644 --- a/include/boost/detail/atomic_count_pthreads.hpp +++ b/include/boost/detail/atomic_count_pthreads.hpp @@ -19,11 +19,9 @@ // inefficiencies. Example: a class with two atomic_count members // can get away with a single mutex. // -// Define a macro so that users can detect the situation and optimize. +// Users can detect this situation by checking BOOST_AC_USE_PTHREADS. // -#define BOOST_ATOMIC_COUNT_USES_PTHREADS - namespace boost { diff --git a/include/boost/detail/atomic_count_win32.hpp b/include/boost/detail/atomic_count_win32.hpp index 163a26d..0482757 100644 --- a/include/boost/detail/atomic_count_win32.hpp +++ b/include/boost/detail/atomic_count_win32.hpp @@ -16,20 +16,14 @@ // warranty, and with no claim as to its suitability for any purpose. // +#include + namespace boost { namespace detail { -// Avoid #including - -namespace win32 -{ -extern "C" __declspec(dllimport) long __stdcall InterlockedIncrement(long volatile *); -extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement(long volatile *); -} - class atomic_count { public: @@ -40,12 +34,12 @@ public: long operator++() { - return win32::InterlockedIncrement(&value_); + return winapi::InterlockedIncrement(&value_); } long operator--() { - return win32::InterlockedDecrement(&value_); + return winapi::InterlockedDecrement(&value_); } operator long() const diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index d199114..6a74397 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -37,16 +37,28 @@ #include +// +// Note to implementors: if you write a platform-specific lightweight_mutex +// for a platform that supports pthreads, be sure to test its performance +// against the pthreads-based version using smart_ptr_timing_test.cpp and +// smart_ptr_mt_test.cpp. Custom versions are usually not worth the trouble +// _unless_ the performance gains are substantial. +// + #ifndef BOOST_HAS_THREADS # include -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -# include -//#elif defined(linux) || defined(__linux) || defined(__linux__) #elif defined(BOOST_USE_ASM_ATOMIC_H) # include +#elif defined(BOOST_LWM_USE_CRITICAL_SECTION) +# include +#elif defined(BOOST_LWM_USE_PTHREADS) +# include +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# include #elif defined(__sgi) # include #elif defined(BOOST_HAS_PTHREADS) +# define BOOST_LWM_USE_PTHREADS # include #else # include diff --git a/include/boost/detail/lwm_win32.hpp b/include/boost/detail/lwm_win32.hpp index 3e79198..a54aefc 100644 --- a/include/boost/detail/lwm_win32.hpp +++ b/include/boost/detail/lwm_win32.hpp @@ -16,17 +16,14 @@ // warranty, and with no claim as to its suitability for any purpose. // +#include + namespace boost { namespace detail { -// avoid including - -extern "C" __declspec(dllimport) long __stdcall InterlockedExchange(long volatile *, long); -extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long); - class lightweight_mutex { private: @@ -58,12 +55,15 @@ public: explicit scoped_lock(lightweight_mutex & m): m_(m) { - while( InterlockedExchange(&m_.l_, 1) ) Sleep(0); + while( winapi::InterlockedExchange(&m_.l_, 1) ) + { + winapi::Sleep(0); + } } ~scoped_lock() { - InterlockedExchange(&m_.l_, 0); + winapi::InterlockedExchange(&m_.l_, 0); // Note: adding a Sleep(0) here will make // the mutex more fair and will increase the overall diff --git a/include/boost/detail/lwm_win32_cs.hpp b/include/boost/detail/lwm_win32_cs.hpp new file mode 100644 index 0000000..3127004 --- /dev/null +++ b/include/boost/detail/lwm_win32_cs.hpp @@ -0,0 +1,78 @@ +#ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED +#define BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/lwm_win32_cs.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include + +namespace boost +{ + +namespace detail +{ + +class lightweight_mutex +{ +private: + + winapi::critical_section cs_; + + lightweight_mutex(lightweight_mutex const &); + lightweight_mutex & operator=(lightweight_mutex const &); + +public: + + lightweight_mutex() + { + winapi::InitializeCriticalSection(&cs_); + } + + ~lightweight_mutex() + { + winapi::DeleteCriticalSection(&cs_); + } + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock + { + private: + + lightweight_mutex & m_; + + scoped_lock(scoped_lock const &); + scoped_lock & operator=(scoped_lock const &); + + public: + + explicit scoped_lock(lightweight_mutex & m): m_(m) + { + winapi::EnterCriticalSection(&m_.cs_); + } + + ~scoped_lock() + { + winapi::LeaveCriticalSection(&m_.cs_); + } + }; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED diff --git a/include/boost/detail/winapi.hpp b/include/boost/detail/winapi.hpp new file mode 100644 index 0000000..0e9bb72 --- /dev/null +++ b/include/boost/detail/winapi.hpp @@ -0,0 +1,75 @@ +#ifndef BOOST_DETAIL_WINAPI_HPP_INCLUDED +#define BOOST_DETAIL_WINAPI_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/winapi.hpp - a lightweight version of +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +namespace boost +{ + +namespace detail +{ + +namespace winapi +{ + +typedef long long_type; +typedef unsigned long dword_type; +typedef void * handle_type; + +#if defined(_WIN64) + +typedef __int64 int_ptr_type; +typedef unsigned __int64 uint_ptr_type; +typedef __int64 long_ptr_type; +typedef unsigned __int64 ulong_ptr_type; + +#else + +typedef int int_ptr_type; +typedef unsigned int uint_ptr_type; +typedef long long_ptr_type; +typedef unsigned long ulong_ptr_type; + +#endif + +struct critical_section +{ + struct critical_section_debug * DebugInfo; + long_type LockCount; + long_type RecursionCount; + handle_type OwningThread; + handle_type LockSemaphore; + ulong_ptr_type SpinCount; +}; + +extern "C" __declspec(dllimport) long_type __stdcall InterlockedIncrement(long_type volatile *); +extern "C" __declspec(dllimport) long_type __stdcall InterlockedDecrement(long_type volatile *); +extern "C" __declspec(dllimport) long_type __stdcall InterlockedExchange(long_type volatile *, long_type); + +extern "C" __declspec(dllimport) void __stdcall Sleep(dword_type); + +extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(critical_section *); + +} // namespace winapi + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_WINAPI_HPP_INCLUDED From fb5b1a20d2b55b76c2a8e9ad6c568f5496eefcfc Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 15 Mar 2002 22:03:56 +0000 Subject: [PATCH 087/513] Small modifications. [SVN r13212] --- shared_ptr_mt_test.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/shared_ptr_mt_test.cpp b/shared_ptr_mt_test.cpp index 831be86..489aa7c 100644 --- a/shared_ptr_mt_test.cpp +++ b/shared_ptr_mt_test.cpp @@ -84,7 +84,7 @@ char const * title = "Using POSIX threads"; #include -extern "C" void* common_thread_routine(void * pv) +extern "C" void * common_thread_routine(void * pv) { abstract_thread * pt = static_cast(pv); pt->run(); @@ -145,9 +145,17 @@ void test(boost::shared_ptr const & pi) int const m = 16; // threads +#if defined(BOOST_LWM_USE_CRITICAL_SECTION) + char const * implementation = "critical section"; +#elif defined(BOOST_LWM_USE_PTHREADS) + char const * implementation = "pthread_mutex"; +#else + char const * implementation = "spinlock"; +#endif + int test_main( int, char ** ) { - std::printf("%s: %d threads, %d iterations, ", title, m, n); + std::printf("%s: %s, %d threads, %d iterations: ", title, implementation, m, n); boost::shared_ptr pi(new int(42)); @@ -167,7 +175,7 @@ int test_main( int, char ** ) t = std::clock() - t; - std::printf("%.4f seconds.\n", static_cast(t) / CLOCKS_PER_SEC); + std::printf("\n\n%.3f seconds.\n", static_cast(t) / CLOCKS_PER_SEC); return 0; } From 9eb1ba7e9fcc68ed83f373d7669ef9252626aef5 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sat, 6 Apr 2002 21:44:37 +0000 Subject: [PATCH 088/513] test_main args must be *[] not ** for new rev of test tools [SVN r13381] --- smart_ptr_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smart_ptr_test.cpp b/smart_ptr_test.cpp index baee93d..79edf7e 100644 --- a/smart_ptr_test.cpp +++ b/smart_ptr_test.cpp @@ -88,7 +88,7 @@ Incomplete * check_incomplete( shared_ptr& incomplete, // This isn't a very systematic test; it just hits some of the basics. -int test_main( int, char ** ) { +int test_main( int, char *[] ) { BOOST_TEST( UDT_use_count == 0 ); // reality check From 513752eee50e714fc7d30badd572847f1ac69896 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 10 Apr 2002 14:12:12 +0000 Subject: [PATCH 089/513] Worked around an MSVC 6 bug (Markus Schoepflin) [SVN r13430] --- include/boost/shared_ptr.hpp | 6 +++++- include/boost/weak_ptr.hpp | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 0c00e9a..ad013d3 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -140,7 +140,9 @@ public: { } -#endif +#endif + +#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) template shared_ptr & operator=(shared_ptr const & r) // never throws @@ -150,6 +152,8 @@ public: return *this; } +#endif + #ifndef BOOST_NO_AUTO_PTR template diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 356ab60..01c248c 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -51,6 +51,8 @@ public: { } +#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) + template weak_ptr & operator=(weak_ptr const & r) // never throws { @@ -67,6 +69,8 @@ public: return *this; } +#endif + void reset() { this_type().swap(*this); From 9b800d4f84b05d51401e66155044ba3a7b39bf35 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 10 Apr 2002 16:04:53 +0000 Subject: [PATCH 090/513] Added more mem_fn, shared_ptr tests. [SVN r13432] --- shared_ptr_assign_fail.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 shared_ptr_assign_fail.cpp diff --git a/shared_ptr_assign_fail.cpp b/shared_ptr_assign_fail.cpp new file mode 100644 index 0000000..993769a --- /dev/null +++ b/shared_ptr_assign_fail.cpp @@ -0,0 +1,31 @@ +#if defined(_MSC_VER) && !defined(__ICL) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// shared_ptr_assign_fail.cpp - a negative test for shared_ptr assignment +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include + +bool boost_error(char const *, char const *, char const *, long) +{ + return true; +} + +int main() +{ + boost::shared_ptr p; + p = new int(42); // assignment must fail + return 0; +} From fbc902831395559dadc40cd3b1f549a75dfe3a79 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 19 Apr 2002 19:34:16 +0000 Subject: [PATCH 091/513] intrusive_ptr.hpp added (still experimental) [SVN r13526] --- include/boost/detail/shared_count.hpp | 23 ++- include/boost/intrusive_ptr.hpp | 201 ++++++++++++++++++++++++++ include/boost/shared_ptr.hpp | 6 + 3 files changed, 226 insertions(+), 4 deletions(-) create mode 100644 include/boost/intrusive_ptr.hpp diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 9dfed4f..22a1e09 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -41,9 +41,6 @@ public: } }; -namespace detail -{ - class counted_base { public: @@ -77,7 +74,7 @@ public: #ifdef BOOST_HAS_THREADS lightweight_mutex::scoped_lock lock(mtx_); #endif - if(use_count_ == 0) throw use_count_is_zero(); + if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero(); ++use_count_; ++weak_count_; } @@ -161,6 +158,19 @@ private: void (*self_deleter_) (counted_base *); }; +inline void intrusive_ptr_add_ref(counted_base * p) +{ + if(p != 0) p->add_ref(); +} + +inline void intrusive_ptr_release(counted_base * p) +{ + if(p != 0) p->release(); +} + +namespace detail +{ + template class counted_base_impl: public counted_base { private: @@ -202,6 +212,11 @@ public: { } + explicit shared_count(counted_base * pi): pi_(pi) // never throws + { + pi_->add_ref(); + } + template shared_count(P p, D d): pi_(0) { try diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp new file mode 100644 index 0000000..1d5349a --- /dev/null +++ b/include/boost/intrusive_ptr.hpp @@ -0,0 +1,201 @@ +#ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED +#define BOOST_INTRUSIVE_PTR_HPP_INCLUDED + +// +// intrusive_ptr.hpp +// +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation. +// + +#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash +# pragma warning(push) +# pragma warning(disable:4284) // odd return type for operator-> +#endif + +#include // std::less + +namespace boost +{ + +// +// intrusive_ptr +// +// A smart pointer that uses intrusive reference counting. +// +// Relies on unqualified calls to +// +// void intrusive_ptr_add_ref(T * p); +// void intrusive_ptr_release(T * p); +// (note: p may be 0!) +// +// The object is responsible for destroying itself. +// + +template class intrusive_ptr +{ +private: + + typedef intrusive_ptr this_type; + +public: + + intrusive_ptr(): p_(0) + { + } + + intrusive_ptr(T * p): p_(p) + { + intrusive_ptr_add_ref(p_); + } + + ~intrusive_ptr() + { + intrusive_ptr_release(p_); + } + +#ifdef BOOST_MSVC6_MEMBER_TEMPLATES + + template intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.get()) + { + intrusive_ptr_add_ref(p_); + } + +#endif + + intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_) + { + intrusive_ptr_add_ref(p_); + } + +#ifdef BOOST_MSVC6_MEMBER_TEMPLATES + + template intrusive_ptr & operator=(intrusive_ptr const & rhs) + { + this_type(rhs).swap(*this); + return *this; + } + +#endif + + intrusive_ptr & operator=(intrusive_ptr const & rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + intrusive_ptr & operator=(T * rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + void swap(intrusive_ptr & rhs) + { + T * tmp = p_; + p_ = rhs.p_; + rhs.p_ = tmp; + } + + T * get() const + { + return p_; + } + + T & operator*() const + { + return *p_; + } + + T * operator->() const + { + return p_; + } + + bool empty() const + { + return p_ == 0; + } + + typedef bool (intrusive_ptr::*bool_type) () const; + + operator bool_type () const + { + return p_ == 0? 0: &intrusive_ptr::empty; + } + +private: + + T * p_; +}; + +template void swap(intrusive_ptr & lhs, intrusive_ptr & rhs) +{ + lhs.swap(rhs); +} + +template intrusive_ptr shared_dynamic_cast(intrusive_ptr const & p) +{ + return dynamic_cast(p.get()); +} + +template intrusive_ptr shared_static_cast(intrusive_ptr const & p) +{ + return static_cast(p.get()); +} + +template inline bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return std::less(a.get(), b.get()); +} + +template inline bool operator==(intrusive_ptr const & a, T * b) +{ + return a.get() == b; +} + +template inline bool operator!=(intrusive_ptr const & a, T * b) +{ + return a.get() != b; +} + +template inline bool operator==(T * a, intrusive_ptr const & b) +{ + return a == b.get(); +} + +template inline bool operator!=(T * a, intrusive_ptr const & b) +{ + return a != b.get(); +} + +// mem_fn support + +template T * get_pointer(intrusive_ptr const & p) +{ + return p.get(); +} + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index ad013d3..6cb187d 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -68,6 +68,7 @@ template<> struct shared_ptr_traits // template class weak_ptr; +template class intrusive_ptr; template class shared_ptr { @@ -110,6 +111,11 @@ public: { } + template + shared_ptr(intrusive_ptr const & r): px(r.get()), pn(r.get()) // never throws + { + } + template shared_ptr(shared_ptr const & r, detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) { From 4c5e355a0b0328f64535d6f19ab5b0f68c6634a4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 22 Apr 2002 09:37:08 +0000 Subject: [PATCH 092/513] Bugfixes. [SVN r13541] --- include/boost/detail/shared_count.hpp | 16 ++++++++++------ include/boost/intrusive_ptr.hpp | 2 +- include/boost/weak_ptr.hpp | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 22a1e09..51df052 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -43,6 +43,10 @@ public: class counted_base { +private: + + typedef detail::lightweight_mutex mutex_type; + public: // pre: initial_use_count <= initial_weak_count @@ -72,7 +76,7 @@ public: void add_ref() { #ifdef BOOST_HAS_THREADS - lightweight_mutex::scoped_lock lock(mtx_); + mutex_type::scoped_lock lock(mtx_); #endif if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero(); ++use_count_; @@ -86,7 +90,7 @@ public: { #ifdef BOOST_HAS_THREADS - lightweight_mutex::scoped_lock lock(mtx_); + mutex_type::scoped_lock lock(mtx_); #endif new_use_count = --use_count_; new_weak_count = --weak_count_; @@ -108,7 +112,7 @@ public: void weak_add_ref() // nothrow { #ifdef BOOST_HAS_THREADS - lightweight_mutex::scoped_lock lock(mtx_); + mutex_type::scoped_lock lock(mtx_); #endif ++weak_count_; } @@ -119,7 +123,7 @@ public: { #ifdef BOOST_HAS_THREADS - lightweight_mutex::scoped_lock lock(mtx_); + mutex_type::scoped_lock lock(mtx_); #endif new_weak_count = --weak_count_; } @@ -133,7 +137,7 @@ public: long use_count() const // nothrow { #ifdef BOOST_HAS_THREADS - lightweight_mutex::scoped_lock lock(mtx_); + mutex_type::scoped_lock lock(mtx_); #endif return use_count_; } @@ -153,7 +157,7 @@ private: long use_count_; long weak_count_; #ifdef BOOST_HAS_THREADS - mutable lightweight_mutex mtx_; + mutable mutex_type mtx_; #endif void (*self_deleter_) (counted_base *); }; diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 1d5349a..87dbece 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -17,7 +17,7 @@ #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash # pragma warning(push) # pragma warning(disable:4284) // odd return type for operator-> -#endif +#endif #include // std::less diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 01c248c..e04b4f1 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -19,7 +19,7 @@ #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash # pragma warning(push) # pragma warning(disable:4284) // odd return type for operator-> -#endif +#endif namespace boost { From 110c0021e2dfa1685ae9b0df10b7a6f7d570b222 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 22 Apr 2002 18:01:19 +0000 Subject: [PATCH 093/513] counted_base default constructor added [SVN r13542] --- include/boost/detail/shared_count.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 51df052..225a56d 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -49,6 +49,11 @@ private: public: + counted_base(): + use_count_(0), weak_count_(0), self_deleter_(&self_delete) + { + } + // pre: initial_use_count <= initial_weak_count explicit counted_base(long initial_use_count, long initial_weak_count): From 11eacab70eb282ca1b7591f39fd16c0c6de7b943 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 23 Apr 2002 14:56:42 +0000 Subject: [PATCH 094/513] Made shared_ptr::share_ptr(Y * p) a member template. [SVN r13551] --- include/boost/shared_ptr.hpp | 14 ++++++++------ shared_ptr_mt_test.cpp | 2 +- shared_ptr_test.cpp | 2 +- shared_ptr_timing_test.cpp | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 6cb187d..cf43a1e 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -75,7 +75,7 @@ template class shared_ptr private: // Borland 5.5.1 specific workarounds - typedef checked_deleter deleter; +// typedef checked_deleter deleter; typedef shared_ptr this_type; public: @@ -86,7 +86,8 @@ public: { } - explicit shared_ptr(T * p): px(p), pn(p, deleter()) // requires complete type + template + explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter()) // Y must be complete { } @@ -96,13 +97,14 @@ public: // shared_ptr will release p by calling d(p) // - template shared_ptr(T * p, D d): px(p), pn(p, d) + template shared_ptr(Y * p, D d): px(p), pn(p, d) { } // generated copy constructor, assignment, destructor are fine - explicit shared_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // may throw + template + explicit shared_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // may throw { } @@ -176,13 +178,13 @@ public: this_type().swap(*this); } - void reset(T * p) // requires complete type + template void reset(Y * p) // Y must be complete { BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors this_type(p).swap(*this); } - template void reset(T * p, D d) + template void reset(Y * p, D d) { this_type(p, d).swap(*this); } diff --git a/shared_ptr_mt_test.cpp b/shared_ptr_mt_test.cpp index 489aa7c..185bd99 100644 --- a/shared_ptr_mt_test.cpp +++ b/shared_ptr_mt_test.cpp @@ -1,4 +1,4 @@ -#if defined(_MSC_VER) && !defined(__ICL) +#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) #pragma warning(disable: 4786) // identifier truncated in debug info #pragma warning(disable: 4710) // function not inlined #pragma warning(disable: 4711) // function selected for automatic inline expansion diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 7b1b960..9ef6d3d 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -1,4 +1,4 @@ -#if defined(_MSC_VER) && !defined(__ICL) +#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) #pragma warning(disable: 4786) // identifier truncated in debug info #pragma warning(disable: 4710) // function not inlined #pragma warning(disable: 4711) // function selected for automatic inline expansion diff --git a/shared_ptr_timing_test.cpp b/shared_ptr_timing_test.cpp index 53fa314..299261b 100644 --- a/shared_ptr_timing_test.cpp +++ b/shared_ptr_timing_test.cpp @@ -1,4 +1,4 @@ -#if defined(_MSC_VER) && !defined(__ICL) +#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) #pragma warning(disable: 4786) // identifier truncated in debug info #pragma warning(disable: 4710) // function not inlined #pragma warning(disable: 4711) // function selected for automatic inline expansion From 4653c3673b779b0cfcabb39982af561ac07a960b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 1 May 2002 11:22:22 +0000 Subject: [PATCH 095/513] shared_ptr now autodetects counted_bases; minor test updates; intrusive_ptr no longer calls addref/release for NULL pointers. [SVN r13602] --- include/boost/detail/shared_count.hpp | 13 ++++++--- include/boost/intrusive_ptr.hpp | 11 ++++---- include/boost/shared_ptr.hpp | 2 +- shared_ptr_test.cpp | 38 ++++++++++++++++++++++++--- 4 files changed, 52 insertions(+), 12 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 225a56d..63316f4 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -169,12 +169,12 @@ private: inline void intrusive_ptr_add_ref(counted_base * p) { - if(p != 0) p->add_ref(); + p->add_ref(); } inline void intrusive_ptr_release(counted_base * p) { - if(p != 0) p->release(); + p->release(); } namespace detail @@ -215,6 +215,8 @@ private: friend class weak_count; + template shared_count(P, D, counted_base const *); + public: shared_count(): pi_(new counted_base(1, 1)) @@ -226,7 +228,7 @@ public: pi_->add_ref(); } - template shared_count(P p, D d): pi_(0) + template shared_count(P p, D d, void const * = 0): pi_(0) { try { @@ -239,6 +241,11 @@ public: } } + template shared_count(P, D, counted_base * pi): pi_(pi) + { + pi_->add_ref(); + } + #ifndef BOOST_NO_AUTO_PTR // auto_ptr is special cased to provide the strong guarantee diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 87dbece..780fe78 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -33,7 +33,8 @@ namespace boost // // void intrusive_ptr_add_ref(T * p); // void intrusive_ptr_release(T * p); -// (note: p may be 0!) +// +// (p != 0) // // The object is responsible for destroying itself. // @@ -52,26 +53,26 @@ public: intrusive_ptr(T * p): p_(p) { - intrusive_ptr_add_ref(p_); + if(p_ != 0) intrusive_ptr_add_ref(p_); } ~intrusive_ptr() { - intrusive_ptr_release(p_); + if(p_ != 0) intrusive_ptr_release(p_); } #ifdef BOOST_MSVC6_MEMBER_TEMPLATES template intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.get()) { - intrusive_ptr_add_ref(p_); + if(p_ != 0) intrusive_ptr_add_ref(p_); } #endif intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_) { - intrusive_ptr_add_ref(p_); + if(p_ != 0) intrusive_ptr_add_ref(p_); } #ifdef BOOST_MSVC6_MEMBER_TEMPLATES diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index cf43a1e..39df95f 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -87,7 +87,7 @@ public: } template - explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter()) // Y must be complete + explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter(), p) // Y must be complete { } diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 9ef6d3d..f96dfc6 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -40,7 +40,7 @@ struct X std::cout << "X(" << this << ")::X()\n"; } - virtual ~X() + ~X() // virtual destructor deliberately omitted { --cnt; std::cout << "X(" << this << ")::~X()\n"; @@ -96,6 +96,28 @@ void release_object(int * p) std::cout << "release_object()\n"; } +class Z: public virtual boost::counted_base +{ +public: + + Z() + { + ++cnt; + std::cout << "Z(" << this << ")::Z()\n"; + } + + ~Z() + { + --cnt; + std::cout << "Z(" << this << ")::~Z()\n"; + } + +private: + + Z(Z const &); + Z & operator= (Z const &); +}; + template void test_is_X(boost::shared_ptr const & p) { BOOST_TEST(p->id() == 1); @@ -244,7 +266,7 @@ int test_main(int, char * []) test_is_nonzero(boost::make_shared(wp2)); } - weak_ptr wp3 = shared_dynamic_cast(boost::make_shared(wp2)); + weak_ptr wp3 = shared_dynamic_cast(boost::make_shared(wp2)); BOOST_TEST(wp3.use_count() == 1); BOOST_TEST(wp3.get() != 0); @@ -302,7 +324,17 @@ int test_main(int, char * []) BOOST_TEST(b1 == (wp1 < wp5)); BOOST_TEST(b2 == (wp5 < wp1)); - shared_ptr p6(get_object(), release_object); + { + // note that both get_object and release_object deal with int* + shared_ptr p6(get_object(), release_object); + } + + { + // test intrusive counting + boost::shared_ptr pv(new Z); + boost::shared_ptr pz = boost::shared_static_cast(pv); + BOOST_TEST(pz.use_count() == pz->use_count()); + } } BOOST_TEST(cnt == 0); From 70255d46bb9058a8f976a2d1f06a97b144204b3d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 4 May 2002 14:27:21 +0000 Subject: [PATCH 096/513] Documented templated pointer constructors, revised the intro a bit. [SVN r13665] --- shared_ptr.htm | 95 ++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 53 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 49649e2..fc9df88 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -31,12 +31,19 @@ work correctly with cyclic data structures. For example, if main() holds a shared_ptr to A, which directly or indirectly holds a shared_ptr back to A, A's use count will be 2. Destruction of the original shared_ptr - will leave A dangling with a use count of 1.

    + 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. T must meet the smart pointer - common requirements. T may be void, but in that case, - either an explicit delete function must be passed in, or the pointed-to object - must have a trivial destructor.

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

    +

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

    Synopsis

    namespace boost {
     
    @@ -47,11 +54,12 @@
       template<typename T> class shared_ptr {
     
         public:
    +
           typedef T element_type;
     
           shared_ptr ();
    -      explicit shared_ptr (T * p); // requires complete type
    -      template<typename D> shared_ptr(T * p, D d);
    +      template<typename Y> explicit shared_ptr (Y * p);
    +      template<typename Y, typename D> shared_ptr(Y * p, D d);
           ~shared_ptr(); // never throws
     
           shared_ptr(shared_ptr const & r); // never throws
    @@ -64,8 +72,8 @@
           template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
     
           void reset ();
    -      void reset (T * p); // requires complete type
    -      template<typename D> void reset(T * p, D d);
    +      template<typename Y> void reset (Y * p);
    +      template<typename Y> template<typename D> void reset(Y * p, D d);
     
           T & operator*() const; // never throws
           T * operator->() const; // never throws
    @@ -113,13 +121,12 @@
     			

    Throws: std::bad_alloc.

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

    -

    Notes: T need not be a complete type. See the smart pointer - common requirements.

    -
    explicit shared_ptr(T * p);
    +
    template<typename Y> explicit shared_ptr(Y * p);
    -

    Requirements: The expression delete p must be well-formed - and must not invoke undefined behavior. +

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

    Effects: Constructs a shared_ptr, storing a copy of p.

    Postconditions: use count is 1.

    @@ -131,11 +138,12 @@ use count is 1 holds even if p is 0; invoking delete on a pointer that has a value of 0 is harmless.

    -
    template<typename D> shared_ptr(T * p, D d);
    +
    template<typename Y, typename D> shared_ptr(Y * p, D d);
    -

    Requirements: 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. +

    Requirements: p must be convertible to T *. 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.

    Effects: Constructs a shared_ptr, storing a copy of p and d.

    Postconditions: use count is 1.

    @@ -180,10 +188,6 @@ template<typename Y> shared_ptr(shared_ptr<Y> const & r); // nev

    Postconditions: use count for all remaining copies is decreased by one.

    Throws: nothing.

    -

    Notes: T need not be a complete type. The guarantee that the - destructor does not throw exceptions depends on the requirement that the - deleted object's destructor does not throw exceptions. See the smart pointer - common requirements.

    assignment

    shared_ptr & operator=(shared_ptr const & r); // never throws
    @@ -207,12 +211,11 @@ q = p;
     		

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

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

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

    -

    Notes: Note the implied requirement that T is a complete type.

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

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

    @@ -234,17 +237,13 @@ q = p;

    Returns: the stored pointer.

    Throws: nothing.

    -

    Notes: T need not be a complete type. See the smart pointer - common requirements.

    unique

    bool unique() const; // never throws

    Returns: use_count() == 1.

    Throws: nothing.

    -

    Notes: unique() may be faster than use_count(). T - need not be a complete type. See the smart pointer - common requirements.

    +

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

    use_count

    long use_count() const; // never throws
    @@ -253,9 +252,7 @@ q = p; stored pointer.

    Throws: nothing.

    Notes: use_count() is not necessarily efficient. Use only - for debugging and testing purposes, not for production code. T need not - be a complete type. See the smart pointer - common requirements.

    + for debugging and testing purposes, not for production code.

    conversions

    operator implementation-defined-type () const; // never throws
    @@ -264,17 +261,15 @@ q = p; 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, avloiding many - of the implicit conversion pitfalls.

    + used in boolean contexts, like if (p && p->valid()) {}. + The actual target type is typically a pointer to a member function, avloiding + many of the implicit conversion pitfalls.

    swap

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

    Effects: Exchanges the contents of the two smart pointers.

    Throws: nothing.

    -

    Notes: T need not be a complete type. See the smart pointer - common requirements.

    Free Functions

    comparison

    @@ -283,27 +278,22 @@ q = p;

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

    Throws: nothing.

    -

    Notes: T need not be a complete type. See the smart pointer - common requirements.

    template<typename T, typename U>
       bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

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

    Throws: nothing.

    -

    Notes: T need not be a complete type. See the smart pointer - common requirements.

    template<typename T>
       bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws
    -

    Returns: an implementation-defined value such that operator< - is a strict weak ordering as described in section 25.3 [lib.alg.sorting] +

    Returns: an implementation-defined value such that operator< is + a strict weak ordering as described in section 25.3 [lib.alg.sorting] of the C++ standard.

    Throws: nothing.

    Notes: Allows shared_ptr objects to be used as keys in - associative containers. T need not be a complete type. See the smart - pointer common requirements.

    + associative containers.

    swap

    template<typename T>
    @@ -337,14 +327,13 @@ q = p;
     			

    Returns:

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

    Throws: std::bad_alloc.

    -

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

    +

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

    Notes: the seemingly equivalent expression

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

    will eventually result in undefined behavior, attempting to delete the same @@ -456,8 +445,8 @@ int * p = a.release(); implementation or a linked list implementation, or some other specific implementation. This is not the intent.


    -

    Revised  - 14 February 2002

    +

    Revised  + 04 May 2002

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in From ecb0b4478bd4228d4b881fc5e5a128f238ae8940 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 9 May 2002 11:16:29 +0000 Subject: [PATCH 097/513] Typo fixed. [SVN r13770] --- shared_ptr.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index fc9df88..be047d7 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -408,7 +408,7 @@ q = p; 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 use where appropriate to +

    Q. I am not convinced. Default parameters can be used where appropriate to hide the complexity. Again, why not policies?
    A. Template parameters affect the type. See the answer to the first question above.

    From 23f68a5657f71b415f2829f1c1d16e694f95e164 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 21 May 2002 16:48:20 +0000 Subject: [PATCH 098/513] =?UTF-8?q?Added=20libstdc++=20v3=20specific=20lig?= =?UTF-8?q?htweight=5Fmutex=20and=20atomic=5Fcount=20(contributed=20by=20L?= =?UTF-8?q?ars=20Gullik=20Bj=C3=B8nnes)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [SVN r13999] --- include/boost/detail/atomic_count.hpp | 2 + include/boost/detail/atomic_count_gcc.hpp | 61 +++++++++++++++++ include/boost/detail/lightweight_mutex.hpp | 10 ++- include/boost/detail/lwm_gcc.hpp | 78 ++++++++++++++++++++++ include/boost/detail/lwm_linux.hpp | 2 +- 5 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 include/boost/detail/atomic_count_gcc.hpp create mode 100644 include/boost/detail/lwm_gcc.hpp diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 2adb57e..b34dc85 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -97,6 +97,8 @@ typedef long atomic_count; # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) # include +#elif defined(__GLIBCPP__) +# include #elif defined(BOOST_HAS_PTHREADS) # define BOOST_AC_USE_PTHREADS # include diff --git a/include/boost/detail/atomic_count_gcc.hpp b/include/boost/detail/atomic_count_gcc.hpp new file mode 100644 index 0000000..c3d29a8 --- /dev/null +++ b/include/boost/detail/atomic_count_gcc.hpp @@ -0,0 +1,61 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED + +// +// boost/detail/atomic_count_gcc.hpp +// +// atomic_count for GNU libstdc++ v3 +// +// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2002 Lars Gullik Bjĝnnes +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count(long v) : value_(v) {} + + void operator++() + { + __atomic_add(&value_, 1); + } + + long operator--() + { + return !__exchange_and_add(&value_, -1); + } + + operator long() const + { + return __exchange_and_add(&value_, 0); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + _Atomic_word value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index 6a74397..b92b576 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -40,10 +40,14 @@ // // Note to implementors: if you write a platform-specific lightweight_mutex // for a platform that supports pthreads, be sure to test its performance -// against the pthreads-based version using smart_ptr_timing_test.cpp and -// smart_ptr_mt_test.cpp. Custom versions are usually not worth the trouble +// against the pthreads-based version using shared_ptr_timing_test.cpp and +// shared_ptr_mt_test.cpp. Custom versions are usually not worth the trouble // _unless_ the performance gains are substantial. // +// Be sure to compare against a "real" pthreads library; +// shared_ptr_timing_test.cpp will compile succesfully with a stub do-nothing +// pthreads library, since it doesn't create any threads. +// #ifndef BOOST_HAS_THREADS # include @@ -57,6 +61,8 @@ # include #elif defined(__sgi) # include +#elif defined(__GLIBCPP__) +# include #elif defined(BOOST_HAS_PTHREADS) # define BOOST_LWM_USE_PTHREADS # include diff --git a/include/boost/detail/lwm_gcc.hpp b/include/boost/detail/lwm_gcc.hpp new file mode 100644 index 0000000..bf8a09a --- /dev/null +++ b/include/boost/detail/lwm_gcc.hpp @@ -0,0 +1,78 @@ +#ifndef BOOST_DETAIL_LWM_GCC_HPP_INCLUDED +#define BOOST_DETAIL_LWM_GCC_HPP_INCLUDED + +// +// boost/detail/lwm_gcc.hpp +// +// lightweight_mutex for GNU libstdc++ v3 +// +// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2002 Lars Gullik Bjĝnnes +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include +#include + +namespace boost +{ + +namespace detail +{ + +class lightweight_mutex +{ +private: + + _Atomic_word a_; + + lightweight_mutex(lightweight_mutex const &); + lightweight_mutex & operator=(lightweight_mutex const &); + +public: + + lightweight_mutex(): a_(1) + { + } + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock + { + private: + + lightweight_mutex & m_; + + scoped_lock(scoped_lock const &); + scoped_lock & operator=(scoped_lock const &); + + public: + + explicit scoped_lock(lightweight_mutex & m): m_(m) + { + while( !__exchange_and_add(&m_.a_, -1) ) + { + __atomic_add(&m_.a_, 1); + sched_yield(); + } + } + + ~scoped_lock() + { + __atomic_add(&m_.a_, 1); + } + }; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LWM_GCC_HPP_INCLUDED diff --git a/include/boost/detail/lwm_linux.hpp b/include/boost/detail/lwm_linux.hpp index c4b3b1d..62d8e64 100644 --- a/include/boost/detail/lwm_linux.hpp +++ b/include/boost/detail/lwm_linux.hpp @@ -86,4 +86,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED +#endif // #ifndef BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED From 951c2b7e833146f20023b0609c67d2689f446f16 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 20 Jun 2002 14:56:10 +0000 Subject: [PATCH 099/513] counted_base is now smaller [SVN r14212] --- include/boost/detail/shared_count.hpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 63316f4..cc325ea 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -50,14 +50,14 @@ private: public: counted_base(): - use_count_(0), weak_count_(0), self_deleter_(&self_delete) + use_count_(0), weak_count_(0) { } // pre: initial_use_count <= initial_weak_count explicit counted_base(long initial_use_count, long initial_weak_count): - use_count_(initial_use_count), weak_count_(initial_weak_count), self_deleter_(&self_delete) + use_count_(initial_use_count), weak_count_(initial_weak_count) { } @@ -78,6 +78,13 @@ public: { } + // destruct() is called when weak_count_ drops to zero. + + virtual void destruct() // nothrow + { + delete this; + } + void add_ref() { #ifdef BOOST_HAS_THREADS @@ -108,9 +115,7 @@ public: if(new_weak_count == 0) { - // not a direct 'delete this', because the inlined - // release() may use a different heap manager - self_deleter_(this); + destruct(); } } @@ -135,7 +140,7 @@ public: if(new_weak_count == 0) { - self_deleter_(this); + destruct(); } } @@ -152,19 +157,14 @@ private: counted_base(counted_base const &); counted_base & operator= (counted_base const &); - static void self_delete(counted_base * p) - { - delete p; - } - // inv: use_count_ <= weak_count_ long use_count_; long weak_count_; + #ifdef BOOST_HAS_THREADS mutable mutex_type mtx_; #endif - void (*self_deleter_) (counted_base *); }; inline void intrusive_ptr_add_ref(counted_base * p) From a322dc54dcf2c774084325f2cb38789a5c174534 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 20 Jun 2002 15:16:03 +0000 Subject: [PATCH 100/513] Platform-specific spinlocks disabled by default unless BOOST_LWM_USE_SPINLOCK is defined. [SVN r14213] --- include/boost/detail/lightweight_mutex.hpp | 33 ++++++++++++++++------ 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index b92b576..da9e575 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -15,10 +15,10 @@ // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // -// typedef boost::detail::lightweight_mutex; +// typedef boost::detail::lightweight_mutex; // -// boost::detail::lightweight_mutex meets the Mutex concept requirements -// See http://www.boost.org/libs/thread/doc/mutex_concept.html#Mutex +// boost::detail::lightweight_mutex meets a subset of the Mutex concept +// requirements: http://www.boost.org/libs/thread/doc/mutex_concept.html#Mutex // // * Used by the smart pointer library // * Performance oriented @@ -30,6 +30,23 @@ // lightweight_mutex does not guarantee fairness. // * Never keep a lightweight_mutex locked for long periods. // +// The current implementation can use a pthread_mutex, a CRITICAL_SECTION, +// or a platform-specific spinlock. +// +// You can force a particular implementation by defining BOOST_LWM_USE_PTHREADS, +// BOOST_LWM_USE_CRITICAL_SECTION, or BOOST_LWM_USE_SPINLOCK. +// +// If neither macro has been defined, the default is to use a spinlock on Win32, +// and a pthread_mutex otherwise. +// +// Note that a spinlock is not a general synchronization primitive. In particular, +// it is not guaranteed to be a memory barrier, and it is possible to "livelock" +// if a lower-priority thread has acquired the spinlock but a higher-priority +// thread is spinning trying to acquire the same lock. +// +// For these reasons, spinlocks have been disabled by default except on Windows, +// where a spinlock can be several orders of magnitude faster than a CRITICAL_SECTION. + // Note: lwm_linux.hpp has been disabled by default; see the comments // inside for more info. @@ -37,8 +54,7 @@ #include -// -// Note to implementors: if you write a platform-specific lightweight_mutex +// Note to implementors: if you write a platform-specific spinlock // for a platform that supports pthreads, be sure to test its performance // against the pthreads-based version using shared_ptr_timing_test.cpp and // shared_ptr_mt_test.cpp. Custom versions are usually not worth the trouble @@ -47,11 +63,10 @@ // Be sure to compare against a "real" pthreads library; // shared_ptr_timing_test.cpp will compile succesfully with a stub do-nothing // pthreads library, since it doesn't create any threads. -// #ifndef BOOST_HAS_THREADS # include -#elif defined(BOOST_USE_ASM_ATOMIC_H) +#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(BOOST_USE_ASM_ATOMIC_H) # include #elif defined(BOOST_LWM_USE_CRITICAL_SECTION) # include @@ -59,9 +74,9 @@ # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) # include -#elif defined(__sgi) +#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(__sgi) # include -#elif defined(__GLIBCPP__) +#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(__GLIBCPP__) # include #elif defined(BOOST_HAS_PTHREADS) # define BOOST_LWM_USE_PTHREADS From d84fa738ef4dabe569da8eace30fa409cf32519b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 22 Jun 2002 15:55:01 +0000 Subject: [PATCH 101/513] Sleep(0) changed to Sleep(1) to (hopefully) avoid livelocks. [SVN r14226] --- include/boost/detail/lwm_win32.hpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/include/boost/detail/lwm_win32.hpp b/include/boost/detail/lwm_win32.hpp index a54aefc..0bc73bd 100644 --- a/include/boost/detail/lwm_win32.hpp +++ b/include/boost/detail/lwm_win32.hpp @@ -57,7 +57,12 @@ public: { while( winapi::InterlockedExchange(&m_.l_, 1) ) { - winapi::Sleep(0); + // Note: changed to Sleep(1) from Sleep(0). + // According to MSDN, Sleep(0) will never yield + // to a lower-priority thread, whereas Sleep(1) + // will. Performance seems not to be affected. + + winapi::Sleep(1); } } @@ -65,8 +70,8 @@ public: { winapi::InterlockedExchange(&m_.l_, 0); - // Note: adding a Sleep(0) here will make - // the mutex more fair and will increase the overall + // Note: adding a yield here will make + // the spinlock more fair and will increase the overall // performance of some applications substantially in // high contention situations, but will penalize the // low contention / single thread case up to 5x From dca9628be35fa44b03ca833a344b806a5b3d384c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 9 Jul 2002 12:06:46 +0000 Subject: [PATCH 102/513] Disabled some Borland warnings (David B. Held) [SVN r14368] --- include/boost/detail/lwm_win32.hpp | 8 ++++++++ include/boost/detail/shared_count.hpp | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/include/boost/detail/lwm_win32.hpp b/include/boost/detail/lwm_win32.hpp index 0bc73bd..abd1869 100644 --- a/include/boost/detail/lwm_win32.hpp +++ b/include/boost/detail/lwm_win32.hpp @@ -18,6 +18,10 @@ #include +#ifdef __BORLANDC__ +# pragma warn -8027 // Functions containing while are not expanded inline +#endif + namespace boost { @@ -83,4 +87,8 @@ public: } // namespace boost +#ifdef __BORLANDC__ +# pragma warn .8027 // Functions containing while are not expanded inline +#endif + #endif // #ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index cc325ea..673a632 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -28,6 +28,11 @@ #include // for std::less #include // for std::exception +#ifdef __BORLANDC__ +# pragma warn -8026 // Functions with excep. spec. are not expanded inline +# pragma warn -8027 // Functions containing try are not expanded inline +#endif + namespace boost { @@ -389,4 +394,9 @@ inline shared_count::shared_count(weak_count const & r): pi_(r.pi_) } // namespace boost +#ifdef __BORLANDC__ +# pragma warn .8027 // Functions containing try are not expanded inline +# pragma warn .8026 // Functions with excep. spec. are not expanded inline +#endif + #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED From af6fe18c9d2f383e10f584df899963aeb89ca1fa Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 15 Jul 2002 12:52:29 +0000 Subject: [PATCH 103/513] Minor fixes. [SVN r14464] --- weak_ptr.htm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/weak_ptr.htm b/weak_ptr.htm index 72104fb..8e284d1 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -8,9 +8,9 @@

    c++boost.gif (8819 bytes)weak_ptr class template

    The weak_ptr class template stores a pointer to an object that's already - managed by a shared_ptr. When the object last shared_ptr to the - object goes away and the object is deleted, all weak_ptr objects have - their stored pointers set to 0.

    + managed by a shared_ptr. When the last shared_ptr to the object + goes away and the object is deleted, all weak_ptr objects have their + stored pointers set to 0.

    Every weak_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 weak_ptr works with the @@ -30,7 +30,7 @@ weak_ptr<int> q(p); if(int * r = q.get()) { - // use *r + // use *r }

    Imagine that after the if, but immediately before r @@ -46,7 +46,7 @@ weak_ptr<int> q(p); if(shared_ptr<int> r = make_shared(q)) { - // use *r + // use *r }

    Now r holds a reference to the object that was pointed by q. @@ -101,7 +101,7 @@ if(shared_ptr<int> r = make_shared(q))

    Provides the type of the template parameter T.

    constructors

    -
    explicit weak_ptr();
    +
     weak_ptr();

    Effects: Constructs a weak_ptr.

    Postconditions: use count is 0; the stored From 547888d50736801d9b05971eb3d84a4fa3a5de07 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Jul 2002 15:15:39 +0000 Subject: [PATCH 104/513] Consistent 'bool' conversions; scoped_ptr(auto_ptr); get_pointer(scoped_ptr) added. [SVN r14496] --- include/boost/scoped_array.hpp | 16 +++++++++++++++ include/boost/scoped_ptr.hpp | 37 +++++++++++++++++++++++++++++++++- include/boost/shared_array.hpp | 14 +++++++++++++ include/boost/shared_ptr.hpp | 28 ++++++++++++------------- 4 files changed, 80 insertions(+), 15 deletions(-) diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index 070925c..a62ba2b 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -33,6 +33,8 @@ private: scoped_array(scoped_array const &); scoped_array & operator=(scoped_array const &); + typedef scoped_array this_type; + public: typedef T element_type; @@ -67,6 +69,20 @@ public: return ptr; } + // implicit conversion to "bool" + + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::get; + } + + bool operator! () const // never throws + { + return px == 0; + } + void swap(scoped_array & b) // never throws { T * tmp = b.ptr; diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index f452f7a..73737e9 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -15,6 +15,10 @@ #include #include +#ifndef BOOST_NO_AUTO_PTR +# include // for std::auto_ptr +#endif + namespace boost { @@ -27,11 +31,13 @@ template class scoped_ptr // noncopyable { private: - T* ptr; + T * ptr; scoped_ptr(scoped_ptr const &); scoped_ptr & operator=(scoped_ptr const &); + typedef scoped_ptr this_type; + public: typedef T element_type; @@ -40,6 +46,14 @@ public: { } +#ifndef BOOST_NO_AUTO_PTR + + explicit scoped_ptr(std::auto_ptr p): ptr(p.release()) // never throws + { + } + +#endif + ~scoped_ptr() // never throws { checked_delete(ptr); @@ -71,6 +85,20 @@ public: return ptr; } + // implicit conversion to "bool" + + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::get; + } + + bool operator! () const // never throws + { + return px == 0; + } + void swap(scoped_ptr & b) // never throws { T * tmp = b.ptr; @@ -84,6 +112,13 @@ template inline void swap(scoped_ptr & a, scoped_ptr & b) // n a.swap(b); } +// get_pointer(p) is a generic way to say p.get() + +template inline T * get_pointer(scoped_ptr const & p) +{ + return p.get(); +} + } // namespace boost #endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index a820abc..880992b 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -92,6 +92,20 @@ public: return px; } + // implicit conversion to "bool" + + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::get; + } + + bool operator! () const // never throws + { + return px == 0; + } + bool unique() const // never throws { return pn.unique(); diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 39df95f..28a6286 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -206,6 +206,20 @@ public: return px; } + // implicit conversion to "bool" + + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::get; + } + + bool operator! () const // never throws + { + return px == 0; + } + bool unique() const // never throws { return pn.unique(); @@ -216,20 +230,6 @@ public: return pn.use_count(); } - // implicit conversion to "bool" - - typedef long (this_type::*bool_type)() const; - - operator bool_type() const // never throws - { - return px == 0? 0: &this_type::use_count; - } - - bool operator! () const // never throws - { - return px == 0; - } - void swap(shared_ptr & other) // never throws { std::swap(px, other.px); From 33077bda7134644ab9df04812c00d491a540746b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 19 Jul 2002 20:06:35 +0000 Subject: [PATCH 105/513] Win64 patch (Tim Fenders) [SVN r14537] --- include/boost/detail/winapi.hpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/include/boost/detail/winapi.hpp b/include/boost/detail/winapi.hpp index 0e9bb72..340036a 100644 --- a/include/boost/detail/winapi.hpp +++ b/include/boost/detail/winapi.hpp @@ -55,10 +55,41 @@ struct critical_section ulong_ptr_type SpinCount; }; +#if defined(_WIN64) + +// Intel 6.0 on Win64 version, posted by Tim Fenders to [boost-users] + +extern "C" long_type __cdecl _InterlockedIncrement(long_type volatile *); +extern "C" long_type __cdecl _InterlockedDecrement(long_type volatile *); +extern "C" long_type __cdecl _InterlockedExchange(long_type volatile *, long_type); + +#pragma intrinsic(_InterlockedIncrement) +#pragma intrinsic(_InterlockedDecrement) +#pragma intrinsic(_InterlockedExchange) + +inline long_type InterlockedIncrement(long_type volatile * lp) +{ + return _InterlockedIncrement(lp); +} + +inline long_type InterlockedDecrement(long_type volatile* lp) +{ + return _InterlockedDecrement(lp); +} + +inline long_type InterlockedExchange(long_type volatile* lp, long_type l) +{ + return _InterlockedExchange(lp, l); +} + +#else + extern "C" __declspec(dllimport) long_type __stdcall InterlockedIncrement(long_type volatile *); extern "C" __declspec(dllimport) long_type __stdcall InterlockedDecrement(long_type volatile *); extern "C" __declspec(dllimport) long_type __stdcall InterlockedExchange(long_type volatile *, long_type); +#endif + extern "C" __declspec(dllimport) void __stdcall Sleep(dword_type); extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *); From 3f0ebd4c71f99cd373657afb330842845cc3d7a9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 22 Jul 2002 16:36:52 +0000 Subject: [PATCH 106/513] 'shared_from_this' added. [SVN r14561] --- include/boost/shared_ptr.hpp | 22 ++++++++++++++++++++++ shared_ptr_test.cpp | 27 ++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 28a6286..bea9e11 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -313,6 +313,28 @@ template inline T * get_pointer(shared_ptr const & p) return p.get(); } +// shared_from_this() creates a shared_ptr from a raw pointer (usually 'this') + +namespace detail +{ + +inline void sp_assert_counted_base(boost::counted_base const *) +{ +} + +template inline T * sp_remove_const(T const * p) +{ + return const_cast(p); +} + +} // namespace detail + +template shared_ptr shared_from_this(T * p) +{ + detail::sp_assert_counted_base(p); + return shared_ptr(detail::sp_remove_const(p)); +} + } // namespace boost #ifdef BOOST_MSVC diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index f96dfc6..6113d26 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -112,6 +112,16 @@ public: std::cout << "Z(" << this << ")::~Z()\n"; } + boost::shared_ptr shared_this() + { + return boost::shared_from_this(this); + } + + boost::shared_ptr shared_this() const + { + return boost::shared_from_this(this); + } + private: Z(Z const &); @@ -331,9 +341,24 @@ int test_main(int, char * []) { // test intrusive counting - boost::shared_ptr pv(new Z); + + boost::shared_ptr pv(new Z); boost::shared_ptr pz = boost::shared_static_cast(pv); BOOST_TEST(pz.use_count() == pz->use_count()); + + // test shared_from_this + + boost::shared_ptr pz2 = pz->shared_this(); + + Z const & z = *pz2; + + boost::shared_ptr pz3 = z.shared_this(); + + BOOST_TEST(pz.use_count() == pz->use_count()); + BOOST_TEST(pz2.use_count() == pz2->use_count()); + BOOST_TEST(pz3.use_count() == pz3->use_count()); + BOOST_TEST(pz.use_count() == pz2.use_count()); + BOOST_TEST(pz.use_count() == pz3.use_count()); } } From f586d3f83ed0a6824f8518f4a0a3679a2066f200 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 23 Jul 2002 12:33:11 +0000 Subject: [PATCH 107/513] shared_ptr support added. [SVN r14570] --- include/boost/shared_ptr.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index bea9e11..ffb8208 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -56,6 +56,15 @@ template<> struct shared_ptr_traits typedef void reference; }; +#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) + +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + +#endif + } // namespace detail From 018c401e47812ac5b57d2386c001df7dcf4e8fe0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 23 Jul 2002 15:19:22 +0000 Subject: [PATCH 108/513] Best practices section, thread safety section, design notes added. [SVN r14572] --- shared_ptr.htm | 181 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 170 insertions(+), 11 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index be047d7..6b5aa1c 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -8,11 +8,13 @@

    c++boost.gif (8819 bytes)shared_ptr class template

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

    Introduction

    @@ -44,6 +46,43 @@ to shared_ptr<T const>, to shared_ptr<U> where U is an accessible base of T, and to shared_ptr<void>.

    +

    Best Practices

    +

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

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

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

    +

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

    +

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

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

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

    Synopsis

    namespace boost {
     
    @@ -122,6 +161,22 @@
     			

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

    +

    [The poscondition of use_count() == 1 is too strong. Having the nothrow + guarantee is important, since reset() is specified in terms of + the default constructor, but the current specification requires that a count be + allocated. Therefore, this postcondition will be dropped in a future release. + The use count of a default-constructed shared_ptr, including + all copies created from it, will probably be left unspecified.

    +

    There are two possible nothrow implementations, one stores 0 as a pointer to the + reference count, the other uses a single statically allocated count for all + default-constructed shared_ptrs. The second option is + difficult to achieve in the current header-only reference implementation due to + thread safety issues and initialization order, but it should not be precluded + by the specification.

    +

    A future release may enable shared_ptr construction from a + literal zero, for consistency with built-in pointers. It is not clear yet + whether this constructor should be left implicit, enabling 0 to + be used as a shorthand for shared_ptr<T>().]

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

    Requirements: p must be convertible to T *. Y @@ -138,6 +193,10 @@ use count is 1 holds even if p is 0; invoking delete on a pointer that has a value of 0 is harmless.

    +

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

    template<typename Y, typename D> shared_ptr(Y * p, D d);

    Requirements: p must be convertible to T *. The copy @@ -152,6 +211,14 @@

    Notes: When the the time comes to delete the object pointed to by p, d(p) is invoked.

    +

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

    +

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

    shared_ptr(shared_ptr const & r); // never throws
     template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws
    @@ -161,6 +228,8 @@ template<typename Y> shared_ptr(shared_ptr<Y> const & r); // nev increased by one.

    Throws: nothing.

    +

    [The postcondition will be relaxed when a default-constructed shared_ptr + is being copied.]

    explicit shared_ptr(weak_ptr const & r);

    Effects: Constructs a shared_ptr, as if by storing a copy of the @@ -171,6 +240,17 @@ template<typename Y> shared_ptr(shared_ptr<Y> const & r); // nev

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

    +

    [This constructor is an optional part of the specification; it depends on the + existence of weak_ptr. It is true that weak_ptr + support imposes overhead on every shared_ptr user, regardless + of whether weak pointers are used.

    +

    On the other hand, cyclic references are a serious problem with all reference + counted designs. Not providing a solution within the library is unacceptable; + if users are forced to reinvent the weak pointer wheel, there is substantial + probability that they will get it wrong, as designing a safe weak_ptr + interface is non-trivial.

    +

    My opinion is that the added functionality is worth the cost. weak_ptr + is provided in the reference implementation as a proof of concept.]

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

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

    @@ -180,6 +260,9 @@ template<typename Y> shared_ptr(shared_ptr<Y> const & r); // nev

    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.]

    destructor

    ~shared_ptr(); // never throws
    @@ -211,6 +294,8 @@ q = p;

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

    +

    [reset() will offer the nothrow guarantee in a future + implementation.]

    template<typename Y> void reset(Y * p);

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

    @@ -243,8 +328,12 @@ q = p;

    Returns: use_count() == 1.

    Throws: nothing.

    -

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

    +

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

    +

    [In a future release, unique() will return an unspecified value + for a default-constructed shared_ptr.]

    use_count

    long use_count() const; // never throws
    @@ -255,16 +344,19 @@ q = p; for debugging and testing purposes, not for production code.

    conversions

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

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

    +

    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, avloiding + 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 + to be declared in conditions when using shared_dynamic_cast or + make_shared.]

    swap

    void swap(shared_ptr & b); // never throws
    @@ -288,13 +380,19 @@ q = p;
    template<typename T>
       bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws
    -

    Returns: an implementation-defined value such that operator< is - a strict weak ordering as described in section 25.3 [lib.alg.sorting] +

    Returns: an unspecified value such that operator< is a + strict weak ordering as described in section 25.3 [lib.alg.sorting] of the C++ standard.

    Throws: nothing.

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

    +

    [Operator< has been preferred over a std::less + specialization for consistency and legality reasons, as std::less + is required to return the results of operator<, and many + standard algorithms use operator< instead of std::less + for comparisons when a predicate is not supplied.

    +

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

    swap

    template<typename T>
       void swap(shared_ptr<T> & a, shared_ptr<T> & b) // never throws
    @@ -304,6 +402,9 @@ q = p;

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

    +

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

    shared_static_cast

    template<typename T, typename U>
       shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws
    @@ -389,6 +490,65 @@ q = p; implementation file. Note that there is no need for an explicit destructor. Unlike ~scoped_ptr, ~shared_ptr does not require that T be a complete type.

    +

    Thread Safety

    +

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

    +

    Any other simultaneous accesses result in undefined behavior.

    +

    Examples:

    +
    +shared_ptr<int> p(new int(42));
    +
    +//--- Example 1 ---
    +
    +// thread A
    +shared_ptr<int> p2(p); // reads p
    +
    +// thread B
    +shared_ptr<int> p3(p); // OK, multiple reads are safe
    +
    +//--- Example 2 ---
    +
    +// thread A
    +
    +p.reset(new int(1912)); // writes p
    +
    +// thread B
    +p2.reset(); // OK, writes p2
    +
    +//--- Example 3 ---
    +
    +// thread A
    +p = p3; // reads p3, writes p
    +
    +// thread B
    +p3.reset(); // writes p3; undefined, simultaneous read/write
    +
    +//--- Example 4 ---
    +
    +// thread A
    +p3 = p2; // reads p2, writes p3
    +
    +// thread B
    +// p2 goes out of scope: undefined, the destructor is considered a "write access"
    +
    +//--- Example 5 ---
    +
    +// thread A
    +p3.reset(new int(1));
    +
    +// thread B
    +p3.reset(new int(2)); // undefined, multiple writes
    +
    +

    shared_ptr uses Boost.Config + to detect whether the implementation supports threads. If your program is + single-threaded, but your platform is autodetected by Boost.Config + as supporting multiple threads, #define BOOST_DISABLE_THREADS to + eliminate the thread safety overhead.

    Frequently Asked Questions

    Q. There are several variations of shared pointers, with different tradeoffs; why does the smart pointer library supply only a single @@ -408,8 +568,8 @@ q = p; pointer of choice for a wide range of applications. (Those interested in policy based smart pointers should read Modern C++ Design by Andrei Alexandrescu.)

    -

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

    Q. I am not convinced. Default parameters can be used where appropriate + to hide the complexity. Again, why not policies?
    A. Template parameters affect the type. See the answer to the first question above.

    Q. Why doesn't shared_ptr use a linked list implementation?
    @@ -445,8 +605,7 @@ int * p = a.release(); implementation or a linked list implementation, or some other specific implementation. This is not the intent.


    -

    Revised  - 04 May 2002

    +

    Revised 23 July 2002

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in From 77ad156c52622c7e45e93923b29433d673a59b6e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 23 Jul 2002 19:12:40 +0000 Subject: [PATCH 109/513] Design notes updated. [SVN r14575] --- shared_ptr.htm | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 6b5aa1c..d08ff7f 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -196,7 +196,29 @@ void bad()

    [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.]

    + not have a virtual destructor, or is void.

    +

    In the current implementation, if p is convertible to counted_base + *, shared_ptr will use the embedded reference + count supplied by counted_base. This is an (experimental) + attempt to provide a way for shared_ptr to be constructed from + a raw pointer such as this. A free function shared_from_this(q) + performs the conversion when q is convertible to counted_base + const *.

    +

    The optional intrusive counting employed by the current implementation allows + shared_ptr to interoperate with intrusive_ptr, an + experimental generic intrusive-counted smart pointer.

    +

    Another possible implementation is to use a global pointer-to-count map instead + of intrusive counting. shared_from_this would no longer be + O(1), which is a concern for some users, although I do not expect any + performance problems, since the operation is rare. Maintaining a global + map is difficult; it needs to be initialized before any shared_ptr + instances are constructed, and the initialization needs to be thread safe. + In addition, under the Windows dynamic library model, it is possible for + several maps to exist.

    +

    It is not yet clear which implementation should be used, or whether the + specification should allow both; nevertheless, the ability to make a shared_ptr + from this is considered essential by experienced smart + pointer users.]

    template<typename Y, typename D> shared_ptr(Y * p, D d);

    Requirements: p must be convertible to T *. The copy @@ -605,7 +627,8 @@ int * p = a.release(); implementation or a linked list implementation, or some other specific implementation. This is not the intent.


    -

    Revised 23 July 2002

    +

    Revised + 23 July 2002

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in From b5e5c356963190a7dfba56074a82d7e8b38c26f1 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 24 Jul 2002 10:20:30 +0000 Subject: [PATCH 110/513] Minor updates. [SVN r14580] --- shared_ptr.htm | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index d08ff7f..dc0c2cb 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -121,7 +121,7 @@ void bad() bool unique() const; // never throws long use_count() const; // never throws - operator implementation-defined-type () const; // never throws + operator unspecified-bool-type () const; // never throws void swap(shared_ptr<T> & b); // never throws }; @@ -145,6 +145,11 @@ void bad() shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws } +

    [It might be convenient to relax the requirements on shared_ptr's + signature, allowing an additional, defaulted, template parameter. This would + help in detecting possible ODR violations. On the other hand, using shared_ptr + as an argument to a template template parameter requires an exact + signature match.]

    Members

    element_type

    typedef T element_type;
    @@ -413,7 +418,9 @@ q = p; specialization for consistency and legality reasons, as std::less is required to return the results of operator<, and many standard algorithms use operator< instead of std::less - for comparisons when a predicate is not supplied.

    + for comparisons when a predicate is not supplied. Composite objects, like std::pair, + also implement their operator< in terms of their contained + subobjects' operator<.

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

    swap

    template<typename T>
    
    From 053aa108e3268703306a54e56cd8ced5de140925 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 24 Jul 2002 14:14:17 +0000
    Subject: [PATCH 111/513] Tabs. Grrr.
    
    [SVN r14588]
    ---
     shared_ptr_test.cpp | 36 ++++++++++++++++++------------------
     1 file changed, 18 insertions(+), 18 deletions(-)
    
    diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp
    index 6113d26..07a2528 100644
    --- a/shared_ptr_test.cpp
    +++ b/shared_ptr_test.cpp
    @@ -112,15 +112,15 @@ public:
             std::cout << "Z(" << this << ")::~Z()\n";
         }
     
    -	boost::shared_ptr shared_this()
    -	{
    -		return boost::shared_from_this(this);
    -	}
    +    boost::shared_ptr shared_this()
    +    {
    +        return boost::shared_from_this(this);
    +    }
     
    -	boost::shared_ptr shared_this() const
    -	{
    -		return boost::shared_from_this(this);
    -	}
    +    boost::shared_ptr shared_this() const
    +    {
    +        return boost::shared_from_this(this);
    +    }
     
     private:
     
    @@ -342,23 +342,23 @@ int test_main(int, char * [])
             {
                 // test intrusive counting
     
    -			boost::shared_ptr pv(new Z);
    +            boost::shared_ptr pv(new Z);
                 boost::shared_ptr pz = boost::shared_static_cast(pv);
                 BOOST_TEST(pz.use_count() == pz->use_count());
     
    -			// test shared_from_this
    +            // test shared_from_this
     
    -			boost::shared_ptr pz2 = pz->shared_this();
    +            boost::shared_ptr pz2 = pz->shared_this();
     
    -			Z const & z = *pz2;
    +            Z const & z = *pz2;
     
    -			boost::shared_ptr pz3 = z.shared_this();
    +            boost::shared_ptr pz3 = z.shared_this();
     
    -			BOOST_TEST(pz.use_count() == pz->use_count());
    -			BOOST_TEST(pz2.use_count() == pz2->use_count());
    -			BOOST_TEST(pz3.use_count() == pz3->use_count());
    -			BOOST_TEST(pz.use_count() == pz2.use_count());
    -			BOOST_TEST(pz.use_count() == pz3.use_count());
    +            BOOST_TEST(pz.use_count() == pz->use_count());
    +            BOOST_TEST(pz2.use_count() == pz2->use_count());
    +            BOOST_TEST(pz3.use_count() == pz3->use_count());
    +            BOOST_TEST(pz.use_count() == pz2.use_count());
    +            BOOST_TEST(pz.use_count() == pz3.use_count());
             }
         }
     
    
    From 927fe730936a6d854ad747dc3756342be6887111 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 24 Jul 2002 15:36:25 +0000
    Subject: [PATCH 112/513] Changed #ifdefs so that member templates aren't
     disabled by an empty config.hpp.
    
    [SVN r14589]
    ---
     include/boost/intrusive_ptr.hpp | 4 ++--
     include/boost/shared_array.hpp  | 4 ++--
     include/boost/shared_ptr.hpp    | 4 ++--
     3 files changed, 6 insertions(+), 6 deletions(-)
    
    diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp
    index 780fe78..4ada734 100644
    --- a/include/boost/intrusive_ptr.hpp
    +++ b/include/boost/intrusive_ptr.hpp
    @@ -61,7 +61,7 @@ public:
             if(p_ != 0) intrusive_ptr_release(p_);
         }
     
    -#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
    +#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
     
         template intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.get())
         {
    @@ -75,7 +75,7 @@ public:
             if(p_ != 0) intrusive_ptr_add_ref(p_);
         }
     
    -#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
    +#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
     
         template intrusive_ptr & operator=(intrusive_ptr const & rhs)
         {
    diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp
    index 880992b..c60a85a 100644
    --- a/include/boost/shared_array.hpp
    +++ b/include/boost/shared_array.hpp
    @@ -17,7 +17,7 @@
     
     #include    // for broken compiler workarounds
     
    -#ifndef BOOST_MSVC6_MEMBER_TEMPLATES
    +#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
     #include 
     #else
     
    @@ -151,6 +151,6 @@ template void swap(shared_array & a, shared_array & b) // neve
     
     } // namespace boost
     
    -#endif  // #ifndef BOOST_MSVC6_MEMBER_TEMPLATES
    +#endif  // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
     
     #endif  // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED
    diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp
    index ffb8208..2634929 100644
    --- a/include/boost/shared_ptr.hpp
    +++ b/include/boost/shared_ptr.hpp
    @@ -17,7 +17,7 @@
     
     #include    // for broken compiler workarounds
     
    -#ifndef BOOST_MSVC6_MEMBER_TEMPLATES
    +#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
     #include 
     #else
     
    @@ -350,6 +350,6 @@ template shared_ptr shared_from_this(T * p)
     # pragma warning(pop)
     #endif    
     
    -#endif  // #ifndef BOOST_MSVC6_MEMBER_TEMPLATES
    +#endif  // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
     
     #endif  // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
    
    From 5328674c2dd6a8a3ca1f123f398eeb2eb0c8343d Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Fri, 26 Jul 2002 14:18:21 +0000
    Subject: [PATCH 113/513] Minor scoped_* fix (px -> ptr) (Thanks to Bertolt
     Mildner)
    
    [SVN r14619]
    ---
     include/boost/scoped_array.hpp | 4 ++--
     include/boost/scoped_ptr.hpp   | 4 ++--
     2 files changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp
    index a62ba2b..8c7fdcc 100644
    --- a/include/boost/scoped_array.hpp
    +++ b/include/boost/scoped_array.hpp
    @@ -75,12 +75,12 @@ public:
     
         operator unspecified_bool_type() const // never throws
         {
    -        return px == 0? 0: &this_type::get;
    +        return ptr == 0? 0: &this_type::get;
         }
     
         bool operator! () const // never throws
         {
    -        return px == 0;
    +        return ptr == 0;
         }
     
         void swap(scoped_array & b) // never throws
    diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp
    index 73737e9..738ad1b 100644
    --- a/include/boost/scoped_ptr.hpp
    +++ b/include/boost/scoped_ptr.hpp
    @@ -91,12 +91,12 @@ public:
     
         operator unspecified_bool_type() const // never throws
         {
    -        return px == 0? 0: &this_type::get;
    +        return ptr == 0? 0: &this_type::get;
         }
     
         bool operator! () const // never throws
         {
    -        return px == 0;
    +        return ptr == 0;
         }
     
         void swap(scoped_ptr & b) // never throws
    
    From 89435a6287ac8d157dc08ef38b33865073e1b355 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Sat, 27 Jul 2002 16:02:26 +0000
    Subject: [PATCH 114/513] get_pointer added.
    
    [SVN r14628]
    ---
     shared_ptr.htm | 15 +++++++++++++--
     1 file changed, 13 insertions(+), 2 deletions(-)
    
    diff --git a/shared_ptr.htm b/shared_ptr.htm
    index dc0c2cb..1333f73 100644
    --- a/shared_ptr.htm
    +++ b/shared_ptr.htm
    @@ -135,6 +135,8 @@ void bad()
     
       template<typename T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
     
    +  template<typename T> T * get_pointer(shared_ptr<T> const & p); // never throws
    +
       template<typename T, typename U>
         shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws
       template<typename T, typename U>
    @@ -424,7 +426,7 @@ q = p;
     		

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

    swap

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

    Effects: Equivalent to a.swap(b).

    Throws: nothing.

    @@ -434,6 +436,15 @@ q = p;

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

    +

    get_pointer

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

    Returns: p.get().

    +

    Throws: nothing.

    +

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

    +

    shared_static_cast

    template<typename T, typename U>
       shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws
    @@ -634,7 +645,7 @@ int * p = a.release(); implementation or a linked list implementation, or some other specific implementation. This is not the intent.


    -

    Revised +

    Revised 23 July 2002

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and From c06b4206f267cf27b067906bb68ee5d8b2b9fb40 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 13 Aug 2002 15:58:12 +0000 Subject: [PATCH 115/513] #include added. [SVN r14813] --- shared_ptr_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 07a2528..262a9b5 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -22,6 +22,8 @@ #include #include +#include + bool boost_error(char const *, char const *, char const *, long) { return true; From e650c7ff1607c033cb38850d9cad350fabc9f90e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 14 Aug 2002 11:59:13 +0000 Subject: [PATCH 116/513] Changed BOOST_TEST(p) to BOOST_TEST(p? true: false) to make sure the right thing is being tested. [SVN r14834] --- shared_ptr_test.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 262a9b5..883d870 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -190,7 +190,10 @@ template void test_is_zero(boost::shared_ptr const & p) template void test_is_nonzero(boost::shared_ptr const & p) { - BOOST_TEST(p); + // p? true: false is used to test p in a boolean context. + // BOOST_TEST(p) is not guaranteed to test the conversion, + // as the macro might test !!p instead. + BOOST_TEST(p? true: false); BOOST_TEST(p.get() != 0); } From a09c2e556f9421da9f0e7e74b98c89a5599b17f8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 14 Aug 2002 12:27:22 +0000 Subject: [PATCH 117/513] BOOST_NO_EXCEPTIONS support added. [SVN r14835] --- include/boost/detail/shared_array_nmt.hpp | 44 +++++++++++++++-------- include/boost/detail/shared_count.hpp | 18 +++++++++- include/boost/detail/shared_ptr_nmt.hpp | 29 +++++++++++---- include/boost/shared_ptr.hpp | 5 +-- 4 files changed, 73 insertions(+), 23 deletions(-) diff --git a/include/boost/detail/shared_array_nmt.hpp b/include/boost/detail/shared_array_nmt.hpp index 3ff1954..8e9b727 100644 --- a/include/boost/detail/shared_array_nmt.hpp +++ b/include/boost/detail/shared_array_nmt.hpp @@ -17,11 +17,13 @@ #include #include +#include #include -#include // for std::ptrdiff_t -#include // for std::swap -#include // for std::less +#include // for std::ptrdiff_t +#include // for std::swap +#include // for std::less +#include // for std::bad_alloc namespace boost { @@ -38,22 +40,36 @@ public: explicit shared_array(T * p = 0): px(p) { +#ifndef BOOST_NO_EXCEPTIONS + try // prevent leak if new throws { pn = new count_type(1); } catch(...) { - checked_array_delete(p); + boost::checked_array_delete(p); throw; - } + } + +#else + + pn = new count_type(1); + + if(pn == 0) + { + boost::checked_array_delete(p); + boost::throw_exception(std::bad_alloc()); + } + +#endif } - + ~shared_array() { if(--*pn == 0) { - checked_array_delete(px); + boost::checked_array_delete(px); delete pn; } } @@ -63,19 +79,19 @@ public: pn = r.pn; ++*pn; } - + shared_array & operator=(shared_array const & r) { shared_array(r).swap(*this); return *this; } - + void reset(T * p = 0) { BOOST_ASSERT(p == 0 || p != px); shared_array(p).swap(*this); } - + T * get() const // never throws { return px; @@ -87,7 +103,7 @@ public: BOOST_ASSERT(i >= 0); return px[i]; } - + long use_count() const // never throws { return *pn; @@ -97,15 +113,15 @@ public: { return *pn == 1; } - + void swap(shared_array & other) // never throws { std::swap(px, other.px); std::swap(pn, other.pn); } - + private: - + T * px; // contained pointer count_type * pn; // ptr to reference counter diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 673a632..17aeb9d 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -23,10 +23,12 @@ #endif #include +#include #include #include // for std::less #include // for std::exception +#include // for std::bad_alloc #ifdef __BORLANDC__ # pragma warn -8026 // Functions with excep. spec. are not expanded inline @@ -95,7 +97,7 @@ public: #ifdef BOOST_HAS_THREADS mutex_type::scoped_lock lock(mtx_); #endif - if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero(); + if(use_count_ == 0 && weak_count_ != 0) boost::throw_exception(boost::use_count_is_zero()); ++use_count_; ++weak_count_; } @@ -235,6 +237,8 @@ public: template shared_count(P p, D d, void const * = 0): pi_(0) { +#ifndef BOOST_NO_EXCEPTIONS + try { pi_ = new counted_base_impl(p, d, 1, 1); @@ -244,6 +248,18 @@ public: d(p); // delete p throw; } + +#else + + pi_ = new counted_base_impl(p, d, 1, 1); + + if(pi_ == 0) + { + d(p); // delete p + boost::throw_exception(std::bad_alloc()); + } + +#endif } template shared_count(P, D, counted_base * pi): pi_(pi) diff --git a/include/boost/detail/shared_ptr_nmt.hpp b/include/boost/detail/shared_ptr_nmt.hpp index 79d5b5d..14fbe65 100644 --- a/include/boost/detail/shared_ptr_nmt.hpp +++ b/include/boost/detail/shared_ptr_nmt.hpp @@ -17,14 +17,16 @@ #include #include +#include #include #ifndef BOOST_NO_AUTO_PTR -#include // for std::auto_ptr +# include // for std::auto_ptr #endif -#include // for std::swap -#include // for std::less +#include // for std::swap +#include // for std::less +#include // for std::bad_alloc namespace boost { @@ -38,25 +40,40 @@ private: public: typedef T element_type; + typedef T value_type; explicit shared_ptr(T * p = 0): px(p) { +#ifndef BOOST_NO_EXCEPTIONS + try // prevent leak if new throws { pn = new count_type(1); } catch(...) { - checked_delete(p); + boost::checked_delete(p); throw; - } + } + +#else + + pn = new count_type(1); + + if(pn == 0) + { + boost::checked_delete(p); + boost::throw_exception(std::bad_alloc()); + } + +#endif } ~shared_ptr() { if(--*pn == 0) { - checked_delete(px); + boost::checked_delete(px); delete pn; } } diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 2634929..8f55948 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -23,7 +23,7 @@ #include #include - +#include #include #include // for std::auto_ptr @@ -90,6 +90,7 @@ private: public: typedef T element_type; + typedef T value_type; shared_ptr(): px(0), pn() { @@ -146,7 +147,7 @@ public: { if (px == 0) { - throw std::bad_cast(); + boost::throw_exception(std::bad_cast()); } } From 8436c4d271ea7fa63fe488e0b34c1ada698c73e0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 16 Aug 2002 15:55:19 +0000 Subject: [PATCH 118/513] #pragma option -pc around use_count_is_zero added for Borland 5.5.1, to enable compilation with -ps set. [SVN r14927] --- include/boost/detail/shared_count.hpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 17aeb9d..299fadb 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -38,16 +38,31 @@ namespace boost { +// The standard library that comes with Borland C++ 5.5.1 +// defines std::exception and its members as having C calling +// convention (-pc). When the definition of use_count_is_zero +// is compiled with -ps, the compiler issues an error. +// Hence, the temporary #pragma option -pc below. The version +// check is deliberately conservative. + +#if defined(__BORLANDC__) && __BORLANDC__ == 0x551 +# pragma option push -pc +#endif + class use_count_is_zero: public std::exception { public: virtual char const * what() const throw() { - return "use_count_is_zero"; + return "boost::use_count_is_zero"; } }; +#if defined(__BORLANDC__) && __BORLANDC__ == 0x551 +# pragma option pop +#endif + class counted_base { private: From c2ee5172b0e94692524b52ca5da3e11678d9f8b9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 16 Aug 2002 16:41:16 +0000 Subject: [PATCH 119/513] Switched to for testing. [SVN r14932] --- shared_ptr_mt_test.cpp | 5 +- shared_ptr_test.cpp | 7 +- smart_ptr_test.cpp | 355 +++++++++++++++++++++-------------------- 3 files changed, 182 insertions(+), 185 deletions(-) diff --git a/shared_ptr_mt_test.cpp b/shared_ptr_mt_test.cpp index 185bd99..52828f5 100644 --- a/shared_ptr_mt_test.cpp +++ b/shared_ptr_mt_test.cpp @@ -19,9 +19,6 @@ #include #include -#define BOOST_INCLUDE_MAIN -#include - #include #include #include @@ -153,7 +150,7 @@ int const m = 16; // threads char const * implementation = "spinlock"; #endif -int test_main( int, char ** ) +int main() { std::printf("%s: %s, %d threads, %d iterations: ", title, implementation, m, n); diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 883d870..56f6e46 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -16,8 +16,7 @@ // warranty, and with no claim as to its suitability for any purpose. // -#define BOOST_INCLUDE_MAIN -#include +#include #include #include @@ -197,7 +196,7 @@ template void test_is_nonzero(boost::shared_ptr const & p) BOOST_TEST(p.get() != 0); } -int test_main(int, char * []) +int main() { using namespace boost; @@ -369,5 +368,5 @@ int test_main(int, char * []) BOOST_TEST(cnt == 0); - return 0; + return boost::report_errors(); } diff --git a/smart_ptr_test.cpp b/smart_ptr_test.cpp index 79edf7e..eead369 100644 --- a/smart_ptr_test.cpp +++ b/smart_ptr_test.cpp @@ -18,8 +18,7 @@ #include #include -#define BOOST_INCLUDE_MAIN -#include +#include #include #include @@ -84,212 +83,214 @@ Incomplete * check_incomplete( shared_ptr& incomplete, cout << incomplete.use_count() << ' ' << incomplete.unique() << '\n'; return incomplete.get(); } -// main --------------------------------------------------------------------// // This isn't a very systematic test; it just hits some of the basics. -int test_main( int, char *[] ) { +void test() +{ + BOOST_TEST( UDT_use_count == 0 ); // reality check - BOOST_TEST( UDT_use_count == 0 ); // reality check + // test scoped_ptr with a built-in type + long * lp = new long; + scoped_ptr sp ( lp ); + BOOST_TEST( sp.get() == lp ); + BOOST_TEST( lp == sp.get() ); + BOOST_TEST( &*sp == lp ); - // test scoped_ptr with a built-in type - long * lp = new long; - scoped_ptr sp ( lp ); - BOOST_TEST( sp.get() == lp ); - BOOST_TEST( lp == sp.get() ); - BOOST_TEST( &*sp == lp ); + *sp = 1234568901L; + BOOST_TEST( *sp == 1234568901L ); + BOOST_TEST( *lp == 1234568901L ); + ck( static_cast(sp.get()), 1234568901L ); + ck( lp, *sp ); - *sp = 1234568901L; - BOOST_TEST( *sp == 1234568901L ); - BOOST_TEST( *lp == 1234568901L ); - ck( static_cast(sp.get()), 1234568901L ); - ck( lp, *sp ); + sp.reset(); + BOOST_TEST( sp.get() == 0 ); - sp.reset(); - BOOST_TEST( sp.get() == 0 ); + // test scoped_ptr with a user defined type + scoped_ptr udt_sp ( new UDT( 999888777 ) ); + BOOST_TEST( udt_sp->value() == 999888777 ); + udt_sp.reset(); + udt_sp.reset( new UDT( 111222333 ) ); + BOOST_TEST( udt_sp->value() == 111222333 ); + udt_sp.reset( new UDT( 333222111 ) ); + BOOST_TEST( udt_sp->value() == 333222111 ); - // test scoped_ptr with a user defined type - scoped_ptr udt_sp ( new UDT( 999888777 ) ); - BOOST_TEST( udt_sp->value() == 999888777 ); - udt_sp.reset(); - udt_sp.reset( new UDT( 111222333 ) ); - BOOST_TEST( udt_sp->value() == 111222333 ); - udt_sp.reset( new UDT( 333222111 ) ); - BOOST_TEST( udt_sp->value() == 333222111 ); + // test scoped_array with a build-in type + char * sap = new char [ 100 ]; + scoped_array sa ( sap ); + BOOST_TEST( sa.get() == sap ); + BOOST_TEST( sap == sa.get() ); - // test scoped_array with a build-in type - char * sap = new char [ 100 ]; - scoped_array sa ( sap ); - BOOST_TEST( sa.get() == sap ); - BOOST_TEST( sap == sa.get() ); + strcpy( sa.get(), "Hot Dog with mustard and relish" ); + BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 ); - strcpy( sa.get(), "Hot Dog with mustard and relish" ); - BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 ); - BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 ); + BOOST_TEST( sa[0] == 'H' ); + BOOST_TEST( sa[30] == 'h' ); - BOOST_TEST( sa[0] == 'H' ); - BOOST_TEST( sa[30] == 'h' ); + sa[0] = 'N'; + sa[4] = 'd'; + BOOST_TEST( strcmp( sap, "Not dog with mustard and relish" ) == 0 ); - sa[0] = 'N'; - sa[4] = 'd'; - BOOST_TEST( strcmp( sap, "Not dog with mustard and relish" ) == 0 ); + sa.reset(); + BOOST_TEST( sa.get() == 0 ); - sa.reset(); - BOOST_TEST( sa.get() == 0 ); + // test shared_ptr with a built-in type + int * ip = new int; + shared_ptr cp ( ip ); + BOOST_TEST( ip == cp.get() ); + BOOST_TEST( cp.use_count() == 1 ); - // test shared_ptr with a built-in type - int * ip = new int; - shared_ptr cp ( ip ); - BOOST_TEST( ip == cp.get() ); - BOOST_TEST( cp.use_count() == 1 ); + *cp = 54321; + BOOST_TEST( *cp == 54321 ); + BOOST_TEST( *ip == 54321 ); + ck( static_cast(cp.get()), 54321 ); + ck( static_cast(ip), *cp ); - *cp = 54321; - BOOST_TEST( *cp == 54321 ); - BOOST_TEST( *ip == 54321 ); - ck( static_cast(cp.get()), 54321 ); - ck( static_cast(ip), *cp ); + shared_ptr cp2 ( cp ); + BOOST_TEST( ip == cp2.get() ); + BOOST_TEST( cp.use_count() == 2 ); + BOOST_TEST( cp2.use_count() == 2 ); - shared_ptr cp2 ( cp ); - BOOST_TEST( ip == cp2.get() ); - BOOST_TEST( cp.use_count() == 2 ); - BOOST_TEST( cp2.use_count() == 2 ); + BOOST_TEST( *cp == 54321 ); + BOOST_TEST( *cp2 == 54321 ); + ck( static_cast(cp2.get()), 54321 ); + ck( static_cast(ip), *cp2 ); - BOOST_TEST( *cp == 54321 ); - BOOST_TEST( *cp2 == 54321 ); - ck( static_cast(cp2.get()), 54321 ); - ck( static_cast(ip), *cp2 ); - - shared_ptr cp3 ( cp ); - BOOST_TEST( cp.use_count() == 3 ); - BOOST_TEST( cp2.use_count() == 3 ); - BOOST_TEST( cp3.use_count() == 3 ); - cp.reset(); - BOOST_TEST( cp2.use_count() == 2 ); - BOOST_TEST( cp3.use_count() == 2 ); - BOOST_TEST( cp.use_count() == 1 ); - cp.reset( new int ); - *cp = 98765; - BOOST_TEST( *cp == 98765 ); - *cp3 = 87654; - BOOST_TEST( *cp3 == 87654 ); - BOOST_TEST( *cp2 == 87654 ); - cp.swap( cp3 ); - BOOST_TEST( *cp == 87654 ); - BOOST_TEST( *cp2 == 87654 ); - BOOST_TEST( *cp3 == 98765 ); - cp.swap( cp3 ); - BOOST_TEST( *cp == 98765 ); - BOOST_TEST( *cp2 == 87654 ); - BOOST_TEST( *cp3 == 87654 ); - cp2 = cp2; - BOOST_TEST( cp2.use_count() == 2 ); - BOOST_TEST( *cp2 == 87654 ); - cp = cp2; - BOOST_TEST( cp2.use_count() == 3 ); - BOOST_TEST( *cp2 == 87654 ); - BOOST_TEST( cp.use_count() == 3 ); - BOOST_TEST( *cp == 87654 ); - - shared_ptr cp4; - swap( cp2, cp4 ); - BOOST_TEST( cp4.use_count() == 3 ); - BOOST_TEST( *cp4 == 87654 ); - BOOST_TEST( cp2.get() == 0 ); - - set< shared_ptr > scp; - scp.insert(cp4); - BOOST_TEST( scp.find(cp4) != scp.end() ); - BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr(cp4) ) ); + shared_ptr cp3 ( cp ); + BOOST_TEST( cp.use_count() == 3 ); + BOOST_TEST( cp2.use_count() == 3 ); + BOOST_TEST( cp3.use_count() == 3 ); + cp.reset(); + BOOST_TEST( cp2.use_count() == 2 ); + BOOST_TEST( cp3.use_count() == 2 ); + BOOST_TEST( cp.use_count() == 1 ); + cp.reset( new int ); + *cp = 98765; + BOOST_TEST( *cp == 98765 ); + *cp3 = 87654; + BOOST_TEST( *cp3 == 87654 ); + BOOST_TEST( *cp2 == 87654 ); + cp.swap( cp3 ); + BOOST_TEST( *cp == 87654 ); + BOOST_TEST( *cp2 == 87654 ); + BOOST_TEST( *cp3 == 98765 ); + cp.swap( cp3 ); + BOOST_TEST( *cp == 98765 ); + BOOST_TEST( *cp2 == 87654 ); + BOOST_TEST( *cp3 == 87654 ); + cp2 = cp2; + BOOST_TEST( cp2.use_count() == 2 ); + BOOST_TEST( *cp2 == 87654 ); + cp = cp2; + BOOST_TEST( cp2.use_count() == 3 ); + BOOST_TEST( *cp2 == 87654 ); + BOOST_TEST( cp.use_count() == 3 ); + BOOST_TEST( *cp == 87654 ); - // test shared_array with a built-in type - char * cap = new char [ 100 ]; - shared_array ca ( cap ); - BOOST_TEST( ca.get() == cap ); - BOOST_TEST( cap == ca.get() ); - BOOST_TEST( &ca[0] == cap ); + shared_ptr cp4; + swap( cp2, cp4 ); + BOOST_TEST( cp4.use_count() == 3 ); + BOOST_TEST( *cp4 == 87654 ); + BOOST_TEST( cp2.get() == 0 ); - strcpy( ca.get(), "Hot Dog with mustard and relish" ); - BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 ); - BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 ); + set< shared_ptr > scp; + scp.insert(cp4); + BOOST_TEST( scp.find(cp4) != scp.end() ); + BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr(cp4) ) ); - BOOST_TEST( ca[0] == 'H' ); - BOOST_TEST( ca[30] == 'h' ); - - shared_array ca2 ( ca ); - shared_array ca3 ( ca2 ); + // test shared_array with a built-in type + char * cap = new char [ 100 ]; + shared_array ca ( cap ); + BOOST_TEST( ca.get() == cap ); + BOOST_TEST( cap == ca.get() ); + BOOST_TEST( &ca[0] == cap ); - ca[0] = 'N'; - ca[4] = 'd'; - BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 ); - BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 ); - BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 ); - BOOST_TEST( ca.use_count() == 3 ); - BOOST_TEST( ca2.use_count() == 3 ); - BOOST_TEST( ca3.use_count() == 3 ); - ca2.reset(); - BOOST_TEST( ca.use_count() == 2 ); - BOOST_TEST( ca3.use_count() == 2 ); - BOOST_TEST( ca2.use_count() == 1 ); + strcpy( ca.get(), "Hot Dog with mustard and relish" ); + BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 ); - ca.reset(); - BOOST_TEST( ca.get() == 0 ); + BOOST_TEST( ca[0] == 'H' ); + BOOST_TEST( ca[30] == 'h' ); - shared_array ca4; - swap( ca3, ca4 ); - BOOST_TEST( ca4.use_count() == 1 ); - BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); - BOOST_TEST( ca3.get() == 0 ); - - set< shared_array > sca; - sca.insert(ca4); - BOOST_TEST( sca.find(ca4) != sca.end() ); - BOOST_TEST( sca.find(ca4) == sca.find( shared_array(ca4) ) ); + shared_array ca2 ( ca ); + shared_array ca3 ( ca2 ); - // test shared_array with user defined type - shared_array udta ( new UDT[3] ); + ca[0] = 'N'; + ca[4] = 'd'; + BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( ca.use_count() == 3 ); + BOOST_TEST( ca2.use_count() == 3 ); + BOOST_TEST( ca3.use_count() == 3 ); + ca2.reset(); + BOOST_TEST( ca.use_count() == 2 ); + BOOST_TEST( ca3.use_count() == 2 ); + BOOST_TEST( ca2.use_count() == 1 ); - udta[0].value( 111 ); - udta[1].value( 222 ); - udta[2].value( 333 ); - shared_array udta2 ( udta ); + ca.reset(); + BOOST_TEST( ca.get() == 0 ); - BOOST_TEST( udta[0].value() == 111 ); - BOOST_TEST( udta[1].value() == 222 ); - BOOST_TEST( udta[2].value() == 333 ); - BOOST_TEST( udta2[0].value() == 111 ); - BOOST_TEST( udta2[1].value() == 222 ); - BOOST_TEST( udta2[2].value() == 333 ); - udta2.reset(); - BOOST_TEST( udta2.get() == 0 ); - BOOST_TEST( udta.use_count() == 1 ); - BOOST_TEST( udta2.use_count() == 1 ); + shared_array ca4; + swap( ca3, ca4 ); + BOOST_TEST( ca4.use_count() == 1 ); + BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( ca3.get() == 0 ); - BOOST_TEST( UDT_use_count == 4 ); // reality check + set< shared_array > sca; + sca.insert(ca4); + BOOST_TEST( sca.find(ca4) != sca.end() ); + BOOST_TEST( sca.find(ca4) == sca.find( shared_array(ca4) ) ); - // test shared_ptr with a user defined type - UDT * up = new UDT; - shared_ptr sup ( up ); - BOOST_TEST( up == sup.get() ); - BOOST_TEST( sup.use_count() == 1 ); + // test shared_array with user defined type + shared_array udta ( new UDT[3] ); - sup->value( 54321 ) ; - BOOST_TEST( sup->value() == 54321 ); - BOOST_TEST( up->value() == 54321 ); + udta[0].value( 111 ); + udta[1].value( 222 ); + udta[2].value( 333 ); + shared_array udta2 ( udta ); - shared_ptr sup2; - sup2 = sup; - BOOST_TEST( sup2->value() == 54321 ); - BOOST_TEST( sup.use_count() == 2 ); - BOOST_TEST( sup2.use_count() == 2 ); - sup2 = sup2; - BOOST_TEST( sup2->value() == 54321 ); - BOOST_TEST( sup.use_count() == 2 ); - BOOST_TEST( sup2.use_count() == 2 ); + BOOST_TEST( udta[0].value() == 111 ); + BOOST_TEST( udta[1].value() == 222 ); + BOOST_TEST( udta[2].value() == 333 ); + BOOST_TEST( udta2[0].value() == 111 ); + BOOST_TEST( udta2[1].value() == 222 ); + BOOST_TEST( udta2[2].value() == 333 ); + udta2.reset(); + BOOST_TEST( udta2.get() == 0 ); + BOOST_TEST( udta.use_count() == 1 ); + BOOST_TEST( udta2.use_count() == 1 ); - cout << "OK\n"; + BOOST_TEST( UDT_use_count == 4 ); // reality check - new char[12345]; // deliberate memory leak to verify leaks detected + // test shared_ptr with a user defined type + UDT * up = new UDT; + shared_ptr sup ( up ); + BOOST_TEST( up == sup.get() ); + BOOST_TEST( sup.use_count() == 1 ); - return 0; - } // main + sup->value( 54321 ) ; + BOOST_TEST( sup->value() == 54321 ); + BOOST_TEST( up->value() == 54321 ); + shared_ptr sup2; + sup2 = sup; + BOOST_TEST( sup2->value() == 54321 ); + BOOST_TEST( sup.use_count() == 2 ); + BOOST_TEST( sup2.use_count() == 2 ); + sup2 = sup2; + BOOST_TEST( sup2->value() == 54321 ); + BOOST_TEST( sup.use_count() == 2 ); + BOOST_TEST( sup2.use_count() == 2 ); + + cout << "OK\n"; + + new char[12345]; // deliberate memory leak to verify leaks detected +} + +int main() +{ + test(); + return boost::report_errors(); +} From 09016db3c3bf9bac9efeb97462334d45e00bc31f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 17 Aug 2002 13:05:25 +0000 Subject: [PATCH 120/513] Note added to shared_ptr(Y*, D). [SVN r14942] --- shared_ptr.htm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 1333f73..013d307 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -247,7 +247,10 @@ void bad() example, a "no-op" deallocator is useful when returning a shared_ptr to a statically allocated object.

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

    + shared_ptr features still require a deallocator to be kept.

    +

    The requirement that the copy constructor of D does not throw is too strong. + It will be removed when some core language issues are resolved (cv-qualified + function types, partial ordering clarifications.)]

    shared_ptr(shared_ptr const & r); // never throws
     template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws
    From bd4f575567ad87839f5c33bcc2ac37995c10f2fb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 17 Aug 2002 13:33:41 +0000 Subject: [PATCH 121/513] HPUX 10.20 patch (problem reported by Tom Matelich) [SVN r14943] --- include/boost/detail/lwm_pthreads.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/boost/detail/lwm_pthreads.hpp b/include/boost/detail/lwm_pthreads.hpp index ba8d762..8ee5550 100644 --- a/include/boost/detail/lwm_pthreads.hpp +++ b/include/boost/detail/lwm_pthreads.hpp @@ -37,7 +37,14 @@ public: lightweight_mutex() { + +// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init + +#if defined(__hpux) && defined(_DECTHREADS_) + pthread_mutex_init(&m_, pthread_mutexattr_default); +#else pthread_mutex_init(&m_, 0); +#endif } ~lightweight_mutex() From 92999be43626c9271226777a7408fbe11b9894ce Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 19 Aug 2002 16:23:07 +0000 Subject: [PATCH 122/513] Corrected the shared_ptr(auto_ptr &) postcondition (reported by Maciej Sobczak) [SVN r14953] --- shared_ptr.htm | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 013d307..72c63f3 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -96,8 +96,8 @@ void bad() typedef T element_type; - shared_ptr (); - template<typename Y> explicit shared_ptr (Y * p); + shared_ptr(); + template<typename Y> explicit shared_ptr(Y * p); template<typename Y, typename D> shared_ptr(Y * p, D d); ~shared_ptr(); // never throws @@ -248,9 +248,9 @@ void bad() to a statically allocated object.

    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 is too strong. - It will be removed when some core language issues are resolved (cv-qualified - function types, partial ordering clarifications.)]

    +

    The requirement that the copy constructor of D does not throw is too + strong. It will be removed when some core language issues are resolved + (cv-qualified function types, partial ordering clarifications.)]

    shared_ptr(shared_ptr const & r); // never throws
     template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws
    @@ -286,8 +286,7 @@ template<typename Y> shared_ptr(shared_ptr<Y> const & r); // nev
    template<typename 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 for all copies is - increased by one.

    +

    Postconditions: use count is 1.

    Throws: std::bad_alloc.

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

    From e84eb3f1ba7b162c2c683ca05181f4ad56fe2f47 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Tue, 20 Aug 2002 11:08:11 +0000 Subject: [PATCH 123/513] Added #pragma's to fix codeguard errors. [SVN r14984] --- include/boost/detail/shared_count.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 299fadb..6de061a 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -202,6 +202,13 @@ inline void intrusive_ptr_release(counted_base * p) namespace detail { +// +// Borland's Codeguard trips up over the -Vx- option here: +// +#ifdef __CODEGUARD__ +#pragma option push -Vx- +#endif + template class counted_base_impl: public counted_base { private: @@ -344,6 +351,11 @@ public: } }; +#ifdef __CODEGUARD__ +#pragma option pop +#endif + + class weak_count { private: From b9dceb23401a9917257e5ecc89575c161ee1c0d2 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 26 Aug 2002 15:27:23 +0000 Subject: [PATCH 124/513] *_ptr.hpp: - Added detail::is_pointerlike_helper function templates for Signals weak_ptr.hpp: - Added get_pointer function template for weak_ptr [SVN r15099] --- include/boost/intrusive_ptr.hpp | 6 ++++++ include/boost/scoped_ptr.hpp | 6 ++++++ include/boost/shared_ptr.hpp | 7 +++++++ include/boost/weak_ptr.hpp | 13 +++++++++++++ 4 files changed, 32 insertions(+) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 4ada734..0a62544 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -193,6 +193,12 @@ template T * get_pointer(intrusive_ptr const & p) return p.get(); } +namespace detail { + // is_pointerlike_helper enables Signals library to recognize intrusive_ptr + template + type_traits::yes_type is_pointerlike_helper(const intrusive_ptr&, int); +} // end namespace detail + } // namespace boost #ifdef BOOST_MSVC diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 738ad1b..7adc0e8 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -119,6 +119,12 @@ template inline T * get_pointer(scoped_ptr const & p) return p.get(); } +namespace detail { + // is_pointerlike_helper enables Signals library to recognize scoped_ptr + template + type_traits::yes_type is_pointerlike_helper(const scoped_ptr&, int); +} // end namespace detail + } // namespace boost #endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 8f55948..d9cc25d 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include // for std::auto_ptr #include // for std::swap @@ -323,6 +324,12 @@ template inline T * get_pointer(shared_ptr const & p) return p.get(); } +namespace detail { + // is_pointerlike_helper enables Signals library to recognize shared_ptr + template + type_traits::yes_type is_pointerlike_helper(const shared_ptr&, int); +} // end namespace detail + // shared_from_this() creates a shared_ptr from a raw pointer (usually 'this') namespace detail diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index e04b4f1..dc11ca0 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -168,6 +168,19 @@ template shared_ptr make_shared(weak_ptr const & r) // never thro } } +// mem_fn support + +template T * get_pointer(weak_ptr const & p) +{ + return p.get(); +} + +namespace detail { + // is_pointerlike_helper enables Signals library to recognize intrusive_ptr + template + type_traits::yes_type is_pointerlike_helper(const weak_ptr&, int); +} // end namespace detail + } // namespace boost #ifdef BOOST_MSVC From e77889679f7ac34c8f6c45d8b6a94b90e9b15945 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 27 Aug 2002 13:33:22 +0000 Subject: [PATCH 125/513] intrusive_ptr.hpp: scoped_ptr.hpp: - include [SVN r15104] --- include/boost/intrusive_ptr.hpp | 1 + include/boost/scoped_ptr.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 0a62544..36bc321 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -20,6 +20,7 @@ #endif #include // std::less +#include namespace boost { diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 7adc0e8..77c77a5 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -14,6 +14,7 @@ #include #include +#include #ifndef BOOST_NO_AUTO_PTR # include // for std::auto_ptr From c02fee701341a32b49cc12b54f58b7ab25d6c77b Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 29 Aug 2002 13:49:05 +0000 Subject: [PATCH 126/513] *_ptr.hpp: - Revert addition of is_pointerlike_helper weak_ptr.hpp: - Revert addition of get_pointer [SVN r15108] --- include/boost/intrusive_ptr.hpp | 7 ------- include/boost/scoped_ptr.hpp | 7 ------- include/boost/shared_ptr.hpp | 7 ------- include/boost/weak_ptr.hpp | 13 ------------- 4 files changed, 34 deletions(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 36bc321..4ada734 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -20,7 +20,6 @@ #endif #include // std::less -#include namespace boost { @@ -194,12 +193,6 @@ template T * get_pointer(intrusive_ptr const & p) return p.get(); } -namespace detail { - // is_pointerlike_helper enables Signals library to recognize intrusive_ptr - template - type_traits::yes_type is_pointerlike_helper(const intrusive_ptr&, int); -} // end namespace detail - } // namespace boost #ifdef BOOST_MSVC diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 77c77a5..738ad1b 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -14,7 +14,6 @@ #include #include -#include #ifndef BOOST_NO_AUTO_PTR # include // for std::auto_ptr @@ -120,12 +119,6 @@ template inline T * get_pointer(scoped_ptr const & p) return p.get(); } -namespace detail { - // is_pointerlike_helper enables Signals library to recognize scoped_ptr - template - type_traits::yes_type is_pointerlike_helper(const scoped_ptr&, int); -} // end namespace detail - } // namespace boost #endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index d9cc25d..8f55948 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -25,7 +25,6 @@ #include #include #include -#include #include // for std::auto_ptr #include // for std::swap @@ -324,12 +323,6 @@ template inline T * get_pointer(shared_ptr const & p) return p.get(); } -namespace detail { - // is_pointerlike_helper enables Signals library to recognize shared_ptr - template - type_traits::yes_type is_pointerlike_helper(const shared_ptr&, int); -} // end namespace detail - // shared_from_this() creates a shared_ptr from a raw pointer (usually 'this') namespace detail diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index dc11ca0..e04b4f1 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -168,19 +168,6 @@ template shared_ptr make_shared(weak_ptr const & r) // never thro } } -// mem_fn support - -template T * get_pointer(weak_ptr const & p) -{ - return p.get(); -} - -namespace detail { - // is_pointerlike_helper enables Signals library to recognize intrusive_ptr - template - type_traits::yes_type is_pointerlike_helper(const weak_ptr&, int); -} // end namespace detail - } // namespace boost #ifdef BOOST_MSVC From b916445dd8c914114da74daad3a2c1b7cc562824 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 29 Aug 2002 15:18:04 +0000 Subject: [PATCH 127/513] weak_ptr documentation updates; get() declared deprecated. [SVN r15111] --- include/boost/weak_ptr.hpp | 6 +++++- weak_ptr.htm | 31 +++++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index e04b4f1..c76cb28 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -76,7 +76,7 @@ public: this_type().swap(*this); } - T * get() const // never throws; unsafe in multithreaded programs! + T * get() const // never throws; deprecated, removal pending, don't use { return pn.use_count() == 0? 0: px; } @@ -168,6 +168,10 @@ template shared_ptr make_shared(weak_ptr const & r) // never thro } } +// Note: there is no get_pointer overload for weak_ptr. +// This is intentional. Even get() will disappear in a +// future release; these accessors are too error-prone. + } // namespace boost #ifdef BOOST_MSVC diff --git a/weak_ptr.htm b/weak_ptr.htm index 8e284d1..92bc284 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -7,10 +7,15 @@

    c++boost.gif (8819 bytes)weak_ptr class template

    -

    The weak_ptr class template stores a pointer to an object that's already - managed by a shared_ptr. When the last shared_ptr to the object - goes away and the object is deleted, all weak_ptr objects have their - stored pointers set to 0.

    +

    The weak_ptr class template stores a "weak reference" to an + object that's already managed by a shared_ptr. To access the object, a + weak_ptr can be converted to a shared_ptr using + the shared_ptr constructor or the function + make_shared. When the last shared_ptr to the object + goes away and the object is deleted, the attempt to obtain a shared_ptr +  from the weak_ptr instances that refer to the deleted object will + fail: the constructor will throw an exception of type boost::use_count_is_zero, + and make_shared will return a default constructed (null) shared_ptr.

    Every weak_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 weak_ptr works with the @@ -20,8 +25,9 @@ common requirements.

    Compared to shared_ptr, weak_ptr provides a very limited subset of operations since accessing its stored pointer is - unsafe in multithreaded programs (that is, it may invoke undefined - behavior.) Consider, for example, this innocent piece of code:

    + often dangerous in multithreaded programs, and sometimes unsafe even + within a single thread (that is, it may invoke undefined behavior.) + Consider, for example, this innocent piece of code:

     shared_ptr<int> p(new int(5));
     weak_ptr<int> q(p);
    @@ -72,7 +78,7 @@ if(shared_ptr<int> r = make_shared(q))
           template<typename Y> weak_ptr & operator=(shared_ptr<Y> const & r); // never throws
     
           void reset();
    -      T * get() const; // never throws; unsafe in multithreaded code!
    +      T * get() const; // never throws; deprecated, will disappear
     
           long use_count() const; // never throws
           bool expired() const; // never throws
    @@ -164,6 +170,11 @@ template<typename Y> weak_ptr & operator=(sh
     				function returns, the pointed-to object may be destroyed by a different thread, 
     				since the weak_ptr doesn't affect its use_count.

    +

    [get is very error-prone. Even single-threaded code may experience + problems, as the returned pointer may be invalidated at any time, for example, + indirectly by a member function of the pointee.

    +

    get is deprecated, and it will disappear in a future + release. Do not use it.]

    use_count

    long use_count() const; // never throws
    @@ -231,8 +242,12 @@ template<typename T, typename U>

    Returns: r.expired()? shared_ptr<T>(): shared_ptr<T>(r).

    Throws: nothing.

    +

    [The current implementation of make_shared can propagate + an exception thrown by the shared_ptr default + constructor, so it doesn't meet the stated requirements. In a future + release, this default constructor will not throw.]


    -

    Revised 12 March 2002

    +

    Revised 29 August 2002

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in From 275cb77378330ebb4a87bf85f12e800543e56693 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 31 Aug 2002 13:04:52 +0000 Subject: [PATCH 128/513] Fixed broken links. [SVN r15123] --- smarttests.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smarttests.htm b/smarttests.htm index 84fd16e..04a4381 100644 --- a/smarttests.htm +++ b/smarttests.htm @@ -22,7 +22,7 @@ a guide for current and future investigations into smart pointer implementation strategies.

    Thanks are due to Dave Abrahams, -Gavin Collings, +Gavin Collings, Greg Colvin and Beman Dawes for test code and trial implementations, the final version of which can be found From f79b8cb7ae8afa34e72ba8d9425b69fc5df2fa8a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 6 Sep 2002 12:50:02 +0000 Subject: [PATCH 129/513] Tabs removed. [SVN r15175] --- include/boost/detail/shared_count.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 6de061a..cd5ae8f 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -55,7 +55,7 @@ public: virtual char const * what() const throw() { - return "boost::use_count_is_zero"; + return "boost::use_count_is_zero"; } }; From 4ea6decc7d9baa2944ccf4738c9b30a5db472c21 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 9 Sep 2002 17:44:33 +0000 Subject: [PATCH 130/513] scoped_ptr::reset changed to copy+swap (problem reported by Thomas Witt) [SVN r15239] --- include/boost/scoped_ptr.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 738ad1b..589bd36 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -61,10 +61,9 @@ public: void reset(T * p = 0) // never throws { - if (ptr != p) + if(ptr != p) { - checked_delete(ptr); - ptr = p; + this_type(p).swap(*this); } } From 0f05f41306c361298cbf9f6493a598507b4491e8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 16 Sep 2002 15:26:52 +0000 Subject: [PATCH 131/513] Documentation fixes (reflecting Dave Abrahams' comments) [SVN r15382] --- scoped_array.htm | 212 ++++++++++++++------------------ shared_array.htm | 313 ++++++++++++++++++++--------------------------- shared_ptr.htm | 36 +++--- 3 files changed, 242 insertions(+), 319 deletions(-) diff --git a/scoped_array.htm b/scoped_array.htm index 4df98a9..834e0d2 100644 --- a/scoped_array.htm +++ b/scoped_array.htm @@ -1,53 +1,38 @@ - - - - -scoped_array - - - - -

    c++boost.gif (8819 bytes)scoped_array class template

    - -

    The scoped_array class template stores a pointer to a dynamically allocated -array. (Dynamically allocated arrays are allocated with the C++ new[] -expression.) The array pointed to is guaranteed to be deleted, -either on destruction of the scoped_array, or via an explicit reset.

    - -

    The scoped_array template is a simple solution for simple -needs. It supplies a basic "resource acquisition is -initialization" facility, without shared-ownership or transfer-of-ownership -semantics. Both its name and enforcement of semantics (by being -noncopyable) -signal its intent to retain ownership solely within the current scope. -Because it is noncopyable, it is -safer than shared_array for pointers which should not be copied.

    - -

    Because scoped_array is so simple, in its usual implementation -every operation is as fast as a built-in array pointer and it has no -more space overhead that a built-in array pointer.

    - -

    It cannot be used in C++ standard library containers. -See shared_array -if scoped_array does not meet your needs.

    - -

    It cannot correctly hold a pointer to a single object. -See scoped_ptr -for that usage.

    - -

    A std::vector is an alternative to a scoped_array that is -a bit heavier duty but far more flexible. -A boost::array is an alternative that does not use dynamic allocation.

    - -

    The class template is parameterized on T, the type of the object -pointed to. T must meet the smart pointer -common requirements.

    - -

    Synopsis

    - -
    namespace boost {
    +	
    +		scoped_array
    +		
    +	
    +	
    +		

    c++boost.gif (8819 bytes)scoped_array + class template

    +

    The scoped_array class template stores a pointer to a dynamically + allocated array. (Dynamically allocated arrays are allocated with the C++ new[] + expression.) The array pointed to is guaranteed to be deleted, either on + destruction of the scoped_array, or via an explicit reset.

    +

    The scoped_array template is a simple solution for simple needs. It + supplies a basic "resource acquisition is initialization" facility, without + shared-ownership or transfer-of-ownership semantics. Both its name and + enforcement of semantics (by being + noncopyable) signal its intent to retain ownership solely within the + current scope. Because it is noncopyable, + it is safer than shared_array for pointers which should not be copied.

    +

    Because scoped_array is so simple, in its usual implementation every + operation is as fast as a built-in array pointer and it has no more space + overhead that a built-in array pointer.

    +

    It cannot be used in C++ standard library containers. See + shared_array if scoped_array does not meet your needs.

    +

    It cannot correctly hold a pointer to a single object. See scoped_ptr + for that usage.

    +

    A std::vector is an alternative to a scoped_array that is a bit + heavier duty but far more flexible. A boost::array is an alternative + that does not use dynamic allocation.

    +

    The class template is parameterized on T, the type of the object pointed + to. T must meet the smart pointer + common requirements.

    +

    Synopsis

    +
    namespace boost {
     
       template<typename T> class scoped_array : noncopyable {
     
    @@ -59,7 +44,7 @@ pointed to. T must meet the smart pointer
     
           void reset(T * p = 0); // never throws
     
    -      T & operator[](std::size_t i) const; // never throws
    +      T & operator[](std::ptrdiff_t i) const; // never throws
           T * get() const; // never throws
          
           void swap(scoped_array & b); // never throws
    @@ -68,78 +53,59 @@ pointed to. T must meet the smart pointer
       template<typename T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws
     
     }
    - -

    Members

    - -

    -element_type

    -
    typedef T element_type;
    -

    Provides the type of the stored pointer.

    - -

    constructors

    -
    explicit scoped_array(T * p = 0); // never throws
    -

    Constructs a scoped_array, storing a copy of p, which must -have been allocated via a C++ new[] expression or be 0. -T is not required be a complete type. -See the smart pointer -common requirements.

    - -

    destructor

    -
    ~scoped_array(); // never throws
    -

    Deletes the array pointed to by the stored pointer. -Note that delete[] on a pointer with a value of 0 is harmless. -The guarantee that this does not throw exceptions depends on the requirement that the -deleted array's objects' destructors do not throw exceptions. -See the smart pointer common requirements.

    - -

    reset

    -
    void reset(T * p = 0); // never throws
    -

    If p is not equal to the stored pointer, deletes the array pointed to by the -stored pointer and then stores a copy of p, which must have been allocated via a -C++ new[] expression or be 0. -The guarantee that this does not throw exceptions depends on the requirement that the -deleted array's objects' destructors do not throw exceptions. -See the smart pointer common requirements.

    - -

    subscripting

    -
    T & operator[](std::size_t i) const; // never throws
    -

    Returns a reference to element i of the array pointed to by the -stored pointer. -Behavior is undefined and almost certainly undesirable if the stored pointer is 0, -or if i is less than 0 or is greater than or equal to the number of elements -in the array.

    - -

    get

    -
    T * get() const; // never throws
    -

    Returns the stored pointer. -T need not be a complete type. -See the smart pointer -common requirements.

    - -

    swap

    -
    void swap(scoped_array & b); // never throws
    -

    Exchanges the contents of the two smart pointers. -T need not be a complete type. -See the smart pointer -common requirements.

    - -

    Free Functions

    - -

    swap

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

    Equivalent to a.swap(b). Matches the interface of std::swap. -Provided as an aid to generic programming.

    - -
    - -

    Revised 1 February 2002

    - -

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

    - - - +

    Members

    +

    + element_type

    +
    typedef T element_type;
    +

    Provides the type of the stored pointer.

    +

    constructors

    +
    explicit scoped_array(T * p = 0); // never throws
    +

    Constructs a scoped_array, storing a copy of p, which must have + been allocated via a C++ new[] expression or be 0. T is not + required be a complete type. See the smart pointer + common requirements.

    +

    destructor

    +
    ~scoped_array(); // never throws
    +

    Deletes the array pointed to by the stored pointer. Note that delete[] on + a pointer with a value of 0 is harmless. The guarantee that this does not throw + exceptions depends on the requirement that the deleted array's objects' + destructors do not throw exceptions. See the smart pointer + common requirements.

    +

    reset

    +
    void reset(T * p = 0); // never throws
    +

    If p is not equal to the stored pointer, deletes the array pointed to by the + stored pointer and then stores a copy of p, which must have been allocated via + a C++ new[] expression or be 0. The guarantee that this does not throw + exceptions depends on the requirement that the deleted array's objects' + destructors do not throw exceptions. See the smart pointer + common requirements.

    +

    subscripting

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

    Returns a reference to element i of the array pointed to by the stored + pointer. Behavior is undefined and almost certainly undesirable if the stored + pointer is 0, or if i is less than 0 or is greater than or equal to the + number of elements in the array.

    +

    get

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

    Returns the stored pointer. T need not be a complete type. See the smart + pointer common requirements.

    +

    swap

    +
    void swap(scoped_array & b); // never throws
    +

    Exchanges the contents of the two smart pointers. T need not be a + complete type. See the smart pointer common + requirements.

    +

    Free Functions

    +

    swap

    +
    template<typename T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws
    +

    Equivalent to a.swap(b). Matches the interface of std::swap. + Provided as an aid to generic programming.

    +
    +

    Revised + 1 February 2002

    +

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

    + diff --git a/shared_array.htm b/shared_array.htm index 3319553..7b904e9 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -1,47 +1,35 @@ - - - - -shared_array - - - - -

    c++boost.gif (8819 bytes)shared_array class template

    - -

    The shared_array class template stores a pointer to a dynamically allocated -array. (Dynamically allocated array are allocated with the C++ new[] -expression.) The object pointed to is guaranteed to be deleted when -the last shared_array pointing to it is destroyed or reset.

    - -

    Every shared_array 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_array works with -the standard library's associative containers.

    - -

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

    - -

    Because the implementation uses reference counting, shared_array will not work -correctly with cyclic data structures. For example, if main() holds a shared_array -to A, which directly or indirectly holds a shared_array back to A, -A's use count will be 2. Destruction of the original shared_array -will leave A dangling with a use count of 1.

    - -

    A shared_ptr to a std::vector is an alternative to a shared_array that is -a bit heavier duty but far more flexible.

    - -

    The class template is parameterized on T, the type of the object -pointed to. T must meet the smart pointer -common requirements.

    - -

    Synopsis

    - -
    namespace boost {
    +	
    +		shared_array
    +		
    +	
    +	
    +		

    c++boost.gif (8819 bytes)shared_array + class template

    +

    The shared_array class template stores a pointer to a dynamically + allocated array. (Dynamically allocated array are allocated with the C++ new[] + expression.) The object pointed to is guaranteed to be deleted when the last shared_array + pointing to it is destroyed or reset.

    +

    Every shared_array 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_array + works with the standard library's associative containers.

    +

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

    +

    Because the implementation uses reference counting, shared_array will not + work correctly with cyclic data structures. For example, if main() holds + a shared_array to A, which directly or indirectly holds a shared_array + back to A, A's use count will be 2. Destruction of the original shared_array + will leave A dangling with a use count of 1.

    +

    A shared_ptr to a std::vector is an alternative to a shared_array + that is a bit heavier duty but far more flexible.

    +

    The class template is parameterized on T, the type of the object pointed + to. T must meet the smart pointer + common requirements.

    +

    Synopsis

    +
    namespace boost {
     
       template<typename T> class shared_array {
     
    @@ -78,147 +66,114 @@ pointed to. T must meet the smart pointer
       template<typename T> void swap(shared_array<T> & a, shared_array<T> & b); // never throws
     
     }
    - -

    Members

    - -

    element_type

    -
    typedef T element_type;
    -

    Provides the type of the stored pointer.

    - -

    constructors

    - -
    explicit shared_array(T * p = 0);
    -

    Constructs a shared_array, storing a copy of p, which -must be a pointer to an array that was allocated via a C++ new[] expression or be 0. -Afterwards, the use count is 1 (even if p == 0; see ~shared_array). -The only exception which may be thrown by this constructor is std::bad_alloc. -If an exception is thrown, delete[] p is called.

    - -
    template<typename D> shared_array(T * p, D d);
    -

    Constructs a shared_array, storing a copy of p and of d. -Afterwards, the use count is 1. -D's copy constructor and destructor must not throw. -When the the time comes to delete the array pointed to by p, the object -d is used in the statement d(p). Invoking the object d with -parameter p in this way must not throw. -The only exception which may be thrown by this constructor is std::bad_alloc. -If an exception is thrown, d(p) is called.

    - -
    shared_array(shared_array const & r); // never throws
    -

    Constructs a shared_array, as if by storing a copy of the -pointer stored in r. Afterwards, the use count -for all copies is 1 more than the initial use count.

    - -

    destructor

    - -
    ~shared_array(); // never throws
    -

    Decrements the use count. Then, if the use count is 0, -deletes the array pointed to by the stored pointer. -Note that delete[] on a pointer with a value of 0 is harmless. -T need not be a complete type. -The guarantee that this does not throw exceptions depends on the requirement that the -deleted object's destructor does not throw exceptions. -See the smart pointer common requirements.

    - -

    assignment

    - -
    shared_array & operator=(shared_array const & r); // never throws
    -

    Constructs a new shared_array as described above, -then replaces this shared_array with the new one, destroying the replaced object.

    - -

    reset

    - -
    void reset(T * p = 0);
    -

    Constructs a new shared_array as described above, -then replaces this shared_array with the new one, destroying the replaced object. -The only exception which may be thrown is std::bad_alloc. If -an exception is thrown, delete[] p is called.

    - -
    template<typename D> void reset(T * p, D d);
    -

    Constructs a new shared_array as described above, -then replaces this shared_array with the new one, destroying the replaced object. -D's copy constructor must not throw. -The only exception which may be thrown is std::bad_alloc. If -an exception is thrown, d(p) is called.

    - -

    indexing

    -
    T & operator[](std::size_t i) const; // never throws
    -

    Returns a reference to element i of the array pointed to by the stored pointer. -Behavior is undefined and almost certainly undesirable if the stored pointer is 0, -or if i is less than 0 or is greater than or equal to the number of elements -in the array.

    - -

    get

    -
    T * get() const; // never throws
    -

    Returns the stored pointer. -T need not be a complete type. -See the smart pointer -common requirements.

    - -

    unique

    -
    bool unique() const; // never throws
    -

    Returns true if no other shared_array is sharing ownership of -the stored pointer, false otherwise. -T need not be a complete type. -See the smart pointer -common requirements.

    - -

    use_count

    -
    long use_count() const; // never throws
    -

    Returns the number of shared_array objects sharing ownership of the -stored pointer. -T need not be a complete type. -See the smart pointer -common requirements.

    -

    Because use_count is not necessarily efficient to implement for -implementations of shared_array that do not use an explicit reference -count, it might be removed from some future version. Thus it should -be used for debugging purposes only, and not production code.

    - -

    swap

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

    Exchanges the contents of the two smart pointers. -T need not be a complete type. -See the smart pointer -common requirements.

    - -

    Free Functions

    - -

    comparison

    -
    template<typename T>
    +		

    Members

    +

    element_type

    +
    typedef T element_type;
    +

    Provides the type of the stored pointer.

    +

    constructors

    +
    explicit shared_array(T * p = 0);
    +

    Constructs a shared_array, storing a copy of p, which must be a + pointer to an array that was allocated via a C++ new[] expression or be + 0. Afterwards, the use count is 1 (even if p == 0; see + ~shared_array). The only exception which may be thrown by this + constructor is std::bad_alloc. If an exception is thrown, delete[] p + is called.

    +
    template<typename D> shared_array(T * p, D d);
    +

    Constructs a shared_array, storing a copy of p and of d. + Afterwards, the use count is 1. D's copy + constructor and destructor must not throw. When the the time comes to delete + the array pointed to by p, the object d is used in the statement d(p). + Invoking the object d with parameter p in this way must not + throw. The only exception which may be thrown by this constructor is std::bad_alloc. + If an exception is thrown, d(p) is called.

    +
    shared_array(shared_array const & r); // never throws
    +

    Constructs a shared_array, as if by storing a copy of the pointer stored + in r. Afterwards, the use count for all copies + is 1 more than the initial use count.

    +

    destructor

    +
    ~shared_array(); // never throws
    +

    Decrements the use count. Then, if the use count is 0, + deletes the array pointed to by the stored pointer. Note that delete[] on + a pointer with a value of 0 is harmless. T need not be a complete type. + The guarantee that this does not throw exceptions depends on the requirement + that the deleted object's destructor does not throw exceptions. See the smart + pointer common requirements.

    +

    assignment

    +
    shared_array & operator=(shared_array const & r); // never throws
    +

    Constructs a new shared_array as described above, + then replaces this shared_array with the new one, destroying the + replaced object.

    +

    reset

    +
    void reset(T * p = 0);
    +

    Constructs a new shared_array as described above, + then replaces this shared_array with the new one, destroying the + replaced object. The only exception which may be thrown is std::bad_alloc. + If an exception is thrown, delete[] p is called.

    +
    template<typename D> void reset(T * p, D d);
    +

    Constructs a new shared_array as described above, + then replaces this shared_array with the new one, destroying the + replaced object. D's copy constructor must not throw. The only exception + which may be thrown is std::bad_alloc. If an exception is thrown, d(p) + is called.

    +

    indexing

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

    Returns a reference to element i of the array pointed to by the stored + pointer. Behavior is undefined and almost certainly undesirable if the stored + pointer is 0, or if i is less than 0 or is greater than or equal to the + number of elements in the array.

    +

    get

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

    Returns the stored pointer. T need not be a complete type. See the smart + pointer common requirements.

    +

    unique

    +
    bool unique() const; // never throws
    +

    Returns true if no other shared_array is sharing ownership of the stored + pointer, false otherwise. T need not be a complete type. See the smart + pointer common requirements.

    +

    use_count

    +
    long use_count() const; // never throws
    +

    Returns the number of shared_array objects sharing ownership of the + stored pointer. T need not be a complete type. See the smart pointer + common requirements.

    +

    Because use_count is not necessarily efficient to implement for + implementations of shared_array that do not use an explicit reference + count, it might be removed from some future version. Thus it should be used for + debugging purposes only, and not production code.

    +

    swap

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

    Exchanges the contents of the two smart pointers. T need not be a + complete type. See the smart pointer common + requirements.

    +

    Free Functions

    +

    comparison

    +
    template<typename T>
       bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws
     template<typename T>
       bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws
     template<typename T>
       bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws
    -

    Compares the stored pointers of the two smart pointers. -T need not be a complete type. -See the smart pointer -common requirements.

    -

    The operator< overload is provided to define an ordering so that shared_array -objects can be used in associative containers such as std::map. -The implementation uses std::less<T *> to perform the -comparison. This ensures that the comparison is handled correctly, since the -standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] -paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] -paragraph 8).

    - -

    swap

    -
    template<typename T>
    +		

    Compares the stored pointers of the two smart pointers. T need not be a + complete type. See the smart pointer common + requirements.

    +

    The operator< overload is provided to define an ordering so that shared_array + objects can be used in associative containers such as std::map. The + implementation uses std::less<T *> to perform the comparison. This + ensures that the comparison is handled correctly, since the standard mandates + that relational operations on pointers are unspecified (5.9 [expr.rel] + paragraph 2) but std::less<> on pointers is well-defined (20.3.3 + [lib.comparisons] paragraph 8).

    +

    swap

    +
    template<typename T>
       void swap(shared_array<T> & a, shared_array<T> & b) // never throws
    -

    Equivalent to a.swap(b). Matches the interface of std::swap. -Provided as an aid to generic programming.

    - -
    - -

    Revised 8 February 2002

    - -

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

    - - - +

    Equivalent to a.swap(b). Matches the interface of std::swap. + Provided as an aid to generic programming.

    +
    +

    Revised + 8 February 2002

    +

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

    + diff --git a/shared_ptr.htm b/shared_ptr.htm index 72c63f3..dce72c4 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -19,9 +19,9 @@ Smart Pointer Timings

    Introduction

    The shared_ptr class template stores a pointer to a dynamically allocated - object. (Dynamically allocated objects are allocated with the 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.

    + 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 @@ -29,11 +29,11 @@

    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, shared_ptr will not - work correctly with cyclic data structures. For example, if main() holds - a shared_ptr to A, which directly or indirectly holds a shared_ptr - back to A, A's use count will be 2. Destruction of the original shared_ptr - will leave A dangling with a use count of 1. Use weak_ptr +

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

    The class template is parameterized on T, the type of the object pointed to. shared_ptr and most of its member functions place no @@ -148,10 +148,11 @@ void bad() }

    [It might be convenient to relax the requirements on shared_ptr's - signature, allowing an additional, defaulted, template parameter. This would - help in detecting possible ODR violations. On the other hand, using shared_ptr - as an argument to a template template parameter requires an exact - signature match.]

    + signature, allowing an additional, defaulted, template parameter; the parameter + can encode the threading model, for example. This would help in detecting + possible ODR violations. On the other hand, using shared_ptr as + an argument to a template template parameter requires an exact signature + match.]

    Members

    element_type

    typedef T element_type;
    @@ -229,16 +230,17 @@ void bad()
    template<typename Y, typename D> shared_ptr(Y * p, D d);

    Requirements: p must be convertible to T *. 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. + constructor and destructor of D must not throw. The expression d2(p), + where d2 is a copy of d, must be well-formed, + must not invoke undefined behavior, and must not throw exceptions.

    Effects: Constructs a shared_ptr, storing a copy of p and d.

    Postconditions: use count is 1.

    Throws: std::bad_alloc.

    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, - d(p) is invoked.

    + d2(p) is invoked, where d2 is the stored copy of + d.

    [Custom deallocators allow a factory function returning a shared_ptr to insulate the user from its memory allocation strategy. Since the deallocator @@ -647,7 +649,7 @@ int * p = a.release(); implementation or a linked list implementation, or some other specific implementation. This is not the intent.


    -

    Revised +

    Revised 23 July 2002

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and From 024f918b867168d42a0cf041b2fd5dbe17c0e870 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 17 Sep 2002 13:59:17 +0000 Subject: [PATCH 132/513] More documentation fixes reflecting Dave Abrahams' comments [SVN r15411] --- scoped_ptr.htm | 309 +++++++++++++++++---------------------- shared_array.htm | 14 +- shared_ptr.htm | 38 +++-- smart_ptr.htm | 367 +++++++++++++++++++++-------------------------- 4 files changed, 329 insertions(+), 399 deletions(-) diff --git a/scoped_ptr.htm b/scoped_ptr.htm index ec0057d..a301fa6 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -1,51 +1,38 @@ - - - - -scoped_ptr - - - - -

    c++boost.gif (8819 bytes)scoped_ptr class template

    - -

    The scoped_ptr class template stores a pointer to a dynamically allocated -object. (Dynamically allocated objects are allocated with the C++ new -expression.) The object pointed to is guaranteed to be deleted, -either on destruction of the scoped_ptr, or via an explicit reset. -See the example.

    - -

    The scoped_ptr template is a simple solution for simple -needs. It supplies a basic "resource acquisition is -initialization" facility, without shared-ownership or transfer-of-ownership -semantics. Both its name and enforcement of semantics (by being -noncopyable) -signal its intent to retain ownership solely within the current scope. -Because it is noncopyable, it is -safer than shared_ptr or std::auto_ptr for pointers which should not be -copied.

    - -

    Because scoped_ptr is simple, in its usual implementation -every operation is as fast as for a built-in pointer and it has no more space overhead -that a built-in pointer.

    - -

    It cannot be used in C++ Standard Library containers. -See shared_ptr -or std::auto_ptr if scoped_ptr does not meet your needs.

    - -

    It cannot correctly hold a pointer to a -dynamically allocated array. See scoped_array -for that usage.

    - -

    The class template is parameterized on T, the type of the object -pointed to. T must meet the smart pointer -common requirements.

    - -

    Synopsis

    - -
    namespace boost {
    +	
    +		scoped_ptr
    +		
    +	
    +	
    +		

    c++boost.gif (8819 bytes)scoped_ptr + class template

    +

    The scoped_ptr class template stores a pointer to a dynamically allocated + object. (Dynamically allocated objects are allocated with the C++ new expression.) + The object pointed to is guaranteed to be deleted, either on destruction of the scoped_ptr, + or via an explicit reset. See the example.

    +

    The scoped_ptr template is a simple solution for simple needs. It + supplies a basic "resource acquisition is initialization" facility, without + shared-ownership or transfer-of-ownership semantics. Both its name and + enforcement of semantics (by being + noncopyable) signal its intent to retain ownership solely within the + current scope. Because it is noncopyable, + it is safer than shared_ptr or std::auto_ptr for pointers which + should not be copied.

    +

    Because scoped_ptr is simple, in its usual implementation every operation + is as fast as for a built-in pointer and it has no more space overhead that a + built-in pointer.

    +

    scoped_ptr cannot be used in C++ Standard Library + containers. Use shared_ptr if you need + a smart pointer that can.

    +

    scoped_ptr cannot correctly hold a pointer to a dynamically + allocated array. See scoped_array for + that usage.

    +

    The class template is parameterized on T, the type of the object pointed + to. T must meet the smart pointer + common requirements.

    +

    Synopsis

    +
    namespace boost {
     
       template<typename T> class scoped_ptr : noncopyable {
     
    @@ -53,7 +40,7 @@ pointed to. T must meet the smart pointer
          typedef T element_type;
     
          explicit scoped_ptr(T * p = 0); // never throws
    -     ~scoped_ptr(); // never throws
    +     ~scoped_ptr(); // never throws
     
          void reset(T * p = 0); // never throws
     
    @@ -67,75 +54,59 @@ pointed to. T must meet the smart pointer
       template<typename T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
     
     }
    - -

    Members

    - -

    element_type

    -
    typedef T element_type;
    -

    Provides the type of the stored pointer.

    - -

    constructors

    -
    explicit scoped_ptr(T * p = 0); // never throws
    -

    Constructs a scoped_ptr, storing a copy of p, which must -have been allocated via a C++ new expression or be 0. -T is not required be a complete type. -See the smart pointer -common requirements.

    - -

    destructor

    -
    ~scoped_ptr(); // never throws
    -

    Deletes the object pointed to by the stored pointer. -Note that delete on a pointer with a value of 0 is harmless. -The guarantee that this does not throw exceptions depends on the requirement that the -deleted object's destructor does not throw exceptions. -See the smart pointer common requirements.

    - -

    reset

    -
    void reset(T * p = 0); // never throws
    -

    If p is not equal to the stored pointer, deletes the object pointed to by the -stored pointer and then stores a copy of p, which must have been allocated via a -C++ new expression or be 0. -The guarantee that this does not throw exceptions depends on the requirement that the -deleted object's destructor does not throw exceptions. -See the smart pointer common requirements.

    - -

    indirection

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

    Returns a reference to the object pointed to by the stored pointer. -Behavior is undefined if the stored pointer is 0.

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

    Returns the stored pointer. Behavior is undefined if the stored pointer is 0.

    - -

    get

    -
    T * get() const; // never throws
    -

    Returns the stored pointer. -T need not be a complete type. -See the smart pointer -common requirements.

    - -

    swap

    -
    void swap(scoped_ptr & b); // never throws
    -

    Exchanges the contents of the two smart pointers. -T need not be a complete type. -See the smart pointer -common requirements.

    - -

    Free Functions

    - -

    swap

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

    Equivalent to a.swap(b). Matches the interface of std::swap. -Provided as an aid to generic programming.

    - -

    Example

    - -

    Here's an example that uses scoped_ptr.

    - -
    -
    #include <boost/scoped_ptr.hpp>
    +		

    Members

    +

    element_type

    +
    typedef T element_type;
    +

    Provides the type of the stored pointer.

    +

    constructors

    +
    explicit scoped_ptr(T * p = 0); // never throws
    +

    Constructs a scoped_ptr, storing a copy of p, which must have been + allocated via a C++ new expression or be 0. T is not required be + a complete type. See the smart pointer common + requirements.

    +

    destructor

    +
    ~scoped_ptr(); // never throws
    +

    Destroys the object pointed to by the stored pointer, if any, as if by using delete + this->get().

    +

    + The guarantee that this does not throw exceptions depends on the requirement + that the deleted object's destructor does not throw exceptions. See the smart + pointer common requirements.

    +

    reset

    +
    void reset(T * p = 0); // never throws
    +

    If p is not equal to the stored pointer, deletes the object pointed to by the + stored pointer and then stores a copy of p, which must have been allocated via + a C++ new expression or be 0. The guarantee that this does not throw + exceptions depends on the requirement that the deleted object's destructor does + not throw exceptions. See the smart pointer + common requirements.

    +

    indirection

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

    Returns a reference to the object pointed to by the stored pointer. Behavior is + undefined if the stored pointer is 0.

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

    Returns the stored pointer. Behavior is undefined if the stored pointer is 0.

    +

    get

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

    Returns the stored pointer. T need not be a complete type. See the smart + pointer common requirements.

    +

    swap

    +
    void swap(scoped_ptr & b); // never throws
    +

    Exchanges the contents of the two smart pointers. T need not be a + complete type. See the smart pointer common + requirements.

    +

    Free Functions

    +

    swap

    +
    template<typename T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
    +

    Equivalent to a.swap(b). Matches the interface of std::swap. + Provided as an aid to generic programming.

    +

    Example

    +

    Here's an example that uses scoped_ptr.

    +
    +
    #include <boost/scoped_ptr.hpp>
     #include <iostream>
     
    -struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } };
    +struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } };
     
     class MyClass {
         boost::scoped_ptr<int> ptr;
    @@ -151,67 +122,55 @@ void main()
         std::cout << my_instance.add_one() << '\n';
         std::cout << my_instance.add_one() << '\n';
     }
    -
    - -

    The example program produces the beginning of a child's nursery rhyme:

    - -
    -
    1
    +		
    +

    The example program produces the beginning of a child's nursery rhyme:

    +
    +
    1
     2
     Buckle my shoe
    -
    - -

    Rationale

    - -

    The primary reason to use scoped_ptr rather than auto_ptr is to let readers -of your code know that you intend "resource acquisition is initialization" to be applied only -for the current scope, and have no intent to transfer ownership.

    - -

    A secondary reason to use scoped_ptr is to prevent a later maintenance programmer -from adding a function that transfers ownership by returning the auto_ptr, -because the maintenance programmer saw auto_ptr, and assumed ownership could safely -be transferred.

    - -

    Think of bool vs int. We all know that under the covers bool is usually -just an int. Indeed, some argued against including bool in the -C++ standard because of that. But by coding bool rather than int, you tell your readers -what your intent is. Same with scoped_ptr; by using it you are signaling intent.

    - -

    It has been suggested that scoped_ptr<T> is equivalent to -std::auto_ptr<T> const. Ed Brey pointed out, however, that -reset will not work on a std::auto_ptr<T> const.

    - -

    Handle/Body Idiom

    - -

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

    - -

    The scoped_ptr_example_test.cpp -sample program includes a header file, scoped_ptr_example.hpp, -which uses a scoped_ptr<> to an incomplete type to hide the -implementation. The -instantiation of member functions which require a complete type occurs in -the scoped_ptr_example.cpp -implementation file.

    - -

    Frequently Asked Questions

    - -

    Q. Why doesn't scoped_ptr have a release() member?
    -A. Because the point of scoped_ptr is to signal intent, not -to transfer ownership. Use std::auto_ptr if ownership transfer is -required.

    - -
    - -

    Revised 1 February 2002

    - -

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

    - - - +
    +

    Rationale

    +

    The primary reason to use scoped_ptr rather than auto_ptr is to + let readers of your code know that you intend "resource acquisition is + initialization" to be applied only for the current scope, and have no intent to + transfer ownership.

    +

    A secondary reason to use scoped_ptr is to prevent a later maintenance + programmer from adding a function that transfers ownership by returning the auto_ptr, + because the maintenance programmer saw auto_ptr, and assumed ownership + could safely be transferred.

    +

    Think of bool vs int. We all know that under the covers bool + is usually just an int. Indeed, some argued against including bool + in the C++ standard because of that. But by coding bool rather than int, + you tell your readers what your intent is. Same with scoped_ptr; by + using it you are signaling intent.

    +

    It has been suggested that scoped_ptr<T> is equivalent to std::auto_ptr<T> + const. Ed Brey pointed out, however, that reset will not work on + a std::auto_ptr<T> const.

    +

    Handle/Body Idiom

    +

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

    +

    The scoped_ptr_example_test.cpp sample + program includes a header file, scoped_ptr_example.hpp, + which uses a scoped_ptr<> to an incomplete type to hide the + implementation. The instantiation of member functions which require a complete + type occurs in the scoped_ptr_example.cpp implementation + file.

    +

    Frequently Asked Questions

    +

    Q. Why doesn't scoped_ptr have a release() member?
    + A. When reading source code, it is valuable to be able to draw + conclusions about program behavior based on the types being used. If scoped_ptr + had a release() member, it would become possible to transfer ownership out of + its scope, weakening its role as a way of limiting resource lifetime to a given + scope. Use std::auto_ptr where transfer of ownership is + required. (supplied by Dave Abrahams)

    +
    +

    Revised + 17 September 2002

    +

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

    + diff --git a/shared_array.htm b/shared_array.htm index 7b904e9..52c58e6 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -15,13 +15,13 @@ requirements of the C++ Standard Library, and so can be used in standard library containers. Comparison operators are supplied so that shared_array works with the standard library's associative containers.

    -

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

    -

    Because the implementation uses reference counting, shared_array will not - work correctly with cyclic data structures. For example, if main() holds - a shared_array to A, which directly or indirectly holds a shared_array - back to A, A's use count will be 2. Destruction of the original shared_array +

    Normally, a shared_array cannot correctly hold a pointer to an object + that has been allocated with the non-array form of new. See + shared_ptr for that usage.

    +

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

    A shared_ptr to a std::vector is an alternative to a shared_array that is a bit heavier duty but far more flexible.

    diff --git a/shared_ptr.htm b/shared_ptr.htm index dce72c4..291005f 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -150,9 +150,12 @@ void bad()

    [It might be convenient to relax the requirements on shared_ptr's signature, allowing an additional, defaulted, template parameter; the parameter can encode the threading model, for example. This would help in detecting - possible ODR violations. On the other hand, using shared_ptr as - an argument to a template template parameter requires an exact signature - match.]

    + possible ODR violations.

    +

    On the other hand, using shared_ptr as an argument to + a template template parameter requires an exact signature match. Metaprogramming + experts tend to deemphasize template template parameters as they are too + inflexible, but the alternative is typically an std::allocator::rebind-type + "hack".]

    Members

    element_type

    typedef T element_type;
    @@ -229,18 +232,18 @@ void bad() pointer users.]

    template<typename Y, typename D> shared_ptr(Y * p, D d);
    -

    Requirements: p must be convertible to T *. The copy - constructor and destructor of D must not throw. The expression d2(p), - where d2 is a copy of d, must be well-formed, - must not invoke undefined behavior, and must not throw exceptions. +

    Requirements: p must be convertible to T *. D + must be CopyConstructible. The copy constructor and destructor + of D must not throw. The expression d(p) must be + well-formed, must not invoke undefined behavior, and must not throw exceptions.

    Effects: Constructs a shared_ptr, storing a copy of p and d.

    Postconditions: use count is 1.

    Throws: std::bad_alloc.

    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, - d2(p) is invoked, where d2 is the stored copy of - d.

    +

    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 @@ -311,9 +314,10 @@ template<typename Y> shared_ptr & operator=(shared_ptr<Y> const template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r);

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

    -

    Notes: The implementation is free to meet the effects (and the implied - guarantees) via different means, without creating a temporary. In particular, - in the example:

    +

    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);
    @@ -322,6 +326,12 @@ q = p;
     

    both assignments may be no-ops.

    +

    [Some experts consider the note to be redundant, as it appears to essentially + mirror the "as if" rile. However, experience suggests that when C++ code is + used to describe effects, it is often misinterpreted as required + implementation. In addition, it is not entirely clear whether the "as if" rule + actually applies here, so it's better to be explicit about the possible + optimizations.]

    reset

    void reset();
    @@ -649,7 +659,7 @@ int * p = a.release(); implementation or a linked list implementation, or some other specific implementation. This is not the intent.


    -

    Revised +

    Revised 23 July 2002

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and diff --git a/smart_ptr.htm b/smart_ptr.htm index 1e045f1..9e5357a 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -1,207 +1,168 @@ - - - - -Smart Pointers - - - - -

    c++boost.gif (8819 bytes)Smart -Pointers

    - -

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

    - -

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

    - -

    The smart pointer library provides five smart pointer class templates:

    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    scoped_ptr<boost/scoped_ptr.hpp>Simple sole ownership of single objects. Noncopyable.
    scoped_array<boost/scoped_array.hpp>Simple sole ownership of arrays. Noncopyable.
    shared_ptr<boost/shared_ptr.hpp>Object ownership shared among multiple pointers
    shared_array<boost/shared_array.hpp>Array ownership shared among multiple pointers.
    weak_ptr<boost/weak_ptr.hpp>Non-owning observers of an object owned by shared_ptr.
    -
    - -

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

    - -

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

    - -

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

    - -

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

    - -

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

    - -

    Common Requirements

    - -

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

    - -

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

    - -

    Rationale

    - -

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

    - -

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

    - -

    Exception Safety

    - -

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

    - -

    Exception-specifications

    - -

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

    - -

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

    - -

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

    - -

    History and Acknowledgements

    - -

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

    - -

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

    - -

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

    - -

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

    - -

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

    - -

    October 1998. In 1994 Greg Colvin proposed to the C++ Standards Committee -classes named auto_ptr and counted_ptr which -were very similar to what we now call scoped_ptr and shared_ptr. -The committee document was 94-168/N0555, Exception Safe Smart Pointers. In -one of the very few cases where the Library Working Group's recommendations were -not followed by the full committee, counted_ptr was rejected -and surprising transfer-of-ownership semantics were added to auto_ptr.

    - -

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

    - -

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

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

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

    - -

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

    - -
    - -

    Revised 4 February 2002 + 4 February 2002

    - -

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

    - - - +

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

    + From 9dcbc46225216a2e7bc35b5cca263357f5ead7d7 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 18 Sep 2002 13:00:38 +0000 Subject: [PATCH 133/513] Minor fix [SVN r15437] --- scoped_ptr.htm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scoped_ptr.htm b/scoped_ptr.htm index a301fa6..d684b6b 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -22,9 +22,9 @@

    Because scoped_ptr is simple, in its usual implementation every operation is as fast as for a built-in pointer and it has no more space overhead that a built-in pointer.

    -

    scoped_ptr cannot be used in C++ Standard Library - containers. Use shared_ptr if you need - a smart pointer that can.

    +

    scoped_ptr cannot be used in C++ Standard Library containers. + Use shared_ptr if you need a smart pointer + that can.

    scoped_ptr cannot correctly hold a pointer to a dynamically allocated array. See scoped_array for that usage.

    @@ -160,10 +160,10 @@ Buckle my shoe

    Q. Why doesn't scoped_ptr have a release() member?
    A. When reading source code, it is valuable to be able to draw conclusions about program behavior based on the types being used. If scoped_ptr - had a release() member, it would become possible to transfer ownership out of - its scope, weakening its role as a way of limiting resource lifetime to a given - scope. Use std::auto_ptr where transfer of ownership is - required. (supplied by Dave Abrahams)

    + had a release() member, it would become possible to transfer ownership of the + held pointer, weakening its role as a way of limiting resource lifetime to a + given context. Use std::auto_ptr where transfer of ownership + is required. (supplied by Dave Abrahams)


    Revised 17 September 2002

    From a8bb455df7a8ff67028c52729ea31eb3dea5f93f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 23 Sep 2002 13:22:38 +0000 Subject: [PATCH 134/513] Fixes, notes. [SVN r15486] --- shared_ptr.htm | 70 ++++++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 291005f..1a91e46 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -47,14 +47,14 @@ where U is an accessible base of T, and to shared_ptr<void>.

    Best Practices

    -

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

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

    shared_ptr<T> p(new Y);

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

    + passing arguments to Y's constructor is also OK.

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

    @@ -96,23 +96,23 @@ void bad() typedef T element_type; - shared_ptr(); + shared_ptr(); template<typename Y> explicit shared_ptr(Y * p); template<typename Y, typename D> shared_ptr(Y * p, D d); - ~shared_ptr(); // never throws + ~shared_ptr(); // never throws - shared_ptr(shared_ptr const & r); // never throws - template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws - explicit shared_ptr(weak_ptr const & r); - template<typename Y> shared_ptr(std::auto_ptr<Y> & r); + shared_ptr(shared_ptr const & r); // never throws + template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws + template<typename Y> explicit shared_ptr(weak_ptr<Y> const & r); + template<typename Y> explicit shared_ptr(std::auto_ptr<Y> & r); shared_ptr & operator=(shared_ptr const & r); // never throws template<typename Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r); - void reset (); - template<typename Y> void reset (Y * p); - template<typename Y> template<typename D> void reset(Y * p, D d); + void reset(); + template<typename Y> void reset(Y * p); + template<typename Y, typename D> void reset(Y * p, D d); T & operator*() const; // never throws T * operator->() const; // never throws @@ -121,9 +121,9 @@ void bad() bool unique() const; // never throws long use_count() const; // never throws - operator unspecified-bool-type () const; // never throws + operator unspecified-bool-type() const; // never throws - void swap(shared_ptr<T> & b); // never throws + void swap(shared_ptr & b); // never throws }; template<typename T, typename U> @@ -147,12 +147,12 @@ void bad() shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws }
    -

    [It might be convenient to relax the requirements on shared_ptr's +

    [It might be convenient to relax the requirements on shared_ptr's signature, allowing an additional, defaulted, template parameter; the parameter can encode the threading model, for example. This would help in detecting possible ODR violations.

    -

    On the other hand, using shared_ptr as an argument to - a template template parameter requires an exact signature match. Metaprogramming +

    On the other hand, using shared_ptr as an argument to a + template template parameter requires an exact signature match. Metaprogramming experts tend to deemphasize template template parameters as they are too inflexible, but the alternative is typically an std::allocator::rebind-type "hack".]

    @@ -222,13 +222,13 @@ void bad() of intrusive counting. shared_from_this would no longer be O(1), which is a concern for some users, although I do not expect any performance problems, since the operation is rare. Maintaining a global - map is difficult; it needs to be initialized before any shared_ptr - instances are constructed, and the initialization needs to be thread safe. + map is difficult; it needs to be initialized before any shared_ptr + instances are constructed, and the initialization needs to be thread safe. In addition, under the Windows dynamic library model, it is possible for several maps to exist.

    It is not yet clear which implementation should be used, or whether the - specification should allow both; nevertheless, the ability to make a shared_ptr - from this is considered essential by experienced smart + specification should allow both; nevertheless, the ability to make a shared_ptr + from this is considered essential by experienced smart pointer users.]

    template<typename Y, typename D> shared_ptr(Y * p, D d);
    @@ -253,9 +253,18 @@ void bad() to a statically allocated object.

    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 is too - strong. It will be removed when some core language issues are resolved - (cv-qualified function types, partial ordering clarifications.)]

    +

    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 problems are + that (1) pass by value conveniently changes functions (function references) to + function pointers (this has to be performed manually otherwise and some + compilers may not be able to do it) and (2) const references don't currently + (per the standard) bind to functions. This can be solved (I think) but it + requires an overload set that breaks on many compilers due to 14.5.5.2 problems + (and of course it will break on compilers that don't do partial ordering at + all.)

    +

    The requrement will be removed when the aforementioned issues are + resolved.]

    shared_ptr(shared_ptr const & r); // never throws
     template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws
    @@ -267,7 +276,7 @@ template<typename Y> shared_ptr(shared_ptr<Y> const & r); // nev

    [The postcondition will be relaxed when a default-constructed shared_ptr is being copied.]

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

    Effects: Constructs a shared_ptr, as if by storing a copy of the pointer stored in r.

    @@ -389,7 +398,7 @@ q = p;

    conversions

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

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

    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 @@ -423,7 +432,7 @@ q = p;

    template<typename T>
       bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws
    -

    Returns: an unspecified value such that operator< is a +

    Returns: an unspecified value such that operator< is a strict weak ordering as described in section 25.3 [lib.alg.sorting] of the C++ standard.

    Throws: nothing.

    @@ -436,7 +445,7 @@ q = p; standard algorithms use operator< instead of std::less for comparisons when a predicate is not supplied. Composite objects, like std::pair, also implement their operator< in terms of their contained - subobjects' operator<.

    + subobjects' operator<.

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

    swap

    template<typename T>
    @@ -546,8 +555,8 @@ q = p;
     			type.

    Thread Safety

    shared_ptr objects offer the same level of thread safety as - built-in types. A shared_ptr instance can be "read" - (accessed using only const operations) simultaneously by multiple threads. + 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 @@ -659,8 +668,7 @@ int * p = a.release(); implementation or a linked list implementation, or some other specific implementation. This is not the intent.


    -

    Revised - 23 July 2002

    +

    Revised $Date$

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in From f2f616a95cf3b4b1cbcf5d7b0fce1b33840f53ef Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 8 Oct 2002 16:37:33 +0000 Subject: [PATCH 135/513] BOOST_SP_USE_STD_ALLOCATOR support [SVN r15807] --- include/boost/detail/shared_count.hpp | 16 +++++ shared_ptr_alloc_test.cpp | 94 +++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 shared_ptr_alloc_test.cpp diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index cd5ae8f..b47fe62 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -219,6 +219,8 @@ private: counted_base_impl(counted_base_impl const &); counted_base_impl & operator= (counted_base_impl const &); + typedef counted_base_impl this_type; + public: // pre: initial_use_count <= initial_weak_count, d(p) must not throw @@ -232,6 +234,20 @@ public: { del(ptr); } + +#if defined(BOOST_SP_USE_STD_ALLOCATOR) + + void * operator new(std::size_t) + { + return std::allocator().allocate(1, static_cast(0)); + } + + void operator delete(void * p) + { + std::allocator().deallocate(static_cast(p), 1); + } + +#endif }; class weak_count; diff --git a/shared_ptr_alloc_test.cpp b/shared_ptr_alloc_test.cpp new file mode 100644 index 0000000..079dde7 --- /dev/null +++ b/shared_ptr_alloc_test.cpp @@ -0,0 +1,94 @@ +// +// shared_ptr_alloc_test.cpp - use to evaluate the impact of count allocations +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include +#include + +#include +#include +#include +#include + +int const n = 1024 * 1024; + +template void test(T * = 0) +{ + std::vector< boost::shared_ptr > v; + + std::clock_t t = std::clock(); + + for(int i = 0; i < n; ++i) + { + boost::shared_ptr pi(new T(i)); + v.push_back(pi); + } + + t = std::clock() - t; + + std::cout << static_cast(t) / CLOCKS_PER_SEC << '\n'; +} + +class X +{ +public: + + explicit X(int n): n_(n) + { + } + + void * operator new(std::size_t) + { + return std::allocator().allocate(1, static_cast(0)); + } + + void operator delete(void * p) + { + std::allocator().deallocate(static_cast(p), 1); + } + +private: + + X(X const &); + X & operator=(X const &); + + int n_; +}; + +int main() +{ + std::cout << BOOST_COMPILER "\n"; + std::cout << BOOST_PLATFORM "\n"; + std::cout << BOOST_STDLIB "\n"; + +#if defined(BOOST_HAS_THREADS) + std::cout << "BOOST_HAS_THREADS: (defined)\n"; +#else + std::cout << "BOOST_HAS_THREADS: (not defined)\n"; +#endif + +#if defined(BOOST_SP_USE_STD_ALLOCATOR) + std::cout << "BOOST_SP_USE_STD_ALLOCATOR: (defined)\n"; +#else + std::cout << "BOOST_SP_USE_STD_ALLOCATOR: (not defined)\n"; +#endif + + std::cout << n << " shared_ptr allocations + deallocations:\n"; + + test(); + test(); + test(); + + std::cout << n << " shared_ptr allocations + deallocations:\n"; + + test(); + test(); + test(); +} From ae60bcaffb4986363ea9384229f333ec20b9d386 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 17 Oct 2002 13:23:11 +0000 Subject: [PATCH 136/513] Small fixes. [SVN r15951] --- shared_ptr.htm | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 1a91e46..87a29b0 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -47,8 +47,8 @@ where U is an accessible base of T, and to shared_ptr<void>.

    Best Practices

    -

    A simple guideline that nearly eliminates the possibility of memory leaks - is: always use a named smart pointer variable to hold the result of new. +

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

    shared_ptr<T> p(new Y);
    @@ -172,7 +172,7 @@ void bad()

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

    -

    [The poscondition of use_count() == 1 is too strong. Having the nothrow +

    [The postcondition of use_count() == 1 is too strong. Having the nothrow guarantee is important, since reset() is specified in terms of the default constructor, but the current specification requires that a count be allocated. Therefore, this postcondition will be dropped in a future release. @@ -221,15 +221,15 @@ void bad()

    Another possible implementation is to use a global pointer-to-count map instead of intrusive counting. shared_from_this would no longer be O(1), which is a concern for some users, although I do not expect any - performance problems, since the operation is rare. Maintaining a global - map is difficult; it needs to be initialized before any shared_ptr - instances are constructed, and the initialization needs to be thread safe. - In addition, under the Windows dynamic library model, it is possible for - several maps to exist.

    + performance problems, since the operation is rare. Maintaining a global map is + difficult; it needs to be initialized before any shared_ptr instances + are constructed, and the initialization needs to be thread safe. In addition, + under the Windows dynamic library model, it is possible for several maps to + exist.

    It is not yet clear which implementation should be used, or whether the specification should allow both; nevertheless, the ability to make a shared_ptr - from this is considered essential by experienced smart - pointer users.]

    + from this is considered essential by experienced smart pointer + users.
    ]

    template<typename Y, typename D> shared_ptr(Y * p, D d);

    Requirements: p must be convertible to T *. D @@ -263,8 +263,7 @@ void bad() requires an overload set that breaks on many compilers due to 14.5.5.2 problems (and of course it will break on compilers that don't do partial ordering at all.)

    -

    The requrement will be removed when the aforementioned issues are - resolved.]

    +

    The requrement will be removed when the aforementioned issues are resolved.]

    shared_ptr(shared_ptr const & r); // never throws
     template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws
    @@ -336,7 +335,7 @@ q = p;

    both assignments may be no-ops.

    [Some experts consider the note to be redundant, as it appears to essentially - mirror the "as if" rile. However, experience suggests that when C++ code is + mirror the "as if" rule. However, experience suggests that when C++ code is used to describe effects, it is often misinterpreted as required implementation. In addition, it is not entirely clear whether the "as if" rule actually applies here, so it's better to be explicit about the possible @@ -398,8 +397,8 @@ q = p;

    conversions

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

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

    +

    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()) {}. @@ -432,9 +431,9 @@ q = p;

    template<typename T>
       bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws
    -

    Returns: an unspecified value such that operator< is a - strict weak ordering as described in section 25.3 [lib.alg.sorting] - of the C++ standard.

    +

    Returns: an unspecified value such that operator< is a strict + weak ordering as described in section 25.3 [lib.alg.sorting] of + the C++ standard.

    Throws: nothing.

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

    @@ -555,12 +554,12 @@ q = p; type.

    Thread Safety

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

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

    Any other simultaneous accesses result in undefined behavior.

    Examples:

    
    From 57c0ad44f399cf3d6e60c0d682a5408ba9600c45 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Wed, 23 Oct 2002 13:55:18 +0000
    Subject: [PATCH 137/513] Changed typename to class; some libraries helpfully
     #define typename
    
    [SVN r15970]
    ---
     include/boost/detail/shared_count.hpp |  2 +-
     include/boost/scoped_array.hpp        |  2 +-
     include/boost/scoped_ptr.hpp          |  6 +--
     include/boost/shared_array.hpp        | 14 ++---
     include/boost/shared_ptr.hpp          | 58 ++++++++++----------
     include/boost/weak_ptr.hpp            | 16 +++---
     scoped_array.htm                      |  6 +--
     scoped_ptr.htm                        |  6 +--
     shared_array.htm                      | 26 ++++-----
     shared_ptr.htm                        | 76 +++++++++++++--------------
     smart_ptr_test.cpp                    |  2 +-
     weak_ptr.htm                          | 38 +++++++-------
     12 files changed, 126 insertions(+), 126 deletions(-)
    
    diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp
    index b47fe62..dd6ba2d 100644
    --- a/include/boost/detail/shared_count.hpp
    +++ b/include/boost/detail/shared_count.hpp
    @@ -309,7 +309,7 @@ public:
     
         // auto_ptr is special cased to provide the strong guarantee
     
    -    template
    +    template
         explicit shared_count(std::auto_ptr & r): pi_(new counted_base_impl< Y *, checked_deleter >(r.get(), checked_deleter(), 1, 1))
         {
             r.release();
    diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp
    index 8c7fdcc..636fad4 100644
    --- a/include/boost/scoped_array.hpp
    +++ b/include/boost/scoped_array.hpp
    @@ -24,7 +24,7 @@ namespace boost
     //  is guaranteed, either on destruction of the scoped_array or via an explicit
     //  reset(). Use shared_array or std::vector if your needs are more complex.
     
    -template class scoped_array // noncopyable
    +template class scoped_array // noncopyable
     {
     private:
     
    diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp
    index 589bd36..1c2a520 100644
    --- a/include/boost/scoped_ptr.hpp
    +++ b/include/boost/scoped_ptr.hpp
    @@ -27,7 +27,7 @@ namespace boost
     //  an explicit reset(). scoped_ptr is a simple solution for simple needs;
     //  use shared_ptr or std::auto_ptr if your needs are more complex.
     
    -template class scoped_ptr // noncopyable
    +template class scoped_ptr // noncopyable
     {
     private:
     
    @@ -106,14 +106,14 @@ public:
         }
     };
     
    -template inline void swap(scoped_ptr & a, scoped_ptr & b) // never throws
    +template inline void swap(scoped_ptr & a, scoped_ptr & b) // never throws
     {
         a.swap(b);
     }
     
     // get_pointer(p) is a generic way to say p.get()
     
    -template inline T * get_pointer(scoped_ptr const & p)
    +template inline T * get_pointer(scoped_ptr const & p)
     {
         return p.get();
     }
    diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp
    index c60a85a..992bdee 100644
    --- a/include/boost/shared_array.hpp
    +++ b/include/boost/shared_array.hpp
    @@ -41,7 +41,7 @@ namespace boost
     //  is destroyed or reset.
     //
     
    -template class shared_array
    +template class shared_array
     {
     private:
     
    @@ -63,7 +63,7 @@ public:
         // shared_array will release p by calling d(p)
         //
     
    -    template shared_array(T * p, D d): px(p), pn(p, d)
    +    template shared_array(T * p, D d): px(p), pn(p, d)
         {
         }
     
    @@ -75,7 +75,7 @@ public:
             this_type(p).swap(*this);
         }
     
    -    template  void reset(T * p, D d)
    +    template  void reset(T * p, D d)
         {
             this_type(p, d).swap(*this);
         }
    @@ -129,22 +129,22 @@ private:
     
     };  // shared_array
     
    -template inline bool operator==(shared_array const & a, shared_array const & b) // never throws
    +template inline bool operator==(shared_array const & a, shared_array const & b) // never throws
     {
         return a.get() == b.get();
     }
     
    -template inline bool operator!=(shared_array const & a, shared_array const & b) // never throws
    +template inline bool operator!=(shared_array const & a, shared_array const & b) // never throws
     {
         return a.get() != b.get();
     }
     
    -template inline bool operator<(shared_array const & a, shared_array const & b) // never throws
    +template inline bool operator<(shared_array const & a, shared_array const & b) // never throws
     {
         return std::less()(a.get(), b.get());
     }
     
    -template void swap(shared_array & a, shared_array & b) // never throws
    +template void swap(shared_array & a, shared_array & b) // never throws
     {
         a.swap(b);
     }
    diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp
    index 8f55948..11202f4 100644
    --- a/include/boost/shared_ptr.hpp
    +++ b/include/boost/shared_ptr.hpp
    @@ -46,7 +46,7 @@ struct static_cast_tag {};
     struct dynamic_cast_tag {};
     struct polymorphic_cast_tag {};
     
    -template struct shared_ptr_traits
    +template struct shared_ptr_traits
     {
         typedef T & reference;
     };
    @@ -76,10 +76,10 @@ template<> struct shared_ptr_traits
     //  is destroyed or reset.
     //
     
    -template class weak_ptr;
    -template class intrusive_ptr;
    +template class weak_ptr;
    +template class intrusive_ptr;
     
    -template class shared_ptr
    +template class shared_ptr
     {
     private:
     
    @@ -96,7 +96,7 @@ public:
         {
         }
     
    -    template
    +    template
         explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter(), p) // Y must be complete
         {
         }
    @@ -107,33 +107,33 @@ public:
         // shared_ptr will release p by calling d(p)
         //
     
    -    template shared_ptr(Y * p, D d): px(p), pn(p, d)
    +    template shared_ptr(Y * p, D d): px(p), pn(p, d)
         {
         }
     
     //  generated copy constructor, assignment, destructor are fine
     
    -    template
    +    template
         explicit shared_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // may throw
         {
         }
     
    -    template
    +    template
         shared_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws
         {
         }
     
    -    template
    +    template
         shared_ptr(intrusive_ptr const & r): px(r.get()), pn(r.get()) // never throws
         {
         }
     
    -    template
    +    template
         shared_ptr(shared_ptr const & r, detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn)
         {
         }
     
    -    template
    +    template
         shared_ptr(shared_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn)
         {
             if (px == 0) // need to allocate new counter -- the cast failed
    @@ -142,7 +142,7 @@ public:
             }
         }
     
    -    template
    +    template
         shared_ptr(shared_ptr const & r, detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn)
         {
             if (px == 0)
    @@ -153,7 +153,7 @@ public:
     
     #ifndef BOOST_NO_AUTO_PTR
     
    -    template
    +    template
         explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn(r)
         {
         }
    @@ -162,7 +162,7 @@ public:
     
     #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
     
    -    template
    +    template
         shared_ptr & operator=(shared_ptr const & r) // never throws
         {
             px = r.px;
    @@ -174,7 +174,7 @@ public:
     
     #ifndef BOOST_NO_AUTO_PTR
     
    -    template
    +    template
         shared_ptr & operator=(std::auto_ptr & r)
         {
             this_type(r).swap(*this);
    @@ -188,13 +188,13 @@ public:
             this_type().swap(*this);
         }
     
    -    template void reset(Y * p) // Y must be complete
    +    template void reset(Y * p) // Y must be complete
         {
             BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
             this_type(p).swap(*this);
         }
     
    -    template void reset(Y * p, D d)
    +    template void reset(Y * p, D d)
         {
             this_type(p, d).swap(*this);
         }
    @@ -253,8 +253,8 @@ public:
     
     private:
     
    -    template friend class shared_ptr;
    -    template friend class weak_ptr;
    +    template friend class shared_ptr;
    +    template friend class weak_ptr;
     
     
     #endif
    @@ -264,12 +264,12 @@ private:
     
     };  // shared_ptr
     
    -template inline bool operator==(shared_ptr const & a, shared_ptr const & b)
    +template inline bool operator==(shared_ptr const & a, shared_ptr const & b)
     {
         return a.get() == b.get();
     }
     
    -template inline bool operator!=(shared_ptr const & a, shared_ptr const & b)
    +template inline bool operator!=(shared_ptr const & a, shared_ptr const & b)
     {
         return a.get() != b.get();
     }
    @@ -278,39 +278,39 @@ template inline bool operator!=(shared_ptr const & a,
     
     // Resolve the ambiguity between our op!= and the one in rel_ops
     
    -template inline bool operator!=(shared_ptr const & a, shared_ptr const & b)
    +template inline bool operator!=(shared_ptr const & a, shared_ptr const & b)
     {
         return a.get() != b.get();
     }
     
     #endif
     
    -template inline bool operator<(shared_ptr const & a, shared_ptr const & b)
    +template inline bool operator<(shared_ptr const & a, shared_ptr const & b)
     {
         return std::less()(a.get(), b.get());
     }
     
    -template inline void swap(shared_ptr & a, shared_ptr & b)
    +template inline void swap(shared_ptr & a, shared_ptr & b)
     {
         a.swap(b);
     }
     
    -template shared_ptr shared_static_cast(shared_ptr const & r)
    +template shared_ptr shared_static_cast(shared_ptr const & r)
     {
         return shared_ptr(r, detail::static_cast_tag());
     }
     
    -template shared_ptr shared_dynamic_cast(shared_ptr const & r)
    +template shared_ptr shared_dynamic_cast(shared_ptr const & r)
     {
         return shared_ptr(r, detail::dynamic_cast_tag());
     }
     
    -template shared_ptr shared_polymorphic_cast(shared_ptr const & r)
    +template shared_ptr shared_polymorphic_cast(shared_ptr const & r)
     {
         return shared_ptr(r, detail::polymorphic_cast_tag());
     }
     
    -template shared_ptr shared_polymorphic_downcast(shared_ptr const & r)
    +template shared_ptr shared_polymorphic_downcast(shared_ptr const & r)
     {
         BOOST_ASSERT(dynamic_cast(r.get()) == r.get());
         return shared_static_cast(r);
    @@ -318,7 +318,7 @@ template shared_ptr shared_polymorphic_downcast(share
     
     // get_pointer() enables boost::mem_fn to recognize shared_ptr
     
    -template inline T * get_pointer(shared_ptr const & p)
    +template inline T * get_pointer(shared_ptr const & p)
     {
         return p.get();
     }
    diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp
    index c76cb28..e17a9f7 100644
    --- a/include/boost/weak_ptr.hpp
    +++ b/include/boost/weak_ptr.hpp
    @@ -24,7 +24,7 @@
     namespace boost
     {
     
    -template class weak_ptr
    +template class weak_ptr
     {
     private:
     
    @@ -41,19 +41,19 @@ public:
     
     //  generated copy constructor, assignment, destructor are fine
     
    -    template
    +    template
         weak_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // never throws
         {
         }
     
    -    template
    +    template
         weak_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws
         {
         }
     
     #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
     
    -    template
    +    template
         weak_ptr & operator=(weak_ptr const & r) // never throws
         {
             px = r.px;
    @@ -61,7 +61,7 @@ public:
             return *this;
         }
     
    -    template
    +    template
         weak_ptr & operator=(shared_ptr const & r) // never throws
         {
             px = r.px;
    @@ -109,8 +109,8 @@ public:
     
     private:
     
    -    template friend class weak_ptr;
    -    template friend class shared_ptr;
    +    template friend class weak_ptr;
    +    template friend class shared_ptr;
     
     #endif
     
    @@ -133,7 +133,7 @@ template inline bool operator!=(weak_ptr const & a, weak_pt
     
     // Resolve the ambiguity between our op!= and the one in rel_ops
     
    -template inline bool operator!=(weak_ptr const & a, weak_ptr const & b)
    +template inline bool operator!=(weak_ptr const & a, weak_ptr const & b)
     {
         return a.get() != b.get();
     }
    diff --git a/scoped_array.htm b/scoped_array.htm
    index 834e0d2..a057b11 100644
    --- a/scoped_array.htm
    +++ b/scoped_array.htm
    @@ -34,7 +34,7 @@
     		

    Synopsis

    namespace boost {
     
    -  template<typename T> class scoped_array : noncopyable {
    +  template<class T> class scoped_array : noncopyable {
     
         public:
           typedef T element_type;
    @@ -50,7 +50,7 @@
           void swap(scoped_array & b); // never throws
       };
     
    -  template<typename T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws
    +  template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws
     
     }

    Members

    @@ -96,7 +96,7 @@ requirements.

    Free Functions

    swap

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

    Equivalent to a.swap(b). Matches the interface of std::swap. Provided as an aid to generic programming.


    diff --git a/scoped_ptr.htm b/scoped_ptr.htm index d684b6b..53815c7 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -34,7 +34,7 @@

    Synopsis

    namespace boost {
     
    -  template<typename T> class scoped_ptr : noncopyable {
    +  template<class T> class scoped_ptr : noncopyable {
     
        public:
          typedef T element_type;
    @@ -51,7 +51,7 @@
          void swap(scoped_ptr & b); // never throws
       };
     
    -  template<typename T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
    +  template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
     
     }

    Members

    @@ -97,7 +97,7 @@ requirements.

    Free Functions

    swap

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

    Equivalent to a.swap(b). Matches the interface of std::swap. Provided as an aid to generic programming.

    Example

    diff --git a/shared_array.htm b/shared_array.htm index 52c58e6..26a6dab 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -31,13 +31,13 @@

    Synopsis

    namespace boost {
     
    -  template<typename T> class shared_array {
    +  template<class T> class shared_array {
     
         public:
           typedef T element_type;
     
           explicit shared_array(T * p = 0);
    -      template<typename D> shared_array(T * p, D d);
    +      template<class D> shared_array(T * p, D d);
           ~shared_array(); // never throws
     
           shared_array(shared_array const & r); // never throws
    @@ -45,7 +45,7 @@
           shared_array & operator=(shared_array const & r); // never throws
     
           void reset(T * p = 0);
    -      template<typename D> void reset(T * p, D d);
    +      template<class D> void reset(T * p, D d);
     
           T & operator[](std::ptrdiff_t i) const() const; // never throws
           T * get() const; // never throws
    @@ -56,14 +56,14 @@
           void swap(shared_array<T> & b); // never throws
       };
     
    -  template<typename T>
    +  template<class T>
         bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws
    -  template<typename T>
    +  template<class T>
         bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws
    -  template<typename T>
    +  template<class T>
         bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws
     
    -  template<typename T> void swap(shared_array<T> & a, shared_array<T> & b); // never throws
    +  template<class T> void swap(shared_array<T> & a, shared_array<T> & b); // never throws
     
     }

    Members

    @@ -78,7 +78,7 @@ ~shared_array). The only exception which may be thrown by this constructor is std::bad_alloc. If an exception is thrown, delete[] p is called.

    -
    template<typename D> shared_array(T * p, D d);
    +
    template<class D> shared_array(T * p, D d);

    Constructs a shared_array, storing a copy of p and of d. Afterwards, the use count is 1. D's copy constructor and destructor must not throw. When the the time comes to delete @@ -109,7 +109,7 @@ then replaces this shared_array with the new one, destroying the replaced object. The only exception which may be thrown is std::bad_alloc. If an exception is thrown, delete[] p is called.

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

    Constructs a new shared_array as described above, then replaces this shared_array with the new one, destroying the replaced object. D's copy constructor must not throw. The only exception @@ -146,11 +146,11 @@ requirements.

    Free Functions

    comparison

    -

    Effects: Constructs a shared_ptr, as if by storing a copy of the pointer stored in r.

    @@ -275,7 +275,7 @@ template<typename Y> shared_ptr(shared_ptr<Y> const & r); // nev

    [The postcondition will be relaxed when a default-constructed shared_ptr is being copied.]

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

    Effects: Constructs a shared_ptr, as if by storing a copy of the pointer stored in r.

    @@ -296,7 +296,7 @@ template<typename Y> shared_ptr(shared_ptr<Y> const & r); // nev interface is non-trivial.

    My opinion is that the added functionality is worth the cost. weak_ptr is provided in the reference implementation as a proof of concept.]

    -
    template<typename Y> shared_ptr(std::auto_ptr<Y> & r);
    +
    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 is 1.

    @@ -318,8 +318,8 @@ template<typename Y> shared_ptr(shared_ptr<Y> const & r); // nev

    assignment

    shared_ptr & operator=(shared_ptr const & r); // never throws
    -template<typename Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
    -template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
    +template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws +template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
    template<typename T>
    +		
    template<class T>
       bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws
    -template<typename T>
    +template<class T>
       bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws
    -template<typename T>
    +template<class T>
       bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws

    Compares the stored pointers of the two smart pointers. T need not be a complete type. See the smart pointer common @@ -163,7 +163,7 @@ template<typename T> paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] paragraph 8).

    swap

    -
    template<typename T>
    +		
    template<class T>
       void swap(shared_array<T> & a, shared_array<T> & b) // never throws

    Equivalent to a.swap(b). Matches the interface of std::swap. Provided as an aid to generic programming.

    diff --git a/shared_ptr.htm b/shared_ptr.htm index 87a29b0..f1ca5b2 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -88,31 +88,31 @@ void bad() class use_count_is_zero: public std::exception; - template<typename T> class weak_ptr; + template<class T> class weak_ptr; - template<typename T> class shared_ptr { + template<class T> class shared_ptr { public: typedef T element_type; shared_ptr(); - template<typename Y> explicit shared_ptr(Y * p); - template<typename Y, typename D> shared_ptr(Y * p, D d); + template<class Y> explicit shared_ptr(Y * p); + template<class Y, class D> shared_ptr(Y * p, D d); ~shared_ptr(); // never throws shared_ptr(shared_ptr const & r); // never throws - template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws - template<typename Y> explicit shared_ptr(weak_ptr<Y> const & r); - template<typename Y> explicit shared_ptr(std::auto_ptr<Y> & r); + template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws + 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 - template<typename Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws - template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r); + template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws + template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r); void reset(); - template<typename Y> void reset(Y * p); - template<typename Y, typename D> void reset(Y * p, D d); + template<class Y> void reset(Y * p); + template<class Y, class D> void reset(Y * p, D d); T & operator*() const; // never throws T * operator->() const; // never throws @@ -126,24 +126,24 @@ void bad() void swap(shared_ptr & b); // never throws }; - template<typename T, typename U> + template<class T, class U> bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws - template<typename T, typename U> + template<class T, class U> bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws - template<typename T> + template<class T> bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws - template<typename T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws + template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws - template<typename T> T * get_pointer(shared_ptr<T> const & p); // never throws + template<class T> T * get_pointer(shared_ptr<T> const & p); // never throws - template<typename T, typename U> + template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws - template<typename T, typename U> + template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r); - template<typename T, typename U> + template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r); - template<typename T, typename U> + template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws }
    @@ -188,7 +188,7 @@ void bad() literal zero, for consistency with built-in pointers. It is not clear yet whether this constructor should be left implicit, enabling 0 to be used as a shorthand for shared_ptr<T>().]

    -
    template<typename Y> explicit shared_ptr(Y * p);
    +
    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 @@ -230,7 +230,7 @@ void bad() specification should allow both; nevertheless, the ability to make a shared_ptr from this is considered essential by experienced smart pointer users.]

    -
    template<typename Y, typename D> shared_ptr(Y * p, D d);
    +
    template<class Y, class D> shared_ptr(Y * p, D d);

    Requirements: p must be convertible to T *. D must be CopyConstructible. The copy constructor and destructor @@ -265,7 +265,7 @@ void bad() all.)

    The requrement will be removed when the aforementioned issues are resolved.]

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

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

    Notes: The use count updates caused by the temporary object construction @@ -347,11 +347,11 @@ q = p;

    [reset() will offer the nothrow guarantee in a future implementation.]

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

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

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

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

    @@ -416,19 +416,19 @@ q = p;

    Free Functions

    comparison

    -
    template<typename T, typename U>
    +		
    template<class T, class U>
       bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

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

    Throws: nothing.

    -
    template<typename T, typename U>
    +		
    template<class T, class U>
       bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

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

    Throws: nothing.

    -
    template<typename T>
    +		
    template<class T>
       bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws

    Returns: an unspecified value such that operator< is a strict @@ -447,7 +447,7 @@ q = p; subobjects' operator<.

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

    swap

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

    Effects: Equivalent to a.swap(b).

    @@ -459,7 +459,7 @@ q = p; as this is currently the only legal way to supply a swap function that has a chance to be used by the standard library.]

    get_pointer

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

    Returns: p.get().

    @@ -468,7 +468,7 @@ q = p; mem_fn.

    shared_static_cast

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

    Requires: The expression static_cast<T*>(r.get()) @@ -482,7 +482,7 @@ q = p; object twice.

    shared_dynamic_cast

    -
    template<typename T, typename U>
    +		
    template<class T, class U>
       shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r);

    Requires: The expression dynamic_cast<T*>(r.get()) @@ -503,7 +503,7 @@ q = p; object twice.

    shared_polymorphic_cast

    -
    template<typename T, typename U>
    +		
    template<class T, class U>
       shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r);

    Requires: The expression @@ -517,7 +517,7 @@ q = p;

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

    shared_polymorphic_downcast

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

    Requires: The expression diff --git a/smart_ptr_test.cpp b/smart_ptr_test.cpp index eead369..0d02f8b 100644 --- a/smart_ptr_test.cpp +++ b/smart_ptr_test.cpp @@ -42,7 +42,7 @@ using boost::scoped_array; using boost::shared_ptr; using boost::shared_array; -template +template void ck( const T* v1, T v2 ) { BOOST_TEST( *v1 == v2 ); } namespace { diff --git a/weak_ptr.htm b/weak_ptr.htm index 92bc284..d0273b4 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -61,21 +61,21 @@ if(shared_ptr<int> r = make_shared(q))

    Synopsis

    namespace boost {
     
    -  template<typename T> class weak_ptr {
    +  template<class T> class weak_ptr {
     
         public:
           typedef T element_type;
     
           weak_ptr();
    -      template<typename Y> weak_ptr(shared_ptr<Y> const & r); // never throws
    +      template<class Y> weak_ptr(shared_ptr<Y> const & r); // never throws
           ~weak_ptr(); // never throws
     
           weak_ptr(weak_ptr const & r); // never throws
    -      template<typename Y> weak_ptr(weak_ptr<Y> const & r); // never throws
    +      template<class Y> weak_ptr(weak_ptr<Y> const & r); // never throws
     
           weak_ptr & operator=(weak_ptr const & r); // never throws  
    -      template<typename Y> weak_ptr & operator=(weak_ptr<Y> const & r); // never throws
    -      template<typename Y> weak_ptr & operator=(shared_ptr<Y> const & r); // never throws
    +      template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r); // never throws
    +      template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r); // never throws
     
           void reset();
           T * get() const; // never throws; deprecated, will disappear
    @@ -86,16 +86,16 @@ if(shared_ptr<int> r = make_shared(q))
           void swap(weak_ptr<T> & b); // never throws
       };
     
    -  template<typename T, typename U>
    +  template<class T, class U>
         bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    -  template<typename T, typename U>
    +  template<class T, class U>
         bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    -  template<typename T>
    +  template<class T>
         bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws
     
    -  template<typename T> void swap(weak_ptr<T> & a, weak_ptr<T> & b); // never throws
    +  template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b); // never throws
     
    -  template<typename T>
    +  template<class T>
         shared_ptr<T> make_shared(weak_ptr<T> const & r); // never throws
     
     }
    @@ -118,7 +118,7 @@ if(shared_ptr<int> r = make_shared(q))
     			

    Notes: T need not be a complete type. See the smart pointer common requirements.

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

    Effects: Constructs a weak_ptr, as if by storing a copy of the pointer stored in r.

    @@ -128,7 +128,7 @@ if(shared_ptr<int> r = make_shared(q)) stored pointer become 0.

    weak_ptr(weak_ptr const & r); // never throws
    -template<typename Y> weak_ptr(weak_ptr<Y> const & r); // never throws
    +template<class Y> weak_ptr(weak_ptr<Y> const & r); // never throws

    Effects: Constructs a weak_ptr, as if by storing a copy of the pointer stored in r.

    @@ -147,8 +147,8 @@ template<typename Y> weak_ptr(weak_ptr<Y> const & r); // never t

    assignment

    weak_ptr & operator=(weak_ptr const & r); // never throws
    -template<typename Y> weak_ptr & operator=(weak_ptr<Y> const & r); // never throws
    -template<typename Y> weak_ptr & operator=(shared_ptr<Y> const & r); // never throws
    +template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r); // never throws +template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r); // never throws

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

    Throws: nothing.

    @@ -205,9 +205,9 @@ template<typename Y> weak_ptr & operator=(sh

    Free Functions

    comparison

    -
    template<typename T, typename U>
    +		
    template<class T, class U>
       bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    -template<typename T, typename U>
    +template<class T, class U>
       bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws

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

    @@ -215,7 +215,7 @@ template<typename T, typename U>

    Notes: T need not be a complete type. See the smart pointer common requirements.

    -
    template<typename T>
    +		
    template<class T>
       bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws

    Returns: an implementation-defined value such that operator< is @@ -227,7 +227,7 @@ template<typename T, typename U> pointer common requirements.

    swap

    -
    template<typename T>
    +		
    template<class T>
       void swap(weak_ptr<T> & a, weak_ptr<T> & b) // never throws

    Effects: Equivalent to a.swap(b).

    @@ -236,7 +236,7 @@ template<typename T, typename U> generic programming.

    make_shared

    -
    template<typename T>
    +		
    template<class T>
       shared_ptr<T> make_shared(weak_ptr<T> & const r) // never throws

    Returns: r.expired()? shared_ptr<T>(): shared_ptr<T>(r).

    From ff7410cad271e1dc9a3d6181b6d691875bbbb8dc Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 12 Nov 2002 13:14:50 +0000 Subject: [PATCH 138/513] Fixed a subtle problem in counted_base::release (report and test case by Per Kristensen) [SVN r16211] --- include/boost/detail/shared_count.hpp | 13 ++++++-- shared_ptr_test.cpp | 46 +++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index dd6ba2d..afdb42b 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -120,19 +120,28 @@ public: void release() // nothrow { long new_use_count; - long new_weak_count; + long new_weak_count = 0; { #ifdef BOOST_HAS_THREADS mutex_type::scoped_lock lock(mtx_); #endif new_use_count = --use_count_; - new_weak_count = --weak_count_; + + if(new_use_count != 0) + { + new_weak_count = --weak_count_; + } } if(new_use_count == 0) { dispose(); + +#ifdef BOOST_HAS_THREADS + mutex_type::scoped_lock lock(mtx_); +#endif + new_weak_count = --weak_count_; } if(new_weak_count == 0) diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 56f6e46..3b0ec5e 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -196,6 +196,45 @@ template void test_is_nonzero(boost::shared_ptr const & p) BOOST_TEST(p.get() != 0); } +class foo +{ +public: + + void setWeak(boost::shared_ptr s) + { + w = s; + } + +private: + + boost::weak_ptr w; +}; + +class deleter +{ +public: + + deleter(): lock(0) + { + } + + ~deleter() + { + BOOST_TEST(lock == 0); + } + + void operator() (foo * p) + { + ++lock; + delete p; + --lock; + } + +private: + + int lock; +}; + int main() { using namespace boost; @@ -368,5 +407,12 @@ int main() BOOST_TEST(cnt == 0); + // Test case by Per Kristensen + { + boost::shared_ptr s(new foo, deleter()); + s->setWeak(s); + s.reset(); + } + return boost::report_errors(); } From 2314f20c4eb8e42b721f679993fb0a56b3b87ef4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 15 Nov 2002 19:44:48 +0000 Subject: [PATCH 139/513] element_type added [SVN r16264] --- include/boost/intrusive_ptr.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 4ada734..26c57b1 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -47,6 +47,8 @@ private: public: + typedef T element_type; + intrusive_ptr(): p_(0) { } From f6b7ff4b34d74f2190a38a7f5b1d9d75a3803075 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 18 Nov 2002 14:37:02 +0000 Subject: [PATCH 140/513] Major changes to shared_ptr and weak_ptr [SVN r16314] --- include/boost/detail/shared_count.hpp | 112 +- include/boost/enable_shared_from_this.hpp | 51 + include/boost/shared_ptr.hpp | 82 +- include/boost/weak_ptr.hpp | 43 +- shared_ptr_test.cpp | 2374 +++++++++++++++++++-- smart_ptr_test.cpp | 6 - 6 files changed, 2351 insertions(+), 317 deletions(-) create mode 100644 include/boost/enable_shared_from_this.hpp diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index afdb42b..c5178c7 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -40,7 +40,7 @@ namespace boost // The standard library that comes with Borland C++ 5.5.1 // defines std::exception and its members as having C calling -// convention (-pc). When the definition of use_count_is_zero +// convention (-pc). When the definition of bad_weak_ptr // is compiled with -ps, the compiler issues an error. // Hence, the temporary #pragma option -pc below. The version // check is deliberately conservative. @@ -49,13 +49,13 @@ namespace boost # pragma option push -pc #endif -class use_count_is_zero: public std::exception +class bad_weak_ptr: public std::exception { public: virtual char const * what() const throw() { - return "boost::use_count_is_zero"; + return "boost::bad_weak_ptr"; } }; @@ -63,6 +63,9 @@ public: # pragma option pop #endif +namespace detail +{ + class counted_base { private: @@ -109,50 +112,36 @@ public: void add_ref() { -#ifdef BOOST_HAS_THREADS +#if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif - if(use_count_ == 0 && weak_count_ != 0) boost::throw_exception(boost::use_count_is_zero()); + if(use_count_ == 0 && weak_count_ != 0) boost::throw_exception(boost::bad_weak_ptr()); ++use_count_; ++weak_count_; } void release() // nothrow { - long new_use_count; - long new_weak_count = 0; - { -#ifdef BOOST_HAS_THREADS +#if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif - new_use_count = --use_count_; + long new_use_count = --use_count_; if(new_use_count != 0) { - new_weak_count = --weak_count_; + --weak_count_; + return; } } - if(new_use_count == 0) - { - dispose(); - -#ifdef BOOST_HAS_THREADS - mutex_type::scoped_lock lock(mtx_); -#endif - new_weak_count = --weak_count_; - } - - if(new_weak_count == 0) - { - destruct(); - } + dispose(); + weak_release(); } void weak_add_ref() // nothrow { -#ifdef BOOST_HAS_THREADS +#if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif ++weak_count_; @@ -163,7 +152,7 @@ public: long new_weak_count; { -#ifdef BOOST_HAS_THREADS +#if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif new_weak_count = --weak_count_; @@ -177,7 +166,7 @@ public: long use_count() const // nothrow { -#ifdef BOOST_HAS_THREADS +#if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif return use_count_; @@ -193,29 +182,16 @@ private: long use_count_; long weak_count_; -#ifdef BOOST_HAS_THREADS +#if defined(BOOST_HAS_THREADS) mutable mutex_type mtx_; #endif }; -inline void intrusive_ptr_add_ref(counted_base * p) -{ - p->add_ref(); -} - -inline void intrusive_ptr_release(counted_base * p) -{ - p->release(); -} - -namespace detail -{ - // // Borland's Codeguard trips up over the -Vx- option here: // #ifdef __CODEGUARD__ -#pragma option push -Vx- +# pragma option push -Vx- #endif template class counted_base_impl: public counted_base @@ -273,16 +249,11 @@ private: public: - shared_count(): pi_(new counted_base(1, 1)) + shared_count(): pi_(0) // (new counted_base(1, 1)) { } - explicit shared_count(counted_base * pi): pi_(pi) // never throws - { - pi_->add_ref(); - } - - template shared_count(P p, D d, void const * = 0): pi_(0) + template shared_count(P p, D d): pi_(0) { #ifndef BOOST_NO_EXCEPTIONS @@ -309,11 +280,6 @@ public: #endif } - template shared_count(P, D, counted_base * pi): pi_(pi) - { - pi_->add_ref(); - } - #ifndef BOOST_NO_AUTO_PTR // auto_ptr is special cased to provide the strong guarantee @@ -328,21 +294,21 @@ public: ~shared_count() // nothrow { - pi_->release(); + if(pi_ != 0) pi_->release(); } shared_count(shared_count const & r): pi_(r.pi_) // nothrow { - pi_->add_ref(); + if(pi_ != 0) pi_->add_ref(); } - explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0 + explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 shared_count & operator= (shared_count const & r) // nothrow { counted_base * tmp = r.pi_; - tmp->add_ref(); - pi_->release(); + if(tmp != 0) tmp->add_ref(); + if(pi_ != 0) pi_->release(); pi_ = tmp; return *this; @@ -357,12 +323,12 @@ public: long use_count() const // nothrow { - return pi_->use_count(); + return pi_ != 0? pi_->use_count(): 42; // '42' is an example of 'unspecified' } bool unique() const // nothrow { - return pi_->use_count() == 1; + return use_count() == 1; } friend inline bool operator==(shared_count const & a, shared_count const & b) @@ -377,7 +343,7 @@ public: }; #ifdef __CODEGUARD__ -#pragma option pop +# pragma option pop #endif @@ -391,30 +357,30 @@ private: public: - weak_count(): pi_(new counted_base(0, 1)) // can throw + weak_count(): pi_(0) // nothrow // (new counted_base(0, 1)) // can throw { } weak_count(shared_count const & r): pi_(r.pi_) // nothrow { - pi_->weak_add_ref(); + if(pi_ != 0) pi_->weak_add_ref(); } weak_count(weak_count const & r): pi_(r.pi_) // nothrow { - pi_->weak_add_ref(); + if(pi_ != 0) pi_->weak_add_ref(); } ~weak_count() // nothrow { - pi_->weak_release(); + if(pi_ != 0) pi_->weak_release(); } weak_count & operator= (shared_count const & r) // nothrow { counted_base * tmp = r.pi_; - tmp->weak_add_ref(); - pi_->weak_release(); + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); pi_ = tmp; return *this; @@ -423,8 +389,8 @@ public: weak_count & operator= (weak_count const & r) // nothrow { counted_base * tmp = r.pi_; - tmp->weak_add_ref(); - pi_->weak_release(); + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); pi_ = tmp; return *this; @@ -439,7 +405,7 @@ public: long use_count() const // nothrow { - return pi_->use_count(); + return pi_ != 0? pi_->use_count(): 804; // '804' is an example of 'unspecified' } friend inline bool operator==(weak_count const & a, weak_count const & b) @@ -455,7 +421,7 @@ public: inline shared_count::shared_count(weak_count const & r): pi_(r.pi_) { - pi_->add_ref(); + if(pi_ != 0) pi_->add_ref(); } } // namespace detail diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp new file mode 100644 index 0000000..199725a --- /dev/null +++ b/include/boost/enable_shared_from_this.hpp @@ -0,0 +1,51 @@ +#ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED +#define BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED + +// +// enable_shared_from_this.hpp +// +// Copyright (c) 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html +// + +#include +#include +#include + +namespace boost +{ + +template class enable_shared_from_this +{ +public: + + shared_ptr shared_from_this() + { + return shared_ptr(weak_this); + } + + shared_ptr shared_from_this() const + { + return shared_ptr(weak_this); + } + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + +private: + + template friend class shared_ptr; + +#endif + + weak_ptr weak_this; +}; + +} // namespace boost + +#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 11202f4..6357fff 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -76,8 +76,14 @@ template<> struct shared_ptr_traits // is destroyed or reset. // +#if defined(BOOST_SP_ENABLE_CONSTRUCTOR_HOOK) + +void shared_ptr_constructor_hook(void * p); + +#endif + template class weak_ptr; -template class intrusive_ptr; +template class enable_shared_from_this; template class shared_ptr { @@ -87,18 +93,36 @@ private: // typedef checked_deleter deleter; typedef shared_ptr this_type; + // enable_shared_from_this support + + template void sp_enable_shared_from_this(boost::enable_shared_from_this * q) + { + q->weak_this = *this; + } + + void sp_enable_shared_from_this(void *) + { + } + public: typedef T element_type; typedef T value_type; + typedef T * pointer; + typedef typename detail::shared_ptr_traits::reference reference; shared_ptr(): px(0), pn() { } template - explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter(), p) // Y must be complete + explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter()) // Y must be complete { + sp_enable_shared_from_this(p); + +#if defined(BOOST_SP_ENABLE_CONSTRUCTOR_HOOK) + shared_ptr_constructor_hook(p); +#endif } // @@ -109,6 +133,7 @@ public: template shared_ptr(Y * p, D d): px(p), pn(p, d) { + sp_enable_shared_from_this(p); } // generated copy constructor, assignment, destructor are fine @@ -123,11 +148,6 @@ public: { } - template - shared_ptr(intrusive_ptr const & r): px(r.get()), pn(r.get()) // never throws - { - } - template shared_ptr(shared_ptr const & r, detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) { @@ -154,8 +174,11 @@ public: #ifndef BOOST_NO_AUTO_PTR template - explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn(r) + explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn() { + Y * tmp = r.get(); + pn = detail::shared_count(r); + sp_enable_shared_from_this(tmp); } #endif @@ -199,7 +222,7 @@ public: this_type(p, d).swap(*this); } - typename detail::shared_ptr_traits::reference operator* () const // never throws + reference operator* () const // never throws { BOOST_ASSERT(px != 0); return *px; @@ -246,6 +269,11 @@ public: pn.swap(other.pn); } + bool less(this_type const & rhs) const // implementation detail, never throws + { + return pn < rhs.pn; + } + // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) @@ -287,7 +315,7 @@ template inline bool operator!=(shared_ptr const & a, shared_ptr template inline bool operator<(shared_ptr const & a, shared_ptr const & b) { - return std::less()(a.get(), b.get()); + return a.less(b); } template inline void swap(shared_ptr & a, shared_ptr & b) @@ -295,6 +323,18 @@ template inline void swap(shared_ptr & a, shared_ptr & b) a.swap(b); } +template shared_ptr static_pointer_cast(shared_ptr const & r) +{ + return shared_ptr(r, detail::static_cast_tag()); +} + +template shared_ptr dynamic_pointer_cast(shared_ptr const & r) +{ + return shared_ptr(r, detail::dynamic_cast_tag()); +} + +// shared_*_cast names are deprecated. Use *_pointer_cast instead. + template shared_ptr shared_static_cast(shared_ptr const & r) { return shared_ptr(r, detail::static_cast_tag()); @@ -323,28 +363,6 @@ template inline T * get_pointer(shared_ptr const & p) return p.get(); } -// shared_from_this() creates a shared_ptr from a raw pointer (usually 'this') - -namespace detail -{ - -inline void sp_assert_counted_base(boost::counted_base const *) -{ -} - -template inline T * sp_remove_const(T const * p) -{ - return const_cast(p); -} - -} // namespace detail - -template shared_ptr shared_from_this(T * p) -{ - detail::sp_assert_counted_base(p); - return shared_ptr(detail::sp_remove_const(p)); -} - } // namespace boost #ifdef BOOST_MSVC diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index e17a9f7..b65309e 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -76,11 +76,6 @@ public: this_type().swap(*this); } - T * get() const // never throws; deprecated, removal pending, don't use - { - return pn.use_count() == 0? 0: px; - } - long use_count() const // never throws { return pn.use_count(); @@ -119,27 +114,6 @@ private: }; // weak_ptr -template inline bool operator==(weak_ptr const & a, weak_ptr const & b) -{ - return a.get() == b.get(); -} - -template inline bool operator!=(weak_ptr const & a, weak_ptr const & b) -{ - return a.get() != b.get(); -} - -#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 - -// Resolve the ambiguity between our op!= and the one in rel_ops - -template inline bool operator!=(weak_ptr const & a, weak_ptr const & b) -{ - return a.get() != b.get(); -} - -#endif - template inline bool operator<(weak_ptr const & a, weak_ptr const & b) { return a.less(b); @@ -152,6 +126,8 @@ template void swap(weak_ptr & a, weak_ptr & b) template shared_ptr make_shared(weak_ptr const & r) // never throws { +#if defined(BOOST_HAS_THREADS) + // optimization: avoid throw overhead if(r.use_count() == 0) { @@ -162,15 +138,20 @@ template shared_ptr make_shared(weak_ptr const & r) // never thro { return shared_ptr(r); } - catch(use_count_is_zero const &) + catch(bad_weak_ptr const &) { + // Q: how can we get here? + // A: another thread may have invalidated r after the use_count test above. return shared_ptr(); } -} -// Note: there is no get_pointer overload for weak_ptr. -// This is intentional. Even get() will disappear in a -// future release; these accessors are too error-prone. +#else + + // optimization: avoid try/catch overhead when single threaded + return r.use_count() == 0? shared_ptr(): shared_ptr(r); + +#endif +} } // namespace boost diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 3b0ec5e..7ebb4d2 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -3,6 +3,7 @@ #pragma warning(disable: 4710) // function not inlined #pragma warning(disable: 4711) // function selected for automatic inline expansion #pragma warning(disable: 4514) // unreferenced inline removed +#pragma warning(disable: 4355) // 'this' : used in base member initializer list #endif // @@ -21,35 +22,73 @@ #include #include -#include +#include +#include -bool boost_error(char const *, char const *, char const *, long) +// + +namespace n_element_type +{ + +void f(int &) { - return true; } -namespace +void test() { - int cnt = 0; + typedef boost::shared_ptr::element_type T; + T t; + f(t); } +} // namespace n_element_type + +namespace n_constructors +{ + +class incomplete; + +void default_constructor() +{ + { + boost::shared_ptr pi; + BOOST_TEST(pi? false: true); + BOOST_TEST(!pi); + BOOST_TEST(pi.get() == 0); + } + + { + boost::shared_ptr pv; + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + } + + { + boost::shared_ptr px; + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + } +} + +struct A +{ + int dummy; +}; + struct X { + static long instances; + X() { - ++cnt; - std::cout << "X(" << this << ")::X()\n"; + ++instances; } - ~X() // virtual destructor deliberately omitted + ~X() { - --cnt; - std::cout << "X(" << this << ")::~X()\n"; - } - - virtual int id() const - { - return 1; + --instances; } private: @@ -58,23 +97,20 @@ private: X & operator= (X const &); }; -struct Y: public X +long X::instances = 0; + +struct Y: public A, public X { + static long instances; + Y() { - ++cnt; - std::cout << "Y(" << this << ")::Y()\n"; + ++instances; } ~Y() { - --cnt; - std::cout << "Y(" << this << ")::~Y()\n"; - } - - virtual int id() const - { - return 2; + --instances; } private: @@ -83,118 +119,1519 @@ private: Y & operator= (Y const &); }; -int * get_object() +long Y::instances = 0; + +void pointer_constructor() { - ++cnt; - std::cout << "get_object()\n"; - return &cnt; + { + boost::shared_ptr pi(static_cast(0)); + BOOST_TEST(pi? false: true); + BOOST_TEST(!pi); + BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + } + + { + boost::shared_ptr pi(static_cast(0)); + BOOST_TEST(pi? false: true); + BOOST_TEST(!pi); + BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + } + + { + boost::shared_ptr pv(static_cast(0)); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + } + + { + boost::shared_ptr pv(static_cast(0)); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + } + + { + boost::shared_ptr px(static_cast(0)); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + } + + { + boost::shared_ptr px(static_cast(0)); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + } + + { + boost::shared_ptr px(static_cast(0)); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + } + + { + boost::shared_ptr px(static_cast(0)); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + } + + { + boost::shared_ptr pv(static_cast(0)); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + } + + { + boost::shared_ptr pv(static_cast(0)); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + } + + { + int * p = new int(7); + boost::shared_ptr pi(p); + BOOST_TEST(pi? true: false); + BOOST_TEST(!!pi); + BOOST_TEST(pi.get() == p); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + BOOST_TEST(*pi == 7); + } + + { + int * p = new int(7); + boost::shared_ptr pi(p); + BOOST_TEST(pi? true: false); + BOOST_TEST(!!pi); + BOOST_TEST(pi.get() == p); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + BOOST_TEST(*pi == 7); + } + + { + int * p = new int(7); + boost::shared_ptr pv(p); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == p); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + } + + { + int * p = new int(7); + boost::shared_ptr pv(p); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == p); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + } + + BOOST_TEST(X::instances == 0); + + { + X * p = new X; + boost::shared_ptr px(p); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(px.get() == p); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(X::instances == 1); + } + + BOOST_TEST(X::instances == 0); + + { + X * p = new X; + boost::shared_ptr px(p); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(px.get() == p); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(X::instances == 1); + } + + BOOST_TEST(X::instances == 0); + + { + X * p = new X; + boost::shared_ptr pv(p); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == p); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + BOOST_TEST(X::instances == 1); + } + + BOOST_TEST(X::instances == 0); + + { + X * p = new X; + boost::shared_ptr pv(p); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == p); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + BOOST_TEST(X::instances == 1); + } + + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + + { + Y * p = new Y; + boost::shared_ptr px(p); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(px.get() == p); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); + } + + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + + { + Y * p = new Y; + boost::shared_ptr px(p); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(px.get() == p); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); + } + + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); } -void release_object(int * p) +int m = 0; + +void deleter(int * p) { - BOOST_TEST(p == &cnt); - --cnt; - std::cout << "release_object()\n"; + BOOST_TEST(p == 0); } -class Z: public virtual boost::counted_base +void deleter2(int * p) { -public: + BOOST_TEST(p == &m); + ++*p; +} - Z() +void deleter3(incomplete * p) +{ + BOOST_TEST(p == 0); +} + +// Borland C++ 5.5.1 fails on static_cast(0) + +incomplete * p0 = 0; + +void deleter_constructor() +{ { - ++cnt; - std::cout << "Z(" << this << ")::Z()\n"; + boost::shared_ptr pi(static_cast(0), deleter); + BOOST_TEST(pi? false: true); + BOOST_TEST(!pi); + BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); } - ~Z() { - --cnt; - std::cout << "Z(" << this << ")::~Z()\n"; + boost::shared_ptr pv(static_cast(0), deleter); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); } - boost::shared_ptr shared_this() { - return boost::shared_from_this(this); + boost::shared_ptr pv(static_cast(0), deleter); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); } - boost::shared_ptr shared_this() const { - return boost::shared_from_this(this); + boost::shared_ptr px(p0, deleter3); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + } + + { + boost::shared_ptr pv(p0, deleter3); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + } + + { + boost::shared_ptr pv(p0, deleter3); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + } + + BOOST_TEST(m == 0); + + { + boost::shared_ptr pi(&m, deleter2); + BOOST_TEST(pi? true: false); + BOOST_TEST(!!pi); + BOOST_TEST(pi.get() == &m); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + } + + BOOST_TEST(m == 1); + + { + boost::shared_ptr pi(&m, deleter2); + BOOST_TEST(pi? true: false); + BOOST_TEST(!!pi); + BOOST_TEST(pi.get() == &m); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + } + + BOOST_TEST(m == 2); + + { + boost::shared_ptr pv(&m, deleter2); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == &m); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + } + + BOOST_TEST(m == 3); + + { + boost::shared_ptr pv(&m, deleter2); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == &m); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + } + + BOOST_TEST(m == 4); +} + +void copy_constructor() +{ + { + boost::shared_ptr pi; + + boost::shared_ptr pi2(pi); + BOOST_TEST(pi2? false: true); + BOOST_TEST(!pi2); + BOOST_TEST(pi2.get() == 0); + + boost::shared_ptr pi3(pi); + BOOST_TEST(pi3? false: true); + BOOST_TEST(!pi3); + BOOST_TEST(pi3.get() == 0); + + boost::shared_ptr pi4(pi3); + BOOST_TEST(pi4? false: true); + BOOST_TEST(!pi4); + BOOST_TEST(pi4.get() == 0); + } + + { + boost::shared_ptr pv; + + boost::shared_ptr pv2(pv); + BOOST_TEST(pv2? false: true); + BOOST_TEST(!pv2); + BOOST_TEST(pv2.get() == 0); + } + + { + boost::shared_ptr px; + + boost::shared_ptr px2(px); + BOOST_TEST(px2? false: true); + BOOST_TEST(!px2); + BOOST_TEST(px2.get() == 0); + + boost::shared_ptr px3(px); + BOOST_TEST(px3? false: true); + BOOST_TEST(!px3); + BOOST_TEST(px3.get() == 0); + } + + { + boost::shared_ptr pi(static_cast(0)); + + boost::shared_ptr pi2(pi); + BOOST_TEST(pi2? false: true); + BOOST_TEST(!pi2); + BOOST_TEST(pi2.get() == 0); + BOOST_TEST(pi2.use_count() == 2); + BOOST_TEST(!pi2.unique()); + + BOOST_TEST(pi.use_count() == pi2.use_count()); + BOOST_TEST(!(pi < pi2 || pi2 < pi)); // shared ownership test + + boost::shared_ptr pi3(pi); + BOOST_TEST(pi3? false: true); + BOOST_TEST(!pi3); + BOOST_TEST(pi3.get() == 0); + BOOST_TEST(pi3.use_count() == 3); + BOOST_TEST(!pi3.unique()); + + boost::shared_ptr pi4(pi2); + BOOST_TEST(pi4? false: true); + BOOST_TEST(!pi4); + BOOST_TEST(pi4.get() == 0); + BOOST_TEST(pi4.use_count() == 4); + BOOST_TEST(!pi4.unique()); + + BOOST_TEST(pi3.use_count() == pi4.use_count()); + BOOST_TEST(!(pi3 < pi4 || pi4 < pi3)); // shared ownership test + } + + { + boost::shared_ptr px(static_cast(0)); + + boost::shared_ptr px2(px); + BOOST_TEST(px2? false: true); + BOOST_TEST(!px2); + BOOST_TEST(px2.get() == 0); + BOOST_TEST(px2.use_count() == 2); + BOOST_TEST(!px2.unique()); + + BOOST_TEST(px.use_count() == px2.use_count()); + BOOST_TEST(!(px < px2 || px2 < px)); // shared ownership test + + boost::shared_ptr px3(px); + BOOST_TEST(px3? false: true); + BOOST_TEST(!px3); + BOOST_TEST(px3.get() == 0); + BOOST_TEST(px3.use_count() == 3); + BOOST_TEST(!px3.unique()); + + boost::shared_ptr px4(px2); + BOOST_TEST(px4? false: true); + BOOST_TEST(!px4); + BOOST_TEST(px4.get() == 0); + BOOST_TEST(px4.use_count() == 4); + BOOST_TEST(!px4.unique()); + + BOOST_TEST(px3.use_count() == px4.use_count()); + BOOST_TEST(!(px3 < px4 || px4 < px3)); // shared ownership test + } + + { + int * p = new int(7); + boost::shared_ptr pi(p); + + boost::shared_ptr pi2(pi); + BOOST_TEST(pi2? true: false); + BOOST_TEST(!!pi2); + BOOST_TEST(pi2.get() == p); + BOOST_TEST(pi2.use_count() == 2); + BOOST_TEST(!pi2.unique()); + BOOST_TEST(*pi2 == 7); + + BOOST_TEST(pi.use_count() == pi2.use_count()); + BOOST_TEST(!(pi < pi2 || pi2 < pi)); // shared ownership test + } + + { + int * p = new int(7); + boost::shared_ptr pv(p); + + boost::shared_ptr pv2(pv); + BOOST_TEST(pv2? true: false); + BOOST_TEST(!!pv2); + BOOST_TEST(pv2.get() == p); + BOOST_TEST(pv2.use_count() == 2); + BOOST_TEST(!pv2.unique()); + + BOOST_TEST(pv.use_count() == pv2.use_count()); + BOOST_TEST(!(pv < pv2 || pv2 < pv)); // shared ownership test + } + + BOOST_TEST(X::instances == 0); + + { + X * p = new X; + boost::shared_ptr px(p); + + boost::shared_ptr px2(px); + BOOST_TEST(px2? true: false); + BOOST_TEST(!!px2); + BOOST_TEST(px2.get() == p); + BOOST_TEST(px2.use_count() == 2); + BOOST_TEST(!px2.unique()); + + BOOST_TEST(X::instances == 1); + + BOOST_TEST(px.use_count() == px2.use_count()); + BOOST_TEST(!(px < px2 || px2 < px)); // shared ownership test + + boost::shared_ptr px3(px); + BOOST_TEST(px3? true: false); + BOOST_TEST(!!px3); + BOOST_TEST(px3.get() == p); + BOOST_TEST(px3.use_count() == 3); + BOOST_TEST(!px3.unique()); + + boost::shared_ptr px4(px2); + BOOST_TEST(px4? true: false); + BOOST_TEST(!!px4); + BOOST_TEST(px4.get() == p); + BOOST_TEST(px4.use_count() == 4); + BOOST_TEST(!px4.unique()); + + BOOST_TEST(px3.use_count() == px4.use_count()); + BOOST_TEST(!(px3 < px4 || px4 < px3)); // shared ownership test + } + + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + + { + Y * p = new Y; + boost::shared_ptr py(p); + + boost::shared_ptr px(py); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(px.get() == p); + BOOST_TEST(px.use_count() == 2); + BOOST_TEST(!px.unique()); + + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); + + boost::shared_ptr pv(px); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == px.get()); + BOOST_TEST(pv.use_count() == 3); + BOOST_TEST(!pv.unique()); + + boost::shared_ptr pv2(py); + BOOST_TEST(pv2? true: false); + BOOST_TEST(!!pv2); + BOOST_TEST(pv2.get() == py.get()); + BOOST_TEST(pv2.use_count() == 4); + BOOST_TEST(!pv2.unique()); + + BOOST_TEST(pv.use_count() == pv2.use_count()); + BOOST_TEST(!(pv < pv2 || pv2 < pv)); // shared ownership test + } + + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); +} + +void weak_ptr_constructor() +{ + boost::shared_ptr p(new Y); + + boost::weak_ptr wp(p); + + { + boost::shared_ptr p2(wp); + BOOST_TEST(p2? true: false); + BOOST_TEST(!!p2); + BOOST_TEST(p2.get() == p.get()); + BOOST_TEST(p2.use_count() == 2); + BOOST_TEST(!p2.unique()); + + BOOST_TEST(p.use_count() == p2.use_count()); + BOOST_TEST(!(p < p2 || p2 < p)); // shared ownership test + + boost::shared_ptr p3(wp); + BOOST_TEST(p3? true: false); + BOOST_TEST(!!p3); + BOOST_TEST(p3.get() == p.get()); + BOOST_TEST(p3.use_count() == 3); + BOOST_TEST(!p3.unique()); + + BOOST_TEST(p.use_count() == p3.use_count()); + } + + p.reset(); + + try + { + boost::shared_ptr p2(wp); + BOOST_ERROR("shared_ptr p2(wp) failed to throw"); + } + catch(boost::bad_weak_ptr) + { + } + + try + { + boost::shared_ptr p3(wp); + BOOST_ERROR("shared_ptr p3(wp) failed to throw"); + } + catch(boost::bad_weak_ptr) + { + } +} + +void auto_ptr_constructor() +{ + { + std::auto_ptr p; + boost::shared_ptr pi(p); + BOOST_TEST(pi? false: true); + BOOST_TEST(!pi); + BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + BOOST_TEST(p.get() == 0); + } + + { + std::auto_ptr p; + boost::shared_ptr pi(p); + BOOST_TEST(pi? false: true); + BOOST_TEST(!pi); + BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + BOOST_TEST(p.get() == 0); + } + + { + std::auto_ptr p; + boost::shared_ptr pv(p); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + BOOST_TEST(p.get() == 0); + } + + { + std::auto_ptr p; + boost::shared_ptr pv(p); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + BOOST_TEST(p.get() == 0); + } + + { + std::auto_ptr p; + boost::shared_ptr px(p); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(p.get() == 0); + } + + { + std::auto_ptr p; + boost::shared_ptr px(p); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(p.get() == 0); + } + + { + std::auto_ptr p; + boost::shared_ptr px(p); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(p.get() == 0); + } + + { + std::auto_ptr p; + boost::shared_ptr px(p); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(p.get() == 0); + } + + { + std::auto_ptr p; + boost::shared_ptr pv(p); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + BOOST_TEST(p.get() == 0); + } + + { + std::auto_ptr p; + boost::shared_ptr pv(p); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + BOOST_TEST(p.get() == 0); + } + + { + std::auto_ptr p(new int(7)); + int * q = p.get(); + boost::shared_ptr pi(p); + BOOST_TEST(pi? true: false); + BOOST_TEST(!!pi); + BOOST_TEST(pi.get() == q); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + BOOST_TEST(*pi == 7); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + BOOST_TEST(p.get() == 0); +#endif + } + + { + std::auto_ptr p(new int(7)); + int * q = p.get(); + boost::shared_ptr pi(p); + BOOST_TEST(pi? true: false); + BOOST_TEST(!!pi); + BOOST_TEST(pi.get() == q); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + BOOST_TEST(*pi == 7); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + BOOST_TEST(p.get() == 0); +#endif + } + + { + std::auto_ptr p(new int(7)); + int * q = p.get(); + boost::shared_ptr pv(p); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == q); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + BOOST_TEST(p.get() == 0); +#endif + } + + { + std::auto_ptr p(new int(7)); + int * q = p.get(); + boost::shared_ptr pv(p); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == q); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + BOOST_TEST(p.get() == 0); +#endif + } + + BOOST_TEST(X::instances == 0); + + { + std::auto_ptr p(new X); + X * q = p.get(); + boost::shared_ptr px(p); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(px.get() == q); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(X::instances == 1); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + BOOST_TEST(p.get() == 0); +#endif + } + + BOOST_TEST(X::instances == 0); + + { + std::auto_ptr p(new X); + X * q = p.get(); + boost::shared_ptr px(p); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(px.get() == q); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(X::instances == 1); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + BOOST_TEST(p.get() == 0); +#endif + } + + BOOST_TEST(X::instances == 0); + + { + std::auto_ptr p(new X); + X * q = p.get(); + boost::shared_ptr pv(p); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == q); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + BOOST_TEST(X::instances == 1); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + BOOST_TEST(p.get() == 0); +#endif + } + + BOOST_TEST(X::instances == 0); + + { + std::auto_ptr p(new X); + X * q = p.get(); + boost::shared_ptr pv(p); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == q); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + BOOST_TEST(X::instances == 1); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + BOOST_TEST(p.get() == 0); +#endif + } + + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + + { + std::auto_ptr p(new Y); + Y * q = p.get(); + boost::shared_ptr px(p); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(px.get() == q); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + BOOST_TEST(p.get() == 0); +#endif + } + + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + + { + std::auto_ptr p(new Y); + Y * q = p.get(); + boost::shared_ptr px(p); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(px.get() == q); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + BOOST_TEST(p.get() == 0); +#endif + } + + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); +} + +void test() +{ + default_constructor(); + pointer_constructor(); + deleter_constructor(); + copy_constructor(); + weak_ptr_constructor(); + auto_ptr_constructor(); +} + +} // namespace n_constructors + +namespace n_assignment +{ + +void test() +{ +} + +} // namespace n_assignment + +namespace n_reset +{ + +void test() +{ +} + +} // namespace n_reset + +namespace n_access +{ + +struct X +{ +}; + +void test() +{ + { + boost::shared_ptr px; + BOOST_TEST(px.get() == 0); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::get_pointer; +#endif + + BOOST_TEST(get_pointer(px) == px.get()); + } + + { + boost::shared_ptr px(static_cast(0)); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::get_pointer; +#endif + + BOOST_TEST(get_pointer(px) == px.get()); + } + + { + boost::shared_ptr px(static_cast(0), boost::checked_deleter()); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::get_pointer; +#endif + + BOOST_TEST(get_pointer(px) == px.get()); + } + + { + X * p = new X; + boost::shared_ptr px(p); + BOOST_TEST(px.get() == p); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(&*px == px.get()); + BOOST_TEST(px.operator ->() == px.get()); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::get_pointer; +#endif + + BOOST_TEST(get_pointer(px) == px.get()); + } + + { + X * p = new X; + boost::shared_ptr px(p, boost::checked_deleter()); + BOOST_TEST(px.get() == p); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(&*px == px.get()); + BOOST_TEST(px.operator ->() == px.get()); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::get_pointer; +#endif + + BOOST_TEST(get_pointer(px) == px.get()); + } +} + +} // namespace n_access + +namespace n_use_count +{ + +struct X +{ +}; + +void test() +{ + { + boost::shared_ptr px(static_cast(0)); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + + boost::shared_ptr px2(px); + BOOST_TEST(px2.use_count() == 2); + BOOST_TEST(!px2.unique()); + BOOST_TEST(px.use_count() == 2); + BOOST_TEST(!px.unique()); + } + + { + boost::shared_ptr px(new X); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + + boost::shared_ptr px2(px); + BOOST_TEST(px2.use_count() == 2); + BOOST_TEST(!px2.unique()); + BOOST_TEST(px.use_count() == 2); + BOOST_TEST(!px.unique()); + } + + { + boost::shared_ptr px(new X, boost::checked_deleter()); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + + boost::shared_ptr px2(px); + BOOST_TEST(px2.use_count() == 2); + BOOST_TEST(!px2.unique()); + BOOST_TEST(px.use_count() == 2); + BOOST_TEST(!px.unique()); + } +} + +} // namespace n_use_count + +namespace n_swap +{ + +struct X +{ +}; + +void test() +{ + { + boost::shared_ptr px; + boost::shared_ptr px2; + + px.swap(px2); + + BOOST_TEST(px.get() == 0); + BOOST_TEST(px2.get() == 0); + + using std::swap; + swap(px, px2); + + BOOST_TEST(px.get() == 0); + BOOST_TEST(px2.get() == 0); + } + + { + X * p = new X; + boost::shared_ptr px; + boost::shared_ptr px2(p); + boost::shared_ptr px3(px2); + + px.swap(px2); + + BOOST_TEST(px.get() == p); + BOOST_TEST(px.use_count() == 2); + BOOST_TEST(px2.get() == 0); + BOOST_TEST(px3.get() == p); + BOOST_TEST(px3.use_count() == 2); + + using std::swap; + swap(px, px2); + + BOOST_TEST(px.get() == 0); + BOOST_TEST(px2.get() == p); + BOOST_TEST(px2.use_count() == 2); + BOOST_TEST(px3.get() == p); + BOOST_TEST(px3.use_count() == 2); + } + + { + X * p1 = new X; + X * p2 = new X; + boost::shared_ptr px(p1); + boost::shared_ptr px2(p2); + boost::shared_ptr px3(px2); + + px.swap(px2); + + BOOST_TEST(px.get() == p2); + BOOST_TEST(px.use_count() == 2); + BOOST_TEST(px2.get() == p1); + BOOST_TEST(px2.use_count() == 1); + BOOST_TEST(px3.get() == p2); + BOOST_TEST(px3.use_count() == 2); + + using std::swap; + swap(px, px2); + + BOOST_TEST(px.get() == p1); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px2.get() == p2); + BOOST_TEST(px2.use_count() == 2); + BOOST_TEST(px3.get() == p2); + BOOST_TEST(px3.use_count() == 2); + } +} + +} // namespace n_swap + +namespace n_comparison +{ + +struct X +{ + int dummy; +}; + +struct Y +{ + int dummy2; +}; + +struct Z: public X, public Y +{ +}; + +void test() +{ + { + boost::shared_ptr px; + boost::shared_ptr px2; + + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(px == px2); + BOOST_TEST(!(px != px2)); + } + + { + boost::shared_ptr px; + boost::shared_ptr px2(px); + + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(px == px2); + BOOST_TEST(!(px != px2)); + } + + { + boost::shared_ptr px; + boost::shared_ptr px2(new X); + + BOOST_TEST(px.get() != px2.get()); + BOOST_TEST(px != px2); + BOOST_TEST(!(px == px2)); + BOOST_TEST(px < px2 || px2 < px); + } + + { + boost::shared_ptr px(new X); + boost::shared_ptr px2(new X); + + BOOST_TEST(px.get() != px2.get()); + BOOST_TEST(px != px2); + BOOST_TEST(!(px == px2)); + BOOST_TEST(px < px2 || px2 < px); + } + + { + boost::shared_ptr px(new X); + boost::shared_ptr px2(px); + + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(px == px2); + BOOST_TEST(!(px != px2)); + BOOST_TEST(!(px < px2 || px2 < px)); + } + + { + boost::shared_ptr px(new X); + boost::shared_ptr py(new Y); + boost::shared_ptr pz(new Z); + + BOOST_TEST(px.get() != pz.get()); + BOOST_TEST(px != pz); + BOOST_TEST(!(px == pz)); + + BOOST_TEST(py.get() != pz.get()); + BOOST_TEST(py != pz); + BOOST_TEST(!(py == pz)); + + boost::shared_ptr pvx(px); + boost::shared_ptr pvy(py); + boost::shared_ptr pvz(pz); + + BOOST_TEST(pvx < pvy || pvy < pvx); + BOOST_TEST(pvx < pvz || pvz < pvx); + BOOST_TEST(pvy < pvz || pvz < pvy); + } + + { + boost::shared_ptr pz(new Z); + boost::shared_ptr px(pz); + boost::shared_ptr py(pz); + + BOOST_TEST(px.get() == pz.get()); + BOOST_TEST(px == pz); + BOOST_TEST(!(px != pz)); + + BOOST_TEST(py.get() == pz.get()); + BOOST_TEST(py == pz); + BOOST_TEST(!(py != pz)); + + boost::shared_ptr pvx(px); + boost::shared_ptr pvy(py); + boost::shared_ptr pvz(pz); + + // pvx and pvy aren't equal... + BOOST_TEST(pvx.get() != pvy.get()); + BOOST_TEST(pvx != pvy); + BOOST_TEST(!(pvx == pvy)); + + // ... but they share ownership ... + BOOST_TEST(!(pvx < pvy || pvy < pvx)); + + // ... with pvz + BOOST_TEST(!(pvx < pvz || pvz < pvx)); + BOOST_TEST(!(pvy < pvz || pvz < pvy)); + } +} + +} // namespace n_comparison + +namespace n_static_cast +{ + +struct X +{ +}; + +struct Y: public X +{ +}; + +void test() +{ + { + boost::shared_ptr pv; + + boost::shared_ptr pi = boost::static_pointer_cast(pv); + BOOST_TEST(pi.get() == 0); + + boost::shared_ptr px = boost::static_pointer_cast(pv); + BOOST_TEST(px.get() == 0); + } + + { + boost::shared_ptr pi(new int); + boost::shared_ptr pv(pi); + + boost::shared_ptr pi2 = boost::static_pointer_cast(pv); + BOOST_TEST(pi.get() == pi2.get()); + BOOST_TEST(!(pi < pi2 || pi2 < pi)); + BOOST_TEST(pi.use_count() == 3); + BOOST_TEST(pv.use_count() == 3); + BOOST_TEST(pi2.use_count() == 3); + } + + { + boost::shared_ptr px(new X); + boost::shared_ptr pv(px); + + boost::shared_ptr px2 = boost::static_pointer_cast(pv); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + BOOST_TEST(px.use_count() == 3); + BOOST_TEST(pv.use_count() == 3); + BOOST_TEST(px2.use_count() == 3); + } + + { + boost::shared_ptr px(new Y); + + boost::shared_ptr py = boost::static_pointer_cast(px); + BOOST_TEST(px.get() == py.get()); + BOOST_TEST(px.use_count() == 2); + BOOST_TEST(py.use_count() == 2); + + boost::shared_ptr px2(py); + BOOST_TEST(!(px < px2 || px2 < px)); + } +} + +} // namespace n_static_cast + +namespace n_dynamic_cast +{ + +struct V +{ + virtual ~V() {} +}; + +struct W: public V +{ +}; + +void test() +{ + { + boost::shared_ptr pv; + boost::shared_ptr pw = boost::dynamic_pointer_cast(pv); + BOOST_TEST(pw.get() == 0); + } + + { + boost::shared_ptr pv(static_cast(0)); + + boost::shared_ptr pw = boost::dynamic_pointer_cast(pv); + BOOST_TEST(pw.get() == 0); + + boost::shared_ptr pv2(pw); + BOOST_TEST(pv < pv2 || pv2 < pv); + } + + { + boost::shared_ptr pv(static_cast(0)); + + boost::shared_ptr pw = boost::dynamic_pointer_cast(pv); + BOOST_TEST(pw.get() == 0); + + boost::shared_ptr pv2(pw); + BOOST_TEST(pv < pv2 || pv2 < pv); + } + + { + boost::shared_ptr pv(new V); + + boost::shared_ptr pw = boost::dynamic_pointer_cast(pv); + BOOST_TEST(pw.get() == 0); + + boost::shared_ptr pv2(pw); + BOOST_TEST(pv < pv2 || pv2 < pv); + } + + { + boost::shared_ptr pv(new W); + + boost::shared_ptr pw = boost::dynamic_pointer_cast(pv); + BOOST_TEST(pw.get() == pv.get()); + BOOST_TEST(pv.use_count() == 2); + BOOST_TEST(pw.use_count() == 2); + + boost::shared_ptr pv2(pw); + BOOST_TEST(!(pv < pv2 || pv2 < pv)); + } +} + +} // namespace n_dynamic_cast + +namespace n_map +{ + +struct X +{ +}; + +void test() +{ + std::vector< boost::shared_ptr > vi; + + { + boost::shared_ptr pi1(new int); + boost::shared_ptr pi2(new int); + boost::shared_ptr pi3(new int); + + vi.push_back(pi1); + vi.push_back(pi1); + vi.push_back(pi1); + vi.push_back(pi2); + vi.push_back(pi1); + vi.push_back(pi2); + vi.push_back(pi1); + vi.push_back(pi3); + vi.push_back(pi3); + vi.push_back(pi2); + vi.push_back(pi1); + } + + std::vector< boost::shared_ptr > vx; + + { + boost::shared_ptr px1(new X); + boost::shared_ptr px2(new X); + boost::shared_ptr px3(new X); + + vx.push_back(px2); + vx.push_back(px2); + vx.push_back(px1); + vx.push_back(px2); + vx.push_back(px1); + vx.push_back(px1); + vx.push_back(px1); + vx.push_back(px2); + vx.push_back(px1); + vx.push_back(px3); + vx.push_back(px2); + } + + std::map< boost::shared_ptr, long > m; + + { + for(std::vector< boost::shared_ptr >::iterator i = vi.begin(); i != vi.end(); ++i) + { + ++m[*i]; + } + } + + { + for(std::vector< boost::shared_ptr >::iterator i = vx.begin(); i != vx.end(); ++i) + { + ++m[*i]; + } + } + + { + for(std::map< boost::shared_ptr, long >::iterator i = m.begin(); i != m.end(); ++i) + { + BOOST_TEST(i->first.use_count() == i->second + 1); + } + } +} + +} // namespace n_map + +namespace n_transitive +{ + +struct X +{ + X(): next() {} + boost::shared_ptr next; +}; + +void test() +{ + boost::shared_ptr p(new X); + p->next = boost::shared_ptr(new X); + BOOST_TEST(!p->next->next); + p = p->next; + BOOST_TEST(!p->next); +} + +} // namespace n_transitive + +namespace n_report_1 +{ + +class foo +{ +public: + + foo(): m_self(this) + { + } + + void suicide() + { + m_self.reset(); } private: - Z(Z const &); - Z & operator= (Z const &); -}; + boost::shared_ptr m_self; +}; -template void test_is_X(boost::shared_ptr const & p) +void test() { - BOOST_TEST(p->id() == 1); - BOOST_TEST((*p).id() == 1); -} + foo * foo_ptr = new foo; + foo_ptr->suicide(); +} -template void test_is_X(boost::weak_ptr const & p) -{ - BOOST_TEST(p.get() != 0); - BOOST_TEST(p.get()->id() == 1); -} +} // namespace n_report_1 -template void test_is_Y(boost::shared_ptr const & p) +// Test case by Per Kristensen +namespace n_report_2 { - BOOST_TEST(p->id() == 2); - BOOST_TEST((*p).id() == 2); -} - -template void test_is_Y(boost::weak_ptr const & p) -{ - BOOST_TEST(p.get() != 0); - BOOST_TEST(p.get()->id() == 2); -} - -template void test_eq(T const & a, T const & b) -{ - BOOST_TEST(a == b); - BOOST_TEST(!(a != b)); - BOOST_TEST(!(a < b)); - BOOST_TEST(!(b < a)); -} - -template void test_ne(T const & a, T const & b) -{ - BOOST_TEST(!(a == b)); - BOOST_TEST(a != b); - BOOST_TEST(a < b || b < a); - BOOST_TEST(!(a < b && b < a)); -} - -template void test_eq2(T const & a, U const & b) -{ - BOOST_TEST(a == b); - BOOST_TEST(!(a != b)); -} - -template void test_ne2(T const & a, U const & b) -{ - BOOST_TEST(!(a == b)); - BOOST_TEST(a != b); -} - -template void test_is_zero(boost::shared_ptr const & p) -{ - BOOST_TEST(!p); - BOOST_TEST(p.get() == 0); -} - -template void test_is_nonzero(boost::shared_ptr const & p) -{ - // p? true: false is used to test p in a boolean context. - // BOOST_TEST(p) is not guaranteed to test the conversion, - // as the macro might test !!p instead. - BOOST_TEST(p? true: false); - BOOST_TEST(p.get() != 0); -} class foo { @@ -235,7 +1672,159 @@ private: int lock; }; -int main() +void test() +{ + boost::shared_ptr s(new foo, deleter()); + s->setWeak(s); + s.reset(); +} + +} // namespace n_report_2 + +namespace n_old +{ + +int cnt = 0; + +struct X +{ + X() + { + ++cnt; + } + + ~X() // virtual destructor deliberately omitted + { + --cnt; + } + + virtual int id() const + { + return 1; + } + +private: + + X(X const &); + X & operator= (X const &); +}; + +struct Y: public X +{ + Y() + { + ++cnt; + } + + ~Y() + { + --cnt; + } + + virtual int id() const + { + return 2; + } + +private: + + Y(Y const &); + Y & operator= (Y const &); +}; + +int * get_object() +{ + ++cnt; + return &cnt; +} + +void release_object(int * p) +{ + BOOST_TEST(p == &cnt); + --cnt; +} + +template void test_is_X(boost::shared_ptr const & p) +{ + BOOST_TEST(p->id() == 1); + BOOST_TEST((*p).id() == 1); +} + +template void test_is_X(boost::weak_ptr const & p) +{ + BOOST_TEST(p.get() != 0); + BOOST_TEST(p.get()->id() == 1); +} + +template void test_is_Y(boost::shared_ptr const & p) +{ + BOOST_TEST(p->id() == 2); + BOOST_TEST((*p).id() == 2); +} + +template void test_is_Y(boost::weak_ptr const & p) +{ + boost::shared_ptr q = boost::make_shared(p); + BOOST_TEST(q.get() != 0); + BOOST_TEST(q->id() == 2); +} + +template void test_eq(T const & a, T const & b) +{ + BOOST_TEST(a == b); + BOOST_TEST(!(a != b)); + BOOST_TEST(!(a < b)); + BOOST_TEST(!(b < a)); +} + +template void test_ne(T const & a, T const & b) +{ + BOOST_TEST(!(a == b)); + BOOST_TEST(a != b); + BOOST_TEST(a < b || b < a); + BOOST_TEST(!(a < b && b < a)); +} + +void test_shared(boost::weak_ptr const & a, boost::weak_ptr const & b) +{ + BOOST_TEST(!(a < b)); + BOOST_TEST(!(b < a)); +} + +void test_nonshared(boost::weak_ptr const & a, boost::weak_ptr const & b) +{ + BOOST_TEST(a < b || b < a); + BOOST_TEST(!(a < b && b < a)); +} + +template void test_eq2(T const & a, U const & b) +{ + BOOST_TEST(a == b); + BOOST_TEST(!(a != b)); +} + +template void test_ne2(T const & a, U const & b) +{ + BOOST_TEST(!(a == b)); + BOOST_TEST(a != b); +} + +template void test_is_zero(boost::shared_ptr const & p) +{ + BOOST_TEST(!p); + BOOST_TEST(p.get() == 0); +} + +template void test_is_nonzero(boost::shared_ptr const & p) +{ + // p? true: false is used to test p in a boolean context. + // BOOST_TEST(p) is not guaranteed to test the conversion, + // as the macro might test !!p instead. + BOOST_TEST(p? true: false); + BOOST_TEST(p.get() != 0); +} + +void test() { using namespace boost; @@ -254,8 +1843,8 @@ int main() test_eq(p, q); } - shared_ptr p3 = shared_dynamic_cast(p); - shared_ptr p4 = shared_dynamic_cast(p2); + shared_ptr p3 = dynamic_pointer_cast(p); + shared_ptr p4 = dynamic_pointer_cast(p2); test_is_nonzero(p3); test_is_zero(p4); @@ -263,7 +1852,6 @@ int main() BOOST_TEST(p.use_count() == 2); BOOST_TEST(p2.use_count() == 1); BOOST_TEST(p3.use_count() == 2); - BOOST_TEST(p4.use_count() == 1); test_is_Y(p3); test_eq2(p, p3); @@ -274,7 +1862,10 @@ int main() test_is_nonzero(p5); test_eq2(p, p5); - std::cout << "--\n"; + weak_ptr wp1(p2); + + BOOST_TEST(!wp1.expired()); + BOOST_TEST(wp1.use_count() != 0); p.reset(); p2.reset(); @@ -286,32 +1877,27 @@ int main() test_is_zero(p3); test_is_zero(p4); - std::cout << "--\n"; - BOOST_TEST(p5.use_count() == 1); - weak_ptr wp1; - + BOOST_TEST(wp1.expired()); BOOST_TEST(wp1.use_count() == 0); - BOOST_TEST(wp1.get() == 0); try { shared_ptr sp1(wp1); BOOST_ERROR("shared_ptr sp1(wp1) failed to throw"); } - catch(boost::use_count_is_zero const &) + catch(boost::bad_weak_ptr const &) { } test_is_zero(boost::make_shared(wp1)); - weak_ptr wp2 = shared_static_cast(p5); + weak_ptr wp2 = static_pointer_cast(p5); BOOST_TEST(wp2.use_count() == 1); - BOOST_TEST(wp2.get() != 0); test_is_Y(wp2); - test_ne(wp1, wp2); + test_nonshared(wp1, wp2); // Scoped to not affect the subsequent use_count() tests. { @@ -319,41 +1905,25 @@ int main() test_is_nonzero(boost::make_shared(wp2)); } - weak_ptr wp3 = shared_dynamic_cast(boost::make_shared(wp2)); + weak_ptr wp3 = dynamic_pointer_cast(boost::make_shared(wp2)); BOOST_TEST(wp3.use_count() == 1); - BOOST_TEST(wp3.get() != 0); - test_eq2(wp2, wp3); + test_shared(wp2, wp3); weak_ptr wp4(wp3); BOOST_TEST(wp4.use_count() == 1); - BOOST_TEST(wp4.get() != 0); - test_eq(wp2, wp4); + test_shared(wp2, wp4); wp1 = p2; - BOOST_TEST(wp1.get() == 0); - - // Note the following test. Construction succeeds, - // but make_shared() returns a null shared_ptr with - // use_count() == 2. - - shared_ptr sp1(wp1); test_is_zero(boost::make_shared(wp1)); - BOOST_TEST(p2.use_count() == 2); - BOOST_TEST(sp1.use_count() == 2); - BOOST_TEST(wp1.use_count() == 2); - - // - wp1 = p4; wp1 = wp3; wp1 = wp2; BOOST_TEST(wp1.use_count() == 1); - BOOST_TEST(wp1.get() != 0); - test_eq(wp1, wp2); + test_shared(wp1, wp2); weak_ptr wp5; @@ -363,13 +1933,8 @@ int main() p5.reset(); BOOST_TEST(wp1.use_count() == 0); - BOOST_TEST(wp1.get() == 0); - BOOST_TEST(wp2.use_count() == 0); - BOOST_TEST(wp2.get() == 0); - BOOST_TEST(wp3.use_count() == 0); - BOOST_TEST(wp3.get() == 0); // Test operator< stability for std::set< weak_ptr<> > // Thanks to Joe Gottman for pointing this out @@ -381,38 +1946,497 @@ int main() // note that both get_object and release_object deal with int* shared_ptr p6(get_object(), release_object); } - - { - // test intrusive counting - - boost::shared_ptr pv(new Z); - boost::shared_ptr pz = boost::shared_static_cast(pv); - BOOST_TEST(pz.use_count() == pz->use_count()); - - // test shared_from_this - - boost::shared_ptr pz2 = pz->shared_this(); - - Z const & z = *pz2; - - boost::shared_ptr pz3 = z.shared_this(); - - BOOST_TEST(pz.use_count() == pz->use_count()); - BOOST_TEST(pz2.use_count() == pz2->use_count()); - BOOST_TEST(pz3.use_count() == pz3->use_count()); - BOOST_TEST(pz.use_count() == pz2.use_count()); - BOOST_TEST(pz.use_count() == pz3.use_count()); - } } BOOST_TEST(cnt == 0); +} + +} // namespace n_old + +namespace n_spt_incomplete +{ + +class file; + +boost::shared_ptr fopen(char const * name, char const * mode); +void fread(boost::shared_ptr f, void * data, long size); + +int file_instances = 0; + +void test() +{ + BOOST_TEST(file_instances == 0); - // Test case by Per Kristensen { - boost::shared_ptr s(new foo, deleter()); - s->setWeak(s); - s.reset(); + boost::shared_ptr pf = fopen("name", "mode"); + BOOST_TEST(file_instances == 1); + fread(pf, 0, 17041); } + BOOST_TEST(file_instances == 0); +} + +} // namespace n_spt_incomplete + +namespace n_spt_pimpl +{ + +class file +{ +private: + + class impl; + boost::shared_ptr pimpl_; + +public: + + file(char const * name, char const * mode); + + // compiler generated members are fine and useful + + void read(void * data, long size); + + long total_size() const; +}; + +int file_instances = 0; + +void test() +{ + BOOST_TEST(file_instances == 0); + + { + file f("name", "mode"); + BOOST_TEST(file_instances == 1); + f.read(0, 152); + + file f2(f); + BOOST_TEST(file_instances == 1); + f2.read(0, 894); + + BOOST_TEST(f.total_size() == 152+894); + + { + file f3("name2", "mode2"); + BOOST_TEST(file_instances == 2); + } + + BOOST_TEST(file_instances == 1); + } + + BOOST_TEST(file_instances == 0); +} + +} // namespace n_spt_pimpl + +namespace n_spt_abstract +{ + +class X +{ +public: + + virtual void f(int) = 0; + virtual int g() = 0; + +protected: + + ~X() {} +}; + +boost::shared_ptr createX(); + +int X_instances = 0; + +void test() +{ + BOOST_TEST(X_instances == 0); + + { + boost::shared_ptr px = createX(); + + BOOST_TEST(X_instances == 1); + + px->f(18); + px->f(152); + + BOOST_TEST(px->g() == 170); + } + + BOOST_TEST(X_instances == 0); +} + +} // namespace n_spt_abstract + +namespace n_spt_preventing_delete +{ + +int X_instances = 0; + +class X +{ +private: + + X() + { + ++X_instances; + } + + ~X() + { + --X_instances; + } + + class deleter; + friend class deleter; + + class deleter + { + public: + + void operator()(X * p) { delete p; } + }; + +public: + + static boost::shared_ptr create() + { + boost::shared_ptr px(new X, X::deleter()); + return px; + } +}; + +void test() +{ + BOOST_TEST(X_instances == 0); + + { + boost::shared_ptr px = X::create(); + BOOST_TEST(X_instances == 1); + } + + BOOST_TEST(X_instances == 0); +} + +} // namespace n_spt_preventing_delete + +namespace n_spt_array +{ + +int X_instances = 0; + +struct X +{ + X() + { + ++X_instances; + } + + ~X() + { + --X_instances; + } +}; + +void test() +{ + BOOST_TEST(X_instances == 0); + + { + boost::shared_ptr px(new X[4], boost::checked_array_deleter()); + BOOST_TEST(X_instances == 4); + } + + BOOST_TEST(X_instances == 0); +} + +} // namespace n_spt_array + +namespace n_spt_static +{ + +class X +{ +private: + + void operator delete(void *); +}; + +struct null_deleter +{ + void operator()(void const *) const + { + } +}; + +static X x; + +void test() +{ + boost::shared_ptr px(&x, null_deleter()); +} + +} // namespace n_spt_static + +namespace n_spt_intrusive +{ + +void test() +{ +} + +} // namespace n_spt_intrusive + +namespace n_spt_another_sp +{ + +void test() +{ +} + +} // namespace n_spt_another_sp + +namespace n_spt_shared_from_this +{ + +class X +{ +public: + + virtual void f() = 0; + +protected: + + ~X() {} +}; + +class Y +{ +public: + + virtual boost::shared_ptr getX() = 0; + +protected: + + ~Y() {} +}; + +class impl: public X, public Y +{ +private: + + boost::weak_ptr weak_this; + + impl(impl const &); + impl & operator=(impl const &); + + impl() {} + +public: + + static boost::shared_ptr create() + { + boost::shared_ptr pi(new impl); + pi->weak_this = pi; + return pi; + } + + virtual void f() {} + + virtual boost::shared_ptr getX() + { + boost::shared_ptr px = boost::make_shared(weak_this); + return px; + } +}; + +void test() +{ + boost::shared_ptr py = impl::create(); + 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); + + 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); +} + +} // namespace n_spt_shared_from_this + +namespace n_spt_wrap +{ + +void test() +{ +} + +} // namespace n_spt_wrap + +int main() +{ + n_element_type::test(); + n_constructors::test(); + n_assignment::test(); + n_reset::test(); + n_access::test(); + n_use_count::test(); + n_swap::test(); + n_comparison::test(); + n_static_cast::test(); + n_dynamic_cast::test(); + + n_map::test(); + + n_transitive::test(); + n_report_1::test(); + n_report_2::test(); + + n_old::test(); + + n_spt_incomplete::test(); + n_spt_pimpl::test(); + n_spt_abstract::test(); + n_spt_preventing_delete::test(); + n_spt_array::test(); + n_spt_static::test(); + n_spt_intrusive::test(); + n_spt_another_sp::test(); + n_spt_shared_from_this::test(); +// n_spt_post_constructors::test(); + n_spt_wrap::test(); + return boost::report_errors(); } + +namespace n_spt_incomplete +{ + +class file +{ +public: + + file(): fread_called(false) + { + ++file_instances; + } + + ~file() + { + BOOST_TEST(fread_called); + --file_instances; + } + + bool fread_called; +}; + +boost::shared_ptr fopen(char const *, char const *) +{ + boost::shared_ptr pf(new file); + return pf; +} + +void fread(boost::shared_ptr pf, void *, long) +{ + pf->fread_called = true; +} + +} // namespace n_spt_incomplete + +namespace n_spt_pimpl +{ + +class file::impl +{ +private: + + impl(impl const &); + impl & operator=(impl const &); + + long total_size_; + +public: + + impl(char const *, char const *): total_size_(0) + { + ++file_instances; + } + + ~impl() + { + --file_instances; + } + + void read(void *, long size) + { + total_size_ += size; + } + + long total_size() const + { + return total_size_; + } +}; + +file::file(char const * name, char const * mode): pimpl_(new impl(name, mode)) +{ +} + +void file::read(void * data, long size) +{ + pimpl_->read(data, size); +} + +long file::total_size() const +{ + return pimpl_->total_size(); +} + +} // namespace n_spt_pimpl + +namespace n_spt_abstract +{ + +class X_impl: public X +{ +private: + + X_impl(X_impl const &); + X_impl & operator=(X_impl const &); + + int n_; + +public: + + X_impl(): n_(0) + { + ++X_instances; + } + + ~X_impl() + { + --X_instances; + } + + virtual void f(int n) + { + n_ += n; + } + + virtual int g() + { + return n_; + } +}; + +boost::shared_ptr createX() +{ + boost::shared_ptr px(new X_impl); + return px; +} + +} // namespace n_spt_abstract diff --git a/smart_ptr_test.cpp b/smart_ptr_test.cpp index 0d02f8b..0dad8e9 100644 --- a/smart_ptr_test.cpp +++ b/smart_ptr_test.cpp @@ -24,11 +24,6 @@ #include #include -bool boost_error(char const *, char const *, char const *, long) -{ - return true; // fail with assert() -} - class Incomplete; Incomplete * get_ptr( boost::shared_ptr& incomplete ) @@ -164,7 +159,6 @@ void test() cp.reset(); BOOST_TEST( cp2.use_count() == 2 ); BOOST_TEST( cp3.use_count() == 2 ); - BOOST_TEST( cp.use_count() == 1 ); cp.reset( new int ); *cp = 98765; BOOST_TEST( *cp == 98765 ); From d0c5e83def125388dc318e87f23f5db180d2d025 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 19 Nov 2002 13:45:33 +0000 Subject: [PATCH 141/513] Test for enable_shared_from_this added. [SVN r16318] --- enable_shared_from_this_test.cpp | 95 ++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 enable_shared_from_this_test.cpp diff --git a/enable_shared_from_this_test.cpp b/enable_shared_from_this_test.cpp new file mode 100644 index 0000000..66f9c17 --- /dev/null +++ b/enable_shared_from_this_test.cpp @@ -0,0 +1,95 @@ +#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// enable_shared_from_this_test.cpp +// +// Copyright (c) 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + + +#include +#include + +#include + +// + +class X +{ +public: + + virtual void f() = 0; + +protected: + + ~X() {} +}; + +class Y +{ +public: + + virtual boost::shared_ptr getX() = 0; + +protected: + + ~Y() {} +}; + +boost::shared_ptr createY(); + +void test() +{ + boost::shared_ptr py = createY(); + 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); + + 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); +} + +int main() +{ + test(); + return boost::report_errors(); +} + +class impl: public X, public Y, public boost::enable_shared_from_this +{ +public: + + virtual void f() + { + } + + virtual boost::shared_ptr getX() + { + boost::shared_ptr pi = shared_from_this(); + BOOST_TEST(pi.get() == this); + return pi; + } +}; + +boost::shared_ptr createY() +{ + boost::shared_ptr pi(new impl); + return pi; +} From 8752c00ebfce63d5081f2aad8f89bfd4af3645ea Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 19 Nov 2002 14:22:58 +0000 Subject: [PATCH 142/513] enable_shared_from_this documentation added. [SVN r16319] --- enable_shared_from_this.html | 93 ++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 enable_shared_from_this.html diff --git a/enable_shared_from_this.html b/enable_shared_from_this.html new file mode 100644 index 0000000..425a781 --- /dev/null +++ b/enable_shared_from_this.html @@ -0,0 +1,93 @@ + + + + Boost: enable_shared_from_this.hpp documentation + + + + + + + + + + + +
    + c++boost.gif (8819 bytes) + +

    enable_shared_from_this.hpp

    +
     
    +

    Purpose

    +

    + The header <boost/enable_shared_from_this.hpp> defines + the class template enable_shared_from_this. It is used as a + base class that allows a shared_ptr to the current + object to be obtained from within a member function. +

    +

    enable_shared_from_this<T> defines two member functions + called shared_from_this that return a shared_ptr<T> + and shared_ptr<T const>, depending on constness, to this.

    +

    Example

    +
    +class Y: public enable_shared_from_this<Y>
    +{
    +public:
    +
    +    shared_ptr<Y> f()
    +    {
    +        return shared_from_this();
    +    }
    +}
    +
    +int main()
    +{
    +    shared_ptr<Y> p(new Y);
    +    shared_ptr<Y> q = p->f();
    +    assert(p == q);
    +    assert(!(p < q || q < p)); // p and q must share ownership
    +}
    +
    +

    Synopsis

    +
    +namespace boost
    +{
    +
    +template<class T> class enable_shared_from_this
    +{
    +public:
    +
    +    shared_ptr<T> shared_from_this();
    +    shared_ptr<T const> shared_from_this() const;
    +}
    +
    +}
    +
    +

    template<class T> shared_ptr<T> + enable_shared_from_this<T>::shared_from_this();

    +

    template<class T> shared_ptr<T const> + enable_shared_from_this<T>::shared_from_this() const;

    +
    +

    + Requires: enable_shared_from_this<T> must be an + accessible base class of T. *this must be a subobject + of an instance t of type T. There must have + existed at least one shared_ptr instance p pointing + to t. +

    +

    + Returns: A shared_ptr<T> instance r that shares + ownership with p. +

    +

    + Postconditions: r.get() == this. +

    +
    +

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

    + + From 7504eff5af15240d12f67258464e6457f47a70db Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 19 Nov 2002 16:10:07 +0000 Subject: [PATCH 143/513] A missing Returns clause added. [SVN r16321] --- shared_ptr.htm | 1 + 1 file changed, 1 insertion(+) diff --git a/shared_ptr.htm b/shared_ptr.htm index f1ca5b2..af055d3 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -322,6 +322,7 @@ template<class Y> shared_ptr & operator=(shared_ptr<Y> const &am template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);

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

    +

    Returns: *this.

    Notes: The use count updates caused by the temporary object construction and destruction are not considered observable side effects, and the implementation is free to meet the effects (and the implied guarantees) via From 7f30268b10b42490576f46f49f6da1f5ff36f73e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 19 Nov 2002 16:10:38 +0000 Subject: [PATCH 144/513] Assignment tests added. [SVN r16322] --- shared_ptr_test.cpp | 469 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 459 insertions(+), 10 deletions(-) diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 7ebb4d2..42e4782 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -354,10 +354,13 @@ void deleter2(int * p) ++*p; } -void deleter3(incomplete * p) +struct deleter3 { - BOOST_TEST(p == 0); -} + void operator()(incomplete * p) + { + BOOST_TEST(p == 0); + } +}; // Borland C++ 5.5.1 fails on static_cast(0) @@ -375,7 +378,7 @@ void deleter_constructor() } { - boost::shared_ptr pv(static_cast(0), deleter); + boost::shared_ptr pv(static_cast(0), &deleter); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); @@ -393,7 +396,7 @@ void deleter_constructor() } { - boost::shared_ptr px(p0, deleter3); + boost::shared_ptr px(p0, deleter3()); BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); @@ -402,7 +405,7 @@ void deleter_constructor() } { - boost::shared_ptr pv(p0, deleter3); + boost::shared_ptr pv(p0, deleter3()); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); @@ -411,7 +414,7 @@ void deleter_constructor() } { - boost::shared_ptr pv(p0, deleter3); + boost::shared_ptr pv(p0, deleter3()); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); @@ -433,7 +436,7 @@ void deleter_constructor() BOOST_TEST(m == 1); { - boost::shared_ptr pi(&m, deleter2); + boost::shared_ptr pi(&m, &deleter2); BOOST_TEST(pi? true: false); BOOST_TEST(!!pi); BOOST_TEST(pi.get() == &m); @@ -455,7 +458,7 @@ void deleter_constructor() BOOST_TEST(m == 3); { - boost::shared_ptr pv(&m, deleter2); + boost::shared_ptr pv(&m, &deleter2); BOOST_TEST(pv? true: false); BOOST_TEST(!!pv); BOOST_TEST(pv.get() == &m); @@ -472,16 +475,19 @@ void copy_constructor() boost::shared_ptr pi; boost::shared_ptr pi2(pi); + BOOST_TEST(pi2 == pi); BOOST_TEST(pi2? false: true); BOOST_TEST(!pi2); BOOST_TEST(pi2.get() == 0); boost::shared_ptr pi3(pi); + BOOST_TEST(pi3 == pi); BOOST_TEST(pi3? false: true); BOOST_TEST(!pi3); BOOST_TEST(pi3.get() == 0); boost::shared_ptr pi4(pi3); + BOOST_TEST(pi4 == pi3); BOOST_TEST(pi4? false: true); BOOST_TEST(!pi4); BOOST_TEST(pi4.get() == 0); @@ -491,6 +497,7 @@ void copy_constructor() boost::shared_ptr pv; boost::shared_ptr pv2(pv); + BOOST_TEST(pv2 == pv); BOOST_TEST(pv2? false: true); BOOST_TEST(!pv2); BOOST_TEST(pv2.get() == 0); @@ -500,11 +507,13 @@ void copy_constructor() boost::shared_ptr px; boost::shared_ptr px2(px); + BOOST_TEST(px2 == px); BOOST_TEST(px2? false: true); BOOST_TEST(!px2); BOOST_TEST(px2.get() == 0); boost::shared_ptr px3(px); + BOOST_TEST(px3 == px); BOOST_TEST(px3? false: true); BOOST_TEST(!px3); BOOST_TEST(px3.get() == 0); @@ -514,6 +523,7 @@ void copy_constructor() boost::shared_ptr pi(static_cast(0)); boost::shared_ptr pi2(pi); + BOOST_TEST(pi2 == pi); BOOST_TEST(pi2? false: true); BOOST_TEST(!pi2); BOOST_TEST(pi2.get() == 0); @@ -524,6 +534,7 @@ void copy_constructor() BOOST_TEST(!(pi < pi2 || pi2 < pi)); // shared ownership test boost::shared_ptr pi3(pi); + BOOST_TEST(pi3 == pi); BOOST_TEST(pi3? false: true); BOOST_TEST(!pi3); BOOST_TEST(pi3.get() == 0); @@ -531,6 +542,7 @@ void copy_constructor() BOOST_TEST(!pi3.unique()); boost::shared_ptr pi4(pi2); + BOOST_TEST(pi4 == pi2); BOOST_TEST(pi4? false: true); BOOST_TEST(!pi4); BOOST_TEST(pi4.get() == 0); @@ -545,6 +557,7 @@ void copy_constructor() boost::shared_ptr px(static_cast(0)); boost::shared_ptr px2(px); + BOOST_TEST(px2 == px); BOOST_TEST(px2? false: true); BOOST_TEST(!px2); BOOST_TEST(px2.get() == 0); @@ -555,6 +568,7 @@ void copy_constructor() BOOST_TEST(!(px < px2 || px2 < px)); // shared ownership test boost::shared_ptr px3(px); + BOOST_TEST(px3 == px); BOOST_TEST(px3? false: true); BOOST_TEST(!px3); BOOST_TEST(px3.get() == 0); @@ -562,6 +576,7 @@ void copy_constructor() BOOST_TEST(!px3.unique()); boost::shared_ptr px4(px2); + BOOST_TEST(px4 == px2); BOOST_TEST(px4? false: true); BOOST_TEST(!px4); BOOST_TEST(px4.get() == 0); @@ -577,6 +592,7 @@ void copy_constructor() boost::shared_ptr pi(p); boost::shared_ptr pi2(pi); + BOOST_TEST(pi2 == pi); BOOST_TEST(pi2? true: false); BOOST_TEST(!!pi2); BOOST_TEST(pi2.get() == p); @@ -591,8 +607,10 @@ void copy_constructor() { int * p = new int(7); boost::shared_ptr pv(p); + BOOST_TEST(pv.get() == p); boost::shared_ptr pv2(pv); + BOOST_TEST(pv2 == pv); BOOST_TEST(pv2? true: false); BOOST_TEST(!!pv2); BOOST_TEST(pv2.get() == p); @@ -608,8 +626,10 @@ void copy_constructor() { X * p = new X; boost::shared_ptr px(p); + BOOST_TEST(px.get() == p); boost::shared_ptr px2(px); + BOOST_TEST(px2 == px); BOOST_TEST(px2? true: false); BOOST_TEST(!!px2); BOOST_TEST(px2.get() == p); @@ -622,6 +642,7 @@ void copy_constructor() BOOST_TEST(!(px < px2 || px2 < px)); // shared ownership test boost::shared_ptr px3(px); + BOOST_TEST(px3 == px); BOOST_TEST(px3? true: false); BOOST_TEST(!!px3); BOOST_TEST(px3.get() == p); @@ -629,6 +650,7 @@ void copy_constructor() BOOST_TEST(!px3.unique()); boost::shared_ptr px4(px2); + BOOST_TEST(px4 == px2); BOOST_TEST(px4? true: false); BOOST_TEST(!!px4); BOOST_TEST(px4.get() == p); @@ -645,8 +667,10 @@ void copy_constructor() { Y * p = new Y; boost::shared_ptr py(p); + BOOST_TEST(py.get() == p); boost::shared_ptr px(py); + BOOST_TEST(px == py); BOOST_TEST(px? true: false); BOOST_TEST(!!px); BOOST_TEST(px.get() == p); @@ -657,6 +681,7 @@ void copy_constructor() BOOST_TEST(Y::instances == 1); boost::shared_ptr pv(px); + BOOST_TEST(pv == px); BOOST_TEST(pv? true: false); BOOST_TEST(!!pv); BOOST_TEST(pv.get() == px.get()); @@ -664,6 +689,7 @@ void copy_constructor() BOOST_TEST(!pv.unique()); boost::shared_ptr pv2(py); + BOOST_TEST(pv2 == py); BOOST_TEST(pv2? true: false); BOOST_TEST(!!pv2); BOOST_TEST(pv2.get() == py.get()); @@ -1031,8 +1057,376 @@ void test() namespace n_assignment { +class incomplete; + +struct A +{ + int dummy; +}; + +struct X +{ + static long instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X(X const &); + X & operator= (X const &); +}; + +long X::instances = 0; + +struct Y: public A, public X +{ + static long instances; + + Y() + { + ++instances; + } + + ~Y() + { + --instances; + } + +private: + + Y(Y const &); + Y & operator= (Y const &); +}; + +long Y::instances = 0; + +void copy_assignment() +{ + { + boost::shared_ptr p1; + + p1 = p1; + + BOOST_TEST(p1 == p1); + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + + boost::shared_ptr p2; + + p1 = p2; + + BOOST_TEST(p1 == p2); + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + + boost::shared_ptr p3(p1); + + p1 = p3; + + BOOST_TEST(p1 == p3); + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + } + + { + boost::shared_ptr p1; + + p1 = p1; + + BOOST_TEST(p1 == p1); + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + + boost::shared_ptr p2; + + p1 = p2; + + BOOST_TEST(p1 == p2); + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + + boost::shared_ptr p3(p1); + + p1 = p3; + + BOOST_TEST(p1 == p3); + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + + boost::shared_ptr p4(new int); + BOOST_TEST(p4.use_count() == 1); + + p1 = p4; + + BOOST_TEST(p1 == p4); + BOOST_TEST(!(p1 < p4 || p4 < p1)); + BOOST_TEST(p1.use_count() == 2); + BOOST_TEST(p4.use_count() == 2); + + p1 = p3; + + BOOST_TEST(p1 == p3); + BOOST_TEST(p4.use_count() == 1); + } + + { + boost::shared_ptr p1; + + p1 = p1; + + BOOST_TEST(p1 == p1); + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + + boost::shared_ptr p2; + + p1 = p2; + + BOOST_TEST(p1 == p2); + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + + boost::shared_ptr p3(p1); + + p1 = p3; + + BOOST_TEST(p1 == p3); + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + + BOOST_TEST(X::instances == 0); + + boost::shared_ptr p4(new X); + + BOOST_TEST(X::instances == 1); + + p1 = p4; + + BOOST_TEST(X::instances == 1); + + BOOST_TEST(p1 == p4); + BOOST_TEST(!(p1 < p4 || p4 < p1)); + + BOOST_TEST(p1.use_count() == 2); + + p1 = p2; + + BOOST_TEST(p1 == p2); + BOOST_TEST(X::instances == 1); + + p4 = p3; + + BOOST_TEST(p4 == p3); + BOOST_TEST(X::instances == 0); + } +} + +void conversion_assignment() +{ + { + boost::shared_ptr p1; + + boost::shared_ptr p2; + + p1 = p2; + + BOOST_TEST(p1 == p2); + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + + boost::shared_ptr p4(new int); + BOOST_TEST(p4.use_count() == 1); + + boost::shared_ptr p5(p4); + BOOST_TEST(p4.use_count() == 2); + + p1 = p4; + + BOOST_TEST(p1 == p4); + BOOST_TEST(!(p1 < p5 || p5 < p1)); + BOOST_TEST(p1.use_count() == 3); + BOOST_TEST(p4.use_count() == 3); + + p1 = p2; + + BOOST_TEST(p1 == p2); + BOOST_TEST(p4.use_count() == 2); + } + + { + boost::shared_ptr p1; + + boost::shared_ptr p2; + + p1 = p2; + + BOOST_TEST(p1 == p2); + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + + boost::shared_ptr p4(new Y); + + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); + BOOST_TEST(p4.use_count() == 1); + + boost::shared_ptr p5(p4); + BOOST_TEST(p4.use_count() == 2); + + p1 = p4; + + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); + + BOOST_TEST(p1 == p4); + BOOST_TEST(!(p1 < p5 || p5 < p1)); + + BOOST_TEST(p1.use_count() == 3); + BOOST_TEST(p4.use_count() == 3); + + p1 = p2; + + BOOST_TEST(p1 == p2); + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); + BOOST_TEST(p4.use_count() == 2); + + p4 = p2; + p5 = p2; + + BOOST_TEST(p4 == p2); + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + } +} + +void auto_ptr_assignment() +{ + { + boost::shared_ptr p1; + + std::auto_ptr p2; + + p1 = p2; + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + BOOST_TEST(p1.use_count() == 1); + + int * p = new int; + std::auto_ptr p3(p); + + p1 = p3; + BOOST_TEST(p1.get() == p); + BOOST_TEST(p1.use_count() == 1); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + BOOST_TEST(p3.get() == 0); +#endif + + p1 = p2; + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + BOOST_TEST(p1.use_count() == 1); + } + + { + boost::shared_ptr p1; + + std::auto_ptr p2; + + p1 = p2; + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + BOOST_TEST(p1.use_count() == 1); + + int * p = new int; + std::auto_ptr p3(p); + + p1 = p3; + BOOST_TEST(p1.get() == p); + BOOST_TEST(p1.use_count() == 1); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + BOOST_TEST(p3.get() == 0); +#endif + + p1 = p2; + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + BOOST_TEST(p1.use_count() == 1); + } + + + { + boost::shared_ptr p1; + + std::auto_ptr p2; + + p1 = p2; + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + BOOST_TEST(p1.use_count() == 1); + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + + Y * p = new Y; + std::auto_ptr p3(p); + + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); + + p1 = p3; + BOOST_TEST(p1.get() == p); + BOOST_TEST(p1.use_count() == 1); + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + BOOST_TEST(p3.get() == 0); +#endif + + p1 = p2; + BOOST_TEST(p1? false: true); + BOOST_TEST(!p1); + BOOST_TEST(p1.get() == 0); + BOOST_TEST(p1.use_count() == 1); + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + } +} + void test() { + copy_assignment(); + conversion_assignment(); + auto_ptr_assignment(); } } // namespace n_assignment @@ -1040,8 +1434,23 @@ void test() namespace n_reset { +void plain_reset() +{ +} + +void pointer_reset() +{ +} + +void deleter_reset() +{ +} + void test() { + plain_reset(); + pointer_reset(); + deleter_reset(); } } // namespace n_reset @@ -1277,30 +1686,45 @@ void test() { { boost::shared_ptr px; - boost::shared_ptr px2; + BOOST_TEST(px == px); + BOOST_TEST(!(px != px)); + BOOST_TEST(!(px < px)); + + boost::shared_ptr px2; BOOST_TEST(px.get() == px2.get()); BOOST_TEST(px == px2); BOOST_TEST(!(px != px2)); + BOOST_TEST(!(px < px2 && px2 < px)); } { boost::shared_ptr px; boost::shared_ptr px2(px); + BOOST_TEST(px2 == px2); + BOOST_TEST(!(px2 != px2)); + BOOST_TEST(!(px2 < px2)); + BOOST_TEST(px.get() == px2.get()); BOOST_TEST(px == px2); BOOST_TEST(!(px != px2)); + BOOST_TEST(!(px < px2 && px2 < px)); } { boost::shared_ptr px; boost::shared_ptr px2(new X); + BOOST_TEST(px2 == px2); + BOOST_TEST(!(px2 != px2)); + BOOST_TEST(!(px2 < px2)); + BOOST_TEST(px.get() != px2.get()); BOOST_TEST(px != px2); BOOST_TEST(!(px == px2)); BOOST_TEST(px < px2 || px2 < px); + BOOST_TEST(!(px < px2 && px2 < px)); } { @@ -1311,12 +1735,17 @@ void test() BOOST_TEST(px != px2); BOOST_TEST(!(px == px2)); BOOST_TEST(px < px2 || px2 < px); + BOOST_TEST(!(px < px2 && px2 < px)); } { boost::shared_ptr px(new X); boost::shared_ptr px2(px); + BOOST_TEST(px2 == px2); + BOOST_TEST(!(px2 != px2)); + BOOST_TEST(!(px2 < px2)); + BOOST_TEST(px.get() == px2.get()); BOOST_TEST(px == px2); BOOST_TEST(!(px != px2)); @@ -1337,17 +1766,31 @@ void test() BOOST_TEST(!(py == pz)); boost::shared_ptr pvx(px); + + BOOST_TEST(pvx == pvx); + BOOST_TEST(!(pvx != pvx)); + BOOST_TEST(!(pvx < pvx)); + boost::shared_ptr pvy(py); boost::shared_ptr pvz(pz); BOOST_TEST(pvx < pvy || pvy < pvx); BOOST_TEST(pvx < pvz || pvz < pvx); BOOST_TEST(pvy < pvz || pvz < pvy); + + BOOST_TEST(!(pvx < pvy && pvy < pvx)); + BOOST_TEST(!(pvx < pvz && pvz < pvx)); + BOOST_TEST(!(pvy < pvz && pvz < pvy)); } { boost::shared_ptr pz(new Z); boost::shared_ptr px(pz); + + BOOST_TEST(px == px); + BOOST_TEST(!(px != px)); + BOOST_TEST(!(px < px)); + boost::shared_ptr py(pz); BOOST_TEST(px.get() == pz.get()); @@ -2157,6 +2600,12 @@ namespace n_spt_static class X { +public: + + X() + { + } + private: void operator delete(void *); From b632f1ef205e43c0102d98b5b91d210089ea41ce Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 19 Nov 2002 16:11:21 +0000 Subject: [PATCH 145/513] Debug hooks, general cleanup. [SVN r16323] --- include/boost/detail/shared_count.hpp | 73 +++++++++++++++++---------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index c5178c7..ed7d452 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -38,6 +38,16 @@ namespace boost { +// Debug hooks + +#if defined(BOOST_ENABLE_SHARED_PTR_DEBUG_HOOKS) + +void shared_ptr_constructor_hook(void * p); +void shared_ptr_destructor_hook(void * p); + +#endif + + // The standard library that comes with Borland C++ 5.5.1 // defines std::exception and its members as having C calling // convention (-pc). When the definition of bad_weak_ptr @@ -74,15 +84,7 @@ private: public: - counted_base(): - use_count_(0), weak_count_(0) - { - } - - // pre: initial_use_count <= initial_weak_count - - explicit counted_base(long initial_use_count, long initial_weak_count): - use_count_(initial_use_count), weak_count_(initial_weak_count) + counted_base(): use_count_(1), weak_count_(1) { } @@ -92,16 +94,8 @@ public: // dispose() is called when use_count_ drops to zero, to release // the resources managed by *this. - // - // counted_base doesn't manage any resources except itself, and - // the default implementation is a no-op. - // - // dispose() is not pure virtual since weak_ptr instantiates a - // counted_base in its default constructor. - virtual void dispose() // nothrow - { - } + virtual void dispose() = 0; // nothrow // destruct() is called when weak_count_ drops to zero. @@ -187,6 +181,28 @@ private: #endif }; +#if defined(BOOST_ENABLE_SHARED_PTR_DEBUG_HOOKS) + +template void cbi_call_constructor_hook(T * p, checked_deleter const &, int) +{ + boost::shared_ptr_constructor_hook(p); +} + +template void cbi_call_constructor_hook(P const &, D const &, long) +{ +} + +template void cbi_call_destructor_hook(T * p, checked_deleter const &, int) +{ + boost::shared_ptr_destructor_hook(p); +} + +template void cbi_call_destructor_hook(P const &, D const &, long) +{ +} + +#endif + // // Borland's Codeguard trips up over the -Vx- option here: // @@ -210,13 +226,18 @@ public: // pre: initial_use_count <= initial_weak_count, d(p) must not throw - counted_base_impl(P p, D d, long initial_use_count, long initial_weak_count): - counted_base(initial_use_count, initial_weak_count), ptr(p), del(d) + counted_base_impl(P p, D d): ptr(p), del(d) { +#if defined(BOOST_ENABLE_SHARED_PTR_DEBUG_HOOKS) + detail::cbi_call_constructor_hook(p, d, 0); +#endif } virtual void dispose() // nothrow { +#if defined(BOOST_ENABLE_SHARED_PTR_DEBUG_HOOKS) + detail::cbi_call_destructor_hook(ptr, del, 0); +#endif del(ptr); } @@ -245,11 +266,9 @@ private: friend class weak_count; - template shared_count(P, D, counted_base const *); - public: - shared_count(): pi_(0) // (new counted_base(1, 1)) + shared_count(): pi_(0) // nothrow { } @@ -259,7 +278,7 @@ public: try { - pi_ = new counted_base_impl(p, d, 1, 1); + pi_ = new counted_base_impl(p, d); } catch(...) { @@ -269,7 +288,7 @@ public: #else - pi_ = new counted_base_impl(p, d, 1, 1); + pi_ = new counted_base_impl(p, d); if(pi_ == 0) { @@ -285,7 +304,7 @@ public: // auto_ptr is special cased to provide the strong guarantee template - explicit shared_count(std::auto_ptr & r): pi_(new counted_base_impl< Y *, checked_deleter >(r.get(), checked_deleter(), 1, 1)) + explicit shared_count(std::auto_ptr & r): pi_(new counted_base_impl< Y *, checked_deleter >(r.get(), checked_deleter())) { r.release(); } @@ -357,7 +376,7 @@ private: public: - weak_count(): pi_(0) // nothrow // (new counted_base(0, 1)) // can throw + weak_count(): pi_(0) // nothrow { } From 11a046f6281c5e18996641c5346a589215c29829 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 19 Nov 2002 16:18:18 +0000 Subject: [PATCH 146/513] BOOST_ASSERTs added. [SVN r16324] --- include/boost/enable_shared_from_this.hpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 199725a..ae5d809 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -14,9 +14,10 @@ // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html // -#include -#include #include +#include +#include +#include namespace boost { @@ -27,12 +28,16 @@ public: shared_ptr shared_from_this() { - return shared_ptr(weak_this); + shared_ptr p(weak_this); + BOOST_ASSERT(p.get() == this); + return p; } shared_ptr shared_from_this() const { - return shared_ptr(weak_this); + shared_ptr p(weak_this); + BOOST_ASSERT(p.get() == this); + return p; } #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS @@ -43,7 +48,8 @@ private: #endif - weak_ptr weak_this; + typedef T element_type; // for bcc 5.5.1 + weak_ptr weak_this; }; } // namespace boost From 45c799f40cd7afec8c7a1fe8045649784dc7ee7e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 19 Nov 2002 16:18:58 +0000 Subject: [PATCH 147/513] Debug hook support moved to shared_count. [SVN r16325] --- include/boost/shared_ptr.hpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 6357fff..e429571 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -76,12 +76,6 @@ template<> struct shared_ptr_traits // is destroyed or reset. // -#if defined(BOOST_SP_ENABLE_CONSTRUCTOR_HOOK) - -void shared_ptr_constructor_hook(void * p); - -#endif - template class weak_ptr; template class enable_shared_from_this; @@ -119,10 +113,6 @@ public: explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter()) // Y must be complete { sp_enable_shared_from_this(p); - -#if defined(BOOST_SP_ENABLE_CONSTRUCTOR_HOOK) - shared_ptr_constructor_hook(p); -#endif } // @@ -156,7 +146,7 @@ public: template shared_ptr(shared_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) { - if (px == 0) // need to allocate new counter -- the cast failed + if(px == 0) // need to allocate new counter -- the cast failed { pn = detail::shared_count(); } From f34866e8a5aa48ce5f8640b64afdf22bb5786025 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 19 Nov 2002 16:23:01 +0000 Subject: [PATCH 148/513] License added. [SVN r16326] --- include/boost/smart_ptr.hpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index da28e87..4ff62e7 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -1,7 +1,18 @@ -// Boost smart_ptr.hpp header file -----------------------------------------// - -// For compatibility, this header includes the header for the four "classic" -// smart pointer class templates. +// +// smart_ptr.hpp +// +// For compatibility, this header includes the headers for the four "classic" +// smart pointer class templates. +// +// Copyright (c) 1998-2002 boost.org +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// http://www.boost.org/libs/smart_ptr/smart_ptr.htm +// #include #include From 4b200e984736023549f8724f30a912abf2beaa30 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 19 Nov 2002 18:21:32 +0000 Subject: [PATCH 149/513] Borland fix (thanks to Fernando Cacciola) [SVN r16331] --- include/boost/shared_ptr.hpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index e429571..b03a391 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -83,8 +83,7 @@ template class shared_ptr { private: - // Borland 5.5.1 specific workarounds -// typedef checked_deleter deleter; + // Borland 5.5.1 specific workaround typedef shared_ptr this_type; // enable_shared_from_this support @@ -126,7 +125,19 @@ public: sp_enable_shared_from_this(p); } -// generated copy constructor, assignment, destructor are fine +// generated copy constructor, assignment, destructor are fine... + +// except on Borland C++ 5.5.1 +#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x551) + + shared_ptr & operator=(shared_ptr const & r) // never throws + { + px = r.px; + pn = r.pn; // shared_count::op= doesn't throw + return *this; + } + +#endif template explicit shared_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // may throw From 804b1483c77862680f48fc18c47042a6e0f26ad4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 20 Nov 2002 12:38:51 +0000 Subject: [PATCH 150/513] enable_shared_from_this-related fixes. [SVN r16341] --- enable_shared_from_this_test.cpp | 13 ++++++-- include/boost/enable_shared_from_this.hpp | 16 +++------- include/boost/shared_ptr.hpp | 38 +++++++++++------------ include/boost/weak_ptr.hpp | 10 ++++-- 4 files changed, 42 insertions(+), 35 deletions(-) diff --git a/enable_shared_from_this_test.cpp b/enable_shared_from_this_test.cpp index 66f9c17..8225a39 100644 --- a/enable_shared_from_this_test.cpp +++ b/enable_shared_from_this_test.cpp @@ -72,7 +72,10 @@ int main() return boost::report_errors(); } -class impl: public X, public Y, public boost::enable_shared_from_this +// virtual inheritance from Y to stress the implementation +// (prevents Y* -> impl* casts) + +class impl: public X, public virtual Y, public boost::enable_shared_from_this { public: @@ -88,8 +91,14 @@ public: } }; +// intermediate impl2 to stress the implementation + +class impl2: public impl +{ +}; + boost::shared_ptr createY() { - boost::shared_ptr pi(new impl); + boost::shared_ptr pi(new impl2); return pi; } diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index ae5d809..4dfdab6 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -28,28 +28,20 @@ public: shared_ptr shared_from_this() { - shared_ptr p(weak_this); + shared_ptr p(_internal_weak_this); BOOST_ASSERT(p.get() == this); return p; } shared_ptr shared_from_this() const { - shared_ptr p(weak_this); + shared_ptr p(_internal_weak_this); BOOST_ASSERT(p.get() == this); return p; } -#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS - -private: - - template friend class shared_ptr; - -#endif - - typedef T element_type; // for bcc 5.5.1 - weak_ptr weak_this; + typedef T _internal_element_type; // for bcc 5.5.1 + weak_ptr<_internal_element_type> _internal_weak_this; }; } // namespace boost diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index b03a391..8fc45ea 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -39,6 +39,9 @@ namespace boost { +template class weak_ptr; +template class enable_shared_from_this; + namespace detail { @@ -65,6 +68,17 @@ template<> struct shared_ptr_traits #endif +// enable_shared_from_this support + +template void sp_enable_shared_from_this(boost::enable_shared_from_this * pe, Y * px, shared_count const & pn) +{ + pe->_internal_weak_this._internal_assign(px, pn); +} + +void sp_enable_shared_from_this(void const *, void const *, shared_count const &) +{ +} + } // namespace detail @@ -76,9 +90,6 @@ template<> struct shared_ptr_traits // is destroyed or reset. // -template class weak_ptr; -template class enable_shared_from_this; - template class shared_ptr { private: @@ -86,17 +97,6 @@ private: // Borland 5.5.1 specific workaround typedef shared_ptr this_type; - // enable_shared_from_this support - - template void sp_enable_shared_from_this(boost::enable_shared_from_this * q) - { - q->weak_this = *this; - } - - void sp_enable_shared_from_this(void *) - { - } - public: typedef T element_type; @@ -111,7 +111,7 @@ public: template explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter()) // Y must be complete { - sp_enable_shared_from_this(p); + detail::sp_enable_shared_from_this(p, p, pn); } // @@ -122,7 +122,7 @@ public: template shared_ptr(Y * p, D d): px(p), pn(p, d) { - sp_enable_shared_from_this(p); + detail::sp_enable_shared_from_this(p, p, pn); } // generated copy constructor, assignment, destructor are fine... @@ -179,7 +179,7 @@ public: { Y * tmp = r.get(); pn = detail::shared_count(r); - sp_enable_shared_from_this(tmp); + detail::sp_enable_shared_from_this(tmp, tmp, pn); } #endif @@ -270,7 +270,7 @@ public: pn.swap(other.pn); } - bool less(this_type const & rhs) const // implementation detail, never throws + bool _internal_less(this_type const & rhs) const // implementation detail, never throws { return pn < rhs.pn; } @@ -316,7 +316,7 @@ template inline bool operator!=(shared_ptr const & a, shared_ptr template inline bool operator<(shared_ptr const & a, shared_ptr const & b) { - return a.less(b); + return a._internal_less(b); } template inline void swap(shared_ptr & a, shared_ptr & b) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index b65309e..a4154ea 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -92,7 +92,13 @@ public: pn.swap(other.pn); } - bool less(this_type const & rhs) const // implementation detail, never throws + void _internal_assign(T * px2, detail::shared_count const & pn2) // implementation detail + { + px = px2; + pn = pn2; + } + + bool _internal_less(this_type const & rhs) const // implementation detail, never throws { return pn < rhs.pn; } @@ -116,7 +122,7 @@ private: template inline bool operator<(weak_ptr const & a, weak_ptr const & b) { - return a.less(b); + return a._internal_less(b); } template void swap(weak_ptr & a, weak_ptr & b) From de68e6ed1e2c26b50d64871ceeed9bed7b43f9c8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 20 Nov 2002 13:34:18 +0000 Subject: [PATCH 151/513] A missing 'inline' added. [SVN r16343] --- include/boost/shared_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 8fc45ea..fedfdd8 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -75,7 +75,7 @@ template void sp_enable_shared_from_this(boost::enable_shared_ pe->_internal_weak_this._internal_assign(px, pn); } -void sp_enable_shared_from_this(void const *, void const *, shared_count const &) +inline void sp_enable_shared_from_this(void const *, void const *, shared_count const &) { } From e555d33695660ef94adb755f41cc4bd04256bc80 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 20 Nov 2002 16:18:13 +0000 Subject: [PATCH 152/513] Added array versions of the hooks. [SVN r16346] --- include/boost/detail/shared_count.hpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index ed7d452..46d0828 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -42,8 +42,10 @@ namespace boost #if defined(BOOST_ENABLE_SHARED_PTR_DEBUG_HOOKS) -void shared_ptr_constructor_hook(void * p); -void shared_ptr_destructor_hook(void * p); +void shared_ptr_scalar_constructor_hook(void * p); +void shared_ptr_array_constructor_hook(void * p); +void shared_ptr_scalar_destructor_hook(void * p); +void shared_ptr_array_destructor_hook(void * p); #endif @@ -185,7 +187,12 @@ private: template void cbi_call_constructor_hook(T * p, checked_deleter const &, int) { - boost::shared_ptr_constructor_hook(p); + boost::shared_ptr_scalar_constructor_hook(p); +} + +template void cbi_call_constructor_hook(T * p, checked_array_deleter const &, int) +{ + boost::shared_ptr_array_constructor_hook(p); } template void cbi_call_constructor_hook(P const &, D const &, long) @@ -194,7 +201,12 @@ template void cbi_call_constructor_hook(P const &, D const &, template void cbi_call_destructor_hook(T * p, checked_deleter const &, int) { - boost::shared_ptr_destructor_hook(p); + boost::shared_ptr_scalar_destructor_hook(p); +} + +template void cbi_call_destructor_hook(T * p, checked_array_deleter const &, int) +{ + boost::shared_ptr_array_destructor_hook(p); } template void cbi_call_destructor_hook(P const &, D const &, long) From e32b2adfdad2cecd088a29fa6f5c5eff036618ca Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 21 Nov 2002 13:10:18 +0000 Subject: [PATCH 153/513] Debug hook support, removed self-reset, fixed #%20links. [SVN r16361] --- include/boost/scoped_array.hpp | 26 +++++++++++++++++++------- include/boost/scoped_ptr.hpp | 28 ++++++++++++++++++++++------ scoped_array.htm | 26 +++++++++++++------------- scoped_ptr.htm | 22 +++++++++++----------- smart_ptr.htm | 8 ++++---- 5 files changed, 69 insertions(+), 41 deletions(-) diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index 636fad4..d99653c 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -9,7 +9,7 @@ // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // -// See http://www.boost.org/libs/smart_ptr/scoped_array.htm for documentation. +// http://www.boost.org/libs/smart_ptr/scoped_array.htm // #include @@ -20,6 +20,15 @@ namespace boost { +// Debug hooks + +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + +void sp_array_constructor_hook(void * p); +void sp_array_destructor_hook(void * p); + +#endif + // scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to // is guaranteed, either on destruction of the scoped_array or via an explicit // reset(). Use shared_array or std::vector if your needs are more complex. @@ -41,20 +50,23 @@ public: explicit scoped_array(T * p = 0) : ptr(p) // never throws { +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + boost::sp_array_constructor_hook(ptr); +#endif } ~scoped_array() // never throws { - checked_array_delete(ptr); +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + boost::sp_array_destructor_hook(ptr); +#endif + boost::checked_array_delete(ptr); } void reset(T * p = 0) // never throws { - if (ptr != p) - { - checked_array_delete(ptr); - ptr = p; - } + BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors + this_type(p).swap(*this); } T & operator[](std::ptrdiff_t i) const // never throws diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 1c2a520..03b34ed 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -9,7 +9,7 @@ // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // -// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation. +// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm // #include @@ -22,6 +22,15 @@ namespace boost { +// Debug hooks + +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + +void sp_scalar_constructor_hook(void * p); +void sp_scalar_destructor_hook(void * p); + +#endif + // scoped_ptr mimics a built-in pointer except that it guarantees deletion // of the object pointed to, either on destruction of the scoped_ptr or via // an explicit reset(). scoped_ptr is a simple solution for simple needs; @@ -44,27 +53,34 @@ public: explicit scoped_ptr(T * p = 0): ptr(p) // never throws { +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + boost::sp_scalar_constructor_hook(ptr); +#endif } #ifndef BOOST_NO_AUTO_PTR explicit scoped_ptr(std::auto_ptr p): ptr(p.release()) // never throws { +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + boost::sp_scalar_constructor_hook(ptr); +#endif } #endif ~scoped_ptr() // never throws { - checked_delete(ptr); +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + boost::sp_scalar_destructor_hook(ptr); +#endif + boost::checked_delete(ptr); } void reset(T * p = 0) // never throws { - if(ptr != p) - { - this_type(p).swap(*this); - } + BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors + this_type(p).swap(*this); } T & operator*() const // never throws diff --git a/scoped_array.htm b/scoped_array.htm index a057b11..5e80f62 100644 --- a/scoped_array.htm +++ b/scoped_array.htm @@ -29,7 +29,7 @@ heavier duty but far more flexible. A boost::array is an alternative that does not use dynamic allocation.

    The class template is parameterized on T, the type of the object pointed - to. T must meet the smart pointer + to. T must meet the smart pointer common requirements.

    Synopsis

    namespace boost {
    @@ -40,7 +40,7 @@
           typedef T element_type;
     
           explicit scoped_array(T * p = 0); // never throws
    -      ~scoped_array(); // never throws
    +      ~scoped_array(); // never throws
     
           void reset(T * p = 0); // never throws
     
    @@ -62,23 +62,23 @@
     		
    explicit scoped_array(T * p = 0); // never throws

    Constructs a scoped_array, storing a copy of p, which must have been allocated via a C++ new[] expression or be 0. T is not - required be a complete type. See the smart pointer + required be a complete type. See the smart pointer common requirements.

    -

    destructor

    +

    destructor

    ~scoped_array(); // never throws

    Deletes the array pointed to by the stored pointer. Note that delete[] on a pointer with a value of 0 is harmless. The guarantee that this does not throw exceptions depends on the requirement that the deleted array's objects' - destructors do not throw exceptions. See the smart pointer + destructors do not throw exceptions. See the smart pointer common requirements.

    reset

    void reset(T * p = 0); // never throws
    -

    If p is not equal to the stored pointer, deletes the array pointed to by the - stored pointer and then stores a copy of p, which must have been allocated via - a C++ new[] expression or be 0. The guarantee that this does not throw - exceptions depends on the requirement that the deleted array's objects' - destructors do not throw exceptions. See the smart pointer - common requirements.

    +

    + Deletes the array pointed to by the stored pointer and then stores a copy of p, + which must have been allocated via a C++ new[] expression or be 0. The + guarantee that this does not throw exceptions depends on the requirement that + the deleted array's objects' destructors do not throw exceptions. See the smart + pointer common requirements.

    subscripting

    T & operator[](std::ptrdiff_t i) const; // never throws

    Returns a reference to element i of the array pointed to by the stored @@ -88,11 +88,11 @@

    get

    T * get() const; // never throws

    Returns the stored pointer. T need not be a complete type. See the smart - pointer common requirements.

    + pointer common requirements.

    swap

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

    Exchanges the contents of the two smart pointers. T need not be a - complete type. See the smart pointer common + complete type. See the smart pointer common requirements.

    Free Functions

    swap

    diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 53815c7..148cd42 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -29,7 +29,7 @@ allocated array. See scoped_array for that usage.

    The class template is parameterized on T, the type of the object pointed - to. T must meet the smart pointer + to. T must meet the smart pointer common requirements.

    Synopsis

    namespace boost {
    @@ -62,7 +62,7 @@
     		
    explicit scoped_ptr(T * p = 0); // never throws

    Constructs a scoped_ptr, storing a copy of p, which must have been allocated via a C++ new expression or be 0. T is not required be - a complete type. See the smart pointer common + a complete type. See the smart pointer common requirements.

    destructor

    ~scoped_ptr(); // never throws
    @@ -71,15 +71,15 @@

    The guarantee that this does not throw exceptions depends on the requirement that the deleted object's destructor does not throw exceptions. See the smart - pointer common requirements.

    + pointer common requirements.

    reset

    void reset(T * p = 0); // never throws
    -

    If p is not equal to the stored pointer, deletes the object pointed to by the - stored pointer and then stores a copy of p, which must have been allocated via - a C++ new expression or be 0. The guarantee that this does not throw - exceptions depends on the requirement that the deleted object's destructor does - not throw exceptions. See the smart pointer - common requirements.

    +

    + Deletes the object pointed to by the stored pointer and then stores a copy of + p, which must have been allocated via a C++ new expression or be 0. The + guarantee that this does not throw exceptions depends on the requirement that + the deleted object's destructor does not throw exceptions. See the smart + pointer common requirements.

    indirection

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

    Returns a reference to the object pointed to by the stored pointer. Behavior is @@ -89,11 +89,11 @@

    get

    T * get() const; // never throws

    Returns the stored pointer. T need not be a complete type. See the smart - pointer common requirements.

    + pointer common requirements.

    swap

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

    Exchanges the contents of the two smart pointers. T need not be a - complete type. See the smart pointer common + complete type. See the smart pointer common requirements.

    Free Functions

    swap

    diff --git a/smart_ptr.htm b/smart_ptr.htm index 9e5357a..ac8a96f 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -56,7 +56,7 @@ versions of the smart pointer implementation.

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

    -

    Common Requirements

    +

    Common Requirements

    These smart pointer class templates have a template parameter, T, which specifies the type of the object pointed to by the smart pointer. The behavior of the smart pointer templates is undefined if the destructor or operator delete @@ -87,7 +87,7 @@ which resulted in the exception being thrown. This amounts to a guarantee that there are no detectable side effects. Other functions never throw exceptions. The only exception ever thrown by functions which do throw (assuming T meets - the common requirements) is std::bad_alloc, + the common requirements) is std::bad_alloc, and that is thrown only by functions which are explicitly documented as possibly throwing std::bad_alloc.

    Exception-specifications

    @@ -99,7 +99,7 @@ // never throws
    .

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

    + throwing exceptions by the common requirements.

    History and Acknowledgements

    January 2002. Peter Dimov reworked all four classes, adding features, fixing bugs, and splitting them into four separate headers, and added weak_ptr. @@ -156,7 +156,7 @@ users", and in the end we choose to supply only the direct implementation.


    Revised +--> 4 February 2002

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. From 8283ec826ba18d4300892cec4c6d3b1e8883f285 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 21 Nov 2002 13:14:04 +0000 Subject: [PATCH 154/513] Changed debug hook names, reverted weak_ptr() to have use_count of zero. [SVN r16362] --- include/boost/detail/shared_count.hpp | 35 ++++++++++++++++----------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 46d0828..9c7e77f 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -40,12 +40,12 @@ namespace boost // Debug hooks -#if defined(BOOST_ENABLE_SHARED_PTR_DEBUG_HOOKS) +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) -void shared_ptr_scalar_constructor_hook(void * p); -void shared_ptr_array_constructor_hook(void * p); -void shared_ptr_scalar_destructor_hook(void * p); -void shared_ptr_array_destructor_hook(void * p); +void sp_scalar_constructor_hook(void * p); +void sp_array_constructor_hook(void * p); +void sp_scalar_destructor_hook(void * p); +void sp_array_destructor_hook(void * p); #endif @@ -183,16 +183,16 @@ private: #endif }; -#if defined(BOOST_ENABLE_SHARED_PTR_DEBUG_HOOKS) +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) template void cbi_call_constructor_hook(T * p, checked_deleter const &, int) { - boost::shared_ptr_scalar_constructor_hook(p); + boost::sp_scalar_constructor_hook(p); } template void cbi_call_constructor_hook(T * p, checked_array_deleter const &, int) { - boost::shared_ptr_array_constructor_hook(p); + boost::sp_array_constructor_hook(p); } template void cbi_call_constructor_hook(P const &, D const &, long) @@ -201,12 +201,12 @@ template void cbi_call_constructor_hook(P const &, D const &, template void cbi_call_destructor_hook(T * p, checked_deleter const &, int) { - boost::shared_ptr_scalar_destructor_hook(p); + boost::sp_scalar_destructor_hook(p); } template void cbi_call_destructor_hook(T * p, checked_array_deleter const &, int) { - boost::shared_ptr_array_destructor_hook(p); + boost::sp_array_destructor_hook(p); } template void cbi_call_destructor_hook(P const &, D const &, long) @@ -240,14 +240,14 @@ public: counted_base_impl(P p, D d): ptr(p), del(d) { -#if defined(BOOST_ENABLE_SHARED_PTR_DEBUG_HOOKS) +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) detail::cbi_call_constructor_hook(p, d, 0); #endif } virtual void dispose() // nothrow { -#if defined(BOOST_ENABLE_SHARED_PTR_DEBUG_HOOKS) +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) detail::cbi_call_destructor_hook(ptr, del, 0); #endif del(ptr); @@ -436,7 +436,7 @@ public: long use_count() const // nothrow { - return pi_ != 0? pi_->use_count(): 804; // '804' is an example of 'unspecified' + return pi_ != 0? pi_->use_count(): 0; } friend inline bool operator==(weak_count const & a, weak_count const & b) @@ -452,7 +452,14 @@ public: inline shared_count::shared_count(weak_count const & r): pi_(r.pi_) { - if(pi_ != 0) pi_->add_ref(); + if(pi_ != 0) + { + pi_->add_ref(); + } + else + { + boost::throw_exception(boost::bad_weak_ptr()); + } } } // namespace detail From 2e53e2e5d7f018eb7dc2037e5654266def864d76 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 21 Nov 2002 13:20:46 +0000 Subject: [PATCH 155/513] More tests added. [SVN r16363] --- shared_ptr_test.cpp | 446 +++++++++++++++++++++++++++++--------------- 1 file changed, 295 insertions(+), 151 deletions(-) diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 42e4782..87553d5 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -356,10 +356,10 @@ void deleter2(int * p) struct deleter3 { - void operator()(incomplete * p) - { - BOOST_TEST(p == 0); - } + void operator()(incomplete * p) + { + BOOST_TEST(p == 0); + } }; // Borland C++ 5.5.1 fails on static_cast(0) @@ -706,8 +706,29 @@ void copy_constructor() void weak_ptr_constructor() { - boost::shared_ptr p(new Y); + { + boost::weak_ptr wp; + try + { + boost::shared_ptr p2(wp); + BOOST_ERROR("shared_ptr p2(wp) failed to throw"); + } + catch(boost::bad_weak_ptr) + { + } + + try + { + boost::shared_ptr p3(wp); + BOOST_ERROR("shared_ptr p3(wp) failed to throw"); + } + catch(boost::bad_weak_ptr) + { + } + } + + boost::shared_ptr p(new Y); boost::weak_ptr wp(p); { @@ -1110,323 +1131,323 @@ long Y::instances = 0; void copy_assignment() { - { - boost::shared_ptr p1; + { + boost::shared_ptr p1; - p1 = p1; + p1 = p1; BOOST_TEST(p1 == p1); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - boost::shared_ptr p2; + boost::shared_ptr p2; - p1 = p2; + p1 = p2; BOOST_TEST(p1 == p2); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - boost::shared_ptr p3(p1); + boost::shared_ptr p3(p1); - p1 = p3; + p1 = p3; BOOST_TEST(p1 == p3); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - } + } - { - boost::shared_ptr p1; + { + boost::shared_ptr p1; - p1 = p1; + p1 = p1; BOOST_TEST(p1 == p1); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - boost::shared_ptr p2; + boost::shared_ptr p2; - p1 = p2; + p1 = p2; BOOST_TEST(p1 == p2); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - boost::shared_ptr p3(p1); + boost::shared_ptr p3(p1); - p1 = p3; + p1 = p3; BOOST_TEST(p1 == p3); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - boost::shared_ptr p4(new int); - BOOST_TEST(p4.use_count() == 1); + boost::shared_ptr p4(new int); + BOOST_TEST(p4.use_count() == 1); - p1 = p4; + p1 = p4; BOOST_TEST(p1 == p4); BOOST_TEST(!(p1 < p4 || p4 < p1)); - BOOST_TEST(p1.use_count() == 2); - BOOST_TEST(p4.use_count() == 2); + BOOST_TEST(p1.use_count() == 2); + BOOST_TEST(p4.use_count() == 2); - p1 = p3; + p1 = p3; BOOST_TEST(p1 == p3); - BOOST_TEST(p4.use_count() == 1); - } + BOOST_TEST(p4.use_count() == 1); + } - { - boost::shared_ptr p1; + { + boost::shared_ptr p1; - p1 = p1; + p1 = p1; BOOST_TEST(p1 == p1); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - boost::shared_ptr p2; + boost::shared_ptr p2; - p1 = p2; + p1 = p2; BOOST_TEST(p1 == p2); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - boost::shared_ptr p3(p1); + boost::shared_ptr p3(p1); - p1 = p3; + p1 = p3; BOOST_TEST(p1 == p3); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - BOOST_TEST(X::instances == 0); + BOOST_TEST(X::instances == 0); - boost::shared_ptr p4(new X); + boost::shared_ptr p4(new X); - BOOST_TEST(X::instances == 1); + BOOST_TEST(X::instances == 1); - p1 = p4; + p1 = p4; - BOOST_TEST(X::instances == 1); + BOOST_TEST(X::instances == 1); BOOST_TEST(p1 == p4); BOOST_TEST(!(p1 < p4 || p4 < p1)); - BOOST_TEST(p1.use_count() == 2); + BOOST_TEST(p1.use_count() == 2); - p1 = p2; + p1 = p2; BOOST_TEST(p1 == p2); - BOOST_TEST(X::instances == 1); + BOOST_TEST(X::instances == 1); - p4 = p3; + p4 = p3; BOOST_TEST(p4 == p3); - BOOST_TEST(X::instances == 0); - } + BOOST_TEST(X::instances == 0); + } } void conversion_assignment() { - { - boost::shared_ptr p1; + { + boost::shared_ptr p1; - boost::shared_ptr p2; + boost::shared_ptr p2; - p1 = p2; + p1 = p2; BOOST_TEST(p1 == p2); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - boost::shared_ptr p4(new int); - BOOST_TEST(p4.use_count() == 1); + boost::shared_ptr p4(new int); + BOOST_TEST(p4.use_count() == 1); - boost::shared_ptr p5(p4); - BOOST_TEST(p4.use_count() == 2); + boost::shared_ptr p5(p4); + BOOST_TEST(p4.use_count() == 2); - p1 = p4; + p1 = p4; BOOST_TEST(p1 == p4); BOOST_TEST(!(p1 < p5 || p5 < p1)); - BOOST_TEST(p1.use_count() == 3); - BOOST_TEST(p4.use_count() == 3); + BOOST_TEST(p1.use_count() == 3); + BOOST_TEST(p4.use_count() == 3); - p1 = p2; + p1 = p2; BOOST_TEST(p1 == p2); - BOOST_TEST(p4.use_count() == 2); - } + BOOST_TEST(p4.use_count() == 2); + } - { - boost::shared_ptr p1; + { + boost::shared_ptr p1; - boost::shared_ptr p2; + boost::shared_ptr p2; - p1 = p2; + p1 = p2; BOOST_TEST(p1 == p2); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - BOOST_TEST(X::instances == 0); - BOOST_TEST(Y::instances == 0); + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); - boost::shared_ptr p4(new Y); + boost::shared_ptr p4(new Y); - BOOST_TEST(X::instances == 1); - BOOST_TEST(Y::instances == 1); - BOOST_TEST(p4.use_count() == 1); + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); + BOOST_TEST(p4.use_count() == 1); - boost::shared_ptr p5(p4); - BOOST_TEST(p4.use_count() == 2); + boost::shared_ptr p5(p4); + BOOST_TEST(p4.use_count() == 2); - p1 = p4; + p1 = p4; - BOOST_TEST(X::instances == 1); - BOOST_TEST(Y::instances == 1); + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); BOOST_TEST(p1 == p4); BOOST_TEST(!(p1 < p5 || p5 < p1)); - BOOST_TEST(p1.use_count() == 3); - BOOST_TEST(p4.use_count() == 3); + BOOST_TEST(p1.use_count() == 3); + BOOST_TEST(p4.use_count() == 3); - p1 = p2; + p1 = p2; BOOST_TEST(p1 == p2); - BOOST_TEST(X::instances == 1); - BOOST_TEST(Y::instances == 1); - BOOST_TEST(p4.use_count() == 2); + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); + BOOST_TEST(p4.use_count() == 2); - p4 = p2; - p5 = p2; + p4 = p2; + p5 = p2; BOOST_TEST(p4 == p2); - BOOST_TEST(X::instances == 0); - BOOST_TEST(Y::instances == 0); - } + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + } } void auto_ptr_assignment() { - { - boost::shared_ptr p1; + { + boost::shared_ptr p1; - std::auto_ptr p2; + std::auto_ptr p2; - p1 = p2; + p1 = p2; BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - BOOST_TEST(p1.use_count() == 1); + BOOST_TEST(p1.use_count() == 1); - int * p = new int; - std::auto_ptr p3(p); + int * p = new int; + std::auto_ptr p3(p); - p1 = p3; - BOOST_TEST(p1.get() == p); - BOOST_TEST(p1.use_count() == 1); + p1 = p3; + BOOST_TEST(p1.get() == p); + BOOST_TEST(p1.use_count() == 1); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p3.get() == 0); #endif - p1 = p2; + p1 = p2; BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - BOOST_TEST(p1.use_count() == 1); - } + BOOST_TEST(p1.use_count() == 1); + } - { - boost::shared_ptr p1; + { + boost::shared_ptr p1; - std::auto_ptr p2; + std::auto_ptr p2; - p1 = p2; + p1 = p2; BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - BOOST_TEST(p1.use_count() == 1); + BOOST_TEST(p1.use_count() == 1); - int * p = new int; - std::auto_ptr p3(p); + int * p = new int; + std::auto_ptr p3(p); - p1 = p3; - BOOST_TEST(p1.get() == p); - BOOST_TEST(p1.use_count() == 1); + p1 = p3; + BOOST_TEST(p1.get() == p); + BOOST_TEST(p1.use_count() == 1); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p3.get() == 0); #endif - p1 = p2; + p1 = p2; BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - BOOST_TEST(p1.use_count() == 1); - } + BOOST_TEST(p1.use_count() == 1); + } - { - boost::shared_ptr p1; + { + boost::shared_ptr p1; - std::auto_ptr p2; + std::auto_ptr p2; - p1 = p2; + p1 = p2; BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - BOOST_TEST(p1.use_count() == 1); - BOOST_TEST(X::instances == 0); - BOOST_TEST(Y::instances == 0); + BOOST_TEST(p1.use_count() == 1); + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); - Y * p = new Y; - std::auto_ptr p3(p); + Y * p = new Y; + std::auto_ptr p3(p); - BOOST_TEST(X::instances == 1); - BOOST_TEST(Y::instances == 1); + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); - p1 = p3; - BOOST_TEST(p1.get() == p); - BOOST_TEST(p1.use_count() == 1); - BOOST_TEST(X::instances == 1); - BOOST_TEST(Y::instances == 1); + p1 = p3; + BOOST_TEST(p1.get() == p); + BOOST_TEST(p1.use_count() == 1); + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p3.get() == 0); #endif - p1 = p2; + p1 = p2; BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); - BOOST_TEST(p1.use_count() == 1); - BOOST_TEST(X::instances == 0); - BOOST_TEST(Y::instances == 0); - } + BOOST_TEST(p1.use_count() == 1); + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + } } void test() { - copy_assignment(); - conversion_assignment(); - auto_ptr_assignment(); + copy_assignment(); + conversion_assignment(); + auto_ptr_assignment(); } } // namespace n_assignment @@ -1448,9 +1469,9 @@ void deleter_reset() void test() { - plain_reset(); - pointer_reset(); - deleter_reset(); + plain_reset(); + pointer_reset(); + deleter_reset(); } } // namespace n_reset @@ -1690,7 +1711,7 @@ void test() BOOST_TEST(!(px != px)); BOOST_TEST(!(px < px)); - boost::shared_ptr px2; + boost::shared_ptr px2; BOOST_TEST(px.get() == px2.get()); BOOST_TEST(px == px2); @@ -1702,7 +1723,7 @@ void test() boost::shared_ptr px; boost::shared_ptr px2(px); - BOOST_TEST(px2 == px2); + BOOST_TEST(px2 == px2); BOOST_TEST(!(px2 != px2)); BOOST_TEST(!(px2 < px2)); @@ -1716,7 +1737,7 @@ void test() boost::shared_ptr px; boost::shared_ptr px2(new X); - BOOST_TEST(px2 == px2); + BOOST_TEST(px2 == px2); BOOST_TEST(!(px2 != px2)); BOOST_TEST(!(px2 < px2)); @@ -1742,7 +1763,7 @@ void test() boost::shared_ptr px(new X); boost::shared_ptr px2(px); - BOOST_TEST(px2 == px2); + BOOST_TEST(px2 == px2); BOOST_TEST(!(px2 != px2)); BOOST_TEST(!(px2 < px2)); @@ -1767,7 +1788,7 @@ void test() boost::shared_ptr pvx(px); - BOOST_TEST(pvx == pvx); + BOOST_TEST(pvx == pvx); BOOST_TEST(!(pvx != pvx)); BOOST_TEST(!(pvx < pvx)); @@ -1778,16 +1799,16 @@ void test() BOOST_TEST(pvx < pvz || pvz < pvx); BOOST_TEST(pvy < pvz || pvz < pvy); - BOOST_TEST(!(pvx < pvy && pvy < pvx)); - BOOST_TEST(!(pvx < pvz && pvz < pvx)); - BOOST_TEST(!(pvy < pvz && pvz < pvy)); + BOOST_TEST(!(pvx < pvy && pvy < pvx)); + BOOST_TEST(!(pvx < pvz && pvz < pvx)); + BOOST_TEST(!(pvy < pvz && pvz < pvy)); } { boost::shared_ptr pz(new Z); boost::shared_ptr px(pz); - BOOST_TEST(px == px); + BOOST_TEST(px == px); BOOST_TEST(!(px != px)); BOOST_TEST(!(px < px)); @@ -2602,9 +2623,9 @@ class X { public: - X() - { - } + X() + { + } private: @@ -2639,8 +2660,131 @@ void test() namespace n_spt_another_sp { +template class another_ptr: private boost::shared_ptr +{ +private: + + typedef boost::shared_ptr base_type; + +public: + + explicit another_ptr(T * p = 0): base_type(p) + { + } + + void reset() + { + base_type::reset(); + } + + T * get() const + { + return base_type::get(); + } +}; + +class event_handler +{ +public: + + virtual ~event_handler() {} + virtual void begin() = 0; + virtual void handle(int event) = 0; + virtual void end() = 0; +}; + +int begin_called = 0; +int handle_called = 0; +int end_called = 0; + +class event_handler_impl: public event_handler +{ +public: + + virtual void begin() + { + ++begin_called; + } + + virtual void handle(int event) + { + handle_called = event; + } + + virtual void end() + { + ++end_called; + } +}; + +another_ptr get_event_handler() +{ + another_ptr p(new event_handler_impl); + return p; +} + +boost::shared_ptr current_handler; + +void install_event_handler(boost::shared_ptr p) +{ + p->begin(); + current_handler = p; +} + +void handle_event(int event) +{ + current_handler->handle(event); +} + +void remove_event_handler() +{ + current_handler->end(); + current_handler.reset(); +} + +template class smart_pointer_deleter +{ +private: + + P p_; + +public: + + smart_pointer_deleter(P const & p): p_(p) + { + } + + void operator()(void const *) + { + p_.reset(); + } +}; + void test() { + another_ptr p = get_event_handler(); + + boost::shared_ptr q(p.get(), smart_pointer_deleter< another_ptr >(p)); + + p.reset(); + + BOOST_TEST(begin_called == 0); + + install_event_handler(q); + + BOOST_TEST(begin_called == 1); + + BOOST_TEST(handle_called == 0); + + handle_event(17041); + + BOOST_TEST(handle_called == 17041); + + BOOST_TEST(end_called == 0); + + remove_event_handler(); + + BOOST_TEST(end_called == 1); } } // namespace n_spt_another_sp From c697e2ef21c97e5179945cb8d85a55e30c3216ef Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 21 Nov 2002 13:23:15 +0000 Subject: [PATCH 156/513] Sample implementation of the smart pointer debug hooks. [SVN r16364] --- sp_debug_hooks.cpp | 228 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 sp_debug_hooks.cpp diff --git a/sp_debug_hooks.cpp b/sp_debug_hooks.cpp new file mode 100644 index 0000000..741ea3a --- /dev/null +++ b/sp_debug_hooks.cpp @@ -0,0 +1,228 @@ +// +// sp_debug_hooks.cpp +// +// Copyright (c) 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// http://www.boost.org/libs/smart_ptr/debug_hooks.html +// + +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + +#include +#include +#include + +int const m = 2; // m * sizeof(int) must be aligned appropriately + +int const allocated_scalar = 0x1234560C; +int const allocated_array = 0x1234560A; +int const adopted_scalar = 0x0567890C; +int const adopted_array = 0x0567890A; +int const deleted = 0x498769DE; + +using namespace std; // for compilers where things aren't in std + +static new_handler get_new_handler() +{ + new_handler p = set_new_handler(0); + set_new_handler(p); + return p; +} + +static void * allocate(size_t n, int mark) +{ + int * pm; + + for(;;) + { + pm = static_cast(malloc(n + m * sizeof(int))); + + if(pm != 0) break; + + if(new_handler pnh = get_new_handler()) + { + pnh(); + } + else + { + return 0; + } + } + + *pm = mark; + + return pm + m; +} + +void * operator new(size_t n) throw(bad_alloc) +{ + void * p = allocate(n, allocated_scalar); + +#if !defined(BOOST_NO_EXCEPTIONS) + + if(p == 0) throw bad_alloc(); + +#endif + + return p; +} + +#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551) + +void * operator new(size_t n, nothrow_t const &) throw() +{ + return allocate(n, allocated_scalar); +} + +#endif + +void * operator new[](size_t n) throw(bad_alloc) +{ + void * p = allocate(n, allocated_array); + +#if !defined(BOOST_NO_EXCEPTIONS) + + if(p == 0) throw bad_alloc(); + +#endif + + return p; +} + +#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551) + +void * operator new[](size_t n, nothrow_t const &) throw() +{ + return allocate(n, allocated_array); +} + +#endif + +namespace boost +{ + +void sp_scalar_constructor_hook(void * p) +{ + if(p == 0) return; + + int * pm = static_cast(p); + pm -= m; + + BOOST_ASSERT(*pm != adopted_scalar); // second smart pointer to the same address + BOOST_ASSERT(*pm != allocated_array); // allocated with new[] + BOOST_ASSERT(*pm == allocated_scalar); // not allocated with new + + *pm = adopted_scalar; +} + +void sp_scalar_destructor_hook(void * p) +{ + if(p == 0) return; + + int * pm = static_cast(p); + pm -= m; + + BOOST_ASSERT(*pm == adopted_scalar); // attempt to destroy nonmanaged block + + *pm = allocated_scalar; +} + +// It is not possible to handle the array hooks in a portable manner. +// The implementation typically reserves a bit of storage for the number +// of objects in the array, and the argument of the array hook isn't +// equal to the return value of operator new[]. + +void sp_array_constructor_hook(void * /* p */) +{ +/* + if(p == 0) return; + + // adjust p depending on the implementation + + int * pm = static_cast(p); + pm -= m; + + BOOST_ASSERT(*pm != adopted_array); // second smart array pointer to the same address + BOOST_ASSERT(*pm != allocated_scalar); // allocated with new + BOOST_ASSERT(*pm == allocated_array); // not allocated with new[] + + *pm = adopted_array; +*/ +} + +void sp_array_destructor_hook(void * /* p */) +{ +/* + if(p == 0) return; + + // adjust p depending on the implementation + + int * pm = static_cast(p); + pm -= m; + + BOOST_ASSERT(*pm == adopted_array); // attempt to destroy nonmanaged block + + *pm = allocated_array; +*/ +} + +} // namespace boost + +void operator delete(void * p) throw() +{ + if(p == 0) return; + + int * pm = static_cast(p); + pm -= m; + + BOOST_ASSERT(*pm != deleted); // double delete + BOOST_ASSERT(*pm != adopted_scalar); // delete p.get(); + BOOST_ASSERT(*pm != allocated_array); // allocated with new[] + BOOST_ASSERT(*pm == allocated_scalar); // not allocated with new + + *pm = deleted; + + free(pm); +} + +#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551) + +void operator delete(void * p, nothrow_t const &) throw() +{ + ::operator delete(p); +} + +#endif + +void operator delete[](void * p) throw() +{ + if(p == 0) return; + + int * pm = static_cast(p); + pm -= m; + + BOOST_ASSERT(*pm != deleted); // double delete + BOOST_ASSERT(*pm != adopted_scalar); // delete p.get(); + BOOST_ASSERT(*pm != allocated_scalar); // allocated with new + BOOST_ASSERT(*pm == allocated_array); // not allocated with new[] + + *pm = deleted; + + free(pm); +} + +#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551) + +void operator delete[](void * p, nothrow_t const &) throw() +{ + ::operator delete[](p); +} + +#endif + +#endif // defined(BOOST_ENABLE_SP_DEBUG_HOOKS) From 66a8e8b3c1125660fea0e057f23feb0fb3eb09e0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 21 Nov 2002 14:46:45 +0000 Subject: [PATCH 157/513] get_deleter<> added. [SVN r16365] --- include/boost/detail/shared_count.hpp | 13 +++++++++++++ include/boost/shared_ptr.hpp | 12 ++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 9c7e77f..a7eb08c 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -29,6 +29,7 @@ #include // for std::less #include // for std::exception #include // for std::bad_alloc +#include // for std::type_info in get_deleter #ifdef __BORLANDC__ # pragma warn -8026 // Functions with excep. spec. are not expanded inline @@ -106,6 +107,8 @@ public: delete this; } + virtual void * get_deleter(std::type_info const & ti) = 0; + void add_ref() { #if defined(BOOST_HAS_THREADS) @@ -253,6 +256,11 @@ public: del(ptr); } + virtual void * get_deleter(std::type_info const & ti) + { + return ti == typeid(D)? &del: 0; + } + #if defined(BOOST_SP_USE_STD_ALLOCATOR) void * operator new(std::size_t) @@ -371,6 +379,11 @@ public: { return std::less()(a.pi_, b.pi_); } + + void * get_deleter(std::type_info const & ti) const + { + return pi_->get_deleter(ti); + } }; #ifdef __CODEGUARD__ diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index fedfdd8..cbd9fd3 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -275,6 +275,11 @@ public: return pn < rhs.pn; } + void * _internal_get_deleter(std::type_info const & ti) const + { + return pn.get_deleter(ti); + } + // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) @@ -364,6 +369,13 @@ template inline T * get_pointer(shared_ptr const & p) return p.get(); } +// get_deleter (experimental) + +template D * get_deleter(shared_ptr const & p) +{ + return static_cast(p._internal_get_deleter(typeid(D))); +} + } // namespace boost #ifdef BOOST_MSVC From 8d6517484cd542cc4c634a8d533557b843f37a47 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 22 Nov 2002 13:49:54 +0000 Subject: [PATCH 158/513] Stricter tests; associated bug fixes. ;-) [SVN r16369] --- include/boost/shared_ptr.hpp | 6 ++++-- include/boost/weak_ptr.hpp | 7 ++++++- shared_ptr_test.cpp | 9 ++++++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index cbd9fd3..5a9a44b 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -140,8 +140,10 @@ public: #endif template - explicit shared_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // may throw + explicit shared_ptr(weak_ptr const & r): pn(r.pn) // may throw { + // it is now safe to copy r.px, as pn(r.pn) did not throw + px = r.px; } template @@ -166,7 +168,7 @@ public: template shared_ptr(shared_ptr const & r, detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) { - if (px == 0) + if(px == 0) { boost::throw_exception(std::bad_cast()); } diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index a4154ea..d08fa5d 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -16,6 +16,8 @@ #include +#include // for std::memcpy + #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash # pragma warning(push) # pragma warning(disable:4284) // odd return type for operator-> @@ -42,8 +44,11 @@ public: // generated copy constructor, assignment, destructor are fine template - weak_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // never throws + weak_ptr(weak_ptr const & r): pn(r.pn) // never throws { + // r.px may be an invalid pointer value + using namespace std; + memcpy(&this->px, &r.px, sizeof(r.px)); } template diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 87553d5..cbaaeed 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -99,7 +99,9 @@ private: long X::instances = 0; -struct Y: public A, public X +// virtual inheritance stresses the implementation + +struct Y: public A, public virtual X { static long instances; @@ -771,6 +773,11 @@ void weak_ptr_constructor() catch(boost::bad_weak_ptr) { } + + { + boost::weak_ptr wp2(wp); + boost::weak_ptr wp3(wp); + } } void auto_ptr_constructor() From ea285b42314abf9c3dbba3f1109ff28ca9769582 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 22 Nov 2002 14:41:22 +0000 Subject: [PATCH 159/513] Fixed the previous weak_ptr 'fix'. [SVN r16370] --- include/boost/weak_ptr.hpp | 47 ++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index d08fa5d..cce5cb8 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -16,8 +16,6 @@ #include -#include // for std::memcpy - #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash # pragma warning(push) # pragma warning(disable:4284) // odd return type for operator-> @@ -26,6 +24,8 @@ namespace boost { +template shared_ptr make_shared(weak_ptr const & r); // never throws + template class weak_ptr { private: @@ -43,12 +43,39 @@ public: // generated copy constructor, assignment, destructor are fine + +// +// The simple implementation of the converting constructor: +// +// template +// weak_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // never throws +// { +// } +// +// has a serious problem. +// +// r.px may already have been invalidated. The px(r.px) +// conversion may require access to *r.px (virtual inheritance). +// +// It is not possible to avoid spurious access violations since +// in multithreaded programs r.px may be invalidated at any point. +// +// A safe conversion between weak_ptr and weak_ptr must involve +// a temporary shared_ptr. +// +// It is not yet clear whether the converting constructor should be +// present at all, or it's better to require an explicit make_shared call. +// +// The only case for the converting constructor is the weak_ptr -> weak_ptr +// conversion. +// + template - weak_ptr(weak_ptr const & r): pn(r.pn) // never throws + weak_ptr(weak_ptr const & r) // never throws { - // r.px may be an invalid pointer value - using namespace std; - memcpy(&this->px, &r.px, sizeof(r.px)); + shared_ptr tmp = make_shared(r); + px = tmp.px; + pn = tmp.pn; } template @@ -58,14 +85,6 @@ public: #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) - template - weak_ptr & operator=(weak_ptr const & r) // never throws - { - px = r.px; - pn = r.pn; - return *this; - } - template weak_ptr & operator=(shared_ptr const & r) // never throws { From fadc0716ce67b569056488d84b98ddc423e8251d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 22 Nov 2002 16:29:51 +0000 Subject: [PATCH 160/513] get_deleter_test added; associated fixes. [SVN r16373] --- get_deleter_test.cpp | 81 ++++++++++++++++++++++++++++++++++++ include/boost/shared_ptr.hpp | 14 +++++++ 2 files changed, 95 insertions(+) create mode 100644 get_deleter_test.cpp diff --git a/get_deleter_test.cpp b/get_deleter_test.cpp new file mode 100644 index 0000000..2b84a2d --- /dev/null +++ b/get_deleter_test.cpp @@ -0,0 +1,81 @@ +// +// get_deleter_test.cpp +// +// Copyright (c) 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include +#include + +struct deleter +{ + int data; + + deleter(): data(0) + { + } + + void operator()(void *) + { + BOOST_TEST(data == 17041); + } +}; + +struct deleter2 +{ +}; + +struct X +{ +}; + +int main() +{ + { + boost::shared_ptr p(new X); + + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + } + + { + X x; + boost::shared_ptr p(&x, deleter()); + + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + + deleter * q = boost::get_deleter(p); + + BOOST_TEST(q != 0); + BOOST_TEST(q->data == 0); + + q->data = 17041; + + deleter const * r = boost::get_deleter(p); + + BOOST_TEST(r == q); + BOOST_TEST(r->data == 17041); + } + + return boost::report_errors(); +} diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 5a9a44b..07ca043 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -373,11 +373,25 @@ template inline T * get_pointer(shared_ptr const & p) // get_deleter (experimental) +#if defined(__GNUC__) && (__GNUC__ < 3) + +// g++ 2.9x doesn't allow static_cast(void *) + +template D * get_deleter(shared_ptr const & p) +{ + void const * q = p._internal_get_deleter(typeid(D)); + return const_cast(static_cast(q)); +} + +#else + template D * get_deleter(shared_ptr const & p) { return static_cast(p._internal_get_deleter(typeid(D))); } +#endif + } // namespace boost #ifdef BOOST_MSVC From 5dd2c621327b68b5412e17fa49a932ff8f5690de Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 23 Nov 2002 12:47:38 +0000 Subject: [PATCH 161/513] weak_ptr converting constructor removed; operator< can now take different types to aid ownership tests. [SVN r16376] --- include/boost/shared_ptr.hpp | 4 ++-- include/boost/weak_ptr.hpp | 25 ++++++------------------- shared_ptr_test.cpp | 12 +++--------- 3 files changed, 11 insertions(+), 30 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 07ca043..6ffca27 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -272,7 +272,7 @@ public: pn.swap(other.pn); } - bool _internal_less(this_type const & rhs) const // implementation detail, never throws + template bool _internal_less(shared_ptr const & rhs) const { return pn < rhs.pn; } @@ -321,7 +321,7 @@ template inline bool operator!=(shared_ptr const & a, shared_ptr #endif -template inline bool operator<(shared_ptr const & a, shared_ptr const & b) +template inline bool operator<(shared_ptr const & a, shared_ptr const & b) { return a._internal_less(b); } diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index cce5cb8..03e3800 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -45,7 +45,7 @@ public: // -// The simple implementation of the converting constructor: +// The "obvious" converting constructor implementation: // // template // weak_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // never throws @@ -60,23 +60,10 @@ public: // It is not possible to avoid spurious access violations since // in multithreaded programs r.px may be invalidated at any point. // -// A safe conversion between weak_ptr and weak_ptr must involve -// a temporary shared_ptr. +// A weak_ptr can safely be obtained from a weak_ptr by using // -// It is not yet clear whether the converting constructor should be -// present at all, or it's better to require an explicit make_shared call. +// weak_ptr wpt = make_shared(wpu); // -// The only case for the converting constructor is the weak_ptr -> weak_ptr -// conversion. -// - - template - weak_ptr(weak_ptr const & r) // never throws - { - shared_ptr tmp = make_shared(r); - px = tmp.px; - pn = tmp.pn; - } template weak_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws @@ -116,13 +103,13 @@ public: pn.swap(other.pn); } - void _internal_assign(T * px2, detail::shared_count const & pn2) // implementation detail + void _internal_assign(T * px2, detail::shared_count const & pn2) { px = px2; pn = pn2; } - bool _internal_less(this_type const & rhs) const // implementation detail, never throws + template bool _internal_less(weak_ptr const & rhs) const { return pn < rhs.pn; } @@ -144,7 +131,7 @@ private: }; // weak_ptr -template inline bool operator<(weak_ptr const & a, weak_ptr const & b) +template inline bool operator<(weak_ptr const & a, weak_ptr const & b) { return a._internal_less(b); } diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index cbaaeed..99ba2de 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -773,11 +773,6 @@ void weak_ptr_constructor() catch(boost::bad_weak_ptr) { } - - { - boost::weak_ptr wp2(wp); - boost::weak_ptr wp3(wp); - } } void auto_ptr_constructor() @@ -2256,13 +2251,13 @@ template void test_ne(T const & a, T const & b) BOOST_TEST(!(a < b && b < a)); } -void test_shared(boost::weak_ptr const & a, boost::weak_ptr const & b) +template void test_shared(boost::weak_ptr const & a, boost::weak_ptr const & b) { BOOST_TEST(!(a < b)); BOOST_TEST(!(b < a)); } -void test_nonshared(boost::weak_ptr const & a, boost::weak_ptr const & b) +template void test_nonshared(boost::weak_ptr const & a, boost::weak_ptr const & b) { BOOST_TEST(a < b || b < a); BOOST_TEST(!(a < b && b < a)); @@ -2381,7 +2376,7 @@ void test() BOOST_TEST(wp3.use_count() == 1); test_shared(wp2, wp3); - weak_ptr wp4(wp3); + weak_ptr wp4 = boost::make_shared(wp3); BOOST_TEST(wp4.use_count() == 1); test_shared(wp2, wp4); @@ -2390,7 +2385,6 @@ void test() test_is_zero(boost::make_shared(wp1)); wp1 = p4; - wp1 = wp3; wp1 = wp2; BOOST_TEST(wp1.use_count() == 1); From 0aaca2fffe648f0b916263eb4c9fbe68a4931949 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 23 Nov 2002 12:59:01 +0000 Subject: [PATCH 162/513] More operator< tests. [SVN r16377] --- shared_ptr_test.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 99ba2de..01f8920 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -1701,7 +1701,7 @@ struct Y int dummy2; }; -struct Z: public X, public Y +struct Z: public X, public virtual Y { }; @@ -1788,6 +1788,14 @@ void test() BOOST_TEST(py != pz); BOOST_TEST(!(py == pz)); + BOOST_TEST(px < py || py < px); + BOOST_TEST(px < pz || pz < px); + BOOST_TEST(py < pz || pz < py); + + BOOST_TEST(!(px < py && py < px)); + BOOST_TEST(!(px < pz && pz < px)); + BOOST_TEST(!(py < pz && pz < py)); + boost::shared_ptr pvx(px); BOOST_TEST(pvx == pvx); @@ -1824,6 +1832,10 @@ void test() BOOST_TEST(py == pz); BOOST_TEST(!(py != pz)); + BOOST_TEST(!(px < py || py < px)); + BOOST_TEST(!(px < pz || pz < px)); + BOOST_TEST(!(py < pz || pz < py)); + boost::shared_ptr pvx(px); boost::shared_ptr pvy(py); boost::shared_ptr pvz(pz); @@ -2376,7 +2388,7 @@ void test() BOOST_TEST(wp3.use_count() == 1); test_shared(wp2, wp3); - weak_ptr wp4 = boost::make_shared(wp3); + weak_ptr wp4 = boost::make_shared(wp3); BOOST_TEST(wp4.use_count() == 1); test_shared(wp2, wp4); From 1f9908be693c4bea44a5ae746ccc3705c049c33e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 23 Nov 2002 19:18:05 +0000 Subject: [PATCH 163/513] Borland C++ 5.6 still needs the workaround. [SVN r16379] --- include/boost/shared_ptr.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 6ffca27..03ea7d4 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -127,8 +127,8 @@ public: // generated copy constructor, assignment, destructor are fine... -// except on Borland C++ 5.5.1 -#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x551) +// except on Borland C++ 5.5.1 (and 5.6) +#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x560) shared_ptr & operator=(shared_ptr const & r) // never throws { From 980307a90ab496e05d61f9b81e83b3030d2a77ad Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 25 Nov 2002 12:09:13 +0000 Subject: [PATCH 164/513] Reintroduced weak_ptr converting constructor; map, ...> is important. [SVN r16400] --- include/boost/weak_ptr.hpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 03e3800..8c2a977 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -60,10 +60,12 @@ public: // It is not possible to avoid spurious access violations since // in multithreaded programs r.px may be invalidated at any point. // -// A weak_ptr can safely be obtained from a weak_ptr by using -// -// weak_ptr wpt = make_shared(wpu); -// + + template + weak_ptr(weak_ptr const & r): pn(r.pn) // never throws + { + px = boost::make_shared(r).get(); + } template weak_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws @@ -72,6 +74,14 @@ public: #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) + template + weak_ptr & operator=(weak_ptr const & r) // never throws + { + px = boost::make_shared(r).get(); + pn = r.pn; + return *this; + } + template weak_ptr & operator=(shared_ptr const & r) // never throws { From 1311731e247b8ae4629e4efdf89f458c85836093 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 25 Nov 2002 12:12:45 +0000 Subject: [PATCH 165/513] Moved the old shared_ptr tests into shared_ptr_basic_test.cpp [SVN r16401] --- shared_ptr_basic_test.cpp | 284 ++++++++++++++++++++++++++++++++++++++ shared_ptr_test.cpp | 277 +------------------------------------ 2 files changed, 286 insertions(+), 275 deletions(-) create mode 100644 shared_ptr_basic_test.cpp diff --git a/shared_ptr_basic_test.cpp b/shared_ptr_basic_test.cpp new file mode 100644 index 0000000..151af07 --- /dev/null +++ b/shared_ptr_basic_test.cpp @@ -0,0 +1,284 @@ +// +// shared_ptr_basic_test.cpp +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include + +#include +#include + +int cnt = 0; + +struct X +{ + X() + { + ++cnt; + } + + ~X() // virtual destructor deliberately omitted + { + --cnt; + } + + virtual int id() const + { + return 1; + } + +private: + + X(X const &); + X & operator= (X const &); +}; + +struct Y: public X +{ + Y() + { + ++cnt; + } + + ~Y() + { + --cnt; + } + + virtual int id() const + { + return 2; + } + +private: + + Y(Y const &); + Y & operator= (Y const &); +}; + +int * get_object() +{ + ++cnt; + return &cnt; +} + +void release_object(int * p) +{ + BOOST_TEST(p == &cnt); + --cnt; +} + +template void test_is_X(boost::shared_ptr const & p) +{ + BOOST_TEST(p->id() == 1); + BOOST_TEST((*p).id() == 1); +} + +template void test_is_X(boost::weak_ptr const & p) +{ + BOOST_TEST(p.get() != 0); + BOOST_TEST(p.get()->id() == 1); +} + +template void test_is_Y(boost::shared_ptr const & p) +{ + BOOST_TEST(p->id() == 2); + BOOST_TEST((*p).id() == 2); +} + +template void test_is_Y(boost::weak_ptr const & p) +{ + boost::shared_ptr q = boost::make_shared(p); + BOOST_TEST(q.get() != 0); + BOOST_TEST(q->id() == 2); +} + +template void test_eq(T const & a, T const & b) +{ + BOOST_TEST(a == b); + BOOST_TEST(!(a != b)); + BOOST_TEST(!(a < b)); + BOOST_TEST(!(b < a)); +} + +template void test_ne(T const & a, T const & b) +{ + BOOST_TEST(!(a == b)); + BOOST_TEST(a != b); + BOOST_TEST(a < b || b < a); + BOOST_TEST(!(a < b && b < a)); +} + +template void test_shared(boost::weak_ptr const & a, boost::weak_ptr const & b) +{ + BOOST_TEST(!(a < b)); + BOOST_TEST(!(b < a)); +} + +template void test_nonshared(boost::weak_ptr const & a, boost::weak_ptr const & b) +{ + BOOST_TEST(a < b || b < a); + BOOST_TEST(!(a < b && b < a)); +} + +template void test_eq2(T const & a, U const & b) +{ + BOOST_TEST(a == b); + BOOST_TEST(!(a != b)); +} + +template void test_ne2(T const & a, U const & b) +{ + BOOST_TEST(!(a == b)); + BOOST_TEST(a != b); +} + +template void test_is_zero(boost::shared_ptr const & p) +{ + BOOST_TEST(!p); + BOOST_TEST(p.get() == 0); +} + +template void test_is_nonzero(boost::shared_ptr const & p) +{ + // p? true: false is used to test p in a boolean context. + // BOOST_TEST(p) is not guaranteed to test the conversion, + // as the macro might test !!p instead. + BOOST_TEST(p? true: false); + BOOST_TEST(p.get() != 0); +} + +int main() +{ + using namespace boost; + + { + shared_ptr p(new Y); + shared_ptr p2(new X); + + test_is_nonzero(p); + test_is_nonzero(p2); + test_is_Y(p); + test_is_X(p2); + test_ne(p, p2); + + { + shared_ptr q(p); + test_eq(p, q); + } + + shared_ptr p3 = dynamic_pointer_cast(p); + shared_ptr p4 = dynamic_pointer_cast(p2); + + test_is_nonzero(p3); + test_is_zero(p4); + + BOOST_TEST(p.use_count() == 2); + BOOST_TEST(p2.use_count() == 1); + BOOST_TEST(p3.use_count() == 2); + + test_is_Y(p3); + test_eq2(p, p3); + test_ne2(p2, p4); + + shared_ptr p5(p); + + test_is_nonzero(p5); + test_eq2(p, p5); + + weak_ptr wp1(p2); + + BOOST_TEST(!wp1.expired()); + BOOST_TEST(wp1.use_count() != 0); + + p.reset(); + p2.reset(); + p3.reset(); + p4.reset(); + + test_is_zero(p); + test_is_zero(p2); + test_is_zero(p3); + test_is_zero(p4); + + BOOST_TEST(p5.use_count() == 1); + + BOOST_TEST(wp1.expired()); + BOOST_TEST(wp1.use_count() == 0); + + try + { + shared_ptr sp1(wp1); + BOOST_ERROR("shared_ptr sp1(wp1) failed to throw"); + } + catch(boost::bad_weak_ptr const &) + { + } + + test_is_zero(boost::make_shared(wp1)); + + weak_ptr wp2 = static_pointer_cast(p5); + + BOOST_TEST(wp2.use_count() == 1); + test_is_Y(wp2); + test_nonshared(wp1, wp2); + + // Scoped to not affect the subsequent use_count() tests. + { + shared_ptr sp2(wp2); + test_is_nonzero(boost::make_shared(wp2)); + } + + weak_ptr wp3 = dynamic_pointer_cast(boost::make_shared(wp2)); + + BOOST_TEST(wp3.use_count() == 1); + test_shared(wp2, wp3); + + weak_ptr wp4(wp3); + + BOOST_TEST(wp4.use_count() == 1); + test_shared(wp2, wp4); + + wp1 = p2; + test_is_zero(boost::make_shared(wp1)); + + wp1 = p4; + wp1 = wp3; + wp1 = wp2; + + BOOST_TEST(wp1.use_count() == 1); + test_shared(wp1, wp2); + + weak_ptr wp5; + + bool b1 = wp1 < wp5; + bool b2 = wp5 < wp1; + + p5.reset(); + + BOOST_TEST(wp1.use_count() == 0); + BOOST_TEST(wp2.use_count() == 0); + BOOST_TEST(wp3.use_count() == 0); + + // Test operator< stability for std::set< weak_ptr<> > + // Thanks to Joe Gottman for pointing this out + + BOOST_TEST(b1 == (wp1 < wp5)); + BOOST_TEST(b2 == (wp5 < wp1)); + + { + // note that both get_object and release_object deal with int* + shared_ptr p6(get_object(), release_object); + } + } + + BOOST_TEST(cnt == 0); + + return boost::report_errors(); +} diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 01f8920..f82cbb3 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -7,9 +7,9 @@ #endif // -// shared_ptr_test.cpp - a test for shared_ptr.hpp and weak_ptr.hpp +// shared_ptr_test.cpp // -// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2002 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. @@ -2159,277 +2159,6 @@ void test() } // namespace n_report_2 -namespace n_old -{ - -int cnt = 0; - -struct X -{ - X() - { - ++cnt; - } - - ~X() // virtual destructor deliberately omitted - { - --cnt; - } - - virtual int id() const - { - return 1; - } - -private: - - X(X const &); - X & operator= (X const &); -}; - -struct Y: public X -{ - Y() - { - ++cnt; - } - - ~Y() - { - --cnt; - } - - virtual int id() const - { - return 2; - } - -private: - - Y(Y const &); - Y & operator= (Y const &); -}; - -int * get_object() -{ - ++cnt; - return &cnt; -} - -void release_object(int * p) -{ - BOOST_TEST(p == &cnt); - --cnt; -} - -template void test_is_X(boost::shared_ptr const & p) -{ - BOOST_TEST(p->id() == 1); - BOOST_TEST((*p).id() == 1); -} - -template void test_is_X(boost::weak_ptr const & p) -{ - BOOST_TEST(p.get() != 0); - BOOST_TEST(p.get()->id() == 1); -} - -template void test_is_Y(boost::shared_ptr const & p) -{ - BOOST_TEST(p->id() == 2); - BOOST_TEST((*p).id() == 2); -} - -template void test_is_Y(boost::weak_ptr const & p) -{ - boost::shared_ptr q = boost::make_shared(p); - BOOST_TEST(q.get() != 0); - BOOST_TEST(q->id() == 2); -} - -template void test_eq(T const & a, T const & b) -{ - BOOST_TEST(a == b); - BOOST_TEST(!(a != b)); - BOOST_TEST(!(a < b)); - BOOST_TEST(!(b < a)); -} - -template void test_ne(T const & a, T const & b) -{ - BOOST_TEST(!(a == b)); - BOOST_TEST(a != b); - BOOST_TEST(a < b || b < a); - BOOST_TEST(!(a < b && b < a)); -} - -template void test_shared(boost::weak_ptr const & a, boost::weak_ptr const & b) -{ - BOOST_TEST(!(a < b)); - BOOST_TEST(!(b < a)); -} - -template void test_nonshared(boost::weak_ptr const & a, boost::weak_ptr const & b) -{ - BOOST_TEST(a < b || b < a); - BOOST_TEST(!(a < b && b < a)); -} - -template void test_eq2(T const & a, U const & b) -{ - BOOST_TEST(a == b); - BOOST_TEST(!(a != b)); -} - -template void test_ne2(T const & a, U const & b) -{ - BOOST_TEST(!(a == b)); - BOOST_TEST(a != b); -} - -template void test_is_zero(boost::shared_ptr const & p) -{ - BOOST_TEST(!p); - BOOST_TEST(p.get() == 0); -} - -template void test_is_nonzero(boost::shared_ptr const & p) -{ - // p? true: false is used to test p in a boolean context. - // BOOST_TEST(p) is not guaranteed to test the conversion, - // as the macro might test !!p instead. - BOOST_TEST(p? true: false); - BOOST_TEST(p.get() != 0); -} - -void test() -{ - using namespace boost; - - { - shared_ptr p(new Y); - shared_ptr p2(new X); - - test_is_nonzero(p); - test_is_nonzero(p2); - test_is_Y(p); - test_is_X(p2); - test_ne(p, p2); - - { - shared_ptr q(p); - test_eq(p, q); - } - - shared_ptr p3 = dynamic_pointer_cast(p); - shared_ptr p4 = dynamic_pointer_cast(p2); - - test_is_nonzero(p3); - test_is_zero(p4); - - BOOST_TEST(p.use_count() == 2); - BOOST_TEST(p2.use_count() == 1); - BOOST_TEST(p3.use_count() == 2); - - test_is_Y(p3); - test_eq2(p, p3); - test_ne2(p2, p4); - - shared_ptr p5(p); - - test_is_nonzero(p5); - test_eq2(p, p5); - - weak_ptr wp1(p2); - - BOOST_TEST(!wp1.expired()); - BOOST_TEST(wp1.use_count() != 0); - - p.reset(); - p2.reset(); - p3.reset(); - p4.reset(); - - test_is_zero(p); - test_is_zero(p2); - test_is_zero(p3); - test_is_zero(p4); - - BOOST_TEST(p5.use_count() == 1); - - BOOST_TEST(wp1.expired()); - BOOST_TEST(wp1.use_count() == 0); - - try - { - shared_ptr sp1(wp1); - BOOST_ERROR("shared_ptr sp1(wp1) failed to throw"); - } - catch(boost::bad_weak_ptr const &) - { - } - - test_is_zero(boost::make_shared(wp1)); - - weak_ptr wp2 = static_pointer_cast(p5); - - BOOST_TEST(wp2.use_count() == 1); - test_is_Y(wp2); - test_nonshared(wp1, wp2); - - // Scoped to not affect the subsequent use_count() tests. - { - shared_ptr sp2(wp2); - test_is_nonzero(boost::make_shared(wp2)); - } - - weak_ptr wp3 = dynamic_pointer_cast(boost::make_shared(wp2)); - - BOOST_TEST(wp3.use_count() == 1); - test_shared(wp2, wp3); - - weak_ptr wp4 = boost::make_shared(wp3); - - BOOST_TEST(wp4.use_count() == 1); - test_shared(wp2, wp4); - - wp1 = p2; - test_is_zero(boost::make_shared(wp1)); - - wp1 = p4; - wp1 = wp2; - - BOOST_TEST(wp1.use_count() == 1); - test_shared(wp1, wp2); - - weak_ptr wp5; - - bool b1 = wp1 < wp5; - bool b2 = wp5 < wp1; - - p5.reset(); - - BOOST_TEST(wp1.use_count() == 0); - BOOST_TEST(wp2.use_count() == 0); - BOOST_TEST(wp3.use_count() == 0); - - // Test operator< stability for std::set< weak_ptr<> > - // Thanks to Joe Gottman for pointing this out - - BOOST_TEST(b1 == (wp1 < wp5)); - BOOST_TEST(b2 == (wp5 < wp1)); - - { - // note that both get_object and release_object deal with int* - shared_ptr p6(get_object(), release_object); - } - } - - BOOST_TEST(cnt == 0); -} - -} // namespace n_old - namespace n_spt_incomplete { @@ -2902,8 +2631,6 @@ int main() n_report_1::test(); n_report_2::test(); - n_old::test(); - n_spt_incomplete::test(); n_spt_pimpl::test(); n_spt_abstract::test(); From 9632464c451346f351b3101648ced05f59584aca Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 25 Nov 2002 12:17:56 +0000 Subject: [PATCH 166/513] Test w/ NULL pointer to enabled_... object added; bug fixed. [SVN r16402] --- enable_shared_from_this_test.cpp | 8 ++++++++ include/boost/shared_ptr.hpp | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/enable_shared_from_this_test.cpp b/enable_shared_from_this_test.cpp index 8225a39..75ca31d 100644 --- a/enable_shared_from_this_test.cpp +++ b/enable_shared_from_this_test.cpp @@ -66,9 +66,12 @@ void test() BOOST_TEST(py.use_count() == 3); } +void test2(); + int main() { test(); + test2(); return boost::report_errors(); } @@ -102,3 +105,8 @@ boost::shared_ptr createY() boost::shared_ptr pi(new impl2); return pi; } + +void test2() +{ + boost::shared_ptr pi(static_cast(0)); +} diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 03ea7d4..473543a 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -72,7 +72,7 @@ template<> struct shared_ptr_traits template void sp_enable_shared_from_this(boost::enable_shared_from_this * pe, Y * px, shared_count const & pn) { - pe->_internal_weak_this._internal_assign(px, pn); + if(pe != 0) pe->_internal_weak_this._internal_assign(px, pn); } inline void sp_enable_shared_from_this(void const *, void const *, shared_count const &) From 12b1871136871ae4b91dbbd4bfe0c370aea5bb28 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 25 Nov 2002 12:27:11 +0000 Subject: [PATCH 167/513] operator<< added, as the conversion to 'bool' implicitly defines one anyway. [SVN r16403] --- include/boost/shared_ptr.hpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 473543a..1e5e8fb 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -26,10 +26,11 @@ #include #include -#include // for std::auto_ptr -#include // for std::swap -#include // for std::less -#include // for std::bad_cast +#include // for std::auto_ptr +#include // for std::swap +#include // for std::less +#include // for std::bad_cast +#include // for std::basic_ostream #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash # pragma warning(push) @@ -371,6 +372,14 @@ template inline T * get_pointer(shared_ptr const & p) return p.get(); } +// operator<< + +template std::basic_ostream & operator<< (std::basic_ostream & os, shared_ptr const & p) +{ + os << p.get(); + return os; +} + // get_deleter (experimental) #if defined(__GNUC__) && (__GNUC__ < 3) From 72bcb8ff46744af5f3725c3190f1d25a37ab02f8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 25 Nov 2002 13:51:56 +0000 Subject: [PATCH 168/513] More tests added. [SVN r16405] --- shared_ptr_test.cpp | 472 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 470 insertions(+), 2 deletions(-) diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index f82cbb3..9f32175 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -1109,7 +1109,7 @@ private: long X::instances = 0; -struct Y: public A, public X +struct Y: public A, public virtual X { static long instances; @@ -1457,16 +1457,427 @@ void test() namespace n_reset { -void plain_reset() +class incomplete; + +incomplete * p0 = 0; + +void deleter(incomplete *) { } +struct X +{ + static long instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X(X const &); + X & operator= (X const &); +}; + +long X::instances = 0; + +void plain_reset() +{ + { + boost::shared_ptr pi; + pi.reset(); + BOOST_TEST(pi? false: true); + BOOST_TEST(!pi); + BOOST_TEST(pi.get() == 0); + } + + { + boost::shared_ptr pi(static_cast(0)); + pi.reset(); + BOOST_TEST(pi? false: true); + BOOST_TEST(!pi); + BOOST_TEST(pi.get() == 0); + } + + { + boost::shared_ptr pi(new int); + pi.reset(); + BOOST_TEST(pi? false: true); + BOOST_TEST(!pi); + BOOST_TEST(pi.get() == 0); + } + + { + boost::shared_ptr px; + px.reset(); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + } + + { + boost::shared_ptr px(p0, deleter); + px.reset(); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + } + + { + boost::shared_ptr px; + px.reset(); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + } + + { + BOOST_TEST(X::instances == 0); + boost::shared_ptr px(new X); + BOOST_TEST(X::instances == 1); + px.reset(); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(X::instances == 0); + } + + { + boost::shared_ptr pv; + pv.reset(); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + } + + { + BOOST_TEST(X::instances == 0); + boost::shared_ptr pv(new X); + BOOST_TEST(X::instances == 1); + pv.reset(); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(X::instances == 0); + } +} + +struct A +{ + int dummy; +}; + +struct Y: public A, public virtual X +{ + static long instances; + + Y() + { + ++instances; + } + + ~Y() + { + --instances; + } + +private: + + Y(Y const &); + Y & operator= (Y const &); +}; + +long Y::instances = 0; + void pointer_reset() { + { + boost::shared_ptr pi; + + pi.reset(static_cast(0)); + BOOST_TEST(pi? false: true); + BOOST_TEST(!pi); + BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + + int * p = new int; + pi.reset(p); + BOOST_TEST(pi? true: false); + BOOST_TEST(!!pi); + BOOST_TEST(pi.get() == p); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + + pi.reset(static_cast(0)); + BOOST_TEST(pi? false: true); + BOOST_TEST(!pi); + BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + } + + { + boost::shared_ptr px; + + px.reset(static_cast(0)); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(X::instances == 0); + + X * p = new X; + px.reset(p); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(px.get() == p); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(X::instances == 1); + + px.reset(static_cast(0)); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + + Y * q = new Y; + px.reset(q); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(px.get() == q); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); + + px.reset(static_cast(0)); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + } + + { + boost::shared_ptr pv; + + pv.reset(static_cast(0)); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + BOOST_TEST(X::instances == 0); + + X * p = new X; + pv.reset(p); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == p); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + BOOST_TEST(X::instances == 1); + + pv.reset(static_cast(0)); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + + Y * q = new Y; + pv.reset(q); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == q); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + BOOST_TEST(X::instances == 1); + BOOST_TEST(Y::instances == 1); + + pv.reset(static_cast(0)); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + BOOST_TEST(X::instances == 0); + BOOST_TEST(Y::instances == 0); + } +} + +void * deleted = 0; + +void deleter2(void * p) +{ + deleted = p; } void deleter_reset() { + { + boost::shared_ptr pi; + + pi.reset(static_cast(0), deleter2); + BOOST_TEST(pi? false: true); + BOOST_TEST(!pi); + BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + + deleted = π + + int m = 0; + pi.reset(&m, deleter2); + BOOST_TEST(deleted == 0); + BOOST_TEST(pi? true: false); + BOOST_TEST(!!pi); + BOOST_TEST(pi.get() == &m); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + + pi.reset(static_cast(0), deleter2); + BOOST_TEST(deleted == &m); + BOOST_TEST(pi? false: true); + BOOST_TEST(!pi); + BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 1); + BOOST_TEST(pi.unique()); + + pi.reset(); + BOOST_TEST(deleted == 0); + } + + { + boost::shared_ptr px; + + px.reset(static_cast(0), deleter2); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + + deleted = &px; + + X x; + px.reset(&x, deleter2); + BOOST_TEST(deleted == 0); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(px.get() == &x); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + + px.reset(static_cast(0), deleter2); + BOOST_TEST(deleted == &x); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + + Y y; + px.reset(&y, deleter2); + BOOST_TEST(deleted == 0); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(px.get() == &y); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + + px.reset(static_cast(0), deleter2); + BOOST_TEST(deleted == &y); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + + px.reset(); + BOOST_TEST(deleted == 0); + } + + { + boost::shared_ptr pv; + + pv.reset(static_cast(0), deleter2); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + + deleted = &pv; + + X x; + pv.reset(&x, deleter2); + BOOST_TEST(deleted == 0); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == &x); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + + pv.reset(static_cast(0), deleter2); + BOOST_TEST(deleted == &x); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + + Y y; + pv.reset(&y, deleter2); + BOOST_TEST(deleted == 0); + BOOST_TEST(pv? true: false); + BOOST_TEST(!!pv); + BOOST_TEST(pv.get() == &y); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + + pv.reset(static_cast(0), deleter2); + BOOST_TEST(deleted == &y); + BOOST_TEST(pv? false: true); + BOOST_TEST(!pv); + BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 1); + BOOST_TEST(pv.unique()); + + pv.reset(); + BOOST_TEST(deleted == 0); + } + + { + boost::shared_ptr px; + + px.reset(p0, deleter2); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 1); + BOOST_TEST(px.unique()); + + deleted = &px; + px.reset(p0, deleter2); + BOOST_TEST(deleted == 0); + } } void test() @@ -2393,8 +2804,65 @@ void test() namespace n_spt_intrusive { +int X_instances = 0; + +struct X +{ + long count; + + X(): count(0) + { + ++X_instances; + } + + ~X() + { + --X_instances; + } +}; + +void intrusive_ptr_add_ref(X * p) +{ + ++p->count; +} + +void intrusive_ptr_release(X * p) +{ + if(--p->count == 0) delete p; +} + +template struct intrusive_deleter +{ + void operator()(T * p) + { + if(p != 0) intrusive_ptr_release(p); + } +}; + +boost::shared_ptr make_shared_from_intrusive(X * p) +{ + if(p != 0) intrusive_ptr_add_ref(p); + boost::shared_ptr px(p, intrusive_deleter()); + return px; +} + void test() { + BOOST_TEST(X_instances == 0); + + { + X * p = new X; + BOOST_TEST(X_instances == 1); + BOOST_TEST(p->count == 0); + boost::shared_ptr px = make_shared_from_intrusive(p); + BOOST_TEST(px.get() == p); + BOOST_TEST(p->count == 1); + boost::shared_ptr px2(px); + BOOST_TEST(px2.get() == p); + BOOST_TEST(p->count == 1); + } + + BOOST_TEST(X_instances == 0); } } // namespace n_spt_intrusive From e60c1f9b4960e0ffe58d16d312e0ad4215657685 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 25 Nov 2002 13:52:42 +0000 Subject: [PATCH 169/513] Some versions of g++ 2.9x don't have basic_ostream. [SVN r16406] --- include/boost/shared_ptr.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 1e5e8fb..f365d8e 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -374,12 +374,24 @@ template inline T * get_pointer(shared_ptr const & p) // operator<< +#if defined(__GNUC__) && (__GNUC__ < 3) + +template std::ostream & operator<< (std::ostream & os, shared_ptr const & p) +{ + os << p.get(); + return os; +} + +#else + template std::basic_ostream & operator<< (std::basic_ostream & os, shared_ptr const & p) { os << p.get(); return os; } +#endif + // get_deleter (experimental) #if defined(__GNUC__) && (__GNUC__ < 3) From 468f63261a851eee07b060d7f614d87a3e7f8631 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 26 Nov 2002 16:01:17 +0000 Subject: [PATCH 170/513] weak_ptr_test.cpp added. [SVN r16427] --- weak_ptr_test.cpp | 1178 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1178 insertions(+) create mode 100644 weak_ptr_test.cpp diff --git a/weak_ptr_test.cpp b/weak_ptr_test.cpp new file mode 100644 index 0000000..f06f1c8 --- /dev/null +++ b/weak_ptr_test.cpp @@ -0,0 +1,1178 @@ +#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#pragma warning(disable: 4355) // 'this' : used in base member initializer list +#endif + +// +// weak_ptr_test.cpp +// +// Copyright (c) 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include + +#include +#include + +#include +#include + +// + +namespace n_element_type +{ + +void f(int &) +{ +} + +void test() +{ + typedef boost::weak_ptr::element_type T; + T t; + f(t); +} + +} // namespace n_element_type + +class incomplete; + +boost::shared_ptr create_incomplete(); + +struct X +{ + int dummy; +}; + +struct Y +{ + int dummy2; +}; + +struct Z: public X, public virtual Y +{ +}; + +namespace n_constructors +{ + +void default_constructor() +{ + { + boost::weak_ptr wp; + BOOST_TEST(wp.use_count() == 0); + } + + { + boost::weak_ptr wp; + BOOST_TEST(wp.use_count() == 0); + } + + { + boost::weak_ptr wp; + BOOST_TEST(wp.use_count() == 0); + } +} + +void shared_ptr_constructor() +{ + { + boost::shared_ptr sp; + + boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == 0); + + boost::weak_ptr wp2(sp); + BOOST_TEST(wp2.use_count() == 0); + } + + { + boost::shared_ptr sp(static_cast(0)); + + { + boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == 1); + boost::shared_ptr sp2(wp); + BOOST_TEST(wp.use_count() == 2); + BOOST_TEST(!(sp < sp2 || sp2 < sp)); + } + + { + boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == 1); + boost::shared_ptr sp2(wp); + BOOST_TEST(wp.use_count() == 2); + BOOST_TEST(!(sp < sp2 || sp2 < sp)); + } + } + + { + boost::shared_ptr sp(new int); + + { + boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == 1); + boost::shared_ptr sp2(wp); + BOOST_TEST(wp.use_count() == 2); + BOOST_TEST(!(sp < sp2 || sp2 < sp)); + } + + { + boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == 1); + boost::shared_ptr sp2(wp); + BOOST_TEST(wp.use_count() == 2); + BOOST_TEST(!(sp < sp2 || sp2 < sp)); + } + } + + { + boost::shared_ptr sp; + + boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == 0); + } + + { + boost::shared_ptr sp(static_cast(0)); + + boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == 1); + boost::shared_ptr sp2(wp); + BOOST_TEST(wp.use_count() == 2); + BOOST_TEST(!(sp < sp2 || sp2 < sp)); + } + + { + boost::shared_ptr sp(new int); + + boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == 1); + boost::shared_ptr sp2(wp); + BOOST_TEST(wp.use_count() == 2); + BOOST_TEST(!(sp < sp2 || sp2 < sp)); + } + + { + boost::shared_ptr sp; + + boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == 0); + + boost::weak_ptr wp2(sp); + BOOST_TEST(wp2.use_count() == 0); + } + + { + boost::shared_ptr sp = create_incomplete(); + + { + boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == 1); + boost::shared_ptr sp2(wp); + BOOST_TEST(wp.use_count() == 2); + BOOST_TEST(!(sp < sp2 || sp2 < sp)); + } + + { + boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == 1); + boost::shared_ptr sp2(wp); + BOOST_TEST(wp.use_count() == 2); + BOOST_TEST(!(sp < sp2 || sp2 < sp)); + } + } + + { + boost::shared_ptr sp = create_incomplete(); + + boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == 1); + boost::shared_ptr sp2(wp); + BOOST_TEST(wp.use_count() == 2); + BOOST_TEST(!(sp < sp2 || sp2 < sp)); + } +} + +void copy_constructor() +{ + { + boost::weak_ptr wp; + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 0); + } + + { + boost::weak_ptr wp; + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 0); + } + + { + boost::weak_ptr wp; + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 0); + } + + { + boost::shared_ptr sp(static_cast(0)); + boost::weak_ptr wp(sp); + + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + sp.reset(); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + } + + { + boost::shared_ptr sp(new int); + boost::weak_ptr wp(sp); + + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + sp.reset(); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + } + + { + boost::shared_ptr sp(static_cast(0)); + boost::weak_ptr wp(sp); + + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + sp.reset(); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + } + + { + boost::shared_ptr sp(new int); + boost::weak_ptr wp(sp); + + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + sp.reset(); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + } + + { + boost::shared_ptr sp = create_incomplete(); + boost::weak_ptr wp(sp); + + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + sp.reset(); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + } +} + +void conversion_constructor() +{ + { + boost::weak_ptr wp; + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 0); + } + + { + boost::weak_ptr wp; + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 0); + } + + { + boost::weak_ptr wp; + + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 0); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == 0); + } + + { + boost::shared_ptr sp(static_cast(0)); + boost::weak_ptr wp(sp); + + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + sp.reset(); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + } + + { + boost::shared_ptr sp(new int); + boost::weak_ptr wp(sp); + + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + sp.reset(); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + } + + { + boost::shared_ptr sp = create_incomplete(); + boost::weak_ptr wp(sp); + + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + sp.reset(); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + } + + { + boost::shared_ptr sp(static_cast(0)); + boost::weak_ptr wp(sp); + + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + sp.reset(); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + } + + { + boost::shared_ptr sp(static_cast(0)); + boost::weak_ptr wp(sp); + + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + sp.reset(); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + } + + { + boost::shared_ptr sp(new Z); + boost::weak_ptr wp(sp); + + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + sp.reset(); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + } + + { + boost::shared_ptr sp(new Z); + boost::weak_ptr wp(sp); + + boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + sp.reset(); + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + } +} + +void test() +{ + default_constructor(); + shared_ptr_constructor(); + copy_constructor(); + conversion_constructor(); +} + +} // namespace n_constructors + +namespace n_assignment +{ + +template void copy_assignment(boost::shared_ptr sp) +{ + BOOST_TEST(sp.unique()); + + boost::weak_ptr p1; + + p1 = p1; + BOOST_TEST(p1.use_count() == 0); + + boost::weak_ptr p2; + + p1 = p2; + BOOST_TEST(p1.use_count() == 0); + + boost::weak_ptr p3(p1); + + p1 = p3; + BOOST_TEST(p1.use_count() == 0); + + boost::weak_ptr p4(sp); + + p4 = p4; + BOOST_TEST(p4.use_count() == 1); + + p1 = p4; + BOOST_TEST(p1.use_count() == 1); + + p4 = p2; + BOOST_TEST(p4.use_count() == 0); + + sp.reset(); + + p1 = p1; + BOOST_TEST(p1.use_count() == 0); + + p4 = p1; + BOOST_TEST(p4.use_count() == 0); +} + +void conversion_assignment() +{ + { + boost::weak_ptr p1; + + boost::weak_ptr p2; + + p1 = p2; + BOOST_TEST(p1.use_count() == 0); + + boost::shared_ptr sp = create_incomplete(); + boost::weak_ptr p3(sp); + + p1 = p3; + BOOST_TEST(p1.use_count() == 1); + + sp.reset(); + + p1 = p3; + BOOST_TEST(p1.use_count() == 0); + + p1 = p2; + BOOST_TEST(p1.use_count() == 0); + } + + { + boost::weak_ptr p1; + + boost::weak_ptr p2; + + p1 = p2; + BOOST_TEST(p1.use_count() == 0); + + boost::shared_ptr sp(new Z); + boost::weak_ptr p3(sp); + + p1 = p3; + BOOST_TEST(p1.use_count() == 1); + + sp.reset(); + + p1 = p3; + BOOST_TEST(p1.use_count() == 0); + + p1 = p2; + BOOST_TEST(p1.use_count() == 0); + } + + { + boost::weak_ptr p1; + + boost::weak_ptr p2; + + p1 = p2; + BOOST_TEST(p1.use_count() == 0); + + boost::shared_ptr sp(new Z); + boost::weak_ptr p3(sp); + + p1 = p3; + BOOST_TEST(p1.use_count() == 1); + + sp.reset(); + + p1 = p3; + BOOST_TEST(p1.use_count() == 0); + + p1 = p2; + BOOST_TEST(p1.use_count() == 0); + } +} + +void shared_ptr_assignment() +{ +} + +void test() +{ + copy_assignment(boost::shared_ptr(new int)); + copy_assignment(boost::shared_ptr(new X)); + copy_assignment(boost::shared_ptr(new int)); + copy_assignment(create_incomplete()); + conversion_assignment(); + shared_ptr_assignment(); +} + +} // namespace n_assignment + +namespace n_reset +{ + +void test() +{ +} + +} // namespace n_reset + +namespace n_use_count +{ + +void test() +{ + { + boost::weak_ptr wp; + BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp.expired()); + + boost::weak_ptr wp2; + BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp.expired()); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp.expired()); + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(wp3.expired()); + } + + { + boost::shared_ptr sp(static_cast(0)); + + boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == 1); + BOOST_TEST(!wp.expired()); + + boost::weak_ptr wp2(sp); + BOOST_TEST(wp.use_count() == 1); + BOOST_TEST(!wp.expired()); + + boost::weak_ptr wp3(wp); + BOOST_TEST(wp.use_count() == 1); + BOOST_TEST(!wp.expired()); + BOOST_TEST(wp3.use_count() == 1); + BOOST_TEST(!wp3.expired()); + + boost::shared_ptr sp2(sp); + + BOOST_TEST(wp.use_count() == 2); + BOOST_TEST(!wp.expired()); + BOOST_TEST(wp2.use_count() == 2); + BOOST_TEST(!wp2.expired()); + BOOST_TEST(wp3.use_count() == 2); + BOOST_TEST(!wp3.expired()); + + boost::shared_ptr sp3(sp); + + BOOST_TEST(wp.use_count() == 3); + BOOST_TEST(!wp.expired()); + BOOST_TEST(wp2.use_count() == 3); + BOOST_TEST(!wp2.expired()); + BOOST_TEST(wp3.use_count() == 3); + BOOST_TEST(!wp3.expired()); + + sp.reset(); + + BOOST_TEST(wp.use_count() == 2); + BOOST_TEST(!wp.expired()); + BOOST_TEST(wp2.use_count() == 2); + BOOST_TEST(!wp2.expired()); + BOOST_TEST(wp3.use_count() == 2); + BOOST_TEST(!wp3.expired()); + + sp2.reset(); + + BOOST_TEST(wp.use_count() == 1); + BOOST_TEST(!wp.expired()); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!wp2.expired()); + BOOST_TEST(wp3.use_count() == 1); + BOOST_TEST(!wp3.expired()); + + sp3.reset(); + + BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp.expired()); + BOOST_TEST(wp2.use_count() == 0); + BOOST_TEST(wp2.expired()); + BOOST_TEST(wp3.use_count() == 0); + BOOST_TEST(wp3.expired()); + } +} + +} // namespace n_use_count + +namespace n_swap +{ + +void test() +{ + { + boost::weak_ptr wp; + boost::weak_ptr wp2; + + wp.swap(wp2); + + BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp2.use_count() == 0); + + using std::swap; + swap(wp, wp2); + + BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp2.use_count() == 0); + } + + { + boost::shared_ptr sp(new X); + boost::weak_ptr wp; + boost::weak_ptr wp2(sp); + boost::weak_ptr wp3(sp); + + wp.swap(wp2); + + BOOST_TEST(wp.use_count() == 1); + BOOST_TEST(wp2.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + + using std::swap; + swap(wp, wp2); + + BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp2 < wp3 || wp3 < wp2)); + + sp.reset(); + + wp.swap(wp2); + + BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp2.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + + using std::swap; + swap(wp, wp2); + + BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp2.use_count() == 0); + BOOST_TEST(!(wp2 < wp3 || wp3 < wp2)); + } + + { + boost::shared_ptr sp(new X); + boost::shared_ptr sp2(new X); + boost::weak_ptr wp(sp); + boost::weak_ptr wp2(sp2); + boost::weak_ptr wp3(sp2); + + wp.swap(wp2); + + BOOST_TEST(wp.use_count() == 1); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + + using std::swap; + swap(wp, wp2); + + BOOST_TEST(wp.use_count() == 1); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp2 < wp3 || wp3 < wp2)); + + sp.reset(); + + wp.swap(wp2); + + BOOST_TEST(wp.use_count() == 1); + BOOST_TEST(wp2.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + + using std::swap; + swap(wp, wp2); + + BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp2.use_count() == 1); + BOOST_TEST(!(wp2 < wp3 || wp3 < wp2)); + + sp2.reset(); + + wp.swap(wp2); + + BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp2.use_count() == 0); + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + + using std::swap; + swap(wp, wp2); + + BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp2.use_count() == 0); + BOOST_TEST(!(wp2 < wp3 || wp3 < wp2)); + } +} + +} // namespace n_swap + +namespace n_comparison +{ + +void test() +{ + { + boost::weak_ptr wp; + BOOST_TEST(!(wp < wp)); + + boost::weak_ptr wp2; + BOOST_TEST(!(wp < wp2 && wp2 < wp)); + + boost::weak_ptr wp3(wp); + BOOST_TEST(!(wp3 < wp3)); + BOOST_TEST(!(wp < wp3 && wp3 < wp)); + } + + { + boost::shared_ptr sp(new X); + + boost::weak_ptr wp(sp); + BOOST_TEST(!(wp < wp)); + + boost::weak_ptr wp2; + BOOST_TEST(wp < wp2 || wp2 < wp); + BOOST_TEST(!(wp < wp2 && wp2 < wp)); + + bool b1 = wp < wp2; + bool b2 = wp2 < wp; + + { + boost::weak_ptr wp3(wp); + + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + BOOST_TEST(!(wp < wp3 && wp3 < wp)); + + BOOST_TEST(wp2 < wp3 || wp3 < wp2); + BOOST_TEST(!(wp2 < wp3 && wp3 < wp2)); + + boost::weak_ptr wp4(wp2); + + BOOST_TEST(wp4 < wp3 || wp3 < wp4); + BOOST_TEST(!(wp4 < wp3 && wp3 < wp4)); + } + + sp.reset(); + + BOOST_TEST(b1 == (wp < wp2)); + BOOST_TEST(b2 == (wp2 < wp)); + + { + boost::weak_ptr wp3(wp); + + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + BOOST_TEST(!(wp < wp3 && wp3 < wp)); + + BOOST_TEST(wp2 < wp3 || wp3 < wp2); + BOOST_TEST(!(wp2 < wp3 && wp3 < wp2)); + + boost::weak_ptr wp4(wp2); + + BOOST_TEST(wp4 < wp3 || wp3 < wp4); + BOOST_TEST(!(wp4 < wp3 && wp3 < wp4)); + } + } + + { + boost::shared_ptr sp(new X); + boost::shared_ptr sp2(new X); + + boost::weak_ptr wp(sp); + boost::weak_ptr wp2(sp2); + + BOOST_TEST(wp < wp2 || wp2 < wp); + BOOST_TEST(!(wp < wp2 && wp2 < wp)); + + bool b1 = wp < wp2; + bool b2 = wp2 < wp; + + { + boost::weak_ptr wp3(wp); + + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + BOOST_TEST(!(wp < wp3 && wp3 < wp)); + + BOOST_TEST(wp2 < wp3 || wp3 < wp2); + BOOST_TEST(!(wp2 < wp3 && wp3 < wp2)); + + boost::weak_ptr wp4(wp2); + + BOOST_TEST(wp4 < wp3 || wp3 < wp4); + BOOST_TEST(!(wp4 < wp3 && wp3 < wp4)); + } + + sp.reset(); + + BOOST_TEST(b1 == (wp < wp2)); + BOOST_TEST(b2 == (wp2 < wp)); + + { + boost::weak_ptr wp3(wp); + + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + BOOST_TEST(!(wp < wp3 && wp3 < wp)); + + BOOST_TEST(wp2 < wp3 || wp3 < wp2); + BOOST_TEST(!(wp2 < wp3 && wp3 < wp2)); + + boost::weak_ptr wp4(wp2); + + BOOST_TEST(wp4 < wp3 || wp3 < wp4); + BOOST_TEST(!(wp4 < wp3 && wp3 < wp4)); + } + + sp2.reset(); + + BOOST_TEST(b1 == (wp < wp2)); + BOOST_TEST(b2 == (wp2 < wp)); + + { + boost::weak_ptr wp3(wp); + + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + BOOST_TEST(!(wp < wp3 && wp3 < wp)); + + BOOST_TEST(wp2 < wp3 || wp3 < wp2); + BOOST_TEST(!(wp2 < wp3 && wp3 < wp2)); + + boost::weak_ptr wp4(wp2); + + BOOST_TEST(wp4 < wp3 || wp3 < wp4); + BOOST_TEST(!(wp4 < wp3 && wp3 < wp4)); + } + } + + { + boost::shared_ptr sp(new X); + boost::shared_ptr sp2(sp); + + boost::weak_ptr wp(sp); + boost::weak_ptr wp2(sp2); + + BOOST_TEST(!(wp < wp2 || wp2 < wp)); + BOOST_TEST(!(wp < wp2 && wp2 < wp)); + + bool b1 = wp < wp2; + bool b2 = wp2 < wp; + + { + boost::weak_ptr wp3(wp); + + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + BOOST_TEST(!(wp < wp3 && wp3 < wp)); + + BOOST_TEST(!(wp2 < wp3 || wp3 < wp2)); + BOOST_TEST(!(wp2 < wp3 && wp3 < wp2)); + + boost::weak_ptr wp4(wp2); + + BOOST_TEST(!(wp4 < wp3 || wp3 < wp4)); + BOOST_TEST(!(wp4 < wp3 && wp3 < wp4)); + } + + sp.reset(); + sp2.reset(); + + BOOST_TEST(b1 == (wp < wp2)); + BOOST_TEST(b2 == (wp2 < wp)); + + { + boost::weak_ptr wp3(wp); + + BOOST_TEST(!(wp < wp3 || wp3 < wp)); + BOOST_TEST(!(wp < wp3 && wp3 < wp)); + + BOOST_TEST(!(wp2 < wp3 || wp3 < wp2)); + BOOST_TEST(!(wp2 < wp3 && wp3 < wp2)); + + boost::weak_ptr wp4(wp2); + + BOOST_TEST(!(wp4 < wp3 || wp3 < wp4)); + BOOST_TEST(!(wp4 < wp3 && wp3 < wp4)); + } + } + + { + boost::shared_ptr spx(new X); + boost::shared_ptr spy(new Y); + boost::shared_ptr spz(new Z); + + boost::weak_ptr px(spx); + boost::weak_ptr py(spy); + boost::weak_ptr pz(spz); + + BOOST_TEST(px < py || py < px); + BOOST_TEST(px < pz || pz < px); + BOOST_TEST(py < pz || pz < py); + + BOOST_TEST(!(px < py && py < px)); + BOOST_TEST(!(px < pz && pz < px)); + BOOST_TEST(!(py < pz && pz < py)); + + boost::weak_ptr pvx(px); + BOOST_TEST(!(pvx < pvx)); + + boost::weak_ptr pvy(py); + BOOST_TEST(!(pvy < pvy)); + + boost::weak_ptr pvz(pz); + BOOST_TEST(!(pvz < pvz)); + + BOOST_TEST(pvx < pvy || pvy < pvx); + BOOST_TEST(pvx < pvz || pvz < pvx); + BOOST_TEST(pvy < pvz || pvz < pvy); + + BOOST_TEST(!(pvx < pvy && pvy < pvx)); + BOOST_TEST(!(pvx < pvz && pvz < pvx)); + BOOST_TEST(!(pvy < pvz && pvz < pvy)); + + spx.reset(); + spy.reset(); + spz.reset(); + + BOOST_TEST(px < py || py < px); + BOOST_TEST(px < pz || pz < px); + BOOST_TEST(py < pz || pz < py); + + BOOST_TEST(!(px < py && py < px)); + BOOST_TEST(!(px < pz && pz < px)); + BOOST_TEST(!(py < pz && pz < py)); + + BOOST_TEST(!(pvx < pvx)); + BOOST_TEST(!(pvy < pvy)); + BOOST_TEST(!(pvz < pvz)); + + BOOST_TEST(pvx < pvy || pvy < pvx); + BOOST_TEST(pvx < pvz || pvz < pvx); + BOOST_TEST(pvy < pvz || pvz < pvy); + + BOOST_TEST(!(pvx < pvy && pvy < pvx)); + BOOST_TEST(!(pvx < pvz && pvz < pvx)); + BOOST_TEST(!(pvy < pvz && pvz < pvy)); + } + + { + boost::shared_ptr spz(new Z); + boost::shared_ptr spx(spz); + + boost::weak_ptr pz(spz); + boost::weak_ptr px(spx); + boost::weak_ptr py(spz); + + BOOST_TEST(!(px < px)); + BOOST_TEST(!(py < py)); + + BOOST_TEST(!(px < py || py < px)); + BOOST_TEST(!(px < pz || pz < px)); + BOOST_TEST(!(py < pz || pz < py)); + + boost::weak_ptr pvx(px); + boost::weak_ptr pvy(py); + boost::weak_ptr pvz(pz); + + BOOST_TEST(!(pvx < pvy || pvy < pvx)); + BOOST_TEST(!(pvx < pvz || pvz < pvx)); + BOOST_TEST(!(pvy < pvz || pvz < pvy)); + + spx.reset(); + spz.reset(); + + BOOST_TEST(!(px < px)); + BOOST_TEST(!(py < py)); + + BOOST_TEST(!(px < py || py < px)); + BOOST_TEST(!(px < pz || pz < px)); + BOOST_TEST(!(py < pz || pz < py)); + + BOOST_TEST(!(pvx < pvy || pvy < pvx)); + BOOST_TEST(!(pvx < pvz || pvz < pvx)); + BOOST_TEST(!(pvy < pvz || pvz < pvy)); + } +} + +} // namespace n_comparison + +namespace n_make_shared +{ + +void test() +{ +} + +} // namespace n_make_shared + +namespace n_map +{ + +void test() +{ + std::vector< boost::shared_ptr > vi; + + { + boost::shared_ptr pi1(new int); + boost::shared_ptr pi2(new int); + boost::shared_ptr pi3(new int); + + vi.push_back(pi1); + vi.push_back(pi1); + vi.push_back(pi1); + vi.push_back(pi2); + vi.push_back(pi1); + vi.push_back(pi2); + vi.push_back(pi1); + vi.push_back(pi3); + vi.push_back(pi3); + vi.push_back(pi2); + vi.push_back(pi1); + } + + std::vector< boost::shared_ptr > vx; + + { + boost::shared_ptr px1(new X); + boost::shared_ptr px2(new X); + boost::shared_ptr px3(new X); + + vx.push_back(px2); + vx.push_back(px2); + vx.push_back(px1); + vx.push_back(px2); + vx.push_back(px1); + vx.push_back(px1); + vx.push_back(px1); + vx.push_back(px2); + vx.push_back(px1); + vx.push_back(px3); + vx.push_back(px2); + } + + std::map< boost::weak_ptr, long > m; + + { + for(std::vector< boost::shared_ptr >::iterator i = vi.begin(); i != vi.end(); ++i) + { + ++m[*i]; + } + } + + { + for(std::vector< boost::shared_ptr >::iterator i = vx.begin(); i != vx.end(); ++i) + { + ++m[*i]; + } + } + + { + for(std::map< boost::weak_ptr, long >::iterator i = m.begin(); i != m.end(); ++i) + { + BOOST_TEST(i->first.use_count() == i->second); + } + } +} + +} // namespace n_map + +int main() +{ + n_element_type::test(); + n_constructors::test(); + n_assignment::test(); + n_reset::test(); + n_use_count::test(); + n_swap::test(); + n_comparison::test(); + n_make_shared::test(); + + n_map::test(); + + return boost::report_errors(); +} + +class incomplete +{ +}; + +boost::shared_ptr create_incomplete() +{ + boost::shared_ptr px(new incomplete); + return px; +} From a3d87ff623a136039f35bc29dcbc4c82fb1371a6 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 28 Nov 2002 13:42:44 +0000 Subject: [PATCH 171/513] Comeau-specific fix. [SVN r16456] --- shared_ptr_test.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 9f32175..4f0fe39 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -2782,7 +2782,11 @@ public: private: - void operator delete(void *); + void operator delete(void *) + { + // Comeau 4.3.0.1 wants a definition + BOOST_ERROR("n_spt_static::X::operator delete() called."); + } }; struct null_deleter From 572a97d3c461ce1bce37f35aac94e492f9fb6bb6 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 29 Nov 2002 14:05:22 +0000 Subject: [PATCH 172/513] Casts renamed. [SVN r16457] --- include/boost/intrusive_ptr.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 26c57b1..5d03548 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -143,12 +143,12 @@ template void swap(intrusive_ptr & lhs, intrusive_ptr & rhs) lhs.swap(rhs); } -template intrusive_ptr shared_dynamic_cast(intrusive_ptr const & p) +template intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & p) { return dynamic_cast(p.get()); } -template intrusive_ptr shared_static_cast(intrusive_ptr const & p) +template intrusive_ptr static_pointer_cast(intrusive_ptr const & p) { return static_cast(p.get()); } From c5f7c973d99b4c7e7beccae1d75dee1ccc3e2c21 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 2 Dec 2002 14:34:06 +0000 Subject: [PATCH 173/513] Bug in get_deleter fixed. [SVN r16477] --- get_deleter_test.cpp | 15 +++++++++++++++ include/boost/detail/shared_count.hpp | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/get_deleter_test.cpp b/get_deleter_test.cpp index 2b84a2d..94d6dd4 100644 --- a/get_deleter_test.cpp +++ b/get_deleter_test.cpp @@ -36,6 +36,21 @@ struct X int main() { + { + boost::shared_ptr p; + + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + BOOST_TEST(boost::get_deleter(p) == 0); + } + { boost::shared_ptr p(new X); diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index a7eb08c..d3c010f 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -382,7 +382,7 @@ public: void * get_deleter(std::type_info const & ti) const { - return pi_->get_deleter(ti); + return pi_? pi_->get_deleter(ti): 0; } }; From 1ef2a5b059df50d2f0fb5bb8ae6baab3f198664f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 3 Dec 2002 13:27:35 +0000 Subject: [PATCH 174/513] More weak_ptr tests. [SVN r16487] --- weak_ptr_test.cpp | 76 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/weak_ptr_test.cpp b/weak_ptr_test.cpp index f06f1c8..7628dc9 100644 --- a/weak_ptr_test.cpp +++ b/weak_ptr_test.cpp @@ -564,8 +564,35 @@ void conversion_assignment() } } -void shared_ptr_assignment() +template void shared_ptr_assignment(boost::shared_ptr sp, T * = 0) { + BOOST_TEST(sp.unique()); + + boost::weak_ptr p1; + boost::weak_ptr p2(p1); + boost::weak_ptr p3(sp); + boost::weak_ptr p4(p3); + + p1 = sp; + BOOST_TEST(p1.use_count() == 1); + + p2 = sp; + BOOST_TEST(p2.use_count() == 1); + + p3 = sp; + BOOST_TEST(p3.use_count() == 1); + + p4 = sp; + BOOST_TEST(p4.use_count() == 1); + + sp.reset(); + + BOOST_TEST(p1.use_count() == 0); + BOOST_TEST(p2.use_count() == 0); + BOOST_TEST(p3.use_count() == 0); + BOOST_TEST(p4.use_count() == 0); + + p1 = sp; } void test() @@ -575,7 +602,13 @@ void test() copy_assignment(boost::shared_ptr(new int)); copy_assignment(create_incomplete()); conversion_assignment(); - shared_ptr_assignment(); + shared_ptr_assignment(boost::shared_ptr(new int)); + shared_ptr_assignment(boost::shared_ptr(new int)); + shared_ptr_assignment(boost::shared_ptr(new X)); + shared_ptr_assignment(boost::shared_ptr(new X)); + shared_ptr_assignment(boost::shared_ptr(new int)); + shared_ptr_assignment(create_incomplete()); + shared_ptr_assignment(create_incomplete()); } } // namespace n_assignment @@ -583,8 +616,47 @@ void test() namespace n_reset { +template void test2(boost::shared_ptr sp, T * = 0) +{ + BOOST_TEST(sp.unique()); + + boost::weak_ptr p1; + boost::weak_ptr p2(p1); + boost::weak_ptr p3(sp); + boost::weak_ptr p4(p3); + boost::weak_ptr p5(sp); + boost::weak_ptr p6(p5); + + p1.reset(); + BOOST_TEST(p1.use_count() == 0); + + p2.reset(); + BOOST_TEST(p2.use_count() == 0); + + p3.reset(); + BOOST_TEST(p3.use_count() == 0); + + p4.reset(); + BOOST_TEST(p4.use_count() == 0); + + sp.reset(); + + p5.reset(); + BOOST_TEST(p5.use_count() == 0); + + p6.reset(); + BOOST_TEST(p6.use_count() == 0); +} + void test() { + test2(boost::shared_ptr(new int)); + test2(boost::shared_ptr(new int)); + test2(boost::shared_ptr(new X)); + test2(boost::shared_ptr(new X)); + test2(boost::shared_ptr(new int)); + test2(create_incomplete()); + test2(create_incomplete()); } } // namespace n_reset From eee96e80592cc5f63edbf08599854957b3c4cfd5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 19 Dec 2002 18:15:53 +0000 Subject: [PATCH 175/513] Borland 5.6.1 still broken. [SVN r16666] --- include/boost/shared_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index f365d8e..8ba4b13 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -129,7 +129,7 @@ public: // generated copy constructor, assignment, destructor are fine... // except on Borland C++ 5.5.1 (and 5.6) -#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x560) +#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x561) shared_ptr & operator=(shared_ptr const & r) // never throws { From 51e9783a217f733a220fd72eaa2c1b3db3b39772 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 20 Dec 2002 18:15:01 +0000 Subject: [PATCH 176/513] Factor out get_pointer, supply an overload for std::auto_ptr. [SVN r16672] --- include/boost/get_pointer.hpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 include/boost/get_pointer.hpp diff --git a/include/boost/get_pointer.hpp b/include/boost/get_pointer.hpp new file mode 100644 index 0000000..09091e4 --- /dev/null +++ b/include/boost/get_pointer.hpp @@ -0,0 +1,30 @@ +// Copyright Peter Dimov and David Abrahams 2002. Permission to copy, +// use, modify, sell and distribute this software is granted provided +// this copyright notice appears in all copies of the source. This +// software is provided "as is" without express or implied warranty, +// and with no claim as to its suitability for any purpose. +#ifndef GET_POINTER_DWA20021219_HPP +# define GET_POINTER_DWA20021219_HPP + +# include + +namespace boost { + +// get_pointer(p) extracts a ->* capable pointer from p + +template T * get_pointer(T * p) +{ + return p; +} + +// get_pointer(shared_ptr const & p) has been moved to shared_ptr.hpp + +template T * get_pointer(std::auto_ptr const& p) +{ + return p.get(); +} + + +} // namespace boost + +#endif // GET_POINTER_DWA20021219_HPP From fafd9a863baf4c993a3967f993cf370e574af113 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 26 Dec 2002 18:23:11 +0000 Subject: [PATCH 177/513] Workarounds for vc6-stlport [SVN r16706] --- include/boost/shared_ptr.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 8ba4b13..c50f13c 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include // for std::auto_ptr #include // for std::swap @@ -384,7 +385,13 @@ template std::ostream & operator<< (std::ostream & os, shared_ptr co #else +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT) +// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL +using std::basic_ostream; +template basic_ostream & operator<< (basic_ostream & os, shared_ptr const & p) +# else template std::basic_ostream & operator<< (std::basic_ostream & os, shared_ptr const & p) +# endif { os << p.get(); return os; From 987a7d32fb1fd1cce348cb1fc08f3cfbc567e266 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 3 Jan 2003 16:53:04 +0000 Subject: [PATCH 178/513] Documentation updated to reflect changes to shared_ptr [SVN r16739] --- include/boost/shared_ptr.hpp | 6 +- shared_ptr.htm | 261 +++++++++++++++-------------------- 2 files changed, 117 insertions(+), 150 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index c50f13c..3f988a7 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -106,7 +106,7 @@ public: typedef T * pointer; typedef typename detail::shared_ptr_traits::reference reference; - shared_ptr(): px(0), pn() + shared_ptr(): px(0), pn() // never throws in 1.30+ { } @@ -211,7 +211,7 @@ public: #endif - void reset() + void reset() // never throws in 1.30+ { this_type().swap(*this); } @@ -253,6 +253,8 @@ public: return px == 0? 0: &this_type::get; } + // operator! is redundant, but some compilers need it + bool operator! () const // never throws { return px == 0; diff --git a/shared_ptr.htm b/shared_ptr.htm index af055d3..6c7b012 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -8,13 +8,13 @@

    c++boost.gif (8819 bytes)shared_ptr class template

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

    Introduction

    @@ -60,8 +60,7 @@ be rare.

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

    -
    -void f(shared_ptr<int>, int);
    +		
    void f(shared_ptr<int>, int);
     int g();
     
     void ok()
    @@ -86,7 +85,7 @@ void bad()
     		

    Synopsis

    namespace boost {
     
    -  class use_count_is_zero: public std::exception;
    +  class bad_weak_ptr: public std::exception;
     
       template<class T> class weak_ptr;
     
    @@ -96,21 +95,21 @@ void bad()
     
           typedef T element_type;
     
    -      shared_ptr();
    +      shared_ptr(); // never throws
           template<class Y> explicit shared_ptr(Y * p);
           template<class Y, class D> shared_ptr(Y * p, D d);
    -      ~shared_ptr(); // never throws
    +      ~shared_ptr(); // never throws
     
    -      shared_ptr(shared_ptr const & r); // never throws
    -      template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
    -      template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
    +      shared_ptr(shared_ptr const & r); // never throws
    +      template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
    +      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  
           template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
           template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
     
    -      void reset();
    +      void reset(); // never throws
           template<class Y> void reset(Y * p);
           template<class Y, class D> void reset(Y * p, D d);
     
    @@ -121,37 +120,39 @@ void bad()
           bool unique() const; // never throws
           long use_count() const; // never throws
     
    -      operator unspecified-bool-type() const; // never throws
    +      operator unspecified-bool-type() const; // never throws
     
           void swap(shared_ptr & b); // never throws
       };
     
       template<class T, class U>
         bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
    +
       template<class T, class U>
         bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
    -  template<class T>
    -    bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws
    +
    +  template<class T, class U>
    +    bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
     
       template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
     
       template<class T> T * get_pointer(shared_ptr<T> const & p); // never throws
     
       template<class T, class U>
    -    shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws
    +    shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws
    +
       template<class T, class U>
    -    shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r);
    -  template<class T, class U>
    -    shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r);
    -  template<class T, class U>
    -    shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws
    +    shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r); // never throws
    +
    +  template<class E, class T, class Y>
    +    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
     
     }

    [It might be convenient to relax the requirements on shared_ptr's signature, allowing an additional, defaulted, template parameter; the parameter can encode the threading model, for example. This would help in detecting possible ODR violations.

    -

    On the other hand, using shared_ptr as an argument to a +

    On the other hand, using shared_ptr as an argument to a template template parameter requires an exact signature match. Metaprogramming experts tend to deemphasize template template parameters as they are too inflexible, but the alternative is typically an std::allocator::rebind-type @@ -163,27 +164,22 @@ void bad()

    Provides the type of the template parameter T.

    constructors

    -
    shared_ptr();
    +
    shared_ptr(); // never throws
    -

    Effects: Constructs a shared_ptr.

    -

    Postconditions: use count is 1; the stored - pointer is 0.

    -

    Throws: std::bad_alloc.

    -

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

    +

    Effects: Constructs an empty shared_ptr. Empty + shared_ptr objects have an unspecified use_count.

    +

    Postconditions: get() == 0.

    +

    Throws: nothing.

    -

    [The postcondition of use_count() == 1 is too strong. Having the nothrow - guarantee is important, since reset() is specified in terms of - the default constructor, but the current specification requires that a count be - allocated. Therefore, this postcondition will be dropped in a future release. - The use count of a default-constructed shared_ptr, including - all copies created from it, will probably be left unspecified.

    -

    There are two possible nothrow implementations, one stores 0 as a pointer to the +

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

    +

    There are two possible implementations, one stores 0 as a pointer to the reference count, the other uses a single statically allocated count for all default-constructed shared_ptrs. The second option is difficult to achieve in the current header-only reference implementation due to thread safety issues and initialization order, but it should not be precluded - by the specification.

    + by the specification. That's why the use_count() has been left unspecified.

    A future release may enable shared_ptr construction from a literal zero, for consistency with built-in pointers. It is not clear yet whether this constructor should be left implicit, enabling 0 to @@ -195,8 +191,9 @@ void bad() well-formed, must not invoke undefined behavior, and must not throw exceptions.

    Effects: Constructs a shared_ptr, storing a copy of p.

    -

    Postconditions: use count is 1.

    -

    Throws: std::bad_alloc.

    +

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

    +

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

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

    Notes: p must be a pointer to an object that was @@ -208,28 +205,11 @@ void bad() 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.

    -

    In the current implementation, if p is convertible to counted_base - *, shared_ptr will use the embedded reference - count supplied by counted_base. This is an (experimental) - attempt to provide a way for shared_ptr to be constructed from - a raw pointer such as this. A free function shared_from_this(q) - performs the conversion when q is convertible to counted_base - const *.

    -

    The optional intrusive counting employed by the current implementation allows - shared_ptr to interoperate with intrusive_ptr, an - experimental generic intrusive-counted smart pointer.

    -

    Another possible implementation is to use a global pointer-to-count map instead - of intrusive counting. shared_from_this would no longer be - O(1), which is a concern for some users, although I do not expect any - performance problems, since the operation is rare. Maintaining a global map is - difficult; it needs to be initialized before any shared_ptr instances - are constructed, and the initialization needs to be thread safe. In addition, - under the Windows dynamic library model, it is possible for several maps to - exist.

    -

    It is not yet clear which implementation should be used, or whether the - specification should allow both; nevertheless, the ability to make a shared_ptr - from this is considered essential by experienced smart pointer - users.]

    +

    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.]

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

    Requirements: p must be convertible to T *. D @@ -238,8 +218,9 @@ void bad() well-formed, must not invoke undefined behavior, and must not throw exceptions.

    Effects: Constructs a shared_ptr, storing a copy of p and d.

    -

    Postconditions: use count is 1.

    -

    Throws: std::bad_alloc.

    +

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

    +

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

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

    Notes: When the the time comes to delete the object pointed to by p, the stored copy of d is invoked with the stored copy of p @@ -250,38 +231,39 @@ void bad() 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.

    + to a statically allocated object, and other variations allow a shared_ptr + to be used as a wrapper for another smart pointer, easing interoperability.

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

    The requirement that the copy constructor of D does not throw comes from the pass by value. If the copy constructor throws, the pointer is leaked. - Removing the requirement requires a pass by (const) reference. The problems are - that (1) pass by value conveniently changes functions (function references) to - function pointers (this has to be performed manually otherwise and some - compilers may not be able to do it) and (2) const references don't currently - (per the standard) bind to functions. This can be solved (I think) but it - requires an overload set that breaks on many compilers due to 14.5.5.2 problems - (and of course it will break on compilers that don't do partial ordering at - all.)

    -

    The requrement will be removed when the aforementioned issues are resolved.]

    + Removing the requirement requires a pass by (const) reference.

    +

    Pass by reference is problematic since (1) pass by value conveniently changes + functions (function references) to function pointers (this has to be performed + manually otherwise and some compilers may not be able to do it) and (2) const + references don't currently (per the standard) bind to functions. This can be + solved (I think) but it requires an overload set that breaks on many compilers + due to 14.5.5.2 problems (and of course it will break on compilers that don't + do partial ordering at all.)

    +

    The main problem with pass by reference, though, 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: Constructs a shared_ptr, as if by storing a copy of the - pointer stored in r.

    -

    Postconditions: use count for all copies is - increased by one.

    +

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

    +

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

    Throws: nothing.

    -

    [The postcondition will be relaxed when a default-constructed shared_ptr - is being copied.]

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

    Effects: Constructs a shared_ptr, as if by storing a copy of the - pointer stored in r.

    -

    Postconditions: use count for all copies is - increased by one.

    -

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

    +

    Effects: If r is empty, constructs an empty shared_ptr; + otherwise, constructs a shared_ptr that shares ownership with r + and stores a copy of the pointer stored in r.

    +

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

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

    @@ -299,21 +281,22 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r); // never
    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 is 1.

    -

    Throws: std::bad_alloc.

    +

    Postconditions: use_count() == 1.

    +

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

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

    [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.]

    + by design, as the constructor offers the strong guarantee; an rvalue reference + would solve this problem, too.]

    destructor

    ~shared_ptr(); // never throws

    Effects: If *this is the sole owner (use_count() == 1), - destroys the object pointed to by the stored pointer.

    -

    Postconditions: use count for all remaining - copies is decreased by one.

    + destroys the object pointed to by the stored pointer as specified at + construction time.

    Throws: nothing.

    assignment

    @@ -327,8 +310,7 @@ template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & 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<int> p(new int);
     shared_ptr<void> q(p);
     p = p;
     q = p;
    @@ -342,12 +324,10 @@ q = p;
     				actually applies here, so it's better to be explicit about the possible 
     				optimizations.]

    reset

    -
    void reset();
    +
    void reset(); // never throws

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

    -

    [reset() will offer the nothrow guarantee in a future - implementation.]

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

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

    @@ -384,13 +364,12 @@ q = p; If you are using unique() to implement copy on write, do not rely on a specific value when the stored pointer is zero.

    -

    [In a future release, unique() will return an unspecified value - for a default-constructed shared_ptr.]

    use_count

    long use_count() const; // never throws
    -

    Returns: the number of shared_ptr objects sharing ownership of the - stored pointer.

    +

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

    Throws: nothing.

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

    @@ -407,8 +386,8 @@ q = p; many of the implicit conversion pitfalls.

    [The conversion to bool is not merely syntactic sugar. It allows shared_ptrs - to be declared in conditions when using shared_dynamic_cast or - make_shared.]

    + to be declared in conditions when using dynamic_pointer_cast or + make_shared.]

    swap

    void swap(shared_ptr & b); // never throws
    @@ -429,12 +408,18 @@ q = p;

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

    Throws: nothing.

    -
    template<class T>
    -  bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws
    +
    template<class T, class U>
    +  bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
    -

    Returns: an unspecified value such that operator< is a strict - weak ordering as described in section 25.3 [lib.alg.sorting] of - the C++ standard.

    +

    Returns: an unspecified value such that

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

    Throws: nothing.

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

    @@ -468,23 +453,24 @@ q = p;

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

    -

    shared_static_cast

    +

    static_pointer_cast

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

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

    -

    Returns: A shared_ptr<T> object that stores a copy - of static_cast<T*>(r.get()) and shares ownership with r.

    +

    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 object twice.

    -

    shared_dynamic_cast

    +

    dynamic_pointer_cast

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

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

    @@ -492,42 +478,22 @@ 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 - ownership with r; + shared_ptr<T> object that stores a copy of it and shares + ownership with r;
    • - Otherwise, a default-constructed shared_ptr<T> object.
    -

    Throws: std::bad_alloc.

    -

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

    + Otherwise, an empty shared_ptr<T> object. +

    Throws: nothing.

    Notes: the seemingly equivalent expression

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

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

    -

    shared_polymorphic_cast

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

    operator<<

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

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

    -

    Returns: A shared_ptr<T> object that stores a copy - of polymorphic_cast<T*>(r.get()) - and shares ownership with r.

    -

    Throws: std::bad_cast when the pointer cannot be - converted.

    -

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

    -
    -

    shared_polymorphic_downcast

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

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

    -

    Returns: A shared_ptr<T> object that stores a copy - of polymorphic_downcast<T*>(r.get()) - and shares ownership with r.

    -

    Throws: nothing.

    +

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

    +

    Returns: os.

    Example

    See shared_ptr_example.cpp for a complete @@ -563,8 +529,7 @@ q = p; underneath.)

    Any other simultaneous accesses result in undefined behavior.

    Examples:

    -
    -shared_ptr<int> p(new int(42));
    +		
    shared_ptr<int> p(new int(42));
     
     //--- Example 1 ---
     
    @@ -577,7 +542,6 @@ shared_ptr<int> p3(p); // OK, multiple reads are safe
     //--- Example 2 ---
     
     // thread A
    -
     p.reset(new int(1912)); // writes p
     
     // thread B
    @@ -668,11 +632,12 @@ int * p = a.release();
     			implementation or a linked list implementation, or some other specific 
     			implementation. This is not the intent.


    -

    Revised $Date$

    +

    + $Date$

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

    From 3e616752c9900b94026bf119699bce731401a45c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 4 Jan 2003 14:24:14 +0000 Subject: [PATCH 179/513] weak_ptr documentation updated; still a work in progress. [SVN r16748] --- include/boost/shared_ptr.hpp | 2 +- include/boost/weak_ptr.hpp | 6 +- shared_ptr.htm | 92 ++++++++----- weak_ptr.htm | 251 +++++++++++++++++------------------ 4 files changed, 186 insertions(+), 165 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 3f988a7..debb9a7 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -5,7 +5,7 @@ // shared_ptr.hpp // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. -// Copyright (c) 2001, 2002 Peter Dimov +// Copyright (c) 2001, 2002, 2003 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 8c2a977..9d56858 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -4,7 +4,7 @@ // // weak_ptr.hpp // -// Copyright (c) 2001, 2002 Peter Dimov +// Copyright (c) 2001, 2002, 2003 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. @@ -37,7 +37,7 @@ public: typedef T element_type; - weak_ptr(): px(0), pn() + weak_ptr(): px(0), pn() // never throws in 1.30+ { } @@ -92,7 +92,7 @@ public: #endif - void reset() + void reset() // never throws in 1.30+ { this_type().swap(*this); } diff --git a/shared_ptr.htm b/shared_ptr.htm index 6c7b012..b2f9dcf 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -8,6 +8,7 @@

    c++boost.gif (8819 bytes)shared_ptr class template

    Introduction
    + Motivation
    Best Practices
    Synopsis
    Members
    @@ -46,6 +47,8 @@ to shared_ptr<T const>, to shared_ptr<U> where U is an accessible base of T, and to shared_ptr<void>.

    +

    Motivation

    +

    [...]

    Best Practices

    A simple guideline that nearly eliminates the possibility of memory leaks is: always use a named smart pointer variable to hold the result of new. @@ -262,22 +265,11 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r); // never

    Effects: If r is empty, constructs an empty shared_ptr; otherwise, constructs a shared_ptr that shares ownership with r - and stores a copy of the pointer stored in r.

    -

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

    + and stores a copy of the pointer stored in r.

    +

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

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

    -

    [This constructor is an optional part of the specification; it depends on the - existence of weak_ptr. It is true that weak_ptr - support imposes overhead on every shared_ptr user, regardless - of whether weak pointers are used.

    -

    On the other hand, cyclic references are a serious problem with all reference - counted designs. Not providing a solution within the library is unacceptable; - if users are forced to reinvent the weak pointer wheel, there is substantial - probability that they will get it wrong, as designing a safe weak_ptr - interface is non-trivial.

    -

    My opinion is that the added functionality is worth the cost. weak_ptr - is provided in the reference implementation as a proof of concept.]

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

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

    @@ -580,45 +572,60 @@ p3.reset(new int(2)); // undefined, multiple writes

    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?
    + as to find the most suitable for the job at hand?

    +

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

    + ownership with a linked pointer (used by library B.)
    +

    Q. Why doesn't shared_ptr have template parameters supplying - traits or policies to allow extensive user customization?
    + 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 based smart pointers should read - Modern C++ Design by Andrei Alexandrescu.)

    + Modern C++ Design by Andrei Alexandrescu.)
    +

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

    +

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

    -

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

    +

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

    +

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

    -

    Q. Why doesn't shared_ptr (or any of the other Boost smart - pointers) supply an automatic conversion to T*?
    - A. Automatic conversion is believed to be too error prone.

    -

    Q. Why does shared_ptr supply use_count()?
    + safe.
    +

    +

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

    +

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

    +

    Q. Why does shared_ptr supply use_count()?

    +

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

    -

    Q. Why doesn't shared_ptr specify complexity requirements?
    + 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 - stringent complexity requirements.

    -

    Q. Why doesn't shared_ptr provide a release() function?
    + stringent complexity requirements.
    +

    +

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

    +

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

    + because the other copy will still destroy the object.

    Consider:

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

    Q. Why doesn't shared_ptr provide (your pet feature here)?
    +

    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 + non-const pointer to the element type?

    +

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

    +

    Q. Why doesn't shared_ptr provide (your pet feature here)?

    +

    A. Because (your pet feature here) would mandate a reference counted implementation or a linked list implementation, or some other specific - implementation. This is not the intent.

    + implementation. This is not the intent.
    +


    $Date$

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

    diff --git a/weak_ptr.htm b/weak_ptr.htm index d0273b4..1bafb3e 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -4,32 +4,39 @@ weak_ptr - -

    c++boost.gif (8819 bytes)weak_ptr + +

    c++boost.gif (8819 bytes)weak_ptr class template

    -

    The weak_ptr class template stores a "weak reference" to an - object that's already managed by a shared_ptr. To access the object, a - weak_ptr can be converted to a shared_ptr using +

    Introduction
    + Motivation
    + Synopsis
    + Members
    + Free Functions
    + Frequently Asked Questions +

    +

    Introduction

    +

    The weak_ptr class template stores a "weak reference" to an object that's + already managed by a shared_ptr. To access the object, a weak_ptr + can be converted to a shared_ptr using the shared_ptr constructor or the function make_shared. When the last shared_ptr to the object - goes away and the object is deleted, the attempt to obtain a shared_ptr -  from the weak_ptr instances that refer to the deleted object will - fail: the constructor will throw an exception of type boost::use_count_is_zero, - and make_shared will return a default constructed (null) shared_ptr.

    + goes away and the object is deleted, the attempt to obtain a shared_ptr + from the weak_ptr instances that refer to the deleted object will fail: + the constructor will throw an exception of type boost::bad_weak_ptr, + and make_shared will return an empty shared_ptr.

    Every weak_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 weak_ptr works with the standard library's associative containers.

    +

    weak_ptr operations never throw exceptions.

    The class template is parameterized on T, the type of the object pointed - to. T must meet the smart pointer - common requirements.

    -

    Compared to shared_ptr, weak_ptr provides - a very limited subset of operations since accessing its stored pointer is - often dangerous in multithreaded programs, and sometimes unsafe even - within a single thread (that is, it may invoke undefined behavior.) - Consider, for example, this innocent piece of code:

    -
    -shared_ptr<int> p(new int(5));
    +			to.

    +

    Compared to shared_ptr, weak_ptr provides a + very limited subset of operations since accessing its stored pointer is often + dangerous in multithreaded programs, and sometimes unsafe even within a single + thread (that is, it may invoke undefined behavior.) Consider, for example, this + innocent piece of code:

    +
    shared_ptr<int> p(new int(5));
     weak_ptr<int> q(p);
     
     // some time later
    @@ -44,13 +51,12 @@ if(int * r = q.get())
     			is a dangling pointer.

    The solution to this problem is to create a temporary shared_ptr from q:

    -
    -shared_ptr<int> p(new int(5));
    +		
    shared_ptr<int> p(new int(5));
     weak_ptr<int> q(p);
     
     // some time later
     
    -if(shared_ptr<int> r = make_shared(q))
    +if(shared_ptr<int> r = make_shared(q))
     {
         // use *r
     }
    @@ -58,45 +64,53 @@ if(shared_ptr<int> r = make_shared(q))
     		

    Now r holds a reference to the object that was pointed by q. Even if p.reset() is executed in another thread, the object will stay alive until r goes out of scope (or is reset.)

    +

    Motivation

    +

    [a mechanism to avoid dangling pointers]

    +

    [a way to break shared_ptr cycles]

    +

    [weak pointer to this - a technique to obtain a shared_ptr to this from within a + member function]

    +

    [map<weak_ptr, ...> - a technique to associate arbitrary data with + shared_ptr managed objects]

    +

    [gameobject/tank example]

    +

    [cache example]

    +

    [comparison: weak_ptr vs observer and other approaches]

    +

    [hard to reinvent, subtle implementation, with many pitfalls]

    Synopsis

    namespace boost {
     
       template<class T> class weak_ptr {
     
         public:
    -      typedef T element_type;
    +      typedef T element_type;
     
    -      weak_ptr();
    -      template<class Y> weak_ptr(shared_ptr<Y> const & r); // never throws
    -      ~weak_ptr(); // never throws
    +      weak_ptr();
     
    -      weak_ptr(weak_ptr const & r); // never throws
    -      template<class Y> weak_ptr(weak_ptr<Y> const & r); // never throws
    +      template<class Y> weak_ptr(shared_ptr<Y> const & r);
    +      weak_ptr(weak_ptr const & r);
    +      template<class Y> weak_ptr(weak_ptr<Y> const & r);
     
    -      weak_ptr & operator=(weak_ptr const & r); // never throws  
    -      template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r); // never throws
    -      template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r); // never throws
    +      ~weak_ptr();
     
    -      void reset();
    -      T * get() const; // never throws; deprecated, will disappear
    +      weak_ptr & operator=(weak_ptr const & r);
    +      template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
    +      template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);
     
    -      long use_count() const; // never throws
    -      bool expired() const; // never throws
    +      void reset();
     
    -      void swap(weak_ptr<T> & b); // never throws
    +      long use_count() const;
    +      bool expired() const;
    +
    +      void swap(weak_ptr<T> & b);
       };
     
       template<class T, class U>
    -    bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    -  template<class T, class U>
    -    bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    -  template<class T>
    -    bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws
    -
    -  template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b); // never throws
    +    bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);
     
       template<class T>
    -    shared_ptr<T> make_shared(weak_ptr<T> const & r); // never throws
    +    void swap(weak_ptr<T> & a, weak_ptr<T> & b);
    +
    +  template<class T>
    +    shared_ptr<T> make_shared(weak_ptr<T> const & r);
     
     }
     
    @@ -106,49 +120,34 @@ if(shared_ptr<int> r = make_shared(q))

    Provides the type of the template parameter T.

    -

    constructors

    -
     weak_ptr();
    +

    constructors

    +
    weak_ptr();
    -

    Effects: Constructs a weak_ptr.

    -

    Postconditions: use count is 0; the stored - pointer is 0.

    -

    Throws: std::bad_alloc.

    -

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

    -

    Notes: T need not be a complete type. See the smart pointer - common requirements.

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

    Effects: Constructs an empty weak_ptr.

    +

    Postconditions: use count() == 0???.

    +

    Throws: nothing.

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

    Effects: Constructs a weak_ptr, as if by storing a copy of the +

    Effects: If r is empty, constructs an empty + weak_ptr; otherwise, constructs a weak_ptr that shares + ownership with r as if by storing a copy of the pointer stored in r.

    Throws: nothing.

    -

    Notes: The use count for all copies is - unchanged. When the last shared_ptr is destroyed, the use count and - stored pointer become 0.

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

    Effects: Constructs a weak_ptr, as if by storing a copy of the - pointer stored in r.

    -

    Throws: nothing.

    -

    Notes: The use count for all copies is - unchanged.

    destructor

    -
    ~weak_ptr(); // never throws
    +
    ~weak_ptr();

    Effects: Destroys this weak_ptr but has no effect on the object its stored pointer points to.

    Throws: nothing.

    -

    Notes: T need not be a complete type. See the smart pointer - common requirements.

    assignment

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

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

    Throws: nothing.

    @@ -160,75 +159,50 @@ template<class Y> weak_ptr & operator=(share

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

    -

    get

    -
    T * get() const; // never throws
    -
    -

    Returns: the stored pointer (0 if all shared_ptr objects for that - pointer are destroyed.)

    -

    Throws: nothing.

    -

    Notes: Using get in multithreaded code is dangerous. After the - function returns, the pointed-to object may be destroyed by a different thread, - since the weak_ptr doesn't affect its use_count.

    -
    -

    [get is very error-prone. Even single-threaded code may experience - problems, as the returned pointer may be invalidated at any time, for example, - indirectly by a member function of the pointee.

    -

    get is deprecated, and it will disappear in a future - release. Do not use it.]

    use_count

    -
    long use_count() const; // never throws
    +
    long use_count() const;
    -

    Returns: the number of shared_ptr objects sharing ownership of the - stored pointer.

    +

    Returns: if *this is empty, an unspecified + nonnegative value; otherwise, the number of shared_ptr objects that share + ownership with *this.

    Throws: nothing.

    Notes: use_count() is not necessarily efficient. Use only - for debugging and testing purposes, not for production code. T need not - be a complete type. See the smart pointer - common requirements.

    + for debugging and testing purposes, not for production code.

    expired

    -
    bool expired() const; // never throws
    +
    bool expired() const;

    Returns: use_count() == 0.

    Throws: nothing.

    -

    Notes: expired() may be faster than use_count(). - T need not be a complete type. See the smart pointer - common requirements.

    +

    Notes: expired() may be faster than use_count().

    swap

    -
    void swap(weak_ptr & b); // never throws
    +
    void swap(weak_ptr & b);

    Effects: Exchanges the contents of the two smart pointers.

    Throws: nothing.

    -

    Notes: T need not be a complete type. See the smart pointer - common requirements.

    Free Functions

    comparison

    template<class T, class U>
    -  bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    -template<class T, class U>
    -  bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
    + bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);
    -

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

    -

    Throws: nothing.

    -

    Notes: T need not be a complete type. See the smart pointer - common requirements.

    -
    -
    template<class T>
    -  bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws
    -
    -

    Returns: an implementation-defined value such that operator< is - a strict weak ordering as described in section 25.3 [lib.alg.sorting] - of the C++ standard.

    +

    Returns: an unspecified value such that

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

    Throws: nothing.

    Notes: Allows weak_ptr objects to be used as keys in - associative containers. T need not be a complete type. See the smart - pointer common requirements.

    + associative containers.

    swap

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

    Effects: Equivalent to a.swap(b).

    Throws: nothing.

    @@ -237,19 +211,44 @@ template<class T, class U>

    make_shared

    template<class T>
    -  shared_ptr<T> make_shared(weak_ptr<T> & const r) // never throws
    + shared_ptr<T> make_shared(weak_ptr<T> & const r)

    Returns: r.expired()? shared_ptr<T>(): shared_ptr<T>(r).

    Throws: nothing.

    -

    [The current implementation of make_shared can propagate - an exception thrown by the shared_ptr default - constructor, so it doesn't meet the stated requirements. In a future - release, this default constructor will not throw.]

    +

    Frequently Asked Questions

    +

    Q. Can an object create a weak_ptr to itself in its + constructor?

    +

    A. No. A weak_ptr can only be created from a shared_ptr, + and at object construction time no shared_ptr to the object + exists yet. Even if you could create a temporary shared_ptr to + this, it would go out of scope at the end of the constructor, and + all weak_ptr instances would instantly expire.

    +

    The solution is to make the constructor private, and supply a factory function + that returns a shared_ptr:
    +

    +
    +class X
    +{
    +private:
    +
    +    X();
    +
    +public:
    +
    +    static shared_ptr<X> create()
    +    {
    +        shared_ptr<X> px(new X);
    +        // create weak pointers from px here
    +        return px;
    +    }
    +};
    +
    +



    -

    Revised 29 August 2002

    +

    $Date$

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

    From e3f2329c1463d433b9ac90fdce2590fcd305a297 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 7 Jan 2003 15:34:56 +0000 Subject: [PATCH 180/513] report_unreachable_objects() added to sp_debug_hooks.cpp [SVN r16780] --- include/boost/detail/shared_count.hpp | 72 +++++++++--- sp_debug_hooks.cpp | 157 ++++++++++++++++++++++++++ 2 files changed, 213 insertions(+), 16 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index d3c010f..9be3d5e 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -30,6 +30,7 @@ #include // for std::exception #include // for std::bad_alloc #include // for std::type_info in get_deleter +#include // for std::size_t #ifdef __BORLANDC__ # pragma warn -8026 // Functions with excep. spec. are not expanded inline @@ -43,10 +44,10 @@ namespace boost #if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) -void sp_scalar_constructor_hook(void * p); -void sp_array_constructor_hook(void * p); -void sp_scalar_destructor_hook(void * p); -void sp_array_destructor_hook(void * p); +void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn); +void sp_array_constructor_hook(void * px); +void sp_scalar_destructor_hook(void * px, std::size_t size, void * pn); +void sp_array_destructor_hook(void * px); #endif @@ -188,31 +189,31 @@ private: #if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) -template void cbi_call_constructor_hook(T * p, checked_deleter const &, int) +template void cbi_call_constructor_hook(counted_base * pn, T * px, checked_deleter const &, int) { - boost::sp_scalar_constructor_hook(p); + boost::sp_scalar_constructor_hook(px, sizeof(T), pn); } -template void cbi_call_constructor_hook(T * p, checked_array_deleter const &, int) +template void cbi_call_constructor_hook(counted_base *, T * px, checked_array_deleter const &, int) { - boost::sp_array_constructor_hook(p); + boost::sp_array_constructor_hook(px); } -template void cbi_call_constructor_hook(P const &, D const &, long) +template void cbi_call_constructor_hook(counted_base *, P const &, D const &, long) { } -template void cbi_call_destructor_hook(T * p, checked_deleter const &, int) +template void cbi_call_destructor_hook(counted_base * pn, T * px, checked_deleter const &, int) { - boost::sp_scalar_destructor_hook(p); + boost::sp_scalar_destructor_hook(px, sizeof(T), pn); } -template void cbi_call_destructor_hook(T * p, checked_array_deleter const &, int) +template void cbi_call_destructor_hook(counted_base *, T * px, checked_array_deleter const &, int) { - boost::sp_array_destructor_hook(p); + boost::sp_array_destructor_hook(px); } -template void cbi_call_destructor_hook(P const &, D const &, long) +template void cbi_call_destructor_hook(counted_base *, P const &, D const &, long) { } @@ -244,14 +245,14 @@ public: counted_base_impl(P p, D d): ptr(p), del(d) { #if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) - detail::cbi_call_constructor_hook(p, d, 0); + detail::cbi_call_constructor_hook(this, p, d, 0); #endif } virtual void dispose() // nothrow { #if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) - detail::cbi_call_destructor_hook(ptr, del, 0); + detail::cbi_call_destructor_hook(this, ptr, del, 0); #endif del(ptr); } @@ -276,6 +277,13 @@ public: #endif }; +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + +int const shared_count_id = 0x2C35F101; +int const weak_count_id = 0x298C38A4; + +#endif + class weak_count; class shared_count @@ -284,15 +292,25 @@ private: counted_base * pi_; +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + int id_; +#endif + friend class weak_count; public: shared_count(): pi_(0) // nothrow +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + , id_(shared_count_id) +#endif { } template shared_count(P p, D d): pi_(0) +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + , id_(shared_count_id) +#endif { #ifndef BOOST_NO_EXCEPTIONS @@ -325,6 +343,9 @@ public: template explicit shared_count(std::auto_ptr & r): pi_(new counted_base_impl< Y *, checked_deleter >(r.get(), checked_deleter())) +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + , id_(shared_count_id) +#endif { r.release(); } @@ -337,6 +358,9 @@ public: } shared_count(shared_count const & r): pi_(r.pi_) // nothrow +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + , id_(shared_count_id) +#endif { if(pi_ != 0) pi_->add_ref(); } @@ -397,20 +421,33 @@ private: counted_base * pi_; +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + int id_; +#endif + friend class shared_count; public: weak_count(): pi_(0) // nothrow +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + , id_(weak_count_id) +#endif { } weak_count(shared_count const & r): pi_(r.pi_) // nothrow +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + , id_(shared_count_id) +#endif { if(pi_ != 0) pi_->weak_add_ref(); } weak_count(weak_count const & r): pi_(r.pi_) // nothrow +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + , id_(shared_count_id) +#endif { if(pi_ != 0) pi_->weak_add_ref(); } @@ -464,6 +501,9 @@ public: }; inline shared_count::shared_count(weak_count const & r): pi_(r.pi_) +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + , id_(shared_count_id) +#endif { if(pi_ != 0) { diff --git a/sp_debug_hooks.cpp b/sp_debug_hooks.cpp index 741ea3a..26d9c51 100644 --- a/sp_debug_hooks.cpp +++ b/sp_debug_hooks.cpp @@ -14,11 +14,17 @@ #if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) #include +#include +#include #include #include +#include +#include int const m = 2; // m * sizeof(int) must be aligned appropriately +// magic values to mark heap blocks with + int const allocated_scalar = 0x1234560C; int const allocated_array = 0x1234560A; int const adopted_scalar = 0x0567890C; @@ -27,6 +33,8 @@ int const deleted = 0x498769DE; using namespace std; // for compilers where things aren't in std +// operator new + static new_handler get_new_handler() { new_handler p = set_new_handler(0); @@ -103,6 +111,139 @@ void * operator new[](size_t n, nothrow_t const &) throw() #endif +// cycle detection + +typedef std::map< void *, std::pair > map_type; + +static map_type & get_map() +{ + static map_type m; + return m; +} + +typedef boost::detail::lightweight_mutex mutex_type; + +static mutex_type & get_mutex() +{ + static mutex_type m; + return m; +} + +static void * init_mutex_before_main = &get_mutex(); + +namespace +{ + class X; + + struct count_layout + { + boost::detail::counted_base * pi; + int id; + }; + + struct shared_ptr_layout + { + X * px; + count_layout pn; + }; +} + +// assume 4 byte alignment for pointers when scanning +size_t const pointer_align = 4; + +static void scan_and_count(void const * area, size_t size, map_type const & m, std::map & m2) +{ + unsigned char const * p = static_cast(area); + + for(size_t n = 0; n < size; p += pointer_align, n += pointer_align) + { + shared_ptr_layout const * q = reinterpret_cast(p); + + if(q->pn.id == boost::detail::shared_count_id && m.count(q->pn.pi) != 0) + { + ++m2[q->pn.pi]; + } + } +} + +static bool scan_and_mark(void const * area, size_t size, map_type const & m, std::map & m2) +{ + bool updated = false; + unsigned char const * p = static_cast(area); + + for(size_t n = 0; n < size; p += pointer_align, n += pointer_align) + { + shared_ptr_layout const * q = reinterpret_cast(p); + + if(q->pn.id == boost::detail::shared_count_id && m.count(q->pn.pi) != 0) + { + // mark as reachable + + if(m2[q->pn.pi] != 0) + { + updated = true; + m2[q->pn.pi] = 0; + } + } + } + + return updated; +} + +void report_unreachable_objects() +{ + std::map m2; + + mutex_type::scoped_lock lock(get_mutex()); + + map_type & m = get_map(); + + // scan objects for shared_ptr members, compute internal counts + + for(map_type::iterator i = m.begin(); i != m.end(); ++i) + { + boost::detail::counted_base const * p = static_cast(i->first); + + BOOST_ASSERT(p->use_count() != 0); // there should be no inactive counts in the map + + scan_and_count(i->second.first, i->second.second, m, m2); + } + + // mark reachable objects + + bool updated; + + do + { + updated = false; + + for(map_type::iterator i = m.begin(); i != m.end(); ++i) + { + boost::detail::counted_base const * p = static_cast(i->first); + + if(p->use_count() != m2[p] && scan_and_mark(i->second.first, i->second.second, m, m2)) + { + updated = true; + } + } + + } while(updated); + + // report unreachable objects + + for(map_type::iterator i = m.begin(); i != m.end(); ++i) + { + boost::detail::counted_base const * p = static_cast(i->first); + + if(p->use_count() == m2[p]) + { + std::cerr << "Unreachable object at " << i->second.first << ", " << i->second.second << " bytes long.\n"; + } + } +} + +// debug hooks + namespace boost { @@ -120,6 +261,13 @@ void sp_scalar_constructor_hook(void * p) *pm = adopted_scalar; } +void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn) +{ + sp_scalar_constructor_hook(px); + mutex_type::scoped_lock lock(get_mutex()); + get_map()[pn] = std::make_pair(px, size); +} + void sp_scalar_destructor_hook(void * p) { if(p == 0) return; @@ -132,6 +280,13 @@ void sp_scalar_destructor_hook(void * p) *pm = allocated_scalar; } +void sp_scalar_destructor_hook(void * px, std::size_t /*size*/, void * pn) +{ + sp_scalar_destructor_hook(px); + mutex_type::scoped_lock lock(get_mutex()); + get_map().erase(pn); +} + // It is not possible to handle the array hooks in a portable manner. // The implementation typically reserves a bit of storage for the number // of objects in the array, and the argument of the array hook isn't @@ -173,6 +328,8 @@ void sp_array_destructor_hook(void * /* p */) } // namespace boost +// operator delete + void operator delete(void * p) throw() { if(p == 0) return; From 1dee6e02294fe547717190eb5bcb86bde149aad4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 7 Jan 2003 23:12:02 +0000 Subject: [PATCH 181/513] Small optimization. [SVN r16790] --- sp_debug_hooks.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sp_debug_hooks.cpp b/sp_debug_hooks.cpp index 26d9c51..3d5fb15 100644 --- a/sp_debug_hooks.cpp +++ b/sp_debug_hooks.cpp @@ -159,7 +159,7 @@ static void scan_and_count(void const * area, size_t size, map_type const & m, s { shared_ptr_layout const * q = reinterpret_cast(p); - if(q->pn.id == boost::detail::shared_count_id && m.count(q->pn.pi) != 0) + if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m.count(q->pn.pi) != 0) { ++m2[q->pn.pi]; } @@ -175,7 +175,7 @@ static bool scan_and_mark(void const * area, size_t size, map_type const & m, st { shared_ptr_layout const * q = reinterpret_cast(p); - if(q->pn.id == boost::detail::shared_count_id && m.count(q->pn.pi) != 0) + if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m.count(q->pn.pi) != 0) { // mark as reachable From 8448bbf0b9b2c73f6f75691633b0003d60aa955d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 8 Jan 2003 15:01:04 +0000 Subject: [PATCH 182/513] Fixes. [SVN r16795] --- sp_debug_hooks.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sp_debug_hooks.cpp b/sp_debug_hooks.cpp index 3d5fb15..458810f 100644 --- a/sp_debug_hooks.cpp +++ b/sp_debug_hooks.cpp @@ -155,7 +155,7 @@ static void scan_and_count(void const * area, size_t size, map_type const & m, s { unsigned char const * p = static_cast(area); - for(size_t n = 0; n < size; p += pointer_align, n += pointer_align) + for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align) { shared_ptr_layout const * q = reinterpret_cast(p); @@ -171,7 +171,7 @@ static bool scan_and_mark(void const * area, size_t size, map_type const & m, st bool updated = false; unsigned char const * p = static_cast(area); - for(size_t n = 0; n < size; p += pointer_align, n += pointer_align) + for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align) { shared_ptr_layout const * q = reinterpret_cast(p); From d36a215554bddce841c4e16a5858c0fe3922f4bb Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 9 Jan 2003 13:11:10 +0000 Subject: [PATCH 183/513] fix invalid bookmarks [SVN r16824] --- scoped_array.htm | 7 +++---- scoped_ptr.htm | 7 +++---- shared_array.htm | 9 ++++----- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/scoped_array.htm b/scoped_array.htm index 5e80f62..0fb8932 100644 --- a/scoped_array.htm +++ b/scoped_array.htm @@ -34,7 +34,7 @@

    Synopsis

    namespace boost {
     
    -  template<class T> class scoped_array : noncopyable {
    +  template<class T> class scoped_array : noncopyable {
     
         public:
           typedef T element_type;
    @@ -100,12 +100,11 @@
     		

    Equivalent to a.swap(b). Matches the interface of std::swap. Provided as an aid to generic programming.


    -

    Revised - 1 February 2002

    +

    Revised 09 January 2003

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

    - + \ No newline at end of file diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 148cd42..8af72c4 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -34,7 +34,7 @@

    Synopsis

    namespace boost {
     
    -  template<class T> class scoped_ptr : noncopyable {
    +  template<class T> class scoped_ptr : noncopyable {
     
        public:
          typedef T element_type;
    @@ -165,12 +165,11 @@ Buckle my shoe
    given context. Use std::auto_ptr where transfer of ownership is required. (supplied by Dave Abrahams)


    -

    Revised - 17 September 2002

    +

    Revised 09 January 2003

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

    - + \ No newline at end of file diff --git a/shared_array.htm b/shared_array.htm index 26a6dab..8a7cc34 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -26,8 +26,8 @@

    A shared_ptr to a std::vector is an alternative to a shared_array that is a bit heavier duty but far more flexible.

    The class template is parameterized on T, the type of the object pointed - to. T must meet the smart pointer - common requirements.

    + to. T must meet the smart pointer + common requirements.

    Synopsis

    namespace boost {
     
    @@ -168,12 +168,11 @@ template<class T>
     		

    Equivalent to a.swap(b). Matches the interface of std::swap. Provided as an aid to generic programming.


    -

    Revised - 8 February 2002

    +

    Revised 09 January 2003

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

    - + \ No newline at end of file From 8eaf187dbdb91daecbdffb0fbde1c3ff7ff08cb8 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 9 Jan 2003 13:37:41 +0000 Subject: [PATCH 184/513] fix bookmarks [SVN r16827] --- scoped_array.htm | 7 ++++--- scoped_ptr.htm | 7 ++++--- shared_array.htm | 15 ++++++++------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/scoped_array.htm b/scoped_array.htm index 0fb8932..9fef424 100644 --- a/scoped_array.htm +++ b/scoped_array.htm @@ -14,9 +14,10 @@

    The scoped_array template is a simple solution for simple needs. It supplies a basic "resource acquisition is initialization" facility, without shared-ownership or transfer-of-ownership semantics. Both its name and - enforcement of semantics (by being - noncopyable) signal its intent to retain ownership solely within the - current scope. Because it is noncopyable, + enforcement of semantics (by being + noncopyable) signal its intent to retain ownership solely within the + current scope. Because it is + noncopyable, it is safer than shared_array for pointers which should not be copied.

    Because scoped_array is so simple, in its usual implementation every operation is as fast as a built-in array pointer and it has no more space diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 8af72c4..4c1dba9 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -14,9 +14,10 @@

    The scoped_ptr template is a simple solution for simple needs. It supplies a basic "resource acquisition is initialization" facility, without shared-ownership or transfer-of-ownership semantics. Both its name and - enforcement of semantics (by being - noncopyable) signal its intent to retain ownership solely within the - current scope. Because it is noncopyable, + enforcement of semantics (by being + noncopyable) signal its intent to retain ownership solely within the + current scope. Because it is + noncopyable, it is safer than shared_ptr or std::auto_ptr for pointers which should not be copied.

    Because scoped_ptr is simple, in its usual implementation every operation diff --git a/shared_array.htm b/shared_array.htm index 8a7cc34..ecf84ae 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -97,7 +97,7 @@ a pointer with a value of 0 is harmless. T need not be a complete type. The guarantee that this does not throw exceptions depends on the requirement that the deleted object's destructor does not throw exceptions. See the smart - pointer common requirements.

    + pointer common requirements.

    assignment

    shared_array & operator=(shared_array const & r); // never throws

    Constructs a new shared_array as described above, @@ -124,16 +124,16 @@

    get

    T * get() const; // never throws

    Returns the stored pointer. T need not be a complete type. See the smart - pointer common requirements.

    + pointer common requirements.

    unique

    bool unique() const; // never throws

    Returns true if no other shared_array is sharing ownership of the stored pointer, false otherwise. T need not be a complete type. See the smart - pointer common requirements.

    + pointer common requirements.

    use_count

    long use_count() const; // never throws

    Returns the number of shared_array objects sharing ownership of the - stored pointer. T need not be a complete type. See the smart pointer + stored pointer. T need not be a complete type. See the smart pointer common requirements.

    Because use_count is not necessarily efficient to implement for implementations of shared_array that do not use an explicit reference @@ -142,7 +142,7 @@

    swap

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

    Exchanges the contents of the two smart pointers. T need not be a - complete type. See the smart pointer common + complete type. See the smart pointer common requirements.

    Free Functions

    comparison

    @@ -153,7 +153,7 @@ template<class T> template<class T> bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws

    Compares the stored pointers of the two smart pointers. T need not be a - complete type. See the smart pointer common + complete type. See the smart pointer common requirements.

    The operator< overload is provided to define an ordering so that shared_array objects can be used in associative containers such as std::map. The @@ -168,7 +168,8 @@ template<class T>

    Equivalent to a.swap(b). Matches the interface of std::swap. Provided as an aid to generic programming.


    -

    Revised 09 January 2003

    +

    Revised + 09 January 2003

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided From 78a47d7619bf9c3bd3167790be3dcd0e0ae0d117 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 13 Jan 2003 17:11:28 +0000 Subject: [PATCH 185/513] Algorithm improvements, free_unreachable_objects() added. [SVN r16894] --- sp_debug_hooks.cpp | 150 +++++++++++++++++++++++++++++++-------------- 1 file changed, 103 insertions(+), 47 deletions(-) diff --git a/sp_debug_hooks.cpp b/sp_debug_hooks.cpp index 458810f..d289ba4 100644 --- a/sp_debug_hooks.cpp +++ b/sp_debug_hooks.cpp @@ -14,11 +14,12 @@ #if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) #include -#include +#include #include #include #include #include +#include #include int const m = 2; // m * sizeof(int) must be aligned appropriately @@ -113,7 +114,7 @@ void * operator new[](size_t n, nothrow_t const &) throw() // cycle detection -typedef std::map< void *, std::pair > map_type; +typedef std::map< void const *, std::pair > map_type; static map_type & get_map() { @@ -151,7 +152,9 @@ namespace // assume 4 byte alignment for pointers when scanning size_t const pointer_align = 4; -static void scan_and_count(void const * area, size_t size, map_type const & m, std::map & m2) +typedef std::map map2_type; + +static void scan_and_count(void const * area, size_t size, map_type const & m, map2_type & m2) { unsigned char const * p = static_cast(area); @@ -166,79 +169,132 @@ static void scan_and_count(void const * area, size_t size, map_type const & m, s } } -static bool scan_and_mark(void const * area, size_t size, map_type const & m, std::map & m2) +typedef std::deque open_type; + +static void scan_and_mark(void const * area, size_t size, map2_type & m2, open_type & open) { - bool updated = false; unsigned char const * p = static_cast(area); for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align) { shared_ptr_layout const * q = reinterpret_cast(p); - if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m.count(q->pn.pi) != 0) + if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0) { - // mark as reachable - - if(m2[q->pn.pi] != 0) - { - updated = true; - m2[q->pn.pi] = 0; - } + open.push_back(q->pn.pi); + m2.erase(q->pn.pi); } } - - return updated; } -void report_unreachable_objects() +static void find_unreachable_objects(map_type const & m, map2_type & m2) { - std::map m2; - - mutex_type::scoped_lock lock(get_mutex()); - - map_type & m = get_map(); - // scan objects for shared_ptr members, compute internal counts - for(map_type::iterator i = m.begin(); i != m.end(); ++i) { - boost::detail::counted_base const * p = static_cast(i->first); + for(map_type::const_iterator i = m.begin(); i != m.end(); ++i) + { + boost::detail::counted_base const * p = static_cast(i->first); - BOOST_ASSERT(p->use_count() != 0); // there should be no inactive counts in the map + BOOST_ASSERT(p->use_count() != 0); // there should be no inactive counts in the map - scan_and_count(i->second.first, i->second.second, m, m2); + scan_and_count(i->second.first, i->second.second, m, m2); + } } // mark reachable objects - bool updated; - - do { - updated = false; + open_type open; - for(map_type::iterator i = m.begin(); i != m.end(); ++i) + for(map2_type::iterator i = m2.begin(); i != m2.end(); ++i) { - boost::detail::counted_base const * p = static_cast(i->first); - - if(p->use_count() != m2[p] && scan_and_mark(i->second.first, i->second.second, m, m2)) - { - updated = true; - } + boost::detail::counted_base const * p = static_cast(i->first); + if(p->use_count() != i->second) open.push_back(p); } - } while(updated); - - // report unreachable objects - - for(map_type::iterator i = m.begin(); i != m.end(); ++i) - { - boost::detail::counted_base const * p = static_cast(i->first); - - if(p->use_count() == m2[p]) + for(open_type::iterator j = open.begin(); j != open.end(); ++j) { - std::cerr << "Unreachable object at " << i->second.first << ", " << i->second.second << " bytes long.\n"; + m2.erase(*j); } + + while(!open.empty()) + { + void const * p = open.front(); + open.pop_front(); + + map_type::const_iterator i = m.find(p); + BOOST_ASSERT(i != m.end()); + + scan_and_mark(i->second.first, i->second.second, m2, open); + } + } + + // m2 now contains the unreachable objects +} + +void report_unreachable_objects(bool verbose) +{ + map2_type m2; + + mutex_type::scoped_lock lock(get_mutex()); + + map_type const & m = get_map(); + + find_unreachable_objects(m, m2); + + if(verbose) + { + for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j) + { + map_type::const_iterator i = m.find(j->first); + BOOST_ASSERT(i != m.end()); +// std::cerr << "Unreachable object at " << i->second.first << ", " << i->second.second << " bytes long.\n"; + } + } + + if(verbose || !m2.empty()) + { + std::cerr << m2.size() << " unreachable objects.\n"; + } +} + +typedef std::deque< boost::shared_ptr > free_list_type; + +static void scan_and_free(void * area, size_t size, map2_type const & m2, free_list_type & free) +{ + unsigned char * p = static_cast(area); + + for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align) + { + shared_ptr_layout * q = reinterpret_cast(p); + + if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0 && q->px != 0) + { + boost::shared_ptr * ppx = reinterpret_cast< boost::shared_ptr * >(p); + free.push_back(*ppx); + ppx->reset(); + } + } +} + +void free_unreachable_objects() +{ + map2_type m2; + + mutex_type::scoped_lock lock(get_mutex()); + + map_type const & m = get_map(); + + find_unreachable_objects(m, m2); + + free_list_type free; + + for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j) + { + map_type::const_iterator i = m.find(j->first); + BOOST_ASSERT(i != m.end()); + scan_and_free(i->second.first, i->second.second, m2, free); } } From c5bae28eeb683d003be8fc2beacbcaa03daa1ef3 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 13 Jan 2003 18:32:16 +0000 Subject: [PATCH 186/513] use_count() postconditions added; enable_..._test.cpp renamed. [SVN r16896] --- include/boost/detail/shared_count.hpp | 4 +- ...this_test.cpp => shared_from_this_test.cpp | 4 +- shared_ptr.htm | 10 +- shared_ptr_test.cpp | 132 ++++++++++++------ sp_debug_hooks.cpp | 2 +- weak_ptr.htm | 6 +- weak_ptr_test.cpp | 52 ++++++- 7 files changed, 148 insertions(+), 62 deletions(-) rename enable_shared_from_this_test.cpp => shared_from_this_test.cpp (96%) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 9be3d5e..c2c10a0 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -8,7 +8,7 @@ // // detail/shared_count.hpp // -// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. @@ -386,7 +386,7 @@ public: long use_count() const // nothrow { - return pi_ != 0? pi_->use_count(): 42; // '42' is an example of 'unspecified' + return pi_ != 0? pi_->use_count(): 0; } bool unique() const // nothrow diff --git a/enable_shared_from_this_test.cpp b/shared_from_this_test.cpp similarity index 96% rename from enable_shared_from_this_test.cpp rename to shared_from_this_test.cpp index 75ca31d..d5dbe6e 100644 --- a/enable_shared_from_this_test.cpp +++ b/shared_from_this_test.cpp @@ -6,9 +6,9 @@ #endif // -// enable_shared_from_this_test.cpp +// shared_from_this_test.cpp // -// Copyright (c) 2002 Peter Dimov +// Copyright (c) 2002, 2003 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. diff --git a/shared_ptr.htm b/shared_ptr.htm index b2f9dcf..0f7d49d 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -258,7 +258,8 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r); // never

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

    -

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

    +

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

    Throws: nothing.

    template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
    @@ -266,6 +267,7 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r); // never

    Effects: If r is empty, constructs an empty shared_ptr; otherwise, constructs a shared_ptr that shares ownership with r and stores a copy of the pointer stored in r.

    +

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

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

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

    @@ -359,9 +361,9 @@ q = p;

    use_count

    long use_count() const; // never throws
    -

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

    +

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

    Throws: nothing.

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

    diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 4f0fe39..4e3e80b 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -9,7 +9,7 @@ // // shared_ptr_test.cpp // -// Copyright (c) 2002 Peter Dimov +// Copyright (c) 2002, 2003 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. @@ -481,18 +481,21 @@ void copy_constructor() BOOST_TEST(pi2? false: true); BOOST_TEST(!pi2); BOOST_TEST(pi2.get() == 0); + BOOST_TEST(pi2.use_count() == pi.use_count()); boost::shared_ptr pi3(pi); BOOST_TEST(pi3 == pi); BOOST_TEST(pi3? false: true); BOOST_TEST(!pi3); BOOST_TEST(pi3.get() == 0); + BOOST_TEST(pi3.use_count() == pi.use_count()); boost::shared_ptr pi4(pi3); BOOST_TEST(pi4 == pi3); BOOST_TEST(pi4? false: true); BOOST_TEST(!pi4); BOOST_TEST(pi4.get() == 0); + BOOST_TEST(pi4.use_count() == pi3.use_count()); } { @@ -503,6 +506,7 @@ void copy_constructor() BOOST_TEST(pv2? false: true); BOOST_TEST(!pv2); BOOST_TEST(pv2.get() == 0); + BOOST_TEST(pv2.use_count() == pv.use_count()); } { @@ -513,12 +517,14 @@ void copy_constructor() BOOST_TEST(px2? false: true); BOOST_TEST(!px2); BOOST_TEST(px2.get() == 0); + BOOST_TEST(px2.use_count() == px.use_count()); boost::shared_ptr px3(px); BOOST_TEST(px3 == px); BOOST_TEST(px3? false: true); BOOST_TEST(!px3); BOOST_TEST(px3.get() == 0); + BOOST_TEST(px3.use_count() == px.use_count()); } { @@ -531,8 +537,7 @@ void copy_constructor() BOOST_TEST(pi2.get() == 0); BOOST_TEST(pi2.use_count() == 2); BOOST_TEST(!pi2.unique()); - - BOOST_TEST(pi.use_count() == pi2.use_count()); + BOOST_TEST(pi2.use_count() == pi.use_count()); BOOST_TEST(!(pi < pi2 || pi2 < pi)); // shared ownership test boost::shared_ptr pi3(pi); @@ -542,6 +547,8 @@ void copy_constructor() BOOST_TEST(pi3.get() == 0); BOOST_TEST(pi3.use_count() == 3); BOOST_TEST(!pi3.unique()); + BOOST_TEST(pi3.use_count() == pi.use_count()); + BOOST_TEST(!(pi < pi3 || pi3 < pi)); // shared ownership test boost::shared_ptr pi4(pi2); BOOST_TEST(pi4 == pi2); @@ -550,6 +557,8 @@ void copy_constructor() BOOST_TEST(pi4.get() == 0); BOOST_TEST(pi4.use_count() == 4); BOOST_TEST(!pi4.unique()); + BOOST_TEST(pi4.use_count() == pi2.use_count()); + BOOST_TEST(!(pi2 < pi4 || pi4 < pi2)); // shared ownership test BOOST_TEST(pi3.use_count() == pi4.use_count()); BOOST_TEST(!(pi3 < pi4 || pi4 < pi3)); // shared ownership test @@ -565,8 +574,7 @@ void copy_constructor() BOOST_TEST(px2.get() == 0); BOOST_TEST(px2.use_count() == 2); BOOST_TEST(!px2.unique()); - - BOOST_TEST(px.use_count() == px2.use_count()); + BOOST_TEST(px2.use_count() == px.use_count()); BOOST_TEST(!(px < px2 || px2 < px)); // shared ownership test boost::shared_ptr px3(px); @@ -576,6 +584,8 @@ void copy_constructor() BOOST_TEST(px3.get() == 0); BOOST_TEST(px3.use_count() == 3); BOOST_TEST(!px3.unique()); + BOOST_TEST(px3.use_count() == px.use_count()); + BOOST_TEST(!(px < px3 || px3 < px)); // shared ownership test boost::shared_ptr px4(px2); BOOST_TEST(px4 == px2); @@ -584,6 +594,8 @@ void copy_constructor() BOOST_TEST(px4.get() == 0); BOOST_TEST(px4.use_count() == 4); BOOST_TEST(!px4.unique()); + BOOST_TEST(px4.use_count() == px2.use_count()); + BOOST_TEST(!(px2 < px4 || px4 < px2)); // shared ownership test BOOST_TEST(px3.use_count() == px4.use_count()); BOOST_TEST(!(px3 < px4 || px4 < px3)); // shared ownership test @@ -601,8 +613,7 @@ void copy_constructor() BOOST_TEST(pi2.use_count() == 2); BOOST_TEST(!pi2.unique()); BOOST_TEST(*pi2 == 7); - - BOOST_TEST(pi.use_count() == pi2.use_count()); + BOOST_TEST(pi2.use_count() == pi.use_count()); BOOST_TEST(!(pi < pi2 || pi2 < pi)); // shared ownership test } @@ -618,8 +629,7 @@ void copy_constructor() BOOST_TEST(pv2.get() == p); BOOST_TEST(pv2.use_count() == 2); BOOST_TEST(!pv2.unique()); - - BOOST_TEST(pv.use_count() == pv2.use_count()); + BOOST_TEST(pv2.use_count() == pv.use_count()); BOOST_TEST(!(pv < pv2 || pv2 < pv)); // shared ownership test } @@ -640,7 +650,7 @@ void copy_constructor() BOOST_TEST(X::instances == 1); - BOOST_TEST(px.use_count() == px2.use_count()); + BOOST_TEST(px2.use_count() == px.use_count()); BOOST_TEST(!(px < px2 || px2 < px)); // shared ownership test boost::shared_ptr px3(px); @@ -650,6 +660,8 @@ void copy_constructor() BOOST_TEST(px3.get() == p); BOOST_TEST(px3.use_count() == 3); BOOST_TEST(!px3.unique()); + BOOST_TEST(px3.use_count() == px.use_count()); + BOOST_TEST(!(px < px3 || px3 < px)); // shared ownership test boost::shared_ptr px4(px2); BOOST_TEST(px4 == px2); @@ -658,6 +670,8 @@ void copy_constructor() BOOST_TEST(px4.get() == p); BOOST_TEST(px4.use_count() == 4); BOOST_TEST(!px4.unique()); + BOOST_TEST(px4.use_count() == px2.use_count()); + BOOST_TEST(!(px2 < px4 || px4 < px2)); // shared ownership test BOOST_TEST(px3.use_count() == px4.use_count()); BOOST_TEST(!(px3 < px4 || px4 < px3)); // shared ownership test @@ -678,6 +692,8 @@ void copy_constructor() BOOST_TEST(px.get() == p); BOOST_TEST(px.use_count() == 2); BOOST_TEST(!px.unique()); + BOOST_TEST(px.use_count() == py.use_count()); + BOOST_TEST(!(px < py || py < px)); // shared ownership test BOOST_TEST(X::instances == 1); BOOST_TEST(Y::instances == 1); @@ -689,6 +705,8 @@ void copy_constructor() BOOST_TEST(pv.get() == px.get()); BOOST_TEST(pv.use_count() == 3); BOOST_TEST(!pv.unique()); + BOOST_TEST(pv.use_count() == px.use_count()); + BOOST_TEST(!(px < pv || pv < px)); // shared ownership test boost::shared_ptr pv2(py); BOOST_TEST(pv2 == py); @@ -697,6 +715,8 @@ void copy_constructor() BOOST_TEST(pv2.get() == py.get()); BOOST_TEST(pv2.use_count() == 4); BOOST_TEST(!pv2.unique()); + BOOST_TEST(pv2.use_count() == py.use_count()); + BOOST_TEST(!(py < pv2 || pv2 < py)); // shared ownership test BOOST_TEST(pv.use_count() == pv2.use_count()); BOOST_TEST(!(pv < pv2 || pv2 < pv)); // shared ownership test @@ -710,6 +730,7 @@ void weak_ptr_constructor() { { boost::weak_ptr wp; + BOOST_TEST(wp.use_count() == 0); try { @@ -730,48 +751,69 @@ void weak_ptr_constructor() } } - boost::shared_ptr p(new Y); - boost::weak_ptr wp(p); - { - boost::shared_ptr p2(wp); - BOOST_TEST(p2? true: false); - BOOST_TEST(!!p2); - BOOST_TEST(p2.get() == p.get()); - BOOST_TEST(p2.use_count() == 2); - BOOST_TEST(!p2.unique()); + boost::shared_ptr p; + boost::weak_ptr wp(p); - BOOST_TEST(p.use_count() == p2.use_count()); - BOOST_TEST(!(p < p2 || p2 < p)); // shared ownership test + if(wp.use_count() != 0) // 0 allowed but not required + { + boost::shared_ptr p2(wp); + BOOST_TEST(p2.use_count() == wp.use_count()); + BOOST_TEST(p2.get() == 0); - boost::shared_ptr p3(wp); - BOOST_TEST(p3? true: false); - BOOST_TEST(!!p3); - BOOST_TEST(p3.get() == p.get()); - BOOST_TEST(p3.use_count() == 3); - BOOST_TEST(!p3.unique()); - - BOOST_TEST(p.use_count() == p3.use_count()); + boost::shared_ptr p3(wp); + BOOST_TEST(p3.use_count() == wp.use_count()); + BOOST_TEST(p3.get() == 0); + } } - p.reset(); + { + boost::shared_ptr p(new Y); + boost::weak_ptr wp(p); - try - { - boost::shared_ptr p2(wp); - BOOST_ERROR("shared_ptr p2(wp) failed to throw"); - } - catch(boost::bad_weak_ptr) - { - } + { + boost::shared_ptr p2(wp); + BOOST_TEST(p2? true: false); + BOOST_TEST(!!p2); + BOOST_TEST(p2.get() == p.get()); + BOOST_TEST(p2.use_count() == 2); + BOOST_TEST(!p2.unique()); + BOOST_TEST(p2.use_count() == wp.use_count()); - try - { - boost::shared_ptr p3(wp); - BOOST_ERROR("shared_ptr p3(wp) failed to throw"); - } - catch(boost::bad_weak_ptr) - { + BOOST_TEST(p.use_count() == p2.use_count()); + BOOST_TEST(!(p < p2 || p2 < p)); // shared ownership test + + boost::shared_ptr p3(wp); + BOOST_TEST(p3? true: false); + BOOST_TEST(!!p3); + BOOST_TEST(p3.get() == p.get()); + BOOST_TEST(p3.use_count() == 3); + BOOST_TEST(!p3.unique()); + BOOST_TEST(p3.use_count() == wp.use_count()); + + BOOST_TEST(p.use_count() == p3.use_count()); + } + + p.reset(); + BOOST_TEST(wp.use_count() == 0); + + try + { + boost::shared_ptr p2(wp); + BOOST_ERROR("shared_ptr p2(wp) failed to throw"); + } + catch(boost::bad_weak_ptr) + { + } + + try + { + boost::shared_ptr p3(wp); + BOOST_ERROR("shared_ptr p3(wp) failed to throw"); + } + catch(boost::bad_weak_ptr) + { + } } } diff --git a/sp_debug_hooks.cpp b/sp_debug_hooks.cpp index d289ba4..9c13a6b 100644 --- a/sp_debug_hooks.cpp +++ b/sp_debug_hooks.cpp @@ -1,7 +1,7 @@ // // sp_debug_hooks.cpp // -// Copyright (c) 2002 Peter Dimov +// Copyright (c) 2002, 2003 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. diff --git a/weak_ptr.htm b/weak_ptr.htm index 1bafb3e..2bf395b 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -124,7 +124,7 @@ if(shared_ptr<int> r = make_shared(q))
    weak_ptr();

    Effects: Constructs an empty weak_ptr.

    -

    Postconditions: use count() == 0???.

    +

    Postconditions: use_count() == 0.

    Throws: nothing.

    template<class Y> weak_ptr(shared_ptr<Y> const & r);
    @@ -135,6 +135,7 @@ template<class Y> weak_ptr(weak_ptr<Y> const & r);
    weak_ptr; otherwise, constructs a weak_ptr that shares ownership with r as if by storing a copy of the pointer stored in r.

    +

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

    Throws: nothing.

    destructor

    @@ -244,7 +245,8 @@ public: } };
    -


    +


    +


    $Date$

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. diff --git a/weak_ptr_test.cpp b/weak_ptr_test.cpp index 7628dc9..8f76d61 100644 --- a/weak_ptr_test.cpp +++ b/weak_ptr_test.cpp @@ -9,7 +9,7 @@ // // weak_ptr_test.cpp // -// Copyright (c) 2002 Peter Dimov +// Copyright (c) 2002, 2003 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. @@ -88,10 +88,10 @@ void shared_ptr_constructor() boost::shared_ptr sp; boost::weak_ptr wp(sp); - BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp.use_count() == sp.use_count()); boost::weak_ptr wp2(sp); - BOOST_TEST(wp2.use_count() == 0); + BOOST_TEST(wp2.use_count() == sp.use_count()); } { @@ -99,6 +99,7 @@ void shared_ptr_constructor() { boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == sp.use_count()); BOOST_TEST(wp.use_count() == 1); boost::shared_ptr sp2(wp); BOOST_TEST(wp.use_count() == 2); @@ -107,6 +108,7 @@ void shared_ptr_constructor() { boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == sp.use_count()); BOOST_TEST(wp.use_count() == 1); boost::shared_ptr sp2(wp); BOOST_TEST(wp.use_count() == 2); @@ -119,6 +121,7 @@ void shared_ptr_constructor() { boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == sp.use_count()); BOOST_TEST(wp.use_count() == 1); boost::shared_ptr sp2(wp); BOOST_TEST(wp.use_count() == 2); @@ -127,6 +130,7 @@ void shared_ptr_constructor() { boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == sp.use_count()); BOOST_TEST(wp.use_count() == 1); boost::shared_ptr sp2(wp); BOOST_TEST(wp.use_count() == 2); @@ -138,13 +142,14 @@ void shared_ptr_constructor() boost::shared_ptr sp; boost::weak_ptr wp(sp); - BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp.use_count() == sp.use_count()); } { boost::shared_ptr sp(static_cast(0)); boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == sp.use_count()); BOOST_TEST(wp.use_count() == 1); boost::shared_ptr sp2(wp); BOOST_TEST(wp.use_count() == 2); @@ -155,6 +160,7 @@ void shared_ptr_constructor() boost::shared_ptr sp(new int); boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == sp.use_count()); BOOST_TEST(wp.use_count() == 1); boost::shared_ptr sp2(wp); BOOST_TEST(wp.use_count() == 2); @@ -165,10 +171,10 @@ void shared_ptr_constructor() boost::shared_ptr sp; boost::weak_ptr wp(sp); - BOOST_TEST(wp.use_count() == 0); + BOOST_TEST(wp.use_count() == sp.use_count()); boost::weak_ptr wp2(sp); - BOOST_TEST(wp2.use_count() == 0); + BOOST_TEST(wp2.use_count() == sp.use_count()); } { @@ -176,6 +182,7 @@ void shared_ptr_constructor() { boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == sp.use_count()); BOOST_TEST(wp.use_count() == 1); boost::shared_ptr sp2(wp); BOOST_TEST(wp.use_count() == 2); @@ -184,6 +191,7 @@ void shared_ptr_constructor() { boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == sp.use_count()); BOOST_TEST(wp.use_count() == 1); boost::shared_ptr sp2(wp); BOOST_TEST(wp.use_count() == 2); @@ -195,6 +203,7 @@ void shared_ptr_constructor() boost::shared_ptr sp = create_incomplete(); boost::weak_ptr wp(sp); + BOOST_TEST(wp.use_count() == sp.use_count()); BOOST_TEST(wp.use_count() == 1); boost::shared_ptr sp2(wp); BOOST_TEST(wp.use_count() == 2); @@ -207,18 +216,21 @@ void copy_constructor() { boost::weak_ptr wp; boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 0); } { boost::weak_ptr wp; boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 0); } { boost::weak_ptr wp; boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 0); } @@ -227,6 +239,7 @@ void copy_constructor() boost::weak_ptr wp(sp); boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 1); BOOST_TEST(!(wp < wp2 || wp2 < wp)); @@ -234,6 +247,7 @@ void copy_constructor() BOOST_TEST(!(wp < wp2 || wp2 < wp)); boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == wp.use_count()); BOOST_TEST(wp3.use_count() == 0); BOOST_TEST(!(wp < wp3 || wp3 < wp)); } @@ -243,6 +257,7 @@ void copy_constructor() boost::weak_ptr wp(sp); boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 1); BOOST_TEST(!(wp < wp2 || wp2 < wp)); @@ -250,6 +265,7 @@ void copy_constructor() BOOST_TEST(!(wp < wp2 || wp2 < wp)); boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == wp.use_count()); BOOST_TEST(wp3.use_count() == 0); BOOST_TEST(!(wp < wp3 || wp3 < wp)); } @@ -259,6 +275,7 @@ void copy_constructor() boost::weak_ptr wp(sp); boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 1); BOOST_TEST(!(wp < wp2 || wp2 < wp)); @@ -266,6 +283,7 @@ void copy_constructor() BOOST_TEST(!(wp < wp2 || wp2 < wp)); boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == wp.use_count()); BOOST_TEST(wp3.use_count() == 0); BOOST_TEST(!(wp < wp3 || wp3 < wp)); } @@ -275,6 +293,7 @@ void copy_constructor() boost::weak_ptr wp(sp); boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 1); BOOST_TEST(!(wp < wp2 || wp2 < wp)); @@ -282,6 +301,7 @@ void copy_constructor() BOOST_TEST(!(wp < wp2 || wp2 < wp)); boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == wp.use_count()); BOOST_TEST(wp3.use_count() == 0); BOOST_TEST(!(wp < wp3 || wp3 < wp)); } @@ -291,6 +311,7 @@ void copy_constructor() boost::weak_ptr wp(sp); boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 1); BOOST_TEST(!(wp < wp2 || wp2 < wp)); @@ -298,6 +319,7 @@ void copy_constructor() BOOST_TEST(!(wp < wp2 || wp2 < wp)); boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == wp.use_count()); BOOST_TEST(wp3.use_count() == 0); BOOST_TEST(!(wp < wp3 || wp3 < wp)); } @@ -308,12 +330,14 @@ void conversion_constructor() { boost::weak_ptr wp; boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 0); } { boost::weak_ptr wp; boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 0); } @@ -321,9 +345,11 @@ void conversion_constructor() boost::weak_ptr wp; boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 0); boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == wp.use_count()); BOOST_TEST(wp3.use_count() == 0); } @@ -332,6 +358,7 @@ void conversion_constructor() boost::weak_ptr wp(sp); boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 1); BOOST_TEST(!(wp < wp2 || wp2 < wp)); @@ -339,6 +366,7 @@ void conversion_constructor() BOOST_TEST(!(wp < wp2 || wp2 < wp)); boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == wp.use_count()); BOOST_TEST(wp3.use_count() == 0); BOOST_TEST(!(wp < wp3 || wp3 < wp)); } @@ -348,6 +376,7 @@ void conversion_constructor() boost::weak_ptr wp(sp); boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 1); BOOST_TEST(!(wp < wp2 || wp2 < wp)); @@ -355,6 +384,7 @@ void conversion_constructor() BOOST_TEST(!(wp < wp2 || wp2 < wp)); boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == wp.use_count()); BOOST_TEST(wp3.use_count() == 0); BOOST_TEST(!(wp < wp3 || wp3 < wp)); } @@ -364,6 +394,7 @@ void conversion_constructor() boost::weak_ptr wp(sp); boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 1); BOOST_TEST(!(wp < wp2 || wp2 < wp)); @@ -371,6 +402,7 @@ void conversion_constructor() BOOST_TEST(!(wp < wp2 || wp2 < wp)); boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == wp.use_count()); BOOST_TEST(wp3.use_count() == 0); BOOST_TEST(!(wp < wp3 || wp3 < wp)); } @@ -380,6 +412,7 @@ void conversion_constructor() boost::weak_ptr wp(sp); boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 1); BOOST_TEST(!(wp < wp2 || wp2 < wp)); @@ -387,6 +420,7 @@ void conversion_constructor() BOOST_TEST(!(wp < wp2 || wp2 < wp)); boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == wp.use_count()); BOOST_TEST(wp3.use_count() == 0); BOOST_TEST(!(wp < wp3 || wp3 < wp)); } @@ -396,6 +430,7 @@ void conversion_constructor() boost::weak_ptr wp(sp); boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 1); BOOST_TEST(!(wp < wp2 || wp2 < wp)); @@ -403,6 +438,7 @@ void conversion_constructor() BOOST_TEST(!(wp < wp2 || wp2 < wp)); boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == wp.use_count()); BOOST_TEST(wp3.use_count() == 0); BOOST_TEST(!(wp < wp3 || wp3 < wp)); } @@ -412,6 +448,7 @@ void conversion_constructor() boost::weak_ptr wp(sp); boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 1); BOOST_TEST(!(wp < wp2 || wp2 < wp)); @@ -419,6 +456,7 @@ void conversion_constructor() BOOST_TEST(!(wp < wp2 || wp2 < wp)); boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == wp.use_count()); BOOST_TEST(wp3.use_count() == 0); BOOST_TEST(!(wp < wp3 || wp3 < wp)); } @@ -428,6 +466,7 @@ void conversion_constructor() boost::weak_ptr wp(sp); boost::weak_ptr wp2(wp); + BOOST_TEST(wp2.use_count() == wp.use_count()); BOOST_TEST(wp2.use_count() == 1); BOOST_TEST(!(wp < wp2 || wp2 < wp)); @@ -435,6 +474,7 @@ void conversion_constructor() BOOST_TEST(!(wp < wp2 || wp2 < wp)); boost::weak_ptr wp3(wp); + BOOST_TEST(wp3.use_count() == wp.use_count()); BOOST_TEST(wp3.use_count() == 0); BOOST_TEST(!(wp < wp3 || wp3 < wp)); } From 6bd66fe0546800d35de536d3aadefad0e05b6f0c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 14 Jan 2003 15:13:53 +0000 Subject: [PATCH 187/513] detail::counted_base renamed to sp_counted_base. [SVN r16900] --- include/boost/detail/shared_count.hpp | 56 +++++++++++++-------------- sp_debug_hooks.cpp | 6 +-- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index c2c10a0..a7b6aaa 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -80,7 +80,7 @@ public: namespace detail { -class counted_base +class sp_counted_base { private: @@ -88,11 +88,11 @@ private: public: - counted_base(): use_count_(1), weak_count_(1) + sp_counted_base(): use_count_(1), weak_count_(1) { } - virtual ~counted_base() // nothrow + virtual ~sp_counted_base() // nothrow { } @@ -174,8 +174,8 @@ public: private: - counted_base(counted_base const &); - counted_base & operator= (counted_base const &); + sp_counted_base(sp_counted_base const &); + sp_counted_base & operator= (sp_counted_base const &); // inv: use_count_ <= weak_count_ @@ -189,31 +189,31 @@ private: #if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) -template void cbi_call_constructor_hook(counted_base * pn, T * px, checked_deleter const &, int) +template void cbi_call_constructor_hook(sp_counted_base * pn, T * px, checked_deleter const &, int) { boost::sp_scalar_constructor_hook(px, sizeof(T), pn); } -template void cbi_call_constructor_hook(counted_base *, T * px, checked_array_deleter const &, int) +template void cbi_call_constructor_hook(sp_counted_base *, T * px, checked_array_deleter const &, int) { boost::sp_array_constructor_hook(px); } -template void cbi_call_constructor_hook(counted_base *, P const &, D const &, long) +template void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long) { } -template void cbi_call_destructor_hook(counted_base * pn, T * px, checked_deleter const &, int) +template void cbi_call_destructor_hook(sp_counted_base * pn, T * px, checked_deleter const &, int) { boost::sp_scalar_destructor_hook(px, sizeof(T), pn); } -template void cbi_call_destructor_hook(counted_base *, T * px, checked_array_deleter const &, int) +template void cbi_call_destructor_hook(sp_counted_base *, T * px, checked_array_deleter const &, int) { boost::sp_array_destructor_hook(px); } -template void cbi_call_destructor_hook(counted_base *, P const &, D const &, long) +template void cbi_call_destructor_hook(sp_counted_base *, P const &, D const &, long) { } @@ -226,23 +226,23 @@ template void cbi_call_destructor_hook(counted_base *, P const # pragma option push -Vx- #endif -template class counted_base_impl: public counted_base +template class sp_counted_base_impl: public sp_counted_base { private: P ptr; // copy constructor must not throw D del; // copy constructor must not throw - counted_base_impl(counted_base_impl const &); - counted_base_impl & operator= (counted_base_impl const &); + sp_counted_base_impl(sp_counted_base_impl const &); + sp_counted_base_impl & operator= (sp_counted_base_impl const &); - typedef counted_base_impl this_type; + typedef sp_counted_base_impl this_type; public: // pre: initial_use_count <= initial_weak_count, d(p) must not throw - counted_base_impl(P p, D d): ptr(p), del(d) + sp_counted_base_impl(P p, D d): ptr(p), del(d) { #if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) detail::cbi_call_constructor_hook(this, p, d, 0); @@ -290,7 +290,7 @@ class shared_count { private: - counted_base * pi_; + sp_counted_base * pi_; #if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) int id_; @@ -316,7 +316,7 @@ public: try { - pi_ = new counted_base_impl(p, d); + pi_ = new sp_counted_base_impl(p, d); } catch(...) { @@ -326,7 +326,7 @@ public: #else - pi_ = new counted_base_impl(p, d); + pi_ = new sp_counted_base_impl(p, d); if(pi_ == 0) { @@ -342,7 +342,7 @@ public: // auto_ptr is special cased to provide the strong guarantee template - explicit shared_count(std::auto_ptr & r): pi_(new counted_base_impl< Y *, checked_deleter >(r.get(), checked_deleter())) + explicit shared_count(std::auto_ptr & r): pi_(new sp_counted_base_impl< Y *, checked_deleter >(r.get(), checked_deleter())) #if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) , id_(shared_count_id) #endif @@ -369,7 +369,7 @@ public: shared_count & operator= (shared_count const & r) // nothrow { - counted_base * tmp = r.pi_; + sp_counted_base * tmp = r.pi_; if(tmp != 0) tmp->add_ref(); if(pi_ != 0) pi_->release(); pi_ = tmp; @@ -379,7 +379,7 @@ public: void swap(shared_count & r) // nothrow { - counted_base * tmp = r.pi_; + sp_counted_base * tmp = r.pi_; r.pi_ = pi_; pi_ = tmp; } @@ -401,7 +401,7 @@ public: friend inline bool operator<(shared_count const & a, shared_count const & b) { - return std::less()(a.pi_, b.pi_); + return std::less()(a.pi_, b.pi_); } void * get_deleter(std::type_info const & ti) const @@ -419,7 +419,7 @@ class weak_count { private: - counted_base * pi_; + sp_counted_base * pi_; #if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) int id_; @@ -459,7 +459,7 @@ public: weak_count & operator= (shared_count const & r) // nothrow { - counted_base * tmp = r.pi_; + sp_counted_base * tmp = r.pi_; if(tmp != 0) tmp->weak_add_ref(); if(pi_ != 0) pi_->weak_release(); pi_ = tmp; @@ -469,7 +469,7 @@ public: weak_count & operator= (weak_count const & r) // nothrow { - counted_base * tmp = r.pi_; + sp_counted_base * tmp = r.pi_; if(tmp != 0) tmp->weak_add_ref(); if(pi_ != 0) pi_->weak_release(); pi_ = tmp; @@ -479,7 +479,7 @@ public: void swap(weak_count & r) // nothrow { - counted_base * tmp = r.pi_; + sp_counted_base * tmp = r.pi_; r.pi_ = pi_; pi_ = tmp; } @@ -496,7 +496,7 @@ public: friend inline bool operator<(weak_count const & a, weak_count const & b) { - return std::less()(a.pi_, b.pi_); + return std::less()(a.pi_, b.pi_); } }; diff --git a/sp_debug_hooks.cpp b/sp_debug_hooks.cpp index 9c13a6b..0f7e365 100644 --- a/sp_debug_hooks.cpp +++ b/sp_debug_hooks.cpp @@ -138,7 +138,7 @@ namespace struct count_layout { - boost::detail::counted_base * pi; + boost::detail::sp_counted_base * pi; int id; }; @@ -194,7 +194,7 @@ static void find_unreachable_objects(map_type const & m, map2_type & m2) { for(map_type::const_iterator i = m.begin(); i != m.end(); ++i) { - boost::detail::counted_base const * p = static_cast(i->first); + boost::detail::sp_counted_base const * p = static_cast(i->first); BOOST_ASSERT(p->use_count() != 0); // there should be no inactive counts in the map @@ -209,7 +209,7 @@ static void find_unreachable_objects(map_type const & m, map2_type & m2) for(map2_type::iterator i = m2.begin(); i != m2.end(); ++i) { - boost::detail::counted_base const * p = static_cast(i->first); + boost::detail::sp_counted_base const * p = static_cast(i->first); if(p->use_count() != i->second) open.push_back(p); } From 868062e81d851daddc799fba54e0072110708dcf Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Wed, 15 Jan 2003 16:35:48 +0000 Subject: [PATCH 188/513] Add TOC and References sections [SVN r16912] --- smart_ptr.htm | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/smart_ptr.htm b/smart_ptr.htm index ac8a96f..6873980 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -7,6 +7,13 @@

    c++boost.gif (8819 bytes)Smart Pointers

    +

    Introduction
    + Common Requirements
    + Exception Safety
    + Exception-specifications
    + History and Acknowledgements
    + References

    +

    Introduction

    Smart pointers are objects which store pointers to dynamically allocated (heap) objects. They behave much like built-in C++ pointers except that they automatically delete the object pointed to at the appropriate time. Smart @@ -79,7 +86,7 @@ these idioms.

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

    -

    Exception Safety

    +

    Exception Safety

    Several functions in these smart pointer classes are specified as having "no effect" or "no effect except such-and-such" if an exception is thrown. This means that when an exception is thrown by an object of one of these classes, @@ -90,7 +97,7 @@ the common requirements) is std::bad_alloc, and that is thrown only by functions which are explicitly documented as possibly throwing std::bad_alloc.

    -

    Exception-specifications

    +

    Exception-specifications

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

    All the smart pointer templates contain member functions which can never throw @@ -100,7 +107,7 @@

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

    -

    History and Acknowledgements

    +

    History and Acknowledgements

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

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

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

    -

    October 1998. In 1994 Greg Colvin proposed to the C++ Standards Committee - classes named auto_ptr and counted_ptr which were very similar to - what we now call scoped_ptr and shared_ptr. The committee - document was 94-168/N0555, Exception Safe Smart Pointers. In one of the very - few cases where the Library Working Group's recommendations were not followed - by the full committee, counted_ptr was rejected and surprising - transfer-of-ownership semantics were added to auto_ptr.

    -

    Beman Dawes proposed reviving the original semantics under the names safe_ptr - and counted_ptr at an October, 1998, meeting of Per Andersson, Matt +

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

    Over the next three months, several implementations were considered for shared_ptr, @@ -154,10 +154,26 @@ experimented with.

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

    +

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

    +

    References

    +

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

    +

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


    Revised - 4 February 200215 January 2003

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Permission to copy, use, modify, sell and distribute this document is granted @@ -165,4 +181,4 @@ "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.

    - + \ No newline at end of file From d04757128c02a9822bcf5a96a85bc87cff265a66 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 21 Jan 2003 15:55:59 +0000 Subject: [PATCH 189/513] shared_ptr techniques initial commit [SVN r16978] --- sp_techniques.html | 689 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 689 insertions(+) create mode 100644 sp_techniques.html diff --git a/sp_techniques.html b/sp_techniques.html new file mode 100644 index 0000000..cc214b8 --- /dev/null +++ b/sp_techniques.html @@ -0,0 +1,689 @@ + + + + Smart pointer programming techniques + + + +

    c++boost.gif (8819 bytes)Smart + pointer programming techniques

    +

    + Using incomplete classes for implementation hiding
    + The "Pimpl" idiom
    + Using abstract classes for implementation hiding
    + Preventing delete px.get()
    + Using a shared_ptr to hold a pointer to an array
    + Encapsulating allocation details, wrapping factory + functions
    + Using a shared_ptr to hold a pointer to a statically allocated + object
    + Using a shared_ptr to hold a pointer to a COM object
    + Using a shared_ptr to hold a pointer to an object with an + embedded reference count
    + Using a shared_ptr to hold another shared ownership smart + pointer
    + Obtaining a shared_ptr from a raw pointer
    + Obtaining a shared_ptr (weak_ptr) to this in a + constructor
    + Obtaining a shared_ptr to this
    + Using shared_ptr as a smart counted handle
    + Using shared_ptr to execute code on block exit
    + Using shared_ptr<void> to hold an arbitrary object
    + Associating arbitrary data with heterogeneous shared_ptr + instances
    + Post-constructors and pre-destructors
    + Using shared_ptr as a CopyConstructible mutex lock
    + Using shared_ptr to wrap member function calls
    + Delayed deallocation
    + Weak pointers to objects not managed by a shared_ptr
    +

    +

    Using incomplete classes for implementation hiding

    +

    [Old, proven technique; can be used in C]

    +
    +class FILE;
    +
    +FILE * fopen(char const * name, char const * mode);
    +void fread(FILE * f, void * data, size_t size);
    +void fclose(FILE * f);
    +
    +

    [Compare with]

    +
    +class FILE;
    +
    +shared_ptr<FILE> fopen(char const * name, char const * mode);
    +void fread(shared_ptr<FILE> f, void * data, size_t size);
    +
    +

    Note that there is no fclose function; shared_ptr's ability to execute a custom deleter makes it unnecessary.

    + +

    [shared_ptr<X> can be copied and destroyed when X is incomplete.]

    +

    The "Pimpl" idiom

    +

    [...]

    +
    +// file.hpp:
    +
    +class file
    +{
    +private:
    +
    +    class impl;
    +    shared_ptr<impl> pimpl_;
    +
    +public:
    +
    +    file(char const * name, char const * mode);
    +
    +    // compiler generated members are fine and useful
    +
    +    void read(void * data, size_t size);
    +};
    +
    +
    +// file.cpp:
    +
    +#include "file.hpp"
    +
    +class file::impl
    +{
    +private:
    +
    +    impl(impl const &);
    +    impl & operator=(impl const &);
    +
    +    // private data
    +
    +public:
    +
    +    impl(char const * name, char const * mode) { ... }
    +    ~impl() { ... }
    +    void read(void * data, size_t size) { ... }
    +};
    +
    +file::file(char const * name, char const * mode): pimpl_(new impl(name, mode))
    +{
    +}
    +
    +void file::read(void * data, size_t size)
    +{
    +    pimpl_->read(data, size);
    +}
    +
    +

    [file is CopyConstructible and Assignable.]

    +

    Using abstract classes for implementation hiding

    +

    [Interface based programming]

    +
    +// X.hpp:
    +
    +class X
    +{
    +public:
    +
    +    virtual void f() = 0;
    +    virtual void g() = 0;
    +
    +protected:
    +
    +    ~X() {}
    +};
    +
    +shared_ptr<X> createX();
    +
    +
    +-- X.cpp:
    +
    +class X_impl: public X
    +{
    +private:
    +
    +    X_impl(X_impl const &);
    +    X_impl & operator=(X_impl const &);
    +
    +public:
    +
    +    virtual void f()
    +    {
    +      // ...
    +    }
    +
    +    virtual void g()
    +    {
    +      // ...
    +    }
    +};
    +
    +shared_ptr<X> createX()
    +{
    +    shared_ptr<X> px(new X_impl);
    +    return px;
    +}
    +
    +

    [Note protected and nonvirtual destructor; client cannot delete X; shared_ptr correctly calls ~X_impl even when nonvirtual.]

    +

    Preventing delete px.get()

    +

    [Alternative 1, use the above.]

    +

    [Alternative 2, use a private deleter:]

    +
    +class X
    +{
    +private:
    +
    +    ~X();
    +
    +    class deleter;
    +    friend class deleter;
    +
    +    class deleter
    +    {
    +    public:
    +
    +        void operator()(X * p) { delete p; }
    +    };
    +
    +public:
    +
    +    static shared_ptr<X> create()
    +    {
    +        shared_ptr<X> px(new X, X::deleter());
    +        return px;
    +    }
    +};
    +
    +

    Using a shared_ptr to hold a pointer to an array

    +

    [...]

    +
    +shared_ptr<X> px(new X[1], checked_array_deleter<X>());
    +
    +

    [shared_array is preferable, has a better interface; shared_ptr has *, ->, derived to base conversions.]

    +

    Encapsulating allocation details, wrapping factory + functions

    +

    [Existing interface, possibly allocates X from its own heap, ~X is private, or X is incomplete.]

    +
    +X * CreateX();
    +void DestroyX(X *);
    +
    +

    [Wrapper:]

    +
    +shared_ptr<X> createX()
    +{
    +    shared_ptr<X> px(CreateX(), DestroyX);
    +}
    +
    +

    [Client remains blissfully oblivious of allocation details; doesn't need to remember to call destroyX.]

    +

    Using a shared_ptr to hold a pointer to a statically allocated + object

    +

    [...]

    +
    +shared_ptr<X> createX();
    +
    +

    [Sometimes needs to return a pointer to a statically allocated X instance.]

    +
    +struct null_deleter
    +{
    +    void operator()(void const *) const
    +    {
    +    }
    +};
    +
    +static X x;
    +
    +shared_ptr<X> createX()
    +{
    +    shared_ptr<X> px(&x, null_deleter());
    +    return px;
    +}
    +
    +

    [The same technique works for any object known to outlive the pointer.]

    +

    Using a shared_ptr to hold a pointer to a COM Object

    +

    [COM objects have an embedded reference count, AddRef() and Release(), Release() self-destroys when reference count drops to zero.]

    +
    +shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
    +{
    +    p->AddRef();
    +    shared_ptr<IWhatever> pw(p, mem_fn(&IWhatever::Release));
    +    return pw;
    +}
    +
    +

    [All pw copies will share a single reference.]

    +

    Using a shared_ptr to hold a pointer to an object with an + embedded reference count

    +

    [A generalization of the above. Example assumes intrusive_ptr-compatible object.]

    +
    +template<class T> struct intrusive_deleter
    +{
    +    void operator()(T * p)
    +    {
    +        if(p) intrusive_ptr_release(p);
    +    }
    +};
    +
    +shared_ptr<X> make_shared_from_intrusive(X * p)
    +{
    +    if(p) intrusive_ptr_add_ref(p);
    +    shared_ptr<X> px(p, intrusive_deleter<X>());
    +    return px;
    +}
    +
    +

    Using a shared_ptr to hold another shared ownership smart + pointer

    +

    [...]

    +
    +template<class P> class smart_pointer_deleter
    +{
    +private:
    +
    +    P p_;
    +
    +public:
    +
    +    smart_pointer_deleter(P const & p): p_(p)
    +    {
    +    }
    +
    +    void operator()(void const *)
    +    {
    +        p_.reset();
    +    }
    +};
    +
    +shared_ptr<X> make_shared_from_another(another_ptr<X> qx)
    +{
    +    shared_ptr<X> px(qx.get(), smart_pointer_deleter< another_ptr<X> >(qx));
    +    return px;
    +}
    +
    +

    [If p_.reset() can throw - wrap in try {} catch(...) {} block, will release p_ when all weak pointers are eliminated.]

    +

    Obtaining a shared_ptr from a raw pointer

    +

    [...]

    +
    +void f(X * p)
    +{
    +    shared_ptr<X> px(???);
    +}
    +
    +

    [Not possible in general, either switch to]

    +
    +void f(shared_ptr<X> px);
    +
    +

    [This transformation can be used for nonvirtual member functions, too; before:]

    +
    +void X::f(int m);
    +
    +

    [after]

    +
    +void f(shared_ptr<X> this_, int m);
    +
    +

    [If f cannot be changed, use knowledge about p's lifetime and allocation details and apply one of the above.]

    +

    Obtaining a shared_ptr (weak_ptr) to this in a + constructor

    +

    [...]

    +
    +class X
    +{
    +public:
    +
    +    X()
    +    {
    +        shared_ptr<X> this_(???);
    +    }
    +};
    +
    +

    [Not possible in general. If X can have automatic or static storage, and this_ doesn't need to keep the object alive, +use a null_deleter. If X is supposed to always live on the heap, and be managed by a shared_ptr, use:]

    +
    +class X
    +{
    +private:
    +
    +    X() { ... }
    +
    +public:
    +
    +    static shared_ptr<X> create()
    +    {
    +        shared_ptr<X> px(new X);
    +        // use px as 'this_'
    +        return px;
    +    }
    +};
    +
    +

    Obtaining a shared_ptr to this

    +

    [Sometimes it is needed to obtain a shared_ptr from this in a virtual member function.]

    +

    [The transformations from above cannot be applied.]

    +
    +class X
    +{
    +public:
    +
    +    virtual void f() = 0;
    +
    +protected:
    +
    +    ~X() {}
    +};
    +
    +class Y
    +{
    +public:
    +
    +    virtual shared_ptr<X> getX() = 0;
    +
    +protected:
    +
    +    ~Y() {}
    +};
    +
    +// --
    +
    +class impl: public X, public Y
    +{
    +public:
    +
    +    impl() { ... }
    +
    +    virtual void f() { ... }
    +
    +    virtual shared_ptr<X> getX()
    +    {
    +        shared_ptr<X> px(???);
    +        return px;
    +    }
    +};
    +
    +

    [Solution:]

    +
    +class impl: public X, public Y
    +{
    +private:
    +
    +    weak_ptr<impl> weak_this;
    +
    +    impl(impl const &);
    +    impl & operator=(impl const &);
    +
    +    impl() { ... }
    +
    +public:
    +
    +    static shared_ptr<impl> create()
    +    {
    +        shared_ptr<impl> pi(new impl);
    +        pi->weak_this = pi;
    +        return pi;
    +    }
    +
    +    virtual void f() { ... }
    +
    +    virtual shared_ptr<X> getX()
    +    {
    +        shared_ptr<X> px = make_shared(weak_this);
    +        return px;
    +    }
    +};
    +
    +

    [Future support planned, impl: public enable_shared_from_this<impl>.]

    +

    Using shared_ptr as a smart counted handle

    +

    [Win32 API allusion]

    +
    +typedef void * HANDLE;
    +HANDLE CreateProcess();
    +void CloseHandle(HANDLE);
    +
    +

    [Quick wrapper]

    +
    +typedef shared_ptr<void> handle;
    +
    +handle createProcess()
    +{
    +    shared_ptr<void> pv(CreateProcess(), CloseHandle);
    +    return pv;
    +}
    +
    +

    [Better, typesafe:]

    +
    +class handle
    +{
    +private:
    +
    +    shared_ptr<void> pv_;
    +
    +public:
    +
    +    explicit handle(HANDLE h): pv_(h, CloseHandle) {}
    +    HANDLE get() { return pv_.get(); }
    +};
    +
    +

    Using shared_ptr to execute code on block exit

    +

    [1. Executing f(p), where p is a pointer:]

    +
    +    shared_ptr<void> guard(p, f);
    +
    +

    [2. Executing arbitrary code: f(x, y):]

    +
    +    shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
    +
    +

    Using shared_ptr<void> to hold an arbitrary object

    +

    [...]

    +
    +    shared_ptr<void> pv(new X);
    +
    +

    [Will correctly call ~X.]

    +

    [Can be used to strip type information: shared_ptr<X> -> (shared_ptr<void>, typeid(X))]

    +

    Associating arbitrary data with heterogeneous shared_ptr + instances

    +

    [...]

    +
    +typedef int Data;
    +
    +std::map< shared_ptr<void>, Data > userData;
    +// or std::map< weak_ptr<void>, Data > userData; to not affect the lifetime
    +
    +shared_ptr<X> px(new X);
    +shared_ptr<int> pi(new int(3));
    +
    +userData[px] = 42;
    +userData[pi] = 91;
    +
    +

    Post-constructors and pre-destructors

    +

    [...]

    +
    +class X
    +{
    +public:
    +
    +    X();
    +    virtual void postconstructor();
    +    virtual void predestructor() throw();
    +    ~X() throw();
    +
    +    struct deleter
    +    {
    +        void operator()(X * p)
    +        {
    +             p->predestructor();
    +             delete p;
    +        }
    +    }
    +
    +    static shared_ptr<X> create()
    +    {
    +        shared_ptr<X> px(new X, X::deleter());
    +        px->postconstructor(); // can throw
    +        return px;
    +    }
    +};
    +
    +

    Using shared_ptr as a CopyConstructible mutex lock

    +

    [Sometimes it's necessary to return a mutex lock from a function. A noncopyable lock cannot be used.]

    +
    +class mutex
    +{
    +public:
    +
    +    void lock();
    +    void unlock();
    +};
    +
    +shared_ptr<mutex> lock(mutex & m)
    +{
    +    m.lock();
    +    return shared_ptr<mutex>(&m, mem_fn(&mutex::unlock));
    +}
    +
    +

    [Or to encapsulate it in a dedicated class:]

    +
    +class shared_lock
    +{
    +private:
    +
    +    shared_ptr<void> pv;
    +
    +public:
    +
    +    template<class Mutex> explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&Mutex::unlock)) {}
    +};
    +
    +

    [Usage:]

    +
    +    shared_lock lock(m);
    +
    +

    [Note that shared_lock is not templated on the mutex type, thanks to shared_ptr<void>'s ability to hide type information.]

    +

    Using shared_ptr to wrap member function calls

    +

    [http://www.research.att.com/~bs/wrapper.pdf]

    +
    +template<class T> class pointer
    +{
    +private:
    +
    +    T * p_;
    +
    +public:
    +
    +    explicit pointer(T * p): p_(p)
    +    {
    +    }
    +
    +    shared_ptr<T> operator->() const
    +    {
    +        p_->prefix();
    +        return shared_ptr<T>(p_, mem_fn(&T::suffix));
    +    }
    +};
    +
    +class X
    +{
    +private:
    +
    +    void prefix();
    +    void suffix();
    +    friend class pointer<X>;
    +    
    +public:
    +
    +    void f();
    +    void g();
    +};
    +
    +int main()
    +{
    +    X x;
    +
    +    pointer<X> px(&x);
    +
    +    px->f();
    +    px->g();
    +}
    +
    +

    Delayed deallocation

    +

    [In some situations, a single px.reset() can trigger an expensive deallocation in a performance-critical region.]

    +
    +class X; // ~X is expensive
    +
    +class Y
    +{
    +    shared_ptr<X> px;
    +
    +public:
    +
    +    void f()
    +    {
    +        px.reset();
    +    }
    +};
    +
    +

    [Solution 1]

    +
    +vector< shared_ptr<void> > free_list;
    +
    +class Y
    +{
    +    shared_ptr<X> px;
    +
    +public:
    +
    +    void f()
    +    {
    +        free_list.push_back(px);
    +        px.reset();
    +    }
    +};
    +
    +// periodically invoke free_list.clear() when convenient
    +
    +

    [Solution 2, as above, but use a delayed deleter]

    +
    +struct delayed_deleter
    +{
    +    template<class T> void operator()(T * p)
    +    {
    +        try
    +        {
    +            shared_ptr<void> pv(p);
    +            free_list.push_back(pv);
    +        }
    +        catch(...)
    +        {
    +        }
    +    }
    +};
    +
    +

    Weak pointers to objects not managed by a shared_ptr

    +

    Make the object hold a shared_ptr to itself, using a null_deleter:

    +
    +class X
    +{
    +private:
    +
    +    shared_ptr<X> this_;
    +    int i_;
    +
    +public:
    +
    +    explicit X(int i): this_(this, null_deleter()), i_(i)
    +    {
    +    }
    +
    +    // repeat in all constructors (including the copy constructor!)
    +
    +    X(X const & rhs): this_(this, null_deleter()), i_(rhs.i_)
    +    {
    +    }
    +
    +    // do not forget to not assign this_ in the copy assignment
    +
    +    X & operator=(X const & rhs)
    +    {
    +	    i_ = rhs.i_;
    +    }
    +
    +    weak_ptr<X> get_weak_ptr() const { return this_; }
    +};
    +
    +

    When the object's lifetime ends, X::this_ will be destroyed, and all weak pointers will automatically expire.

    +
    +

    + $Date$

    +

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

    + + From bd39e2ededbe9b0d90e451ca07451d20a9623612 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 21 Jan 2003 17:21:24 +0000 Subject: [PATCH 190/513] intrusive_ptr.html added. [SVN r16981] --- include/boost/intrusive_ptr.hpp | 108 ++++++++----- intrusive_ptr.html | 276 ++++++++++++++++++++++++++++++++ 2 files changed, 343 insertions(+), 41 deletions(-) create mode 100644 intrusive_ptr.html diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 5d03548..074720f 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -19,7 +19,12 @@ # pragma warning(disable:4284) // odd return type for operator-> #endif -#include // std::less +#include +#include + +#include // for std::less +#include // for std::basic_ostream + namespace boost { @@ -53,14 +58,9 @@ public: { } - intrusive_ptr(T * p): p_(p) + intrusive_ptr(T * p, bool add_ref = true): p_(p) { - if(p_ != 0) intrusive_ptr_add_ref(p_); - } - - ~intrusive_ptr() - { - if(p_ != 0) intrusive_ptr_release(p_); + if(p_ != 0 && add_ref) intrusive_ptr_add_ref(p_); } #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) @@ -77,6 +77,11 @@ public: if(p_ != 0) intrusive_ptr_add_ref(p_); } + ~intrusive_ptr() + { + if(p_ != 0) intrusive_ptr_release(p_); + } + #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) template intrusive_ptr & operator=(intrusive_ptr const & rhs) @@ -99,13 +104,6 @@ public: return *this; } - void swap(intrusive_ptr & rhs) - { - T * tmp = p_; - p_ = rhs.p_; - rhs.p_ = tmp; - } - T * get() const { return p_; @@ -121,16 +119,18 @@ public: return p_; } - bool empty() const + typedef T * (intrusive_ptr::*unspecified_bool_type) () const; + + operator unspecified_bool_type () const { - return p_ == 0; + return p_ == 0? 0: &intrusive_ptr::get; } - typedef bool (intrusive_ptr::*bool_type) () const; - - operator bool_type () const + void swap(intrusive_ptr & rhs) { - return p_ == 0? 0: &intrusive_ptr::empty; + T * tmp = p_; + p_ = rhs.p_; + rhs.p_ = tmp; } private: @@ -138,21 +138,6 @@ private: T * p_; }; -template void swap(intrusive_ptr & lhs, intrusive_ptr & rhs) -{ - lhs.swap(rhs); -} - -template intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & p) -{ - return dynamic_cast(p.get()); -} - -template intrusive_ptr static_pointer_cast(intrusive_ptr const & p) -{ - return static_cast(p.get()); -} - template inline bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) { return a.get() == b.get(); @@ -163,11 +148,6 @@ template inline bool operator!=(intrusive_ptr const & a, in return a.get() != b.get(); } -template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) -{ - return std::less(a.get(), b.get()); -} - template inline bool operator==(intrusive_ptr const & a, T * b) { return a.get() == b; @@ -188,6 +168,16 @@ template inline bool operator!=(T * a, intrusive_ptr const & b) return a != b.get(); } +template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return std::less()(a.get(), b.get()); +} + +template void swap(intrusive_ptr & lhs, intrusive_ptr & rhs) +{ + lhs.swap(rhs); +} + // mem_fn support template T * get_pointer(intrusive_ptr const & p) @@ -195,6 +185,42 @@ template T * get_pointer(intrusive_ptr const & p) return p.get(); } +template intrusive_ptr static_pointer_cast(intrusive_ptr const & p) +{ + return static_cast(p.get()); +} + +template intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & p) +{ + return dynamic_cast(p.get()); +} + +// operator<< + +#if defined(__GNUC__) && (__GNUC__ < 3) + +template std::ostream & operator<< (std::ostream & os, intrusive_ptr const & p) +{ + os << p.get(); + return os; +} + +#else + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT) +// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL +using std::basic_ostream; +template basic_ostream & operator<< (basic_ostream & os, intrusive_ptr const & p) +# else +template std::basic_ostream & operator<< (std::basic_ostream & os, intrusive_ptr const & p) +# endif +{ + os << p.get(); + return os; +} + +#endif + } // namespace boost #ifdef BOOST_MSVC diff --git a/intrusive_ptr.html b/intrusive_ptr.html new file mode 100644 index 0000000..fca484d --- /dev/null +++ b/intrusive_ptr.html @@ -0,0 +1,276 @@ + + + + intrusive_ptr + + + +

    c++boost.gif (8819 bytes)intrusive_ptr + class template

    +

    + Introduction
    + Synopsis
    + Members
    + Free Functions
    +

    +

    Introduction

    +

    The intrusive_ptr class template stores a pointer to an object with an + embedded reference count. Every new intrusive_ptr instance increments + the reference count by using an unqualified call to the function intrusive_ptr_add_ref, + passing it the pointer as an argument. Similarly, when an intrusive_ptr + is destroyed, it calls intrusive_ptr_release; this function is + responsible for destroying the object when its reference count drops to + zero. The user is expected to provide suitable definitions of these two + functions. On compilers that support argument-dependent lookup, intrusive_ptr_add_ref + and intrusive_ptr_release should be defined in the namespace + that corresponds to their parameter; otherwise, the definitions need to go in + namespace boost.

    +

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

    +

    The main reasons to use intrusive_ptr are:

    +
      +
    • + Some existing frameworks or OSes provide objects with embedded reference + counts;
    • +
    • + The memory footprint of intrusive_ptr is the same as the + corresponding raw pointer;
    • +
    • + intrusive_ptr<T> can be constructed from an arbitrary + raw pointer of type T *.
    +

    As a general rule, if it isn't obvious whether intrusive_ptr + better fits your needs than shared_ptr, try a shared_ptr-based + design first.

    +

    Synopsis

    +
    namespace boost {
    +
    +  template<class T> class intrusive_ptr {
    +
    +    public:
    +
    +      typedef T element_type;
    +
    +      intrusive_ptr(); // never throws
    +      intrusive_ptr(T * p, bool add_ref = true);
    +
    +      intrusive_ptr(intrusive_ptr const & r);
    +      template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
    +
    +      ~intrusive_ptr();
    +
    +      intrusive_ptr & operator=(intrusive_ptr const & r);
    +      template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
    +      template<class Y> intrusive_ptr & operator=(T * r);
    +
    +      T & operator*() const; // never throws
    +      T * operator->() const; // never throws
    +      T * get() const; // never throws
    +
    +      operator unspecified-bool-type() const; // never throws
    +
    +      void swap(intrusive_ptr & b); // never throws
    +  };
    +
    +  template<class T, class U>
    +    bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
    +
    +  template<class T, class U>
    +    bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
    +
    +  template<class T>
    +    bool operator==(intrusive_ptr<T> const & a, T * b); // never throws
    +
    +  template<class T>
    +    bool operator!=(intrusive_ptr<T> const & a, T * b); // never throws
    +
    +  template<class T>
    +    bool operator==(T * a, intrusive_ptr<T> const & b); // never throws
    +
    +  template<class T>
    +    bool operator!=(T * a, intrusive_ptr<T> const & b); // never throws
    +
    +  template<class T, class U>
    +    bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
    +
    +  template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b); // never throws
    +
    +  template<class T> T * get_pointer(intrusive_ptr<T> const & p); // never throws
    +
    +  template<class T, class U>
    +    intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r); // never throws
    +
    +  template<class T, class U>
    +    intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r); // never throws
    +
    +  template<class E, class T, class Y>
    +    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p);
    +
    +}
    +

    Members

    +

    element_type

    +
    typedef T element_type;
    +
    +

    Provides the type of the template parameter T.

    +
    +

    constructors

    +
    intrusive_ptr(); // never throws
    +
    +

    Postconditions: get() == 0.

    +

    Throws: nothing.

    +
    +
    intrusive_ptr(T * p, bool add_ref = true);
    +
    +

    Effects: if(p != 0 && add_ref) intrusive_ptr_add_ref(p);.

    +

    Postconditions: get() == p.

    +
    +
    intrusive_ptr(intrusive_ptr const & r); // never throws
    +template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r); // never throws
    +
    +

    Effects: if(r.get() != 0) intrusive_ptr_add_ref(r.get());.

    +

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

    +
    +

    destructor

    +
    ~intrusive_ptr();
    +
    +

    Effects: if(get() != 0) intrusive_ptr_release(get());.

    +
    +

    assignment

    +
    intrusive_ptr & operator=(intrusive_ptr const & r); // never throws
    +template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r); // never throws
    +intrusive_ptr & operator=(T * r);
    +
    +

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

    +

    Returns: *this.

    +
    +

    indirection

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

    Requirements: get() != 0.

    +

    Returns: *get().

    +

    Throws: nothing.

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

    Requirements: get() != 0.

    +

    Returns: get().

    +

    Throws: nothing.

    +
    +

    get

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

    Returns: the stored pointer.

    +

    Throws: nothing.

    +
    +

    conversions

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

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

    +

    Throws: nothing.

    +

    Notes: This conversion operator allows intrusive_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.

    +
    +

    swap

    +
    void swap(intrusive_ptr & b); // never throws
    +
    +

    Effects: Exchanges the contents of the two smart pointers.

    +

    Throws: nothing.

    +
    +

    Free Functions

    +

    comparison

    +
    template<class T, class U>
    +  bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
    +
    +

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

    +

    Throws: nothing.

    +
    +
    template<class T, class U>
    +  bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
    +
    +

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

    +

    Throws: nothing.

    +
    +
    template<class T>
    +  bool operator==(intrusive_ptr<T> const & a, T * b); // never throws
    +
    +

    Returns: a.get() == b.

    +

    Throws: nothing.

    +
    +
    template<class T>
    +  bool operator!=(intrusive_ptr<T> const & a, T * b); // never throws
    +
    +

    Returns: a.get() != b.

    +

    Throws: nothing.

    +
    +
    template<class T>
    +  bool operator==(T * a, intrusive_ptr<T> const & b); // never throws
    +
    +

    Returns: a == b.get().

    +

    Throws: nothing.

    +
    +
    template<class T>
    +  bool operator!=(T * a, intrusive_ptr<T> const & b); // never throws
    +
    +

    Returns: a != b.get().

    +

    Throws: nothing.

    +
    +
    template<class T, class U>
    +  bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
    +
    +

    Returns: std::less<T *>()(a.get(), b.get()).

    +

    Throws: nothing.

    +

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

    +
    +

    swap

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

    Effects: Equivalent to a.swap(b).

    +

    Throws: nothing.

    +

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

    +
    +

    get_pointer

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

    Returns: p.get().

    +

    Throws: nothing.

    +

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

    +
    +

    static_pointer_cast

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

    Returns: intrusive_ptr<T>(static_cast<T*>(r.get())).

    +

    Throws: nothing.

    +
    +

    dynamic_pointer_cast

    +
    template<class T, class U>
    +  intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r);
    +
    +

    Returns: intrusive_ptr<T>(dynamic_cast<T*>(r.get())).

    +

    Throws: nothing.

    +
    +

    operator<<

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

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

    +

    Returns: os.

    +
    +
    +

    + $Date$

    +

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

    + + From d030182e87e51f8da69af3065e845c5b0de02ab2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 22 Jan 2003 15:22:30 +0000 Subject: [PATCH 191/513] intrusive_ptr_test added. [SVN r16993] --- include/boost/intrusive_ptr.hpp | 17 + intrusive_ptr_test.cpp | 553 ++++++++++++++++++++++++++++++++ 2 files changed, 570 insertions(+) create mode 100644 intrusive_ptr_test.cpp diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 074720f..3b988a8 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -126,6 +126,12 @@ public: return p_ == 0? 0: &intrusive_ptr::get; } + // operator! is a Borland-specific workaround + bool operator! () const + { + return p_ == 0; + } + void swap(intrusive_ptr & rhs) { T * tmp = p_; @@ -168,6 +174,17 @@ template inline bool operator!=(T * a, intrusive_ptr const & b) return a != b.get(); } +#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 + +// Resolve the ambiguity between our op!= and the one in rel_ops + +template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() != b.get(); +} + +#endif + template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) { return std::less()(a.get(), b.get()); diff --git a/intrusive_ptr_test.cpp b/intrusive_ptr_test.cpp new file mode 100644 index 0000000..f780d19 --- /dev/null +++ b/intrusive_ptr_test.cpp @@ -0,0 +1,553 @@ +#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#pragma warning(disable: 4355) // 'this' : used in base member initializer list +#pragma warning(disable: 4511) // copy constructor could not be generated +#pragma warning(disable: 4512) // assignment operator could not be generated +#endif + +// +// intrusive_ptr_test.cpp +// +// Copyright (c) 2002, 2003 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include +#include +#include +#include +#include + +// + +namespace N +{ + +class base +{ +private: + + long use_count_; + + base(base const &); + base & operator=(base const &); + +protected: + + base(): use_count_(0) + { + } + + virtual ~base() + { + } + +public: + + long use_count() const + { + return use_count_; + } + +#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + + inline friend void intrusive_ptr_add_ref(base * p) + { + ++p->use_count_; + } + + inline friend void intrusive_ptr_release(base * p) + { + if(--p->use_count_ == 0) delete p; + } + +#else + + void add_ref() + { + ++use_count_; + } + + void release() + { + if(--use_count_ == 0) delete this; + } + +#endif +}; + +} // namespace N + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + +namespace boost +{ + +inline void intrusive_ptr_add_ref(N::base * p) +{ + p->add_ref(); +} + +inline void intrusive_ptr_release(N::base * p) +{ + p->release(); +} + +} // namespace boost + +#endif + +// + +struct X: public virtual N::base +{ +}; + +struct Y: public X +{ +}; + +// + +namespace n_element_type +{ + +void f(X &) +{ +} + +void test() +{ + typedef boost::intrusive_ptr::element_type T; + T t; + f(t); +} + +} // namespace n_element_type + +namespace n_constructors +{ + +void default_constructor() +{ + boost::intrusive_ptr px; + BOOST_TEST(px.get() == 0); +} + +void pointer_constructor() +{ + { + boost::intrusive_ptr px(0); + BOOST_TEST(px.get() == 0); + } + + { + boost::intrusive_ptr px(0, false); + BOOST_TEST(px.get() == 0); + } + + { + X * p = new X; + BOOST_TEST(p->use_count() == 0); + + boost::intrusive_ptr px(p); + BOOST_TEST(px.get() == p); + BOOST_TEST(px->use_count() == 1); + } + + { + X * p = new X; + BOOST_TEST(p->use_count() == 0); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::intrusive_ptr_add_ref; +#endif + intrusive_ptr_add_ref(p); + BOOST_TEST(p->use_count() == 1); + + boost::intrusive_ptr px(p, false); + BOOST_TEST(px.get() == p); + BOOST_TEST(px->use_count() == 1); + } +} + +void copy_constructor() +{ + { + boost::intrusive_ptr px; + boost::intrusive_ptr px2(px); + BOOST_TEST(px2.get() == px.get()); + } + + { + boost::intrusive_ptr py; + boost::intrusive_ptr px(py); + BOOST_TEST(px.get() == py.get()); + } + + { + boost::intrusive_ptr px(0); + boost::intrusive_ptr px2(px); + BOOST_TEST(px2.get() == px.get()); + } + + { + boost::intrusive_ptr py(0); + boost::intrusive_ptr px(py); + BOOST_TEST(px.get() == py.get()); + } + + { + boost::intrusive_ptr px(0, false); + boost::intrusive_ptr px2(px); + BOOST_TEST(px2.get() == px.get()); + } + + { + boost::intrusive_ptr py(0, false); + boost::intrusive_ptr px(py); + BOOST_TEST(px.get() == py.get()); + } + + { + boost::intrusive_ptr px(new X); + boost::intrusive_ptr px2(px); + BOOST_TEST(px2.get() == px.get()); + } + + { + boost::intrusive_ptr py(new Y); + boost::intrusive_ptr px(py); + BOOST_TEST(px.get() == py.get()); + } +} + +void test() +{ + default_constructor(); + pointer_constructor(); + copy_constructor(); +} + +} // namespace n_constructors + +namespace n_destructor +{ + +void test() +{ + boost::intrusive_ptr px(new X); + BOOST_TEST(px->use_count() == 1); + + { + boost::intrusive_ptr px2(px); + BOOST_TEST(px->use_count() == 2); + } + + BOOST_TEST(px->use_count() == 1); +} + +} // namespace n_destructor + +namespace n_assignment +{ + +void copy_assignment() +{ +} + +void conversion_assignment() +{ +} + +void pointer_assignment() +{ +} + +void test() +{ + copy_assignment(); + conversion_assignment(); + pointer_assignment(); +} + +} // namespace n_assignment + +namespace n_access +{ + +void test() +{ + { + boost::intrusive_ptr px; + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::get_pointer; +#endif + + BOOST_TEST(get_pointer(px) == px.get()); + } + + { + boost::intrusive_ptr px(0); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::get_pointer; +#endif + + BOOST_TEST(get_pointer(px) == px.get()); + } + + { + boost::intrusive_ptr px(new X); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(&*px == px.get()); + BOOST_TEST(px.operator ->() == px.get()); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::get_pointer; +#endif + + BOOST_TEST(get_pointer(px) == px.get()); + } +} + +} // namespace n_access + +namespace n_swap +{ + +void test() +{ + { + boost::intrusive_ptr px; + boost::intrusive_ptr px2; + + px.swap(px2); + + BOOST_TEST(px.get() == 0); + BOOST_TEST(px2.get() == 0); + + using std::swap; + swap(px, px2); + + BOOST_TEST(px.get() == 0); + BOOST_TEST(px2.get() == 0); + } + + { + X * p = new X; + boost::intrusive_ptr px; + boost::intrusive_ptr px2(p); + boost::intrusive_ptr px3(px2); + + px.swap(px2); + + BOOST_TEST(px.get() == p); + BOOST_TEST(px->use_count() == 2); + BOOST_TEST(px2.get() == 0); + BOOST_TEST(px3.get() == p); + BOOST_TEST(px3->use_count() == 2); + + using std::swap; + swap(px, px2); + + BOOST_TEST(px.get() == 0); + BOOST_TEST(px2.get() == p); + BOOST_TEST(px2->use_count() == 2); + BOOST_TEST(px3.get() == p); + BOOST_TEST(px3->use_count() == 2); + } + + { + X * p1 = new X; + X * p2 = new X; + boost::intrusive_ptr px(p1); + boost::intrusive_ptr px2(p2); + boost::intrusive_ptr px3(px2); + + px.swap(px2); + + BOOST_TEST(px.get() == p2); + BOOST_TEST(px->use_count() == 2); + BOOST_TEST(px2.get() == p1); + BOOST_TEST(px2->use_count() == 1); + BOOST_TEST(px3.get() == p2); + BOOST_TEST(px3->use_count() == 2); + + using std::swap; + swap(px, px2); + + BOOST_TEST(px.get() == p1); + BOOST_TEST(px->use_count() == 1); + BOOST_TEST(px2.get() == p2); + BOOST_TEST(px2->use_count() == 2); + BOOST_TEST(px3.get() == p2); + BOOST_TEST(px3->use_count() == 2); + } +} + +} // namespace n_swap + +namespace n_comparison +{ + +template void test2(boost::intrusive_ptr const & p, boost::intrusive_ptr const & q) +{ + BOOST_TEST((p == q) == (p.get() == q.get())); + BOOST_TEST((p != q) == (p.get() != q.get())); +} + +template void test3(boost::intrusive_ptr const & p, boost::intrusive_ptr const & q) +{ + BOOST_TEST((p == q) == (p.get() == q.get())); + BOOST_TEST((p.get() == q) == (p.get() == q.get())); + BOOST_TEST((p == q.get()) == (p.get() == q.get())); + BOOST_TEST((p != q) == (p.get() != q.get())); + BOOST_TEST((p.get() != q) == (p.get() != q.get())); + BOOST_TEST((p != q.get()) == (p.get() != q.get())); + + // 'less' moved here as a g++ 2.9x parse error workaround + std::less less; + BOOST_TEST((p < q) == less(p.get(), q.get())); +} + +void test() +{ + { + boost::intrusive_ptr px; + test3(px, px); + + boost::intrusive_ptr px2; + test3(px, px2); + + boost::intrusive_ptr px3(px); + test3(px3, px3); + test3(px, px3); + } + + { + boost::intrusive_ptr px; + + boost::intrusive_ptr px2(new X); + test3(px, px2); + test3(px2, px2); + + boost::intrusive_ptr px3(new X); + test3(px2, px3); + + boost::intrusive_ptr px4(px2); + test3(px2, px4); + test3(px4, px4); + } + + { + boost::intrusive_ptr px(new X); + + boost::intrusive_ptr py(new Y); + test2(px, py); + + boost::intrusive_ptr px2(py); + test2(px2, py); + test3(px, px2); + test3(px2, px2); + } +} + +} // namespace n_comparison + +namespace n_static_cast +{ + +void test() +{ +} + +} // namespace n_static_cast + +namespace n_dynamic_cast +{ + +void test() +{ +} + +} // namespace n_dynamic_cast + +namespace n_transitive +{ + +struct X: public N::base +{ + boost::intrusive_ptr next; +}; + +void test() +{ + boost::intrusive_ptr p(new X); + p->next = boost::intrusive_ptr(new X); + BOOST_TEST(!p->next->next); + p = p->next; + BOOST_TEST(!p->next); +} + +} // namespace n_transitive + +namespace n_report_1 +{ + +class foo: public N::base +{ +public: + + foo(): m_self(this) + { + } + + void suicide() + { + m_self = 0; + } + +private: + + boost::intrusive_ptr m_self; +}; + +void test() +{ + foo * foo_ptr = new foo; + foo_ptr->suicide(); +} + +} // namespace n_report_1 + +int main() +{ + n_element_type::test(); + n_constructors::test(); + n_destructor::test(); + n_assignment::test(); + n_access::test(); + n_swap::test(); + n_comparison::test(); + n_static_cast::test(); + n_dynamic_cast::test(); + + n_transitive::test(); + n_report_1::test(); + + return boost::report_errors(); +} From abb0d9e725de0afcf5908cf2bb7e480d262485a2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 25 Jan 2003 16:17:17 +0000 Subject: [PATCH 192/513] Moved smart_ptr contents to subdirectories, switched to a local test/Jamfile. [SVN r17042] --- .../scoped_ptr_example.cpp | 0 .../scoped_ptr_example.hpp | 0 .../scoped_ptr_example_test.cpp | 0 .../shared_ptr_example.cpp | 0 .../shared_ptr_example2.cpp | 0 .../shared_ptr_example2.hpp | 0 .../shared_ptr_example2_test.cpp | 0 sp_debug_hooks.cpp => src/sp_debug_hooks.cpp | 0 test/Jamfile | 25 +++++++++++++++++++ .../get_deleter_test.cpp | 0 .../intrusive_ptr_test.cpp | 0 .../shared_from_this_test.cpp | 0 .../shared_ptr_alloc_test.cpp | 0 .../shared_ptr_assign_fail.cpp | 0 .../shared_ptr_basic_test.cpp | 0 .../shared_ptr_mt_test.cpp | 0 .../shared_ptr_test.cpp | 0 .../shared_ptr_timing_test.cpp | 0 smart_ptr_test.cpp => test/smart_ptr_test.cpp | 0 weak_ptr_test.cpp => test/weak_ptr_test.cpp | 0 20 files changed, 25 insertions(+) rename scoped_ptr_example.cpp => example/scoped_ptr_example.cpp (100%) rename scoped_ptr_example.hpp => example/scoped_ptr_example.hpp (100%) rename scoped_ptr_example_test.cpp => example/scoped_ptr_example_test.cpp (100%) rename shared_ptr_example.cpp => example/shared_ptr_example.cpp (100%) rename shared_ptr_example2.cpp => example/shared_ptr_example2.cpp (100%) rename shared_ptr_example2.hpp => example/shared_ptr_example2.hpp (100%) rename shared_ptr_example2_test.cpp => example/shared_ptr_example2_test.cpp (100%) rename sp_debug_hooks.cpp => src/sp_debug_hooks.cpp (100%) create mode 100644 test/Jamfile rename get_deleter_test.cpp => test/get_deleter_test.cpp (100%) rename intrusive_ptr_test.cpp => test/intrusive_ptr_test.cpp (100%) rename shared_from_this_test.cpp => test/shared_from_this_test.cpp (100%) rename shared_ptr_alloc_test.cpp => test/shared_ptr_alloc_test.cpp (100%) rename shared_ptr_assign_fail.cpp => test/shared_ptr_assign_fail.cpp (100%) rename shared_ptr_basic_test.cpp => test/shared_ptr_basic_test.cpp (100%) rename shared_ptr_mt_test.cpp => test/shared_ptr_mt_test.cpp (100%) rename shared_ptr_test.cpp => test/shared_ptr_test.cpp (100%) rename shared_ptr_timing_test.cpp => test/shared_ptr_timing_test.cpp (100%) rename smart_ptr_test.cpp => test/smart_ptr_test.cpp (100%) rename weak_ptr_test.cpp => test/weak_ptr_test.cpp (100%) diff --git a/scoped_ptr_example.cpp b/example/scoped_ptr_example.cpp similarity index 100% rename from scoped_ptr_example.cpp rename to example/scoped_ptr_example.cpp diff --git a/scoped_ptr_example.hpp b/example/scoped_ptr_example.hpp similarity index 100% rename from scoped_ptr_example.hpp rename to example/scoped_ptr_example.hpp diff --git a/scoped_ptr_example_test.cpp b/example/scoped_ptr_example_test.cpp similarity index 100% rename from scoped_ptr_example_test.cpp rename to example/scoped_ptr_example_test.cpp diff --git a/shared_ptr_example.cpp b/example/shared_ptr_example.cpp similarity index 100% rename from shared_ptr_example.cpp rename to example/shared_ptr_example.cpp diff --git a/shared_ptr_example2.cpp b/example/shared_ptr_example2.cpp similarity index 100% rename from shared_ptr_example2.cpp rename to example/shared_ptr_example2.cpp diff --git a/shared_ptr_example2.hpp b/example/shared_ptr_example2.hpp similarity index 100% rename from shared_ptr_example2.hpp rename to example/shared_ptr_example2.hpp diff --git a/shared_ptr_example2_test.cpp b/example/shared_ptr_example2_test.cpp similarity index 100% rename from shared_ptr_example2_test.cpp rename to example/shared_ptr_example2_test.cpp diff --git a/sp_debug_hooks.cpp b/src/sp_debug_hooks.cpp similarity index 100% rename from sp_debug_hooks.cpp rename to src/sp_debug_hooks.cpp diff --git a/test/Jamfile b/test/Jamfile new file mode 100644 index 0000000..88cfbfe --- /dev/null +++ b/test/Jamfile @@ -0,0 +1,25 @@ +# Boost.SmartPtr Library test Jamfile + +subproject libs/smart_ptr/test ; + +# bring in rules for testing +SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; +include testing.jam ; + +# Make tests run by default. +DEPENDS all : test ; + +{ + # look in BOOST_ROOT for sources first, just in this Jamfile + local SEARCH_SOURCE = $(BOOST_ROOT) $(SEARCH_SOURCE) ; + + test-suite "smart_ptr" + : [ run libs/smart_ptr/test/smart_ptr_test.cpp ] + [ run libs/smart_ptr/test/shared_ptr_basic_test.cpp : : : <*>-Wno-non-virtual-dtor ] + [ run libs/smart_ptr/test/shared_ptr_test.cpp : : : <*>-Wno-non-virtual-dtor ] + [ run libs/smart_ptr/test/weak_ptr_test.cpp ] + [ run libs/smart_ptr/test/shared_from_this_test.cpp : : : <*>-Wno-non-virtual-dtor ] + [ run libs/smart_ptr/test/get_deleter_test.cpp ] + [ compile-fail libs/smart_ptr/test/shared_ptr_assign_fail.cpp ] + ; +} diff --git a/get_deleter_test.cpp b/test/get_deleter_test.cpp similarity index 100% rename from get_deleter_test.cpp rename to test/get_deleter_test.cpp diff --git a/intrusive_ptr_test.cpp b/test/intrusive_ptr_test.cpp similarity index 100% rename from intrusive_ptr_test.cpp rename to test/intrusive_ptr_test.cpp diff --git a/shared_from_this_test.cpp b/test/shared_from_this_test.cpp similarity index 100% rename from shared_from_this_test.cpp rename to test/shared_from_this_test.cpp diff --git a/shared_ptr_alloc_test.cpp b/test/shared_ptr_alloc_test.cpp similarity index 100% rename from shared_ptr_alloc_test.cpp rename to test/shared_ptr_alloc_test.cpp diff --git a/shared_ptr_assign_fail.cpp b/test/shared_ptr_assign_fail.cpp similarity index 100% rename from shared_ptr_assign_fail.cpp rename to test/shared_ptr_assign_fail.cpp diff --git a/shared_ptr_basic_test.cpp b/test/shared_ptr_basic_test.cpp similarity index 100% rename from shared_ptr_basic_test.cpp rename to test/shared_ptr_basic_test.cpp diff --git a/shared_ptr_mt_test.cpp b/test/shared_ptr_mt_test.cpp similarity index 100% rename from shared_ptr_mt_test.cpp rename to test/shared_ptr_mt_test.cpp diff --git a/shared_ptr_test.cpp b/test/shared_ptr_test.cpp similarity index 100% rename from shared_ptr_test.cpp rename to test/shared_ptr_test.cpp diff --git a/shared_ptr_timing_test.cpp b/test/shared_ptr_timing_test.cpp similarity index 100% rename from shared_ptr_timing_test.cpp rename to test/shared_ptr_timing_test.cpp diff --git a/smart_ptr_test.cpp b/test/smart_ptr_test.cpp similarity index 100% rename from smart_ptr_test.cpp rename to test/smart_ptr_test.cpp diff --git a/weak_ptr_test.cpp b/test/weak_ptr_test.cpp similarity index 100% rename from weak_ptr_test.cpp rename to test/weak_ptr_test.cpp From 2dbfc89d4e557326704d386d50a17c76d73f2146 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 25 Jan 2003 16:51:45 +0000 Subject: [PATCH 193/513] Removed redundant copy constructor and copy assignment. [SVN r17043] --- example/shared_ptr_example2.cpp | 4 ---- example/shared_ptr_example2.hpp | 6 ++---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/example/shared_ptr_example2.cpp b/example/shared_ptr_example2.cpp index 746dd48..e062a1f 100644 --- a/example/shared_ptr_example2.cpp +++ b/example/shared_ptr_example2.cpp @@ -10,10 +10,6 @@ class example::implementation }; example::example() : _imp( new implementation ) {} -example::example( const example & s ) : _imp( s._imp ) {} - -example & example::operator=( const example & s ) - { _imp = s._imp; return *this; } void example::do_something() { std::cout << "use_count() is " << _imp.use_count() << "\n"; } diff --git a/example/shared_ptr_example2.hpp b/example/shared_ptr_example2.hpp index 93b77e5..9b63fc9 100644 --- a/example/shared_ptr_example2.hpp +++ b/example/shared_ptr_example2.hpp @@ -14,12 +14,10 @@ class example { - public: +public: example(); - example( const example & ); - example & operator=( const example & ); void do_something(); - private: +private: class implementation; boost::shared_ptr< implementation > _imp; // hide implementation details }; From b60de38d28e804fa07f69b1589fc2087235937c9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 25 Jan 2003 17:58:01 +0000 Subject: [PATCH 194/513] Fixed broken links. [SVN r17044] --- index.htm | 88 ++++++++++++++++++++++++------------------------ scoped_ptr.htm | 20 +++++------ shared_array.htm | 15 +++++---- shared_ptr.htm | 18 +++++----- smart_ptr.htm | 52 ++++++++++++++-------------- 5 files changed, 96 insertions(+), 97 deletions(-) diff --git a/index.htm b/index.htm index 676c78c..f53a933 100644 --- a/index.htm +++ b/index.htm @@ -1,47 +1,47 @@ - - - - -Boost Smart Pointer Library - - - - - - - - - - - - - -
    c++boost.gif (8819 bytes)HomeLibrariesPeopleFAQMore
    -

    Smart Pointer Library

    -

    The smart pointer library includes five smart pointer class templates. Smart -pointers ease the management of memory dynamically allocated with C++ new -expressions. In addition, scoped_ptr can ease the management of memory -dynamically allocated in other ways.

    - - -

    Revised 1 February 2002.

    - - - + + + Boost Smart Pointer Library + + + + + + + + + + + +
    c++boost.gif (8819 bytes)HomeLibrariesPeopleFAQMore
    +

    Smart Pointer Library

    +

    The smart pointer library includes five smart pointer class templates. Smart + pointers ease the management of memory dynamically allocated with C++ new + expressions. In addition, scoped_ptr can ease the management of memory + dynamically allocated in other ways.

    + +

    Revised + 1 February 2002 .

    + diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 4c1dba9..4a15223 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -14,10 +14,9 @@

    The scoped_ptr template is a simple solution for simple needs. It supplies a basic "resource acquisition is initialization" facility, without shared-ownership or transfer-of-ownership semantics. Both its name and - enforcement of semantics (by being - noncopyable) signal its intent to retain ownership solely within the - current scope. Because it is - noncopyable, + enforcement of semantics (by being + noncopyable) signal its intent to retain ownership solely within the + current scope. Because it is noncopyable, it is safer than shared_ptr or std::auto_ptr for pointers which should not be copied.

    Because scoped_ptr is simple, in its usual implementation every operation @@ -151,12 +150,12 @@ Buckle my shoe

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

    -

    The scoped_ptr_example_test.cpp sample - program includes a header file, scoped_ptr_example.hpp, +

    The scoped_ptr_example_test.cpp sample + program includes a header file, scoped_ptr_example.hpp, which uses a scoped_ptr<> to an incomplete type to hide the implementation. The instantiation of member functions which require a complete - type occurs in the scoped_ptr_example.cpp implementation - file.

    + type occurs in the scoped_ptr_example.cpp + implementation file.

    Frequently Asked Questions

    Q. Why doesn't scoped_ptr have a release() member?
    A. When reading source code, it is valuable to be able to draw @@ -166,11 +165,12 @@ Buckle my shoe

    given context. Use std::auto_ptr where transfer of ownership is required. (supplied by Dave Abrahams)


    -

    Revised 09 January 2003

    +

    Revised + 09 January 2003

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

    - \ No newline at end of file + diff --git a/shared_array.htm b/shared_array.htm index ecf84ae..f4d5f04 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -26,8 +26,8 @@

    A shared_ptr to a std::vector is an alternative to a shared_array that is a bit heavier duty but far more flexible.

    The class template is parameterized on T, the type of the object pointed - to. T must meet the smart pointer - common requirements.

    + to. T must meet the smart pointer + common requirements.

    Synopsis

    namespace boost {
     
    @@ -98,8 +98,8 @@
     			The guarantee that this does not throw exceptions depends on the requirement 
     			that the deleted object's destructor does not throw exceptions. See the smart 
     			pointer common requirements.

    -

    assignment

    -
    shared_array & operator=(shared_array const & r); // never throws
    +

    assignment

    +
    shared_array & operator=(shared_array const & r); // never throws

    Constructs a new shared_array as described above, then replaces this shared_array with the new one, destroying the replaced object.

    @@ -115,7 +115,7 @@ replaced object. D's copy constructor must not throw. The only exception which may be thrown is std::bad_alloc. If an exception is thrown, d(p) is called.

    -

    indexing

    +

    indexing

    T & operator[](std::ptrdiff_t i) const; // never throws

    Returns a reference to element i of the array pointed to by the stored pointer. Behavior is undefined and almost certainly undesirable if the stored @@ -169,11 +169,12 @@ template<class T> Provided as an aid to generic programming.


    Revised - 09 January 2003

    + + 09 January 2003

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

    - \ No newline at end of file + diff --git a/shared_ptr.htm b/shared_ptr.htm index 0f7d49d..652cc49 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -361,9 +361,9 @@ q = p;

    use_count

    long use_count() const; // never throws
    -

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

    +

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

    Throws: nothing.

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

    @@ -490,9 +490,9 @@ q = p;

    Returns: os.

    Example

    -

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

    +

    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 @@ -505,11 +505,11 @@ q = p;

    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, +

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

    diff --git a/smart_ptr.htm b/smart_ptr.htm index 6873980..bec58f1 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -8,11 +8,11 @@

    c++boost.gif (8819 bytes)Smart Pointers

    Introduction
    - Common Requirements
    - Exception Safety
    - Exception-specifications
    - History and Acknowledgements
    - References

    + Common Requirements
    + Exception Safety
    + Exception-specifications
    + History and Acknowledgements
    + References

    Introduction

    Smart pointers are objects which store pointers to dynamically allocated (heap) objects. They behave much like built-in C++ pointers except that they @@ -56,7 +56,7 @@

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

    -

    A test program, smart_ptr_test.cpp, is provided +

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

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

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

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

    -

    October 1998. Beman Dawes proposed reviving the original semantics under the names safe_ptr - and counted_ptr, meeting of Per Andersson, Matt +

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

    Over the next three months, several implementations were considered for shared_ptr, @@ -154,26 +154,24 @@ experimented with.

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

    -

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

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

    References

    -

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

    -

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

    +

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

    +

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


    Revised 15 January 2003 + 15 January 2003

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Permission to copy, use, modify, sell and distribute this document is granted @@ -181,4 +179,4 @@ "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.

    - \ No newline at end of file + From fabd6e5755e767c236ec32dc62ae24f857bf3ff9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 27 Jan 2003 14:02:00 +0000 Subject: [PATCH 195/513] Moved 'garbage collector' to sp_collector.cpp, collector_test.cpp added. [SVN r17050] --- include/boost/detail/shared_count.hpp | 6 + src/sp_collector.cpp | 267 ++++++++++++++++++++++++++ src/sp_debug_hooks.cpp | 201 +------------------ test/collector_test.cpp | 100 ++++++++++ 4 files changed, 375 insertions(+), 199 deletions(-) create mode 100644 src/sp_collector.cpp create mode 100644 test/collector_test.cpp diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index a7b6aaa..cb9e713 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -355,6 +355,9 @@ public: ~shared_count() // nothrow { if(pi_ != 0) pi_->release(); +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + id_ = 0; +#endif } shared_count(shared_count const & r): pi_(r.pi_) // nothrow @@ -455,6 +458,9 @@ public: ~weak_count() // nothrow { if(pi_ != 0) pi_->weak_release(); +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + id_ = 0; +#endif } weak_count & operator= (shared_count const & r) // nothrow diff --git a/src/sp_collector.cpp b/src/sp_collector.cpp new file mode 100644 index 0000000..d56bf1a --- /dev/null +++ b/src/sp_collector.cpp @@ -0,0 +1,267 @@ +// +// sp_collector.cpp +// +// Copyright (c) 2002, 2003 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) + +#include +#include +#include +#include +#include +#include +#include + +typedef std::map< void const *, std::pair > map_type; + +static map_type & get_map() +{ + static map_type m; + return m; +} + +typedef boost::detail::lightweight_mutex mutex_type; + +static mutex_type & get_mutex() +{ + static mutex_type m; + return m; +} + +static void * init_mutex_before_main = &get_mutex(); + +namespace +{ + class X; + + struct count_layout + { + boost::detail::sp_counted_base * pi; + int id; + }; + + struct shared_ptr_layout + { + X * px; + count_layout pn; + }; +} + +// assume 4 byte alignment for pointers when scanning +size_t const pointer_align = 4; + +typedef std::map map2_type; + +static void scan_and_count(void const * area, size_t size, map_type const & m, map2_type & m2) +{ + unsigned char const * p = static_cast(area); + + for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align) + { + shared_ptr_layout const * q = reinterpret_cast(p); + + if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m.count(q->pn.pi) != 0) + { + ++m2[q->pn.pi]; + } + } +} + +typedef std::deque open_type; + +static void scan_and_mark(void const * area, size_t size, map2_type & m2, open_type & open) +{ + unsigned char const * p = static_cast(area); + + for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align) + { + shared_ptr_layout const * q = reinterpret_cast(p); + + if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0) + { + open.push_back(q->pn.pi); + m2.erase(q->pn.pi); + } + } +} + +static void find_unreachable_objects_impl(map_type const & m, map2_type & m2) +{ + // scan objects for shared_ptr members, compute internal counts + + { + std::cout << "... " << m.size() << " objects in m.\n"; + + for(map_type::const_iterator i = m.begin(); i != m.end(); ++i) + { + boost::detail::sp_counted_base const * p = static_cast(i->first); + + BOOST_ASSERT(p->use_count() != 0); // there should be no inactive counts in the map + + scan_and_count(i->second.first, i->second.second, m, m2); + } + + std::cout << "... " << m2.size() << " objects in m2.\n"; + } + + // mark reachable objects + + { + open_type open; + + for(map2_type::iterator i = m2.begin(); i != m2.end(); ++i) + { + boost::detail::sp_counted_base const * p = static_cast(i->first); + if(p->use_count() != i->second) open.push_back(p); + } + + std::cout << "... " << m2.size() << " objects in open.\n"; + + for(open_type::iterator j = open.begin(); j != open.end(); ++j) + { + m2.erase(*j); + } + + while(!open.empty()) + { + void const * p = open.front(); + open.pop_front(); + + map_type::const_iterator i = m.find(p); + BOOST_ASSERT(i != m.end()); + + scan_and_mark(i->second.first, i->second.second, m2, open); + } + } + + // m2 now contains the unreachable objects +} + +std::size_t find_unreachable_objects(bool report) +{ + map2_type m2; + +#ifdef BOOST_HAS_THREADS + + // This will work without the #ifdef, but some compilers warn + // that lock is not referenced + + mutex_type::scoped_lock lock(get_mutex()); + +#endif + + map_type const & m = get_map(); + + find_unreachable_objects_impl(m, m2); + + if(report) + { + for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j) + { + map_type::const_iterator i = m.find(j->first); + BOOST_ASSERT(i != m.end()); + std::cout << "Unreachable object at " << i->second.first << ", " << i->second.second << " bytes long.\n"; + } + } + + return m2.size(); +} + +typedef std::deque< boost::shared_ptr > free_list_type; + +static void scan_and_free(void * area, size_t size, map2_type const & m2, free_list_type & free) +{ + unsigned char * p = static_cast(area); + + for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align) + { + shared_ptr_layout * q = reinterpret_cast(p); + + if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0 && q->px != 0) + { + boost::shared_ptr * ppx = reinterpret_cast< boost::shared_ptr * >(p); + free.push_back(*ppx); + ppx->reset(); + } + } +} + +void free_unreachable_objects() +{ + map2_type m2; + +#ifdef BOOST_HAS_THREADS + + mutex_type::scoped_lock lock(get_mutex()); + +#endif + + map_type const & m = get_map(); + + find_unreachable_objects_impl(m, m2); + + free_list_type free; + + for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j) + { + map_type::const_iterator i = m.find(j->first); + BOOST_ASSERT(i != m.end()); + scan_and_free(i->second.first, i->second.second, m2, free); + } + + std::cout << "... about to free " << free.size() << " objects.\n"; +} + +// debug hooks + +namespace boost +{ + +void sp_scalar_constructor_hook(void *) +{ +} + +void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn) +{ +#ifdef BOOST_HAS_THREADS + + mutex_type::scoped_lock lock(get_mutex()); + +#endif + + get_map()[pn] = std::make_pair(px, size); +} + +void sp_scalar_destructor_hook(void *) +{ +} + +void sp_scalar_destructor_hook(void *, std::size_t, void * pn) +{ +#ifdef BOOST_HAS_THREADS + + mutex_type::scoped_lock lock(get_mutex()); + +#endif + + get_map().erase(pn); +} + +void sp_array_constructor_hook(void *) +{ +} + +void sp_array_destructor_hook(void *) +{ +} + +} // namespace boost + +#endif // defined(BOOST_ENABLE_SP_DEBUG_HOOKS) diff --git a/src/sp_debug_hooks.cpp b/src/sp_debug_hooks.cpp index 0f7e365..6ad1edc 100644 --- a/src/sp_debug_hooks.cpp +++ b/src/sp_debug_hooks.cpp @@ -8,19 +8,12 @@ // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // -// http://www.boost.org/libs/smart_ptr/debug_hooks.html -// #if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) #include -#include -#include #include #include -#include -#include -#include int const m = 2; // m * sizeof(int) must be aligned appropriately @@ -112,192 +105,6 @@ void * operator new[](size_t n, nothrow_t const &) throw() #endif -// cycle detection - -typedef std::map< void const *, std::pair > map_type; - -static map_type & get_map() -{ - static map_type m; - return m; -} - -typedef boost::detail::lightweight_mutex mutex_type; - -static mutex_type & get_mutex() -{ - static mutex_type m; - return m; -} - -static void * init_mutex_before_main = &get_mutex(); - -namespace -{ - class X; - - struct count_layout - { - boost::detail::sp_counted_base * pi; - int id; - }; - - struct shared_ptr_layout - { - X * px; - count_layout pn; - }; -} - -// assume 4 byte alignment for pointers when scanning -size_t const pointer_align = 4; - -typedef std::map map2_type; - -static void scan_and_count(void const * area, size_t size, map_type const & m, map2_type & m2) -{ - unsigned char const * p = static_cast(area); - - for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align) - { - shared_ptr_layout const * q = reinterpret_cast(p); - - if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m.count(q->pn.pi) != 0) - { - ++m2[q->pn.pi]; - } - } -} - -typedef std::deque open_type; - -static void scan_and_mark(void const * area, size_t size, map2_type & m2, open_type & open) -{ - unsigned char const * p = static_cast(area); - - for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align) - { - shared_ptr_layout const * q = reinterpret_cast(p); - - if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0) - { - open.push_back(q->pn.pi); - m2.erase(q->pn.pi); - } - } -} - -static void find_unreachable_objects(map_type const & m, map2_type & m2) -{ - // scan objects for shared_ptr members, compute internal counts - - { - for(map_type::const_iterator i = m.begin(); i != m.end(); ++i) - { - boost::detail::sp_counted_base const * p = static_cast(i->first); - - BOOST_ASSERT(p->use_count() != 0); // there should be no inactive counts in the map - - scan_and_count(i->second.first, i->second.second, m, m2); - } - } - - // mark reachable objects - - { - open_type open; - - for(map2_type::iterator i = m2.begin(); i != m2.end(); ++i) - { - boost::detail::sp_counted_base const * p = static_cast(i->first); - if(p->use_count() != i->second) open.push_back(p); - } - - for(open_type::iterator j = open.begin(); j != open.end(); ++j) - { - m2.erase(*j); - } - - while(!open.empty()) - { - void const * p = open.front(); - open.pop_front(); - - map_type::const_iterator i = m.find(p); - BOOST_ASSERT(i != m.end()); - - scan_and_mark(i->second.first, i->second.second, m2, open); - } - } - - // m2 now contains the unreachable objects -} - -void report_unreachable_objects(bool verbose) -{ - map2_type m2; - - mutex_type::scoped_lock lock(get_mutex()); - - map_type const & m = get_map(); - - find_unreachable_objects(m, m2); - - if(verbose) - { - for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j) - { - map_type::const_iterator i = m.find(j->first); - BOOST_ASSERT(i != m.end()); -// std::cerr << "Unreachable object at " << i->second.first << ", " << i->second.second << " bytes long.\n"; - } - } - - if(verbose || !m2.empty()) - { - std::cerr << m2.size() << " unreachable objects.\n"; - } -} - -typedef std::deque< boost::shared_ptr > free_list_type; - -static void scan_and_free(void * area, size_t size, map2_type const & m2, free_list_type & free) -{ - unsigned char * p = static_cast(area); - - for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align) - { - shared_ptr_layout * q = reinterpret_cast(p); - - if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0 && q->px != 0) - { - boost::shared_ptr * ppx = reinterpret_cast< boost::shared_ptr * >(p); - free.push_back(*ppx); - ppx->reset(); - } - } -} - -void free_unreachable_objects() -{ - map2_type m2; - - mutex_type::scoped_lock lock(get_mutex()); - - map_type const & m = get_map(); - - find_unreachable_objects(m, m2); - - free_list_type free; - - for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j) - { - map_type::const_iterator i = m.find(j->first); - BOOST_ASSERT(i != m.end()); - scan_and_free(i->second.first, i->second.second, m2, free); - } -} - // debug hooks namespace boost @@ -317,11 +124,9 @@ void sp_scalar_constructor_hook(void * p) *pm = adopted_scalar; } -void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn) +void sp_scalar_constructor_hook(void * px, std::size_t, void *) { sp_scalar_constructor_hook(px); - mutex_type::scoped_lock lock(get_mutex()); - get_map()[pn] = std::make_pair(px, size); } void sp_scalar_destructor_hook(void * p) @@ -336,11 +141,9 @@ void sp_scalar_destructor_hook(void * p) *pm = allocated_scalar; } -void sp_scalar_destructor_hook(void * px, std::size_t /*size*/, void * pn) +void sp_scalar_destructor_hook(void * px, std::size_t, void *) { sp_scalar_destructor_hook(px); - mutex_type::scoped_lock lock(get_mutex()); - get_map().erase(pn); } // It is not possible to handle the array hooks in a portable manner. diff --git a/test/collector_test.cpp b/test/collector_test.cpp new file mode 100644 index 0000000..89fd208 --- /dev/null +++ b/test/collector_test.cpp @@ -0,0 +1,100 @@ +// +// collector_test.cpp +// +// Copyright (c) 2003 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include +#include +#include +#include +#include + +// sp_collector.cpp exported functions + +std::size_t find_unreachable_objects(bool report); +void free_unreachable_objects(); + +struct X +{ + void* fill[32]; + boost::shared_ptr p; +}; + +void report() +{ + std::cout << "Calling find_unreachable_objects:\n"; + + std::clock_t t = std::clock(); + + std::size_t n = find_unreachable_objects(false); + + t = std::clock() - t; + + std::cout << n << " unreachable objects.\n"; + std::cout << " " << static_cast(t) / CLOCKS_PER_SEC << " seconds.\n"; +} + +void free() +{ + std::cout << "Calling free_unreachable_objects:\n"; + + std::clock_t t = std::clock(); + + free_unreachable_objects(); + + t = std::clock() - t; + + std::cout << " " << static_cast(t) / CLOCKS_PER_SEC << " seconds.\n"; +} + +int main() +{ + std::vector< boost::shared_ptr > v1, v2; + + int const n = 256 * 1024; + + std::cout << "Filling v1 and v2\n"; + + for(int i = 0; i < n; ++i) + { + v1.push_back(boost::shared_ptr(new X)); + v2.push_back(boost::shared_ptr(new X)); + } + + report(); + + std::cout << "Creating the cycles\n"; + + for(int i = 0; i < n - 1; ++i) + { + v2[i]->p = v2[i+1]; + } + + v2[n-1]->p = v2[0]; + + report(); + + std::cout << "Resizing v2 to size of 1\n"; + + v2.resize(1); + report(); + + std::cout << "Clearing v2\n"; + + v2.clear(); + report(); + + std::cout << "Clearing v1\n"; + + v1.clear(); + report(); + + free(); + report(); +} From 89ea2156bc1b107e3fa1daac182dc1a22db40131 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 27 Jan 2003 14:09:21 +0000 Subject: [PATCH 196/513] intrusive_ptr_test.cpp added. [SVN r17051] --- test/Jamfile | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Jamfile b/test/Jamfile index 88cfbfe..dfb20fb 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -20,6 +20,7 @@ DEPENDS all : test ; [ run libs/smart_ptr/test/weak_ptr_test.cpp ] [ run libs/smart_ptr/test/shared_from_this_test.cpp : : : <*>-Wno-non-virtual-dtor ] [ run libs/smart_ptr/test/get_deleter_test.cpp ] + [ run libs/smart_ptr/test/intrusive_ptr_test.cpp ] [ compile-fail libs/smart_ptr/test/shared_ptr_assign_fail.cpp ] ; } From cd41426fe9bedcd982a3f81d17d8e4a8ed276b20 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 30 Jan 2003 14:20:22 +0000 Subject: [PATCH 197/513] Dave's quick_allocator added, #define BOOST_SP_USE_QUICK_ALLOCATOR to make shared_ptr use it. [SVN r17087] --- include/boost/detail/shared_count.hpp | 33 +++++++++++--- test/shared_ptr_alloc_test.cpp | 66 ++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 9 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index cb9e713..0e2783c 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -18,19 +18,24 @@ #include -#ifndef BOOST_NO_AUTO_PTR -# include +#if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR) +# error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible. #endif #include #include #include -#include // for std::less -#include // for std::exception -#include // for std::bad_alloc -#include // for std::type_info in get_deleter -#include // for std::size_t +#if defined(BOOST_SP_USE_QUICK_ALLOCATOR) +#include +#endif + +#include // std::auto_ptr, std::allocator +#include // std::less +#include // std::exception +#include // std::bad_alloc +#include // std::type_info in get_deleter +#include // std::size_t #ifdef __BORLANDC__ # pragma warn -8026 // Functions with excep. spec. are not expanded inline @@ -274,6 +279,20 @@ public: std::allocator().deallocate(static_cast(p), 1); } +#endif + +#if defined(BOOST_SP_USE_QUICK_ALLOCATOR) + + void * operator new(std::size_t) + { + return quick_allocator::alloc(); + } + + void operator delete(void * p) + { + quick_allocator::dealloc(p); + } + #endif }; diff --git a/test/shared_ptr_alloc_test.cpp b/test/shared_ptr_alloc_test.cpp index 079dde7..5a3e17a 100644 --- a/test/shared_ptr_alloc_test.cpp +++ b/test/shared_ptr_alloc_test.cpp @@ -1,7 +1,7 @@ // // shared_ptr_alloc_test.cpp - use to evaluate the impact of count allocations // -// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2002, 2003 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. @@ -11,10 +11,12 @@ #include #include +#include #include #include #include +#include #include int const n = 1024 * 1024; @@ -33,7 +35,7 @@ template void test(T * = 0) t = std::clock() - t; - std::cout << static_cast(t) / CLOCKS_PER_SEC << '\n'; + std::cout << " " << static_cast(t) / CLOCKS_PER_SEC << " seconds.\n"; } class X @@ -62,6 +64,48 @@ private: int n_; }; +class Y +{ +public: + + explicit Y(int n): n_(n) + { + } + + void * operator new(std::size_t n) + { + return boost::detail::quick_allocator::alloc(n); + } + + void operator delete(void * p, std::size_t n) + { + boost::detail::quick_allocator::dealloc(p, n); + } + +private: + + Y(Y const &); + Y & operator=(Y const &); + + int n_; +}; + +class Z: public Y +{ +public: + + explicit Z(int n): Y(n), m_(n + 1) + { + } + +private: + + Z(Z const &); + Z & operator=(Z const &); + + int m_; +}; + int main() { std::cout << BOOST_COMPILER "\n"; @@ -80,6 +124,12 @@ int main() std::cout << "BOOST_SP_USE_STD_ALLOCATOR: (not defined)\n"; #endif +#if defined(BOOST_SP_USE_QUICK_ALLOCATOR) + std::cout << "BOOST_SP_USE_QUICK_ALLOCATOR: (defined)\n"; +#else + std::cout << "BOOST_SP_USE_QUICK_ALLOCATOR: (not defined)\n"; +#endif + std::cout << n << " shared_ptr allocations + deallocations:\n"; test(); @@ -91,4 +141,16 @@ int main() test(); test(); test(); + + std::cout << n << " shared_ptr allocations + deallocations:\n"; + + test(); + test(); + test(); + + std::cout << n << " shared_ptr allocations + deallocations:\n"; + + test(); + test(); + test(); } From ddf1f0fdcc847e33cf57305a7db8eb40a1f18bbd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 30 Jan 2003 15:06:32 +0000 Subject: [PATCH 198/513] Fixed a deadlock in free_unreachable_objects. [SVN r17090] --- src/sp_collector.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/sp_collector.cpp b/src/sp_collector.cpp index d56bf1a..7b96ed7 100644 --- a/src/sp_collector.cpp +++ b/src/sp_collector.cpp @@ -195,25 +195,27 @@ static void scan_and_free(void * area, size_t size, map2_type const & m2, free_l void free_unreachable_objects() { - map2_type m2; + free_list_type free; + + { + map2_type m2; #ifdef BOOST_HAS_THREADS - mutex_type::scoped_lock lock(get_mutex()); + mutex_type::scoped_lock lock(get_mutex()); #endif - map_type const & m = get_map(); + map_type const & m = get_map(); - find_unreachable_objects_impl(m, m2); + find_unreachable_objects_impl(m, m2); - free_list_type free; - - for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j) - { - map_type::const_iterator i = m.find(j->first); - BOOST_ASSERT(i != m.end()); - scan_and_free(i->second.first, i->second.second, m2, free); + for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j) + { + map_type::const_iterator i = m.find(j->first); + BOOST_ASSERT(i != m.end()); + scan_and_free(i->second.first, i->second.second, m2, free); + } } std::cout << "... about to free " << free.size() << " objects.\n"; From d2c7febd269908680e46071e35f861a938ff78c1 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 30 Jan 2003 18:20:51 +0000 Subject: [PATCH 199/513] cleanup, add shared_ptr_alloc_test. [SVN r17095] --- test/Jamfile | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/test/Jamfile b/test/Jamfile index dfb20fb..2986e82 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -7,20 +7,28 @@ SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; include testing.jam ; # Make tests run by default. -DEPENDS all : test ; +DEPENDS all : smart_ptr ; { - # look in BOOST_ROOT for sources first, just in this Jamfile - local SEARCH_SOURCE = $(BOOST_ROOT) $(SEARCH_SOURCE) ; - test-suite "smart_ptr" - : [ run libs/smart_ptr/test/smart_ptr_test.cpp ] - [ run libs/smart_ptr/test/shared_ptr_basic_test.cpp : : : <*>-Wno-non-virtual-dtor ] - [ run libs/smart_ptr/test/shared_ptr_test.cpp : : : <*>-Wno-non-virtual-dtor ] - [ run libs/smart_ptr/test/weak_ptr_test.cpp ] - [ run libs/smart_ptr/test/shared_from_this_test.cpp : : : <*>-Wno-non-virtual-dtor ] - [ run libs/smart_ptr/test/get_deleter_test.cpp ] - [ run libs/smart_ptr/test/intrusive_ptr_test.cpp ] - [ compile-fail libs/smart_ptr/test/shared_ptr_assign_fail.cpp ] + : [ run smart_ptr_test.cpp ] + [ run shared_ptr_basic_test.cpp : : : <*>-Wno-non-virtual-dtor ] + [ run shared_ptr_test.cpp : : : <*>-Wno-non-virtual-dtor ] + [ run weak_ptr_test.cpp ] + [ run shared_from_this_test.cpp : : : <*>-Wno-non-virtual-dtor ] + [ run get_deleter_test.cpp ] + [ run intrusive_ptr_test.cpp ] + [ run intrusive_ptr_test.cpp ] + [ compile-fail shared_ptr_assign_fail.cpp ] ; + + # this one is too slow to run unless explicitly requested, and ALL + # tests are run by default when this file is subincluded from + # boost/status, so it's guarded from that case. It will only be + # built from this directory when the targets "test" (all tests) or + # "shared_ptr_alloc_test" are requested. + if ! $(gIN_LIB_INCLUDE) + { + run shared_ptr_alloc_test.cpp ; + } } From 44afc7e5cd9350de9c0b0831339ad97c635ea75b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 30 Jan 2003 20:57:34 +0000 Subject: [PATCH 200/513] really prevent shared_ptr_alloc_test building from status/. [SVN r17097] --- test/Jamfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Jamfile b/test/Jamfile index 2986e82..e2591a9 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -27,7 +27,7 @@ DEPENDS all : smart_ptr ; # boost/status, so it's guarded from that case. It will only be # built from this directory when the targets "test" (all tests) or # "shared_ptr_alloc_test" are requested. - if ! $(gIN_LIB_INCLUDE) + if [ in-invocation-subdir ] { run shared_ptr_alloc_test.cpp ; } From be0267f9a3f9f5e8abcb0111fdfe56b35fd04495 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 3 Feb 2003 13:48:33 +0000 Subject: [PATCH 201/513] Enabled copy assignment on all Borland versions (for Kylix) and g++ (for -Wsynth, report by Wolfgang Bangerth) [SVN r17173] --- include/boost/shared_ptr.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index debb9a7..e66373a 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -129,8 +129,8 @@ public: // generated copy constructor, assignment, destructor are fine... -// except on Borland C++ 5.5.1 (and 5.6) -#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x561) +// 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 { From 98fa979aefeb9b99d1a92ef91af39569707b7290 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 4 Feb 2003 13:35:06 +0000 Subject: [PATCH 202/513] Added copyright. [SVN r17197] --- example/scoped_ptr_example.cpp | 8 ++++++++ example/scoped_ptr_example.hpp | 8 ++++++++ example/scoped_ptr_example_test.cpp | 8 ++++++++ example/shared_ptr_example2.cpp | 8 ++++++++ example/shared_ptr_example2.hpp | 8 ++++++++ example/shared_ptr_example2_test.cpp | 8 ++++++++ 6 files changed, 48 insertions(+) diff --git a/example/scoped_ptr_example.cpp b/example/scoped_ptr_example.cpp index 3e2e511..b15356b 100644 --- a/example/scoped_ptr_example.cpp +++ b/example/scoped_ptr_example.cpp @@ -1,5 +1,13 @@ // Boost scoped_ptr_example implementation file -----------------------------// +// (C) Copyright Beman Dawes 2001. Permission to copy, +// use, modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided "as is" +// without express or implied warranty, and with no claim as to its +// suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. + #include "scoped_ptr_example.hpp" #include diff --git a/example/scoped_ptr_example.hpp b/example/scoped_ptr_example.hpp index d3009f7..14c1c6b 100644 --- a/example/scoped_ptr_example.hpp +++ b/example/scoped_ptr_example.hpp @@ -1,5 +1,13 @@ // Boost scoped_ptr_example header file ------------------------------------// +// (C) Copyright Beman Dawes 2001. Permission to copy, +// use, modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided "as is" +// without express or implied warranty, and with no claim as to its +// suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. + #include #include diff --git a/example/scoped_ptr_example_test.cpp b/example/scoped_ptr_example_test.cpp index 1b77af2..4037997 100644 --- a/example/scoped_ptr_example_test.cpp +++ b/example/scoped_ptr_example_test.cpp @@ -1,5 +1,13 @@ // Boost scoped_ptr_example_test main program -------------------------------// +// (C) Copyright Beman Dawes 2001. Permission to copy, +// use, modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided "as is" +// without express or implied warranty, and with no claim as to its +// suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. + #include "scoped_ptr_example.hpp" int main() diff --git a/example/shared_ptr_example2.cpp b/example/shared_ptr_example2.cpp index e062a1f..cbf69ec 100644 --- a/example/shared_ptr_example2.cpp +++ b/example/shared_ptr_example2.cpp @@ -1,5 +1,13 @@ // Boost shared_ptr_example2 implementation file -----------------------------// +// (C) Copyright Beman Dawes 2001. Permission to copy, +// use, modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided "as is" +// without express or implied warranty, and with no claim as to its +// suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. + #include "shared_ptr_example2.hpp" #include diff --git a/example/shared_ptr_example2.hpp b/example/shared_ptr_example2.hpp index 9b63fc9..bb9050e 100644 --- a/example/shared_ptr_example2.hpp +++ b/example/shared_ptr_example2.hpp @@ -1,5 +1,13 @@ // Boost shared_ptr_example2 header file -----------------------------------// +// (C) Copyright Beman Dawes 2001. Permission to copy, +// use, modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided "as is" +// without express or implied warranty, and with no claim as to its +// suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. + #include // This example demonstrates the handle/body idiom (also called pimpl and diff --git a/example/shared_ptr_example2_test.cpp b/example/shared_ptr_example2_test.cpp index 3a2cf53..a03511e 100644 --- a/example/shared_ptr_example2_test.cpp +++ b/example/shared_ptr_example2_test.cpp @@ -1,5 +1,13 @@ // Boost shared_ptr_example2_test main program ------------------------------// +// (C) Copyright Beman Dawes 2001. Permission to copy, +// use, modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided "as is" +// without express or implied warranty, and with no claim as to its +// suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. + #include "shared_ptr_example2.hpp" int main() From 86e9a322bae9a9635666fbe20ef4b116cae69207 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 5 Feb 2003 12:56:48 +0000 Subject: [PATCH 203/513] Documentation fixes, make_shared -> get_shared_ptr. [SVN r17230] --- enable_shared_from_this.html | 12 +++---- include/boost/weak_ptr.hpp | 14 +++++--- index.htm | 8 +++-- intrusive_ptr.html | 14 ++++---- shared_ptr.htm | 59 +++++++++++++++++++++------------- sp_techniques.html | 2 +- test/shared_ptr_basic_test.cpp | 10 +++--- test/shared_ptr_test.cpp | 2 +- test/weak_ptr_test.cpp | 6 ++-- weak_ptr.htm | 32 ++++++------------ 10 files changed, 85 insertions(+), 74 deletions(-) diff --git a/enable_shared_from_this.html b/enable_shared_from_this.html index 425a781..8ff0a73 100644 --- a/enable_shared_from_this.html +++ b/enable_shared_from_this.html @@ -71,9 +71,9 @@ public:

    Requires: enable_shared_from_this<T> must be an accessible base class of T. *this must be a subobject - of an instance t of type T. There must have - existed at least one shared_ptr instance p pointing - to t. + of an instance t of type T . There must exist + at least one shared_ptr instance p that owns + t.

    Returns: A shared_ptr<T> instance r that shares @@ -85,9 +85,9 @@ public:


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

    diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 9d56858..29e7e9f 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -24,7 +24,7 @@ namespace boost { -template shared_ptr make_shared(weak_ptr const & r); // never throws +template shared_ptr get_shared_ptr(weak_ptr const & r); // never throws template class weak_ptr { @@ -64,7 +64,7 @@ public: template weak_ptr(weak_ptr const & r): pn(r.pn) // never throws { - px = boost::make_shared(r).get(); + px = boost::get_shared_ptr(r).get(); } template @@ -77,7 +77,7 @@ public: template weak_ptr & operator=(weak_ptr const & r) // never throws { - px = boost::make_shared(r).get(); + px = boost::get_shared_ptr(r).get(); pn = r.pn; return *this; } @@ -151,7 +151,7 @@ template void swap(weak_ptr & a, weak_ptr & b) a.swap(b); } -template shared_ptr make_shared(weak_ptr const & r) // never throws +template shared_ptr get_shared_ptr(weak_ptr const & r) // never throws { #if defined(BOOST_HAS_THREADS) @@ -180,6 +180,12 @@ template shared_ptr make_shared(weak_ptr const & r) // never thro #endif } +// deprecated, provided for backward compatibility +template shared_ptr make_shared(weak_ptr const & r) +{ + return boost::get_shared_ptr(r); +} + } // namespace boost #ifdef BOOST_MSVC diff --git a/index.htm b/index.htm index f53a933..2c775ac 100644 --- a/index.htm +++ b/index.htm @@ -33,6 +33,10 @@ Header shared_array.hpp.
  • Header weak_ptr.hpp.
  • +
  • + Header enable_shared_from_this.hpp.
  • +
  • + Header intrusive_ptr.hpp.
  • Test program smart_ptr_test.cpp.
  • @@ -41,7 +45,7 @@ by Peter Dimov and Darin Adler.
  • -

    Revised - 1 February 2002 .

    +
    +

    $Date$

    diff --git a/intrusive_ptr.html b/intrusive_ptr.html index fca484d..22bbc0c 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -19,9 +19,9 @@ the reference count by using an unqualified call to the function intrusive_ptr_add_ref, passing it the pointer as an argument. Similarly, when an intrusive_ptr is destroyed, it calls intrusive_ptr_release; this function is - responsible for destroying the object when its reference count drops to - zero. The user is expected to provide suitable definitions of these two - functions. On compilers that support argument-dependent lookup, intrusive_ptr_add_ref + responsible for destroying the object when its reference count drops to zero. + The user is expected to provide suitable definitions of these two functions. On + compilers that support argument-dependent lookup, intrusive_ptr_add_ref and intrusive_ptr_release should be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in namespace boost.

    @@ -39,8 +39,8 @@
  • intrusive_ptr<T> can be constructed from an arbitrary raw pointer of type T *.
  • -

    As a general rule, if it isn't obvious whether intrusive_ptr - better fits your needs than shared_ptr, try a shared_ptr-based +

    As a general rule, if it isn't obvious whether intrusive_ptr better + fits your needs than shared_ptr, try a shared_ptr-based design first.

    Synopsis

    namespace boost {
    @@ -268,9 +268,9 @@ intrusive_ptr & operator=(T * r);

    $Date$

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

    + warranty, and with no claim as to its suitability for any purpose.

    diff --git a/shared_ptr.htm b/shared_ptr.htm index 652cc49..bdd8d22 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -8,7 +8,6 @@

    c++boost.gif (8819 bytes)shared_ptr class template

    Introduction
    - Motivation
    Best Practices
    Synopsis
    Members
    @@ -47,8 +46,6 @@ to shared_ptr<T const>, to shared_ptr<U> where U is an accessible base of T, and to shared_ptr<void>.

    -

    Motivation

    -

    [...]

    Best Practices

    A simple guideline that nearly eliminates the possibility of memory leaks is: always use a named smart pointer variable to hold the result of new. @@ -83,8 +80,8 @@ void bad() evaluated in unspecified order, it is possible for new int(2) to be evaluated first, g() second, and we may never get to the shared_ptr constructor if g throws an exception. - See Herb Sutter's treatment of - the issue for more information.

    + See Herb Sutter's treatment (also + here) of the issue for more information.

    Synopsis

    namespace boost {
     
    @@ -150,6 +147,8 @@ void bad()
       template<class E, class T, class Y>
         std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
     
    +  template<class D, class T>
    +    D * get_deleter(shared_ptr<T> const & p);
     }

    [It might be convenient to relax the requirements on shared_ptr's signature, allowing an additional, defaulted, template parameter; the parameter @@ -193,7 +192,7 @@ void bad() 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, storing a copy of p.

    +

    Effects: Constructs a shared_ptr that owns the pointer p.

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

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

    @@ -220,7 +219,8 @@ void bad() of D must not throw. The expression d(p) must be well-formed, must not invoke undefined behavior, and must not throw exceptions.

    -

    Effects: Constructs a shared_ptr, storing a copy of p and d.

    +

    Effects: Constructs a shared_ptr that owns the pointer + p and the deleter d.

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

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

    @@ -288,9 +288,19 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r); // never

    destructor

    ~shared_ptr(); // never throws
    -

    Effects: If *this is the sole owner (use_count() == 1), - destroys the object pointed to by the stored pointer as specified at - construction time.

    +

    Effects:

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

    Throws: nothing.

    assignment

    @@ -381,7 +391,7 @@ q = p;

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

    + get_shared_ptr.]

    swap

    void swap(shared_ptr & b); // never throws
    @@ -489,6 +499,14 @@ q = p;

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

    Returns: os.

    +

    get_deleter

    +
    template<class D, class T>
    +    D * get_deleter(shared_ptr<T> const & p);
    +
    +

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

    +

    Example

    See shared_ptr_example.cpp for a complete example program. The program builds a std::vector and std::set @@ -505,7 +523,7 @@ q = p;

    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 +

    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 @@ -648,20 +666,15 @@ int * p = a.release(); 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".
    -

    -

    Q. Why doesn't shared_ptr provide (your pet feature here)?

    -

    - A. Because (your pet feature here) would mandate a reference counted - implementation or a linked list implementation, or some other specific - implementation. This is not the intent.
    +


    $Date$

    -

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

    +

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

    diff --git a/sp_techniques.html b/sp_techniques.html index cc214b8..aa104ab 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -413,7 +413,7 @@ public: virtual shared_ptr<X> getX() { - shared_ptr<X> px = make_shared(weak_this); + shared_ptr<X> px = get_shared_ptr(weak_this); return px; } }; diff --git a/test/shared_ptr_basic_test.cpp b/test/shared_ptr_basic_test.cpp index 151af07..db5c0c1 100644 --- a/test/shared_ptr_basic_test.cpp +++ b/test/shared_ptr_basic_test.cpp @@ -94,7 +94,7 @@ template void test_is_Y(boost::shared_ptr const & p) template void test_is_Y(boost::weak_ptr const & p) { - boost::shared_ptr q = boost::make_shared(p); + boost::shared_ptr q = boost::get_shared_ptr(p); BOOST_TEST(q.get() != 0); BOOST_TEST(q->id() == 2); } @@ -221,7 +221,7 @@ int main() { } - test_is_zero(boost::make_shared(wp1)); + test_is_zero(boost::get_shared_ptr(wp1)); weak_ptr wp2 = static_pointer_cast(p5); @@ -232,10 +232,10 @@ int main() // Scoped to not affect the subsequent use_count() tests. { shared_ptr sp2(wp2); - test_is_nonzero(boost::make_shared(wp2)); + test_is_nonzero(boost::get_shared_ptr(wp2)); } - weak_ptr wp3 = dynamic_pointer_cast(boost::make_shared(wp2)); + weak_ptr wp3 = dynamic_pointer_cast(boost::get_shared_ptr(wp2)); BOOST_TEST(wp3.use_count() == 1); test_shared(wp2, wp3); @@ -246,7 +246,7 @@ int main() test_shared(wp2, wp4); wp1 = p2; - test_is_zero(boost::make_shared(wp1)); + test_is_zero(boost::get_shared_ptr(wp1)); wp1 = p4; wp1 = wp3; diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp index 4e3e80b..7525d7a 100644 --- a/test/shared_ptr_test.cpp +++ b/test/shared_ptr_test.cpp @@ -3094,7 +3094,7 @@ public: virtual boost::shared_ptr getX() { - boost::shared_ptr px = boost::make_shared(weak_this); + boost::shared_ptr px = boost::get_shared_ptr(weak_this); return px; } }; diff --git a/test/weak_ptr_test.cpp b/test/weak_ptr_test.cpp index 8f76d61..7408bb9 100644 --- a/test/weak_ptr_test.cpp +++ b/test/weak_ptr_test.cpp @@ -1183,14 +1183,14 @@ void test() } // namespace n_comparison -namespace n_make_shared +namespace n_get_shared_ptr { void test() { } -} // namespace n_make_shared +} // namespace n_get_shared_ptr namespace n_map { @@ -1272,7 +1272,7 @@ int main() n_use_count::test(); n_swap::test(); n_comparison::test(); - n_make_shared::test(); + n_get_shared_ptr::test(); n_map::test(); diff --git a/weak_ptr.htm b/weak_ptr.htm index 2bf395b..80fcb7a 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -8,7 +8,6 @@

    c++boost.gif (8819 bytes)weak_ptr class template

    Introduction
    - Motivation
    Synopsis
    Members
    Free Functions
    @@ -18,12 +17,12 @@

    The weak_ptr class template stores a "weak reference" to an object that's already managed by a shared_ptr. To access the object, a weak_ptr can be converted to a shared_ptr using - the shared_ptr constructor or the function - make_shared. When the last shared_ptr to the object - goes away and the object is deleted, the attempt to obtain a shared_ptr + the shared_ptr constructor or the function + get_shared_ptr. When the last shared_ptr to the + object goes away and the object is deleted, the attempt to obtain a shared_ptr from the weak_ptr instances that refer to the deleted object will fail: the constructor will throw an exception of type boost::bad_weak_ptr, - and make_shared will return an empty shared_ptr.

    + and get_shared_ptr will return an empty shared_ptr.

    Every weak_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 weak_ptr works with the @@ -56,7 +55,7 @@ weak_ptr<int> q(p); // some time later -if(shared_ptr<int> r = make_shared(q)) +if(shared_ptr<int> r = get_shared_ptr(q)) { // use *r } @@ -64,17 +63,6 @@ if(shared_ptr<int> r = make_shared(q))

    Now r holds a reference to the object that was pointed by q. Even if p.reset() is executed in another thread, the object will stay alive until r goes out of scope (or is reset.)

    -

    Motivation

    -

    [a mechanism to avoid dangling pointers]

    -

    [a way to break shared_ptr cycles]

    -

    [weak pointer to this - a technique to obtain a shared_ptr to this from within a - member function]

    -

    [map<weak_ptr, ...> - a technique to associate arbitrary data with - shared_ptr managed objects]

    -

    [gameobject/tank example]

    -

    [cache example]

    -

    [comparison: weak_ptr vs observer and other approaches]

    -

    [hard to reinvent, subtle implementation, with many pitfalls]

    Synopsis

    namespace boost {
     
    @@ -110,7 +98,7 @@ if(shared_ptr<int> r = make_shared(q))
         void swap(weak_ptr<T> & a, weak_ptr<T> & b);
     
       template<class T>
    -    shared_ptr<T> make_shared(weak_ptr<T> const & r);
    +    shared_ptr<T> get_shared_ptr(weak_ptr<T> const & r);
     
     }
     
    @@ -210,9 +198,9 @@ template<class Y> weak_ptr & operator=(shar

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

    -

    make_shared

    +

    get_shared_ptr

    template<class T>
    -  shared_ptr<T> make_shared(weak_ptr<T> & const r)
    + shared_ptr<T> get_shared_ptr(weak_ptr<T> & const r)

    Returns: r.expired()? shared_ptr<T>(): shared_ptr<T>(r).

    Throws: nothing.

    @@ -249,11 +237,11 @@ public:


    $Date$

    -

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

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

    + warranty, and with no claim as to its suitability for any purpose.

    From a790191bc57e3b033176d006014f89781eabeefd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 6 Feb 2003 14:54:15 +0000 Subject: [PATCH 204/513] Small fixes. [SVN r17251] --- smart_ptr.htm | 16 +++++++++------- weak_ptr.htm | 14 +++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/smart_ptr.htm b/smart_ptr.htm index bec58f1..ddf5e39 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -24,7 +24,7 @@ responsible for deletion of the object when it is no longer needed.

    The smart pointer library provides five smart pointer class templates:

    - +
    @@ -50,14 +50,19 @@ + + + + +
    scoped_ptr <boost/scoped_ptr.hpp><boost/weak_ptr.hpp> Non-owning observers of an object owned by shared_ptr.
    intrusive_ptr<boost/intrusive_ptr.hpp>Shared ownership of objects with an embedded reference count.

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

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

    -

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

    +

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

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

    @@ -169,10 +174,7 @@ February, 1994. This paper includes an extensive discussion of weak pointers and an extensive bibliography.


    -

    Revised - 15 January 2003

    +

    $Date$

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided diff --git a/weak_ptr.htm b/weak_ptr.htm index 80fcb7a..e8dd32d 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -134,9 +134,9 @@ template<class Y> weak_ptr(weak_ptr<Y> const & r);

    Throws: nothing.

    assignment

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

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

    Throws: nothing.

    @@ -238,10 +238,10 @@ public:

    $Date$

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

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

    From 23f7532a9ffb4476b4f9f2fb1d4debf2145b41a9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 6 Feb 2003 17:16:06 +0000 Subject: [PATCH 205/513] Disabled some watnings. [SVN r17255] --- test/smart_ptr_test.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp index 0dad8e9..26924f0 100644 --- a/test/smart_ptr_test.cpp +++ b/test/smart_ptr_test.cpp @@ -1,3 +1,14 @@ +#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) +# pragma warning(disable: 4786) // identifier truncated in debug info +# pragma warning(disable: 4710) // function not inlined +# pragma warning(disable: 4711) // function selected for automatic inline expansion +# pragma warning(disable: 4514) // unreferenced inline removed +#endif + +#ifdef __BORLANDC__ +# pragma warn -8092 // template argument passed to 'find' is not an iterator +#endif + // smart pointer test program ----------------------------------------------// // (C) Copyright Beman Dawes 1998, 1999. Permission to copy, use, modify, sell From a24ec3988a6dfbe9e3aefa6381806e79098a17ce Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 7 Feb 2003 15:08:52 +0000 Subject: [PATCH 206/513] Quick_allocator updates. [SVN r17267] --- test/shared_ptr_alloc_test.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/test/shared_ptr_alloc_test.cpp b/test/shared_ptr_alloc_test.cpp index 5a3e17a..d77b56d 100644 --- a/test/shared_ptr_alloc_test.cpp +++ b/test/shared_ptr_alloc_test.cpp @@ -23,19 +23,24 @@ int const n = 1024 * 1024; template void test(T * = 0) { - std::vector< boost::shared_ptr > v; - std::clock_t t = std::clock(); + std::clock_t t2; - for(int i = 0; i < n; ++i) { - boost::shared_ptr pi(new T(i)); - v.push_back(pi); + std::vector< boost::shared_ptr > v; + + for(int i = 0; i < n; ++i) + { + boost::shared_ptr pi(new T(i)); + v.push_back(pi); + } + + t2 = std::clock(); } - t = std::clock() - t; + std::clock_t t3 = std::clock(); - std::cout << " " << static_cast(t) / CLOCKS_PER_SEC << " seconds.\n"; + std::cout << " " << static_cast(t3 - t) / CLOCKS_PER_SEC << " seconds, " << static_cast(t2 - t) / CLOCKS_PER_SEC << " + " << static_cast(t3 - t2) / CLOCKS_PER_SEC << ".\n"; } class X From 4b502993b5acb4e013d9ec3f8a7443536057e2a1 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 7 Feb 2003 18:43:48 +0000 Subject: [PATCH 207/513] Added BOOST_QA_PAGE_SIZE. [SVN r17270] --- test/shared_ptr_alloc_test.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/shared_ptr_alloc_test.cpp b/test/shared_ptr_alloc_test.cpp index d77b56d..6eed3c3 100644 --- a/test/shared_ptr_alloc_test.cpp +++ b/test/shared_ptr_alloc_test.cpp @@ -135,6 +135,12 @@ int main() std::cout << "BOOST_SP_USE_QUICK_ALLOCATOR: (not defined)\n"; #endif +#if defined(BOOST_QA_PAGE_SIZE) + std::cout << "BOOST_QA_PAGE_SIZE: " << BOOST_QA_PAGE_SIZE << "\n"; +#else + std::cout << "BOOST_QA_PAGE_SIZE: (not defined)\n"; +#endif + std::cout << n << " shared_ptr allocations + deallocations:\n"; test(); From 4244992d4dbe18f672e0e702666acdf89ed47fcc Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 8 Feb 2003 16:05:46 +0000 Subject: [PATCH 208/513] Split winapi.hpp across win32-specific headers, added BOOST_USE_WINDOWS_H option. [SVN r17277] --- include/boost/detail/atomic_count_win32.hpp | 42 +++++++- include/boost/detail/lwm_win32.hpp | 37 ++++++- include/boost/detail/lwm_win32_cs.hpp | 39 +++++-- include/boost/detail/winapi.hpp | 106 -------------------- test/shared_ptr_mt_test.cpp | 14 +-- test/shared_ptr_timing_test.cpp | 8 +- 6 files changed, 116 insertions(+), 130 deletions(-) delete mode 100644 include/boost/detail/winapi.hpp diff --git a/include/boost/detail/atomic_count_win32.hpp b/include/boost/detail/atomic_count_win32.hpp index 0482757..0f00c43 100644 --- a/include/boost/detail/atomic_count_win32.hpp +++ b/include/boost/detail/atomic_count_win32.hpp @@ -8,7 +8,7 @@ // // boost/detail/atomic_count_win32.hpp // -// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2001, 2002, 2003 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. @@ -16,7 +16,9 @@ // warranty, and with no claim as to its suitability for any purpose. // -#include +#ifdef BOOST_USE_WINDOWS_H +# include +#endif namespace boost { @@ -24,6 +26,37 @@ namespace boost namespace detail { +#ifndef BOOST_USE_WINDOWS_H + +#ifdef _WIN64 + +// Intel 6.0 on Win64 version, posted by Tim Fenders to [boost-users] + +extern "C" long_type __cdecl _InterlockedIncrement(long volatile *); +extern "C" long_type __cdecl _InterlockedDecrement(long volatile *); + +#pragma intrinsic(_InterlockedIncrement) +#pragma intrinsic(_InterlockedDecrement) + +inline long InterlockedIncrement(long volatile * lp) +{ + return _InterlockedIncrement(lp); +} + +inline long InterlockedDecrement(long volatile* lp) +{ + return _InterlockedDecrement(lp); +} + +#else // _WIN64 + +extern "C" __declspec(dllimport) long __stdcall InterlockedIncrement(long volatile *); +extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement(long volatile *); + +#endif // _WIN64 + +#endif // #ifndef BOOST_USE_WINDOWS_H + class atomic_count { public: @@ -34,12 +67,13 @@ public: long operator++() { - return winapi::InterlockedIncrement(&value_); + // Some older versions do not accept volatile + return InterlockedIncrement(const_cast(&value_)); } long operator--() { - return winapi::InterlockedDecrement(&value_); + return InterlockedDecrement(const_cast(&value_)); } operator long() const diff --git a/include/boost/detail/lwm_win32.hpp b/include/boost/detail/lwm_win32.hpp index abd1869..6d37068 100644 --- a/include/boost/detail/lwm_win32.hpp +++ b/include/boost/detail/lwm_win32.hpp @@ -8,7 +8,7 @@ // // boost/detail/lwm_win32.hpp // -// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2002, 2003 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. @@ -16,7 +16,9 @@ // warranty, and with no claim as to its suitability for any purpose. // -#include +#ifdef BOOST_USE_WINDOWS_H +# include +#endif #ifdef __BORLANDC__ # pragma warn -8027 // Functions containing while are not expanded inline @@ -28,6 +30,31 @@ namespace boost namespace detail { +#ifndef BOOST_USE_WINDOWS_H + +#ifdef _WIN64 + +// Intel 6.0 on Win64 version, posted by Tim Fenders to [boost-users] + +extern "C" long_type __cdecl _InterlockedExchange(long volatile *, long); + +#pragma intrinsic(_InterlockedExchange) + +inline long InterlockedExchange(long volatile* lp, long l) +{ + return _InterlockedExchange(lp, l); +} + +#else // _WIN64 + +extern "C" __declspec(dllimport) long __stdcall InterlockedExchange(long volatile *, long); + +#endif // _WIN64 + +extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long); + +#endif // #ifndef BOOST_USE_WINDOWS_H + class lightweight_mutex { private: @@ -59,20 +86,20 @@ public: explicit scoped_lock(lightweight_mutex & m): m_(m) { - while( winapi::InterlockedExchange(&m_.l_, 1) ) + while( InterlockedExchange(&m_.l_, 1) ) { // Note: changed to Sleep(1) from Sleep(0). // According to MSDN, Sleep(0) will never yield // to a lower-priority thread, whereas Sleep(1) // will. Performance seems not to be affected. - winapi::Sleep(1); + Sleep(1); } } ~scoped_lock() { - winapi::InterlockedExchange(&m_.l_, 0); + InterlockedExchange(&m_.l_, 0); // Note: adding a yield here will make // the spinlock more fair and will increase the overall diff --git a/include/boost/detail/lwm_win32_cs.hpp b/include/boost/detail/lwm_win32_cs.hpp index 3127004..8b40ae9 100644 --- a/include/boost/detail/lwm_win32_cs.hpp +++ b/include/boost/detail/lwm_win32_cs.hpp @@ -8,7 +8,7 @@ // // boost/detail/lwm_win32_cs.hpp // -// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2002, 2003 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. @@ -16,7 +16,9 @@ // warranty, and with no claim as to its suitability for any purpose. // -#include +#ifdef BOOST_USE_WINDOWS_H +# include +#endif namespace boost { @@ -24,11 +26,34 @@ namespace boost namespace detail { +#ifndef BOOST_USE_WINDOWS_H + +struct CRITICAL_SECTION +{ + struct critical_section_debug * DebugInfo; + long LockCount; + long RecursionCount; + void * OwningThread; + void * LockSemaphore; +#if defined(_WIN64) + unsigned __int64 SpinCount; +#else + unsigned long SpinCount; +#endif +}; + +extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(CRITICAL_SECTION *); +extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(CRITICAL_SECTION *); +extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(CRITICAL_SECTION *); +extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(CRITICAL_SECTION *); + +#endif // #ifndef BOOST_USE_WINDOWS_H + class lightweight_mutex { private: - winapi::critical_section cs_; + CRITICAL_SECTION cs_; lightweight_mutex(lightweight_mutex const &); lightweight_mutex & operator=(lightweight_mutex const &); @@ -37,12 +62,12 @@ public: lightweight_mutex() { - winapi::InitializeCriticalSection(&cs_); + InitializeCriticalSection(&cs_); } ~lightweight_mutex() { - winapi::DeleteCriticalSection(&cs_); + DeleteCriticalSection(&cs_); } class scoped_lock; @@ -61,12 +86,12 @@ public: explicit scoped_lock(lightweight_mutex & m): m_(m) { - winapi::EnterCriticalSection(&m_.cs_); + EnterCriticalSection(&m_.cs_); } ~scoped_lock() { - winapi::LeaveCriticalSection(&m_.cs_); + LeaveCriticalSection(&m_.cs_); } }; }; diff --git a/include/boost/detail/winapi.hpp b/include/boost/detail/winapi.hpp deleted file mode 100644 index 340036a..0000000 --- a/include/boost/detail/winapi.hpp +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef BOOST_DETAIL_WINAPI_HPP_INCLUDED -#define BOOST_DETAIL_WINAPI_HPP_INCLUDED - -#if _MSC_VER >= 1020 -#pragma once -#endif - -// -// boost/detail/winapi.hpp - a lightweight version of -// -// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// - -namespace boost -{ - -namespace detail -{ - -namespace winapi -{ - -typedef long long_type; -typedef unsigned long dword_type; -typedef void * handle_type; - -#if defined(_WIN64) - -typedef __int64 int_ptr_type; -typedef unsigned __int64 uint_ptr_type; -typedef __int64 long_ptr_type; -typedef unsigned __int64 ulong_ptr_type; - -#else - -typedef int int_ptr_type; -typedef unsigned int uint_ptr_type; -typedef long long_ptr_type; -typedef unsigned long ulong_ptr_type; - -#endif - -struct critical_section -{ - struct critical_section_debug * DebugInfo; - long_type LockCount; - long_type RecursionCount; - handle_type OwningThread; - handle_type LockSemaphore; - ulong_ptr_type SpinCount; -}; - -#if defined(_WIN64) - -// Intel 6.0 on Win64 version, posted by Tim Fenders to [boost-users] - -extern "C" long_type __cdecl _InterlockedIncrement(long_type volatile *); -extern "C" long_type __cdecl _InterlockedDecrement(long_type volatile *); -extern "C" long_type __cdecl _InterlockedExchange(long_type volatile *, long_type); - -#pragma intrinsic(_InterlockedIncrement) -#pragma intrinsic(_InterlockedDecrement) -#pragma intrinsic(_InterlockedExchange) - -inline long_type InterlockedIncrement(long_type volatile * lp) -{ - return _InterlockedIncrement(lp); -} - -inline long_type InterlockedDecrement(long_type volatile* lp) -{ - return _InterlockedDecrement(lp); -} - -inline long_type InterlockedExchange(long_type volatile* lp, long_type l) -{ - return _InterlockedExchange(lp, l); -} - -#else - -extern "C" __declspec(dllimport) long_type __stdcall InterlockedIncrement(long_type volatile *); -extern "C" __declspec(dllimport) long_type __stdcall InterlockedDecrement(long_type volatile *); -extern "C" __declspec(dllimport) long_type __stdcall InterlockedExchange(long_type volatile *, long_type); - -#endif - -extern "C" __declspec(dllimport) void __stdcall Sleep(dword_type); - -extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *); -extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(critical_section *); -extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(critical_section *); -extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(critical_section *); - -} // namespace winapi - -} // namespace detail - -} // namespace boost - -#endif // #ifndef BOOST_DETAIL_WINAPI_HPP_INCLUDED diff --git a/test/shared_ptr_mt_test.cpp b/test/shared_ptr_mt_test.cpp index 52828f5..ec9d790 100644 --- a/test/shared_ptr_mt_test.cpp +++ b/test/shared_ptr_mt_test.cpp @@ -152,11 +152,13 @@ int const m = 16; // threads int main() { - std::printf("%s: %s, %d threads, %d iterations: ", title, implementation, m, n); + using namespace std; // printf, clock_t, clock + + printf("%s: %s, %d threads, %d iterations: ", title, implementation, m, n); boost::shared_ptr pi(new int(42)); - std::clock_t t = std::clock(); + clock_t t = clock(); pthread_t a[m]; @@ -165,14 +167,14 @@ int main() a[i] = createThread( boost::bind(test, pi) ); } - for(int i = 0; i < m; ++i) + for(int j = 0; j < m; ++j) { - pthread_join(a[i], 0); + pthread_join(a[j], 0); } - t = std::clock() - t; + t = clock() - t; - std::printf("\n\n%.3f seconds.\n", static_cast(t) / CLOCKS_PER_SEC); + printf("\n\n%.3f seconds.\n", static_cast(t) / CLOCKS_PER_SEC); return 0; } diff --git a/test/shared_ptr_timing_test.cpp b/test/shared_ptr_timing_test.cpp index 299261b..d42b960 100644 --- a/test/shared_ptr_timing_test.cpp +++ b/test/shared_ptr_timing_test.cpp @@ -25,17 +25,21 @@ int const n = 8 * 1024 * 1024; int main() { + using namespace std; + std::vector< boost::shared_ptr > v; boost::shared_ptr pi(new int); - std::clock_t t = std::clock(); + clock_t t = clock(); for(int i = 0; i < n; ++i) { v.push_back(pi); } - t = std::clock() - t; + t = clock() - t; std::cout << static_cast(t) / CLOCKS_PER_SEC << '\n'; + + return 0; } From 190893a1ce514fa61388cb2c985ae4eccc060d3a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 10 Feb 2003 12:54:43 +0000 Subject: [PATCH 209/513] BOOST_ENABLE_SP_DEBUG_HOOKS -> BOOST_SP_ENABLE_DEBUG_HOOKS [SVN r17301] --- include/boost/detail/shared_count.hpp | 34 +++++++++++++-------------- include/boost/scoped_array.hpp | 6 ++--- include/boost/scoped_ptr.hpp | 8 +++---- src/sp_collector.cpp | 4 ++-- src/sp_debug_hooks.cpp | 4 ++-- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 0e2783c..417071c 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -47,7 +47,7 @@ namespace boost // Debug hooks -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn); void sp_array_constructor_hook(void * px); @@ -192,7 +192,7 @@ private: #endif }; -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) template void cbi_call_constructor_hook(sp_counted_base * pn, T * px, checked_deleter const &, int) { @@ -249,14 +249,14 @@ public: sp_counted_base_impl(P p, D d): ptr(p), del(d) { -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) detail::cbi_call_constructor_hook(this, p, d, 0); #endif } virtual void dispose() // nothrow { -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) detail::cbi_call_destructor_hook(this, ptr, del, 0); #endif del(ptr); @@ -296,7 +296,7 @@ public: #endif }; -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) int const shared_count_id = 0x2C35F101; int const weak_count_id = 0x298C38A4; @@ -311,7 +311,7 @@ private: sp_counted_base * pi_; -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) int id_; #endif @@ -320,14 +320,14 @@ private: public: shared_count(): pi_(0) // nothrow -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { } template shared_count(P p, D d): pi_(0) -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { @@ -362,7 +362,7 @@ public: template explicit shared_count(std::auto_ptr & r): pi_(new sp_counted_base_impl< Y *, checked_deleter >(r.get(), checked_deleter())) -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { @@ -374,13 +374,13 @@ public: ~shared_count() // nothrow { if(pi_ != 0) pi_->release(); -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) id_ = 0; #endif } shared_count(shared_count const & r): pi_(r.pi_) // nothrow -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { @@ -443,7 +443,7 @@ private: sp_counted_base * pi_; -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) int id_; #endif @@ -452,14 +452,14 @@ private: public: weak_count(): pi_(0) // nothrow -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(weak_count_id) #endif { } weak_count(shared_count const & r): pi_(r.pi_) // nothrow -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { @@ -467,7 +467,7 @@ public: } weak_count(weak_count const & r): pi_(r.pi_) // nothrow -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { @@ -477,7 +477,7 @@ public: ~weak_count() // nothrow { if(pi_ != 0) pi_->weak_release(); -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) id_ = 0; #endif } @@ -526,7 +526,7 @@ public: }; inline shared_count::shared_count(weak_count const & r): pi_(r.pi_) -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index d99653c..abd75ad 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -22,7 +22,7 @@ namespace boost // Debug hooks -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) void sp_array_constructor_hook(void * p); void sp_array_destructor_hook(void * p); @@ -50,14 +50,14 @@ public: explicit scoped_array(T * p = 0) : ptr(p) // never throws { -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_array_constructor_hook(ptr); #endif } ~scoped_array() // never throws { -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_array_destructor_hook(ptr); #endif boost::checked_array_delete(ptr); diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 03b34ed..19396a5 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -24,7 +24,7 @@ namespace boost // Debug hooks -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) void sp_scalar_constructor_hook(void * p); void sp_scalar_destructor_hook(void * p); @@ -53,7 +53,7 @@ public: explicit scoped_ptr(T * p = 0): ptr(p) // never throws { -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_scalar_constructor_hook(ptr); #endif } @@ -62,7 +62,7 @@ public: explicit scoped_ptr(std::auto_ptr p): ptr(p.release()) // never throws { -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_scalar_constructor_hook(ptr); #endif } @@ -71,7 +71,7 @@ public: ~scoped_ptr() // never throws { -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_scalar_destructor_hook(ptr); #endif boost::checked_delete(ptr); diff --git a/src/sp_collector.cpp b/src/sp_collector.cpp index 7b96ed7..42fd16c 100644 --- a/src/sp_collector.cpp +++ b/src/sp_collector.cpp @@ -9,7 +9,7 @@ // warranty, and with no claim as to its suitability for any purpose. // -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #include #include @@ -266,4 +266,4 @@ void sp_array_destructor_hook(void *) } // namespace boost -#endif // defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS) diff --git a/src/sp_debug_hooks.cpp b/src/sp_debug_hooks.cpp index 6ad1edc..1f6be5f 100644 --- a/src/sp_debug_hooks.cpp +++ b/src/sp_debug_hooks.cpp @@ -9,7 +9,7 @@ // warranty, and with no claim as to its suitability for any purpose. // -#if defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #include #include @@ -241,4 +241,4 @@ void operator delete[](void * p, nothrow_t const &) throw() #endif -#endif // defined(BOOST_ENABLE_SP_DEBUG_HOOKS) +#endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS) From 34f423f811b45aa912bec6d4aaa6100ac6ea0cf2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 10 Feb 2003 12:58:50 +0000 Subject: [PATCH 210/513] atomic_count and lightweight_mutex now report an #error on unknown threading configs. [SVN r17303] --- include/boost/detail/atomic_count.hpp | 15 ++------------- include/boost/detail/lightweight_mutex.hpp | 3 ++- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index b34dc85..5321232 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -104,19 +104,8 @@ typedef long atomic_count; # include #else -// #warning Unrecognized platform, detail::atomic_count will not be thread safe - -namespace boost -{ - -namespace detail -{ - -typedef long atomic_count; - -} - -} +// Use #define BOOST_DISABLE_THREADS to avoid the error +#error Unrecognized threading platform #endif diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index da9e575..1310da3 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -82,7 +82,8 @@ # define BOOST_LWM_USE_PTHREADS # include #else -# include +// Use #define BOOST_DISABLE_THREADS to avoid the error +# error Unrecognized threading platform #endif #endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED From 851d87a1bbc8443f74ad8c61fde8dab577e2e0ed Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 10 Feb 2003 15:56:36 +0000 Subject: [PATCH 211/513] get_shared_ptr renamed to weak_ptr::lock. [SVN r17307] --- include/boost/weak_ptr.hpp | 70 +++++++++++++++++----------------- shared_ptr.htm | 4 +- sp_techniques.html | 2 +- test/shared_ptr_basic_test.cpp | 10 ++--- test/shared_ptr_test.cpp | 2 +- test/weak_ptr_test.cpp | 6 +-- weak_ptr.htm | 48 +++++++++++------------ 7 files changed, 69 insertions(+), 73 deletions(-) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 29e7e9f..d44b201 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -24,8 +24,6 @@ namespace boost { -template shared_ptr get_shared_ptr(weak_ptr const & r); // never throws - template class weak_ptr { private: @@ -64,7 +62,7 @@ public: template weak_ptr(weak_ptr const & r): pn(r.pn) // never throws { - px = boost::get_shared_ptr(r).get(); + px = r.lock().get(); } template @@ -77,7 +75,7 @@ public: template weak_ptr & operator=(weak_ptr const & r) // never throws { - px = boost::get_shared_ptr(r).get(); + px = r.lock().get(); pn = r.pn; return *this; } @@ -92,9 +90,33 @@ public: #endif - void reset() // never throws in 1.30+ + shared_ptr lock() const // never throws { - this_type().swap(*this); +#if defined(BOOST_HAS_THREADS) + + // optimization: avoid throw overhead + if(expired()) + { + return shared_ptr(); + } + + try + { + return shared_ptr(*this); + } + catch(bad_weak_ptr const &) + { + // Q: how can we get here? + // A: another thread may have invalidated r after the use_count test above. + return shared_ptr(); + } + +#else + + // optimization: avoid try/catch overhead when single threaded + return expired()? shared_ptr(): shared_ptr(*this); + +#endif } long use_count() const // never throws @@ -107,6 +129,11 @@ public: return pn.use_count() == 0; } + void reset() // never throws in 1.30+ + { + this_type().swap(*this); + } + void swap(this_type & other) // never throws { std::swap(px, other.px); @@ -151,39 +178,10 @@ template void swap(weak_ptr & a, weak_ptr & b) a.swap(b); } -template shared_ptr get_shared_ptr(weak_ptr const & r) // never throws -{ -#if defined(BOOST_HAS_THREADS) - - // optimization: avoid throw overhead - if(r.use_count() == 0) - { - return shared_ptr(); - } - - try - { - return shared_ptr(r); - } - catch(bad_weak_ptr const &) - { - // Q: how can we get here? - // A: another thread may have invalidated r after the use_count test above. - return shared_ptr(); - } - -#else - - // optimization: avoid try/catch overhead when single threaded - return r.use_count() == 0? shared_ptr(): shared_ptr(r); - -#endif -} - // deprecated, provided for backward compatibility template shared_ptr make_shared(weak_ptr const & r) { - return boost::get_shared_ptr(r); + return r.lock(); } } // namespace boost diff --git a/shared_ptr.htm b/shared_ptr.htm index bdd8d22..4e5f561 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -390,8 +390,8 @@ q = p; many of the implicit conversion pitfalls.

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

    + to be declared in conditions when using dynamic_pointer_cast or + weak_ptr::lock.]

    swap

    void swap(shared_ptr & b); // never throws
    diff --git a/sp_techniques.html b/sp_techniques.html index aa104ab..59159a2 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -413,7 +413,7 @@ public: virtual shared_ptr<X> getX() { - shared_ptr<X> px = get_shared_ptr(weak_this); + shared_ptr<X> px = weak_this.lock(); return px; } }; diff --git a/test/shared_ptr_basic_test.cpp b/test/shared_ptr_basic_test.cpp index db5c0c1..1b9c3cc 100644 --- a/test/shared_ptr_basic_test.cpp +++ b/test/shared_ptr_basic_test.cpp @@ -94,7 +94,7 @@ template void test_is_Y(boost::shared_ptr const & p) template void test_is_Y(boost::weak_ptr const & p) { - boost::shared_ptr q = boost::get_shared_ptr(p); + boost::shared_ptr q = p.lock(); BOOST_TEST(q.get() != 0); BOOST_TEST(q->id() == 2); } @@ -221,7 +221,7 @@ int main() { } - test_is_zero(boost::get_shared_ptr(wp1)); + test_is_zero(wp1.lock()); weak_ptr wp2 = static_pointer_cast(p5); @@ -232,10 +232,10 @@ int main() // Scoped to not affect the subsequent use_count() tests. { shared_ptr sp2(wp2); - test_is_nonzero(boost::get_shared_ptr(wp2)); + test_is_nonzero(wp2.lock()); } - weak_ptr wp3 = dynamic_pointer_cast(boost::get_shared_ptr(wp2)); + weak_ptr wp3 = dynamic_pointer_cast(wp2.lock()); BOOST_TEST(wp3.use_count() == 1); test_shared(wp2, wp3); @@ -246,7 +246,7 @@ int main() test_shared(wp2, wp4); wp1 = p2; - test_is_zero(boost::get_shared_ptr(wp1)); + test_is_zero(wp1.lock()); wp1 = p4; wp1 = wp3; diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp index 7525d7a..447dd9c 100644 --- a/test/shared_ptr_test.cpp +++ b/test/shared_ptr_test.cpp @@ -3094,7 +3094,7 @@ public: virtual boost::shared_ptr getX() { - boost::shared_ptr px = boost::get_shared_ptr(weak_this); + boost::shared_ptr px = weak_this.lock(); return px; } }; diff --git a/test/weak_ptr_test.cpp b/test/weak_ptr_test.cpp index 7408bb9..098d32d 100644 --- a/test/weak_ptr_test.cpp +++ b/test/weak_ptr_test.cpp @@ -1183,14 +1183,14 @@ void test() } // namespace n_comparison -namespace n_get_shared_ptr +namespace n_lock { void test() { } -} // namespace n_get_shared_ptr +} // namespace n_lock namespace n_map { @@ -1272,7 +1272,7 @@ int main() n_use_count::test(); n_swap::test(); n_comparison::test(); - n_get_shared_ptr::test(); + n_lock::test(); n_map::test(); diff --git a/weak_ptr.htm b/weak_ptr.htm index e8dd32d..fb9f44f 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -17,12 +17,12 @@

    The weak_ptr class template stores a "weak reference" to an object that's already managed by a shared_ptr. To access the object, a weak_ptr can be converted to a shared_ptr using - the shared_ptr constructor or the function - get_shared_ptr. When the last shared_ptr to the - object goes away and the object is deleted, the attempt to obtain a shared_ptr + the shared_ptr constructor or the member function + lock. When the last shared_ptr to the object goes + away and the object is deleted, the attempt to obtain a shared_ptr from the weak_ptr instances that refer to the deleted object will fail: the constructor will throw an exception of type boost::bad_weak_ptr, - and get_shared_ptr will return an empty shared_ptr.

    + and weak_ptr::lock will return an empty shared_ptr.

    Every weak_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 weak_ptr works with the @@ -33,7 +33,8 @@

    Compared to shared_ptr, weak_ptr provides a very limited subset of operations since accessing its stored pointer is often dangerous in multithreaded programs, and sometimes unsafe even within a single - thread (that is, it may invoke undefined behavior.) Consider, for example, this + thread (that is, it may invoke undefined behavior.) Pretend for a moment that weak_ptr + has a get member function that returns a raw pointer, and consider this innocent piece of code:

    shared_ptr<int> p(new int(5));
     weak_ptr<int> q(p);
    @@ -55,14 +56,16 @@ weak_ptr<int> q(p);
     
     // some time later
     
    -if(shared_ptr<int> r = get_shared_ptr(q))
    +if(shared_ptr<int> r = q.lock())
     {
         // use *r
     }
     

    Now r holds a reference to the object that was pointed by q. Even if p.reset() is executed in another thread, the object will - stay alive until r goes out of scope (or is reset.)

    + stay alive until r goes out of scope or is reset. By obtaining + a shared_ptr to the object, we have effectively locked it + against destruction.

    Synopsis

    namespace boost {
     
    @@ -83,11 +86,11 @@ if(shared_ptr<int> r = get_shared_ptr(q))
           template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
           template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);
     
    -      void reset();
    -
           long use_count() const;
           bool expired() const;
    +      shared_ptr<T> lock() const;
     
    +      void reset();
           void swap(weak_ptr<T> & b);
       };
     
    @@ -96,10 +99,6 @@ if(shared_ptr<int> r = get_shared_ptr(q))
     
       template<class T>
         void swap(weak_ptr<T> & a, weak_ptr<T> & b);
    -
    -  template<class T>
    -    shared_ptr<T> get_shared_ptr(weak_ptr<T> const & r);
    -
     }
     

    Members

    @@ -143,11 +142,6 @@ template<class Y> weak_ptr & operator=(shared_ptr<Y> const &

    Notes: The implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary.

    -

    reset

    -
    void reset();
    -
    -

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

    -

    use_count

    long use_count() const;
    @@ -165,6 +159,17 @@ template<class Y> weak_ptr & operator=(shared_ptr<Y> const &

    Throws: nothing.

    Notes: expired() may be faster than use_count().

    +

    lock

    +
    shared_ptr<T> lock() const;
    +
    +

    Returns: expired()? shared_ptr<T>(): shared_ptr<T>(*this).

    +

    Throws: nothing.

    +
    +

    reset

    +
    void reset();
    +
    +

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

    +

    swap

    void swap(weak_ptr & b);
    @@ -198,13 +203,6 @@ template<class Y> weak_ptr & operator=(shared_ptr<Y> const &

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

    -

    get_shared_ptr

    -
    template<class T>
    -  shared_ptr<T> get_shared_ptr(weak_ptr<T> & const r)
    -
    -

    Returns: r.expired()? shared_ptr<T>(): shared_ptr<T>(r).

    -

    Throws: nothing.

    -

    Frequently Asked Questions

    Q. Can an object create a weak_ptr to itself in its constructor?

    From 6d6bcc7be907f4544f6d3070b17f7a85d216ff6f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 12 Feb 2003 17:11:29 +0000 Subject: [PATCH 212/513] Some prose added. [SVN r17331] --- sp_techniques.html | 340 +++++++++++++++++++++++++++++---------------- 1 file changed, 219 insertions(+), 121 deletions(-) diff --git a/sp_techniques.html b/sp_techniques.html index 59159a2..0aad415 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -15,21 +15,23 @@ Using a shared_ptr to hold a pointer to an array
    Encapsulating allocation details, wrapping factory functions
    - Using a shared_ptr to hold a pointer to a statically allocated - object
    + Using a shared_ptr to hold a pointer to a statically + allocated object
    Using a shared_ptr to hold a pointer to a COM object
    - Using a shared_ptr to hold a pointer to an object with an - embedded reference count
    - Using a shared_ptr to hold another shared ownership smart - pointer
    + Using a shared_ptr to hold a pointer to an object + with an embedded reference count
    + Using a shared_ptr to hold another shared + ownership smart pointer
    Obtaining a shared_ptr from a raw pointer
    - Obtaining a shared_ptr (weak_ptr) to this in a - constructor
    + Obtaining a shared_ptr (weak_ptr) + to this in a constructor
    Obtaining a shared_ptr to this
    Using shared_ptr as a smart counted handle
    - Using shared_ptr to execute code on block exit
    - Using shared_ptr<void> to hold an arbitrary object
    - Associating arbitrary data with heterogeneous shared_ptr + Using shared_ptr to execute code on block + exit
    + Using shared_ptr<void> to hold an arbitrary + object
    + Associating arbitrary data with heterogeneous shared_ptr instances
    Post-constructors and pre-destructors
    Using shared_ptr as a CopyConstructible mutex lock
    @@ -38,27 +40,32 @@ Weak pointers to objects not managed by a shared_ptr

    Using incomplete classes for implementation hiding

    -

    [Old, proven technique; can be used in C]

    -
    +		

    A proven technique (that works in C, too) for separating interface from + implementation is to use a pointer to an incomplete class as an opaque handle:

    +
     class FILE;
     
     FILE * fopen(char const * name, char const * mode);
     void fread(FILE * f, void * data, size_t size);
     void fclose(FILE * f);
     
    -

    [Compare with]

    -
    +		

    It is possible to express the above interface using shared_ptr, + eliminating the need to manually call fclose:

    +
     class FILE;
     
     shared_ptr<FILE> fopen(char const * name, char const * mode);
     void fread(shared_ptr<FILE> f, void * data, size_t size);
     
    -

    Note that there is no fclose function; shared_ptr's ability to execute a custom deleter makes it unnecessary.

    - -

    [shared_ptr<X> can be copied and destroyed when X is incomplete.]

    +

    This technique relies on shared_ptr's ability to execute a custom + deleter, eliminating the explicit call to fclose, and on the fact + that shared_ptr<X> can be copied and destroyed when X + is incomplete.

    The "Pimpl" idiom

    -

    [...]

    -
    +		

    A C++ specific variation of the incomplete class pattern is the "Pimpl" idiom. + The incomplete class is not exposed to the user; it is hidden behind a + forwarding facade. shared_ptr can be used to implement a "Pimpl":

    +
     // file.hpp:
     
     class file
    @@ -77,7 +84,7 @@ public:
         void read(void * data, size_t size);
     };
     
    -
    +		
     // file.cpp:
     
     #include "file.hpp"
    @@ -107,10 +114,17 @@ void file::read(void * data, size_t size)
         pimpl_->read(data, size);
     }
     
    -

    [file is CopyConstructible and Assignable.]

    +

    The key thing to note here is that the compiler-generated copy constructor, + assignment operator, and destructor all have a sensible meaning. As a result, + file is CopyConstructible and Assignable, + allowing its use in standard containers.

    Using abstract classes for implementation hiding

    -

    [Interface based programming]

    -
    +		

    Another widely used C++ idiom for separating inteface and implementation is to + use abstract base classes and factory functions. The abstract classes are + sometimes called "interfaces" and the pattern is known as "interface-based + programming". Again, shared_ptr can be used as the return type of + the factory functions:

    +
     // X.hpp:
     
     class X
    @@ -127,7 +141,7 @@ protected:
     
     shared_ptr<X> createX();
     
    -
    +		
     -- X.cpp:
     
     class X_impl: public X
    @@ -156,11 +170,18 @@ shared_ptr<X> createX()
         return px;
     }
     
    -

    [Note protected and nonvirtual destructor; client cannot delete X; shared_ptr correctly calls ~X_impl even when nonvirtual.]

    +

    A key property of shared_ptr is that the allocation, construction, deallocation, + and destruction details are captured at the point of construction, inside the + factory function. Note the protected and nonvirtual destructor in the example + above. The client code cannot, and does not need to, delete a pointer to X; + the shared_ptr<X> instance returned from createX + will correctly call ~X_impl.

    Preventing delete px.get()

    -

    [Alternative 1, use the above.]

    -

    [Alternative 2, use a private deleter:]

    -
    +		

    It is often desirable to prevent client code from deleting a pointer that is + being managed by shared_ptr. The previous technique showed one + possible approach, using a protected destructor. Another alternative is to use + a private deleter:

    +
     class X
     {
     private:
    @@ -187,34 +208,51 @@ public:
     };
     

    Using a shared_ptr to hold a pointer to an array

    -

    [...]

    -
    -shared_ptr<X> px(new X[1], checked_array_deleter<X>());
    +		

    A shared_ptr can be used to hold a pointer to an array allocated + with new[]:

    +
    +shared_ptr<X> px(new X[1], checked_array_deleter<X>());
     
    -

    [shared_array is preferable, has a better interface; shared_ptr has *, ->, derived to base conversions.]

    +

    Note, however, that shared_array is + often preferable, if this is an option. It has an array-specific interface, + without operator* and operator->, and does not + allow pointer conversions.

    Encapsulating allocation details, wrapping factory functions

    -

    [Existing interface, possibly allocates X from its own heap, ~X is private, or X is incomplete.]

    -
    +		

    shared_ptr can be used in creating C++ wrappers over existing C + style library interfaces that return raw pointers from their factory functions + to encapsulate allocation details. As an example, consider this interface, + where CreateX might allocate X from its own private + heap, ~X may be inaccessible, or X may be incomplete:

    +
     X * CreateX();
     void DestroyX(X *);
     
    -

    [Wrapper:]

    -
    +		

    The only way to reliably destroy a pointer returned by CreateX is + to call DestroyX.

    +

    Here is how a shared_ptr-based wrapper may look like:

    +
     shared_ptr<X> createX()
     {
         shared_ptr<X> px(CreateX(), DestroyX);
    +    return px;
     }
     
    -

    [Client remains blissfully oblivious of allocation details; doesn't need to remember to call destroyX.]

    -

    Using a shared_ptr to hold a pointer to a statically allocated - object

    -

    [...]

    -
    +		

    Client code that calls createX still does not need to know how the + object has been allocated, but now the destruction is automatic.

    +

    Using a shared_ptr to hold a pointer to a statically + allocated object

    +

    Sometimes it is desirable to create a shared_ptr to an already + existing object, so that the shared_ptr does not attempt to + destroy the object when there are no more references left. As an example, the + factory function:

    +
     shared_ptr<X> createX();
     
    -

    [Sometimes needs to return a pointer to a statically allocated X instance.]

    -
    +		

    in certain situations may need to return a pointer to a statically allocated X + instance.

    +

    The solution is to use a custom deleter that does nothing:

    +
     struct null_deleter
     {
         void operator()(void const *) const
    @@ -230,22 +268,31 @@ shared_ptr<X> createX()
         return px;
     }
     
    -

    [The same technique works for any object known to outlive the pointer.]

    +

    The same technique works for any object known to outlive the pointer.

    Using a shared_ptr to hold a pointer to a COM Object

    -

    [COM objects have an embedded reference count, AddRef() and Release(), Release() self-destroys when reference count drops to zero.]

    -
    +		

    Background: COM objects have an embedded reference count and two member + functions that manipulate it. AddRef() increments the count. Release() + decrements the count and destroys itself when the count drops to zero.

    +

    It is possible to hold a pointer to a COM object in a shared_ptr:

    +
     shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
     {
         p->AddRef();
    -    shared_ptr<IWhatever> pw(p, mem_fn(&IWhatever::Release));
    +    shared_ptr<IWhatever> pw(p, mem_fn(&IWhatever::Release));
         return pw;
     }
     
    -

    [All pw copies will share a single reference.]

    -

    Using a shared_ptr to hold a pointer to an object with an - embedded reference count

    -

    [A generalization of the above. Example assumes intrusive_ptr-compatible object.]

    -
    +		

    Note, however, that shared_ptr copies created from pw will + not "register" in the embedded count of the COM object; they will share the + single reference created in make_shared_from_COM. Weak pointers + created from pw will be invalidated when the last shared_ptr + is destroyed, regardless of whether the COM object itself is still alive.

    +

    Using a shared_ptr to hold a pointer to an object + with an embedded reference count

    +

    This is a generalization of the above technique. The example assumes that the + object implements the two functions required by intrusive_ptr, + intrusive_ptr_add_ref and intrusive_ptr_release:

    +
     template<class T> struct intrusive_deleter
     {
         void operator()(T * p)
    @@ -261,11 +308,16 @@ shared_ptr<X> make_shared_from_intrusive(X * p)
         return px;
     }
     
    -

    Using a shared_ptr to hold another shared ownership smart - pointer

    -

    [...]

    -
    -template<class P> class smart_pointer_deleter
    +		

    Using a shared_ptr to hold another shared + ownership smart pointer

    +

    One of the design goals of shared_ptr is to be used in library + interfaces. It is possible to encounter a situation where a library takes a shared_ptr + argument, but the object at hand is being managed by a different reference + counted or linked smart pointer.

    +

    It is possible to exploit shared_ptr's custom deleter feature to + wrap this existing smart pointer behind a shared_ptr facade:

    +
    +template<class P> struct smart_pointer_deleter
     {
     private:
     
    @@ -281,40 +333,77 @@ public:
         {
             p_.reset();
         }
    +    
    +    P const & get() const
    +    {
    +        return p_;
    +    }
     };
     
     shared_ptr<X> make_shared_from_another(another_ptr<X> qx)
     {
    -    shared_ptr<X> px(qx.get(), smart_pointer_deleter< another_ptr<X> >(qx));
    +    shared_ptr<X> px(qx.get(), smart_pointer_deleter< another_ptr<X> >(qx));
         return px;
     }
     
    -

    [If p_.reset() can throw - wrap in try {} catch(...) {} block, will release p_ when all weak pointers are eliminated.]

    +

    One subtle point is that deleters are not allowed to throw exceptions, and the + above example as written assumes that p_.reset() doesn't throw. If + this is not the case, p_.reset() should be wrapped in a try {} + catch(...) {} block that ignores exceptions. In the (usually + unlikely) event when an exception is thrown and ignored, p_ will + be released when the lifetime of the deleter ends. This happens when all + references, including weak pointers, are destroyed or reset.

    +

    Another twist is that it is possible, given the above shared_ptr instance, + to recover the original smart pointer, using + get_deleter:

    +
    +void extract_another_from_shared(shared_ptr<X> px)
    +{
    +    typedef smart_pointer_deleter< another_ptr<X> > deleter;
    +
    +    if(deleter const * pd = get_deleter<deleter>(px))
    +    {
    +        another_ptr<X> qx = pd->get();
    +    }
    +    else
    +    {
    +        // not one of ours
    +    }
    +}
    +

    Obtaining a shared_ptr from a raw pointer

    -

    [...]

    -
    +		

    Sometimes it is necessary to obtain a shared_ptr given a raw + pointer to an object that is already managed by another shared_ptr + instance. Example:

    +
     void f(X * p)
     {
         shared_ptr<X> px(???);
     }
     
    -

    [Not possible in general, either switch to]

    -
    +		

    Inside f, we'd like to create a shared_ptr to *p.

    +

    In the general case, this problem has no solution. One approach is to modify f + to take a shared_ptr, if possible:

    +
     void f(shared_ptr<X> px);
     
    -

    [This transformation can be used for nonvirtual member functions, too; before:]

    -
    +		

    The same transformation can be used for nonvirtual member functions, to convert + the implicit this:

    +
     void X::f(int m);
     
    -

    [after]

    -
    +		

    would become a free function with a shared_ptr first argument:

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

    [If f cannot be changed, use knowledge about p's lifetime and allocation details and apply one of the above.]

    -

    Obtaining a shared_ptr (weak_ptr) to this in a - constructor

    -

    [...]

    -
    +		

    If f cannot be changed, but X has an embedded + reference count, use make_shared_from_intrusive + described above. Or, if it's known that the shared_ptr created in + f will never outlive the object, use a null deleter.

    +

    Obtaining a shared_ptr (weak_ptr) + to this in a constructor

    +

    [...]

    +
     class X
     {
     public:
    @@ -325,9 +414,11 @@ public:
         }
     };
     
    -

    [Not possible in general. If X can have automatic or static storage, and this_ doesn't need to keep the object alive, -use a null_deleter. If X is supposed to always live on the heap, and be managed by a shared_ptr, use:]

    -
    +		

    [Not possible in general. If X can have automatic or static + storage, and this_ doesn't need to keep the object alive, use a null_deleter. + If X is supposed to always live on the heap, and be managed by a + shared_ptr, use:]

    +
     class X
     {
     private:
    @@ -345,9 +436,10 @@ public:
     };
     

    Obtaining a shared_ptr to this

    -

    [Sometimes it is needed to obtain a shared_ptr from this in a virtual member function.]

    -

    [The transformations from above cannot be applied.]

    -
    +		

    [Sometimes it is needed to obtain a shared_ptr from this in a virtual member + function.]

    +

    [The transformations from above cannot be applied.]

    +
     class X
     {
     public:
    @@ -387,8 +479,8 @@ public:
         }
     };
     
    -

    [Solution:]

    -
    +		

    [Solution:]

    +
     class impl: public X, public Y
     {
     private:
    @@ -418,16 +510,16 @@ public:
         }
     };
     
    -

    [Future support planned, impl: public enable_shared_from_this<impl>.]

    +

    [Future support planned, impl: public enable_shared_from_this<impl>.]

    Using shared_ptr as a smart counted handle

    -

    [Win32 API allusion]

    -
    +		

    [Win32 API allusion]

    +
     typedef void * HANDLE;
     HANDLE CreateProcess();
     void CloseHandle(HANDLE);
     
    -

    [Quick wrapper]

    -
    +		

    [Quick wrapper]

    +
     typedef shared_ptr<void> handle;
     
     handle createProcess()
    @@ -436,8 +528,8 @@ handle createProcess()
         return pv;
     }
     
    -

    [Better, typesafe:]

    -
    +		

    [Better, typesafe:]

    +
     class handle
     {
     private:
    @@ -451,25 +543,27 @@ public:
     };
     

    Using shared_ptr to execute code on block exit

    -

    [1. Executing f(p), where p is a pointer:]

    -
    +		

    [1. Executing f(p), where p is a pointer:]

    +
         shared_ptr<void> guard(p, f);
     
    -

    [2. Executing arbitrary code: f(x, y):]

    -
    +		

    [2. Executing arbitrary code: f(x, y):]

    +
         shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
     
    -

    Using shared_ptr<void> to hold an arbitrary object

    -

    [...]

    -
    +		

    Using shared_ptr<void> to hold an arbitrary + object

    +

    [...]

    +
         shared_ptr<void> pv(new X);
     
    -

    [Will correctly call ~X.]

    -

    [Can be used to strip type information: shared_ptr<X> -> (shared_ptr<void>, typeid(X))]

    -

    Associating arbitrary data with heterogeneous shared_ptr +

    [Will correctly call ~X.]

    +

    [Can be used to strip type information: shared_ptr<X> -> + (shared_ptr<void>, typeid(X))]

    +

    Associating arbitrary data with heterogeneous shared_ptr instances

    -

    [...]

    -
    +		

    [...]

    +
     typedef int Data;
     
     std::map< shared_ptr<void>, Data > userData;
    @@ -482,8 +576,8 @@ userData[px] = 42;
     userData[pi] = 91;
     

    Post-constructors and pre-destructors

    -

    [...]

    -
    +		

    [...]

    +
     class X
     {
     public:
    @@ -511,8 +605,9 @@ public:
     };
     

    Using shared_ptr as a CopyConstructible mutex lock

    -

    [Sometimes it's necessary to return a mutex lock from a function. A noncopyable lock cannot be used.]

    -
    +		

    [Sometimes it's necessary to return a mutex lock from a function. A noncopyable + lock cannot be used.]

    +
     class mutex
     {
     public:
    @@ -527,8 +622,8 @@ shared_ptr<mutex> lock(mutex & m)
         return shared_ptr<mutex>(&m, mem_fn(&mutex::unlock));
     }
     
    -

    [Or to encapsulate it in a dedicated class:]

    -
    +		

    [Or to encapsulate it in a dedicated class:]

    +
     class shared_lock
     {
     private:
    @@ -540,14 +635,15 @@ public:
         template<class Mutex> explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&Mutex::unlock)) {}
     };
     
    -

    [Usage:]

    -
    +		

    [Usage:]

    +
         shared_lock lock(m);
     
    -

    [Note that shared_lock is not templated on the mutex type, thanks to shared_ptr<void>'s ability to hide type information.]

    +

    [Note that shared_lock is not templated on the mutex type, thanks + to shared_ptr<void>'s ability to hide type information.]

    Using shared_ptr to wrap member function calls

    -

    [http://www.research.att.com/~bs/wrapper.pdf]

    -
    +		

    [http://www.research.att.com/~bs/wrapper.pdf]

    +
     template<class T> class pointer
     {
     private:
    @@ -592,8 +688,9 @@ int main()
     }
     

    Delayed deallocation

    -

    [In some situations, a single px.reset() can trigger an expensive deallocation in a performance-critical region.]

    -
    +		

    [In some situations, a single px.reset() can trigger an expensive + deallocation in a performance-critical region.]

    +
     class X; // ~X is expensive
     
     class Y
    @@ -608,8 +705,8 @@ public:
         }
     };
     
    -

    [Solution 1]

    -
    +		

    [Solution 1]

    +
     vector< shared_ptr<void> > free_list;
     
     class Y
    @@ -627,8 +724,8 @@ public:
     
     // periodically invoke free_list.clear() when convenient
     
    -

    [Solution 2, as above, but use a delayed deleter]

    -
    +		

    [Solution 2, as above, but use a delayed deleter]

    +
     struct delayed_deleter
     {
         template<class T> void operator()(T * p)
    @@ -645,8 +742,8 @@ struct delayed_deleter
     };
     

    Weak pointers to objects not managed by a shared_ptr

    -

    Make the object hold a shared_ptr to itself, using a null_deleter:

    -
    +		

    Make the object hold a shared_ptr to itself, using a null_deleter:

    +
     class X
     {
     private:
    @@ -676,12 +773,13 @@ public:
         weak_ptr<X> get_weak_ptr() const { return this_; }
     };
     
    -

    When the object's lifetime ends, X::this_ will be destroyed, and all weak pointers will automatically expire.

    +

    When the object's lifetime ends, X::this_ will be destroyed, and + all weak pointers will automatically expire.


    $Date$

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

    From 8f0bdd48f8cf61c965a30424b7ffb6a5983bedbb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 12 Feb 2003 19:11:52 +0000 Subject: [PATCH 213/513] Minor edits. [SVN r17335] --- sp_techniques.html | 145 ++++++++++++++++----------------------------- 1 file changed, 51 insertions(+), 94 deletions(-) diff --git a/sp_techniques.html b/sp_techniques.html index 0aad415..eb6dcfd 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -7,8 +7,7 @@

    c++boost.gif (8819 bytes)Smart pointer programming techniques

    -

    - Using incomplete classes for implementation hiding
    +

    Using incomplete classes for implementation hiding
    The "Pimpl" idiom
    Using abstract classes for implementation hiding
    Preventing delete px.get()
    @@ -42,8 +41,7 @@

    Using incomplete classes for implementation hiding

    A proven technique (that works in C, too) for separating interface from implementation is to use a pointer to an incomplete class as an opaque handle:

    -
    -class FILE;
    +		
    class FILE;
     
     FILE * fopen(char const * name, char const * mode);
     void fread(FILE * f, void * data, size_t size);
    @@ -51,8 +49,7 @@ void fclose(FILE * f);
     

    It is possible to express the above interface using shared_ptr, eliminating the need to manually call fclose:

    -
    -class FILE;
    +		
    class FILE;
     
     shared_ptr<FILE> fopen(char const * name, char const * mode);
     void fread(shared_ptr<FILE> f, void * data, size_t size);
    @@ -65,8 +62,7 @@ void fread(shared_ptr<FILE> f, void * data, size_t size);
     		

    A C++ specific variation of the incomplete class pattern is the "Pimpl" idiom. The incomplete class is not exposed to the user; it is hidden behind a forwarding facade. shared_ptr can be used to implement a "Pimpl":

    -
    -// file.hpp:
    +		
    // file.hpp:
     
     class file
     {
    @@ -84,8 +80,7 @@ public:
         void read(void * data, size_t size);
     };
     
    -
    -// file.cpp:
    +		
    // file.cpp:
     
     #include "file.hpp"
     
    @@ -124,8 +119,7 @@ void file::read(void * data, size_t size)
     			sometimes called "interfaces" and the pattern is known as "interface-based 
     			programming". Again, shared_ptr can be used as the return type of 
     			the factory functions:

    -
    -// X.hpp:
    +		
    // X.hpp:
     
     class X
     {
    @@ -141,8 +135,7 @@ protected:
     
     shared_ptr<X> createX();
     
    -
    --- X.cpp:
    +		
    -- X.cpp:
     
     class X_impl: public X
     {
    @@ -181,8 +174,7 @@ shared_ptr<X> createX()
     			being managed by shared_ptr. The previous technique showed one 
     			possible approach, using a protected destructor. Another alternative is to use 
     			a private deleter:

    -
    -class X
    +		
    class X
     {
     private:
     
    @@ -210,8 +202,7 @@ public:
     		

    Using a shared_ptr to hold a pointer to an array

    A shared_ptr can be used to hold a pointer to an array allocated with new[]:

    -
    -shared_ptr<X> px(new X[1], checked_array_deleter<X>());
    +		
    shared_ptr<X> px(new X[1], checked_array_deleter<X>());
     

    Note, however, that shared_array is often preferable, if this is an option. It has an array-specific interface, @@ -224,15 +215,13 @@ shared_ptr<X> px(new X[1], checke to encapsulate allocation details. As an example, consider this interface, where CreateX might allocate X from its own private heap, ~X may be inaccessible, or X may be incomplete:

    -
    -X * CreateX();
    +		
    X * CreateX();
     void DestroyX(X *);
     

    The only way to reliably destroy a pointer returned by CreateX is to call DestroyX.

    Here is how a shared_ptr-based wrapper may look like:

    -
    -shared_ptr<X> createX()
    +		
    shared_ptr<X> createX()
     {
         shared_ptr<X> px(CreateX(), DestroyX);
         return px;
    @@ -246,14 +235,12 @@ shared_ptr<X> createX()
     			existing object, so that the shared_ptr does not attempt to 
     			destroy the object when there are no more references left. As an example, the 
     			factory function:

    -
    -shared_ptr<X> createX();
    +		
    shared_ptr<X> createX();
     

    in certain situations may need to return a pointer to a statically allocated X instance.

    The solution is to use a custom deleter that does nothing:

    -
    -struct null_deleter
    +		
    struct null_deleter
     {
         void operator()(void const *) const
         {
    @@ -274,11 +261,10 @@ shared_ptr<X> createX()
     			functions that manipulate it. AddRef() increments the count. Release()
     			decrements the count and destroys itself when the count drops to zero.

    It is possible to hold a pointer to a COM object in a shared_ptr:

    -
    -shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
    +		
    shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
     {
         p->AddRef();
    -    shared_ptr<IWhatever> pw(p, mem_fn(&IWhatever::Release));
    +    shared_ptr<IWhatever> pw(p, mem_fn(&IWhatever::Release));
         return pw;
     }
     
    @@ -292,8 +278,7 @@ shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)

    This is a generalization of the above technique. The example assumes that the object implements the two functions required by intrusive_ptr, intrusive_ptr_add_ref and intrusive_ptr_release:

    -
    -template<class T> struct intrusive_deleter
    +		
    template<class T> struct intrusive_deleter
     {
         void operator()(T * p)
         {
    @@ -316,8 +301,7 @@ shared_ptr<X> make_shared_from_intrusive(X * p)
     			counted or linked smart pointer.

    It is possible to exploit shared_ptr's custom deleter feature to wrap this existing smart pointer behind a shared_ptr facade:

    -
    -template<class P> struct smart_pointer_deleter
    +		
    template<class P> struct smart_pointer_deleter
     {
     private:
     
    @@ -356,8 +340,7 @@ shared_ptr<X> make_shared_from_another(another_ptr<X> qx)
     		

    Another twist is that it is possible, given the above shared_ptr instance, to recover the original smart pointer, using get_deleter:

    -
    -void extract_another_from_shared(shared_ptr<X> px)
    +		
    void extract_another_from_shared(shared_ptr<X> px)
     {
         typedef smart_pointer_deleter< another_ptr<X> > deleter;
     
    @@ -375,42 +358,37 @@ void extract_another_from_shared(shared_ptr<X> px)
     		

    Sometimes it is necessary to obtain a shared_ptr given a raw pointer to an object that is already managed by another shared_ptr instance. Example:

    -
    -void f(X * p)
    +		
    void f(X * p)
     {
    -    shared_ptr<X> px(???);
    +    shared_ptr<X> px(???);
     }
     

    Inside f, we'd like to create a shared_ptr to *p.

    In the general case, this problem has no solution. One approach is to modify f to take a shared_ptr, if possible:

    -
    -void f(shared_ptr<X> px);
    +		
    void f(shared_ptr<X> px);
     

    The same transformation can be used for nonvirtual member functions, to convert the implicit this:

    -
    -void X::f(int m);
    +		
    void X::f(int m);
     

    would become a free function with a shared_ptr first argument:

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

    If f cannot be changed, but X has an embedded - reference count, use make_shared_from_intrusive - described above. Or, if it's known that the shared_ptr created in - f will never outlive the object, use a null deleter.

    +

    If f cannot be changed, but X uses intrusive counting, + use make_shared_from_intrusive described + above. Or, if it's known that the shared_ptr created in f + will never outlive the object, use a null deleter.

    Obtaining a shared_ptr (weak_ptr) to this in a constructor

    [...]

    -
    -class X
    +		
    class X
     {
     public:
     
         X()
         {
    -        shared_ptr<X> this_(???);
    +        shared_ptr<X> this_(???);
         }
     };
     
    @@ -418,8 +396,7 @@ public: storage, and this_ doesn't need to keep the object alive, use a null_deleter. If X is supposed to always live on the heap, and be managed by a shared_ptr, use:]

    -
    -class X
    +		
    class X
     {
     private:
     
    @@ -439,8 +416,7 @@ public:
     		

    [Sometimes it is needed to obtain a shared_ptr from this in a virtual member function.]

    [The transformations from above cannot be applied.]

    -
    -class X
    +		
    class X
     {
     public:
     
    @@ -474,14 +450,13 @@ public:
     
         virtual shared_ptr<X> getX()
         {
    -        shared_ptr<X> px(???);
    +        shared_ptr<X> px(???);
             return px;
         }
     };
     

    [Solution:]

    -
    -class impl: public X, public Y
    +		
    class impl: public X, public Y
     {
     private:
     
    @@ -513,14 +488,12 @@ public:
     		

    [Future support planned, impl: public enable_shared_from_this<impl>.]

    Using shared_ptr as a smart counted handle

    [Win32 API allusion]

    -
    -typedef void * HANDLE;
    +		
    typedef void * HANDLE;
     HANDLE CreateProcess();
     void CloseHandle(HANDLE);
     

    [Quick wrapper]

    -
    -typedef shared_ptr<void> handle;
    +		
    typedef shared_ptr<void> handle;
     
     handle createProcess()
     {
    @@ -529,8 +502,7 @@ handle createProcess()
     }
     

    [Better, typesafe:]

    -
    -class handle
    +		
    class handle
     {
     private:
     
    @@ -544,18 +516,15 @@ public:
     

    Using shared_ptr to execute code on block exit

    [1. Executing f(p), where p is a pointer:]

    -
    -    shared_ptr<void> guard(p, f);
    +		
        shared_ptr<void> guard(p, f);
     

    [2. Executing arbitrary code: f(x, y):]

    -
    -    shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
    +		
        shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
     

    Using shared_ptr<void> to hold an arbitrary object

    [...]

    -
    -    shared_ptr<void> pv(new X);
    +		
        shared_ptr<void> pv(new X);
     

    [Will correctly call ~X.]

    [Can be used to strip type information: shared_ptr<X> -> @@ -563,8 +532,7 @@ public:

    Associating arbitrary data with heterogeneous shared_ptr instances

    [...]

    -
    -typedef int Data;
    +		
    typedef int Data;
     
     std::map< shared_ptr<void>, Data > userData;
     // or std::map< weak_ptr<void>, Data > userData; to not affect the lifetime
    @@ -577,8 +545,7 @@ userData[pi] = 91;
     

    Post-constructors and pre-destructors

    [...]

    -
    -class X
    +		
    class X
     {
     public:
     
    @@ -607,8 +574,7 @@ public:
     		

    Using shared_ptr as a CopyConstructible mutex lock

    [Sometimes it's necessary to return a mutex lock from a function. A noncopyable lock cannot be used.]

    -
    -class mutex
    +		
    class mutex
     {
     public:
     
    @@ -623,8 +589,7 @@ shared_ptr<mutex> lock(mutex & m)
     }
     

    [Or to encapsulate it in a dedicated class:]

    -
    -class shared_lock
    +		
    class shared_lock
     {
     private:
     
    @@ -636,15 +601,13 @@ public:
     };
     

    [Usage:]

    -
    -    shared_lock lock(m);
    +		
        shared_lock lock(m);
     

    [Note that shared_lock is not templated on the mutex type, thanks to shared_ptr<void>'s ability to hide type information.]

    Using shared_ptr to wrap member function calls

    [http://www.research.att.com/~bs/wrapper.pdf]

    -
    -template<class T> class pointer
    +		
    template<class T> class pointer
     {
     private:
     
    @@ -690,8 +653,7 @@ int main()
     		

    Delayed deallocation

    [In some situations, a single px.reset() can trigger an expensive deallocation in a performance-critical region.]

    -
    -class X; // ~X is expensive
    +		
    class X; // ~X is expensive
     
     class Y
     {
    @@ -706,8 +668,7 @@ public:
     };
     

    [Solution 1]

    -
    -vector< shared_ptr<void> > free_list;
    +		
    vector< shared_ptr<void> > free_list;
     
     class Y
     {
    @@ -725,8 +686,7 @@ public:
     // periodically invoke free_list.clear() when convenient
     

    [Solution 2, as above, but use a delayed deleter]

    -
    -struct delayed_deleter
    +		
    struct delayed_deleter
     {
         template<class T> void operator()(T * p)
         {
    @@ -743,8 +703,7 @@ struct delayed_deleter
     

    Weak pointers to objects not managed by a shared_ptr

    Make the object hold a shared_ptr to itself, using a null_deleter:

    -
    -class X
    +		
    class X
     {
     private:
     
    @@ -776,10 +735,8 @@ public:
     		

    When the object's lifetime ends, X::this_ will be destroyed, and all weak pointers will automatically expire.


    -

    - $Date$

    -

    - Copyright İ 2003 Peter Dimov. Permission to copy, use, modify, sell and +

    $Date$

    +

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

    From b400d34becef445dbe21e738a768faef5249c5a4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 13 Feb 2003 15:41:26 +0000 Subject: [PATCH 214/513] Added copyright to Jamfiles. [SVN r17363] --- test/Jamfile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/Jamfile b/test/Jamfile index e2591a9..df8c543 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -1,4 +1,12 @@ -# Boost.SmartPtr Library test Jamfile +# Boost.SmartPtr Library test Jamfile +# +# Copyright (c) 2003 Peter Dimov +# Copyright (c) 2003 Dave Abrahams +# +# Permission to copy, use, modify, sell and distribute this software +# is granted provided this copyright notice appears in all copies. +# This software is provided "as is" without express or implied +# warranty, and with no claim as to its suitability for any purpose. subproject libs/smart_ptr/test ; From f4dce1cb88aba8076b37d278d1bc18c2a78b9ee5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 13 Feb 2003 16:56:07 +0000 Subject: [PATCH 215/513] More prose. [SVN r17369] --- sp_techniques.html | 107 ++++++++++++++++++++++++++++++--------------- 1 file changed, 71 insertions(+), 36 deletions(-) diff --git a/sp_techniques.html b/sp_techniques.html index eb6dcfd..7b24efe 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -360,7 +360,7 @@ shared_ptr<X> make_shared_from_another(another_ptr<X> qx) instance. Example:

    void f(X * p)
     {
    -    shared_ptr<X> px(???);
    +    shared_ptr<X> px(???);
     }
     

    Inside f, we'd like to create a shared_ptr to *p.

    @@ -381,21 +381,32 @@ shared_ptr<X> make_shared_from_another(another_ptr<X> qx) will never outlive the object, use a null deleter.

    Obtaining a shared_ptr (weak_ptr) to this in a constructor

    -

    [...]

    +

    Some designs require objects to register themselves on construction with a + central authority. When the registration routines take a shared_ptr, this leads + to the question how could a constructor obtain a shared_ptr to this:

    class X
     {
     public:
     
         X()
         {
    -        shared_ptr<X> this_(???);
    +        shared_ptr<X> this_(???);
         }
     };
     
    -

    [Not possible in general. If X can have automatic or static - storage, and this_ doesn't need to keep the object alive, use a null_deleter. - If X is supposed to always live on the heap, and be managed by a - shared_ptr, use:]

    +

    In the general case, the problem cannot be solved. The X instance + being constructed can be an automatic variable or a static variable; it can be + created on the heap:

    +
    shared_ptr<X> px(new X);
    +

    but at construction time, px does not exist yet, and it is + impossible to create another shared_ptr instance that shares + ownership with it.

    +

    + Depending on context, if the inner shared_ptr this_ doesn't + need to keep the object alive, use a null_deleter as explained + here and here. If X is + supposed to always live on the heap, and be managed by a shared_ptr, + use a static factory function:

    class X
     {
     private:
    @@ -413,9 +424,11 @@ public:
     };
     

    Obtaining a shared_ptr to this

    -

    [Sometimes it is needed to obtain a shared_ptr from this in a virtual member - function.]

    -

    [The transformations from above cannot be applied.]

    +

    Sometimes it is needed to obtain a shared_ptr from this + in a virtual member function under the assumption that this is + already managed by a shared_ptr. The transformations + described in the previous technique cannot be applied.

    +

    A typical example:

    class X
     {
     public:
    @@ -450,12 +463,12 @@ public:
     
         virtual shared_ptr<X> getX()
         {
    -        shared_ptr<X> px(???);
    +        shared_ptr<X> px(???);
             return px;
         }
     };
     
    -

    [Solution:]

    +

    The solution is to keep a weak pointer to this as a member in impl:

    class impl: public X, public Y
     {
     private:
    @@ -480,19 +493,40 @@ public:
     
         virtual shared_ptr<X> getX()
         {
    -        shared_ptr<X> px = weak_this.lock();
    +        shared_ptr<X> px(weak_this);
             return px;
         }
     };
     
    -

    [Future support planned, impl: public enable_shared_from_this<impl>.]

    +

    The library now includes a helper class template enable_shared_from_this + that can be used to encapsulate the solution:

    +
    +class impl: public X, public Y, public enable_shared_from_this<impl>
    +{
    +public:
    +
    +    impl(impl const &);
    +    impl & operator=(impl const &);
    +
    +public:
    +
    +    virtual void f() { ... }
    +
    +    virtual shared_ptr<X> getX()
    +    {
    +        return shared_from_this();
    +    }
    +}
    +

    Using shared_ptr as a smart counted handle

    -

    [Win32 API allusion]

    +

    Some library interfaces use opaque handles, a variation of the + incomplete class technique described above. An example:

    typedef void * HANDLE;
     HANDLE CreateProcess();
     void CloseHandle(HANDLE);
     
    -

    [Quick wrapper]

    +

    Instead of a raw pointer, it is possible to use shared_ptr as the + handle and get reference counting and automatic resource management for free:

    typedef shared_ptr<void> handle;
     
     handle createProcess()
    @@ -500,35 +534,36 @@ handle createProcess()
         shared_ptr<void> pv(CreateProcess(), CloseHandle);
         return pv;
     }
    -
    -

    [Better, typesafe:]

    -
    class handle
    -{
    -private:
    -
    -    shared_ptr<void> pv_;
    -
    -public:
    -
    -    explicit handle(HANDLE h): pv_(h, CloseHandle) {}
    -    HANDLE get() { return pv_.get(); }
    -};
     

    Using shared_ptr to execute code on block exit

    -

    [1. Executing f(p), where p is a pointer:]

    +

    It is possible to use shared_ptr<void> to automatically + execute cleanup code when control leaves a scope.

    +
      +
    • + Executing f(p), where p is a pointer:
        shared_ptr<void> guard(p, f);
     
    -

    [2. Executing arbitrary code: f(x, y):]

    -
        shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
    +		
      +
    • + Executing arbitrary code: f(x, y):
    +
        shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
     
    +

    For a more thorough treatment, see the article "Simplify Your Exception-Safe + Code" by Andrei Alexandrescu and Petru Marginean, available online at + http://www.cuj.com/experts/1812/alexandr.htm?topic=experts.

    Using shared_ptr<void> to hold an arbitrary object

    -

    [...]

    +

    It is possible to use shared_ptr<void> as a generic object + pointer similar to void*. When a shared_ptr<void> + instance constructed as:

        shared_ptr<void> pv(new X);
     
    -

    [Will correctly call ~X.]

    -

    [Can be used to strip type information: shared_ptr<X> -> - (shared_ptr<void>, typeid(X))]

    +

    is destroyed, it will correctly dispose of the X object by + executing ~X.

    +

    This propery can be used in much the same manner as a raw void* is + used to temporarily strip type information from an object pointer. A shared_ptr<void> + can later be cast back to the correct type by using + static_pointer_cast.

    Associating arbitrary data with heterogeneous shared_ptr instances

    [...]

    From d7c841484a924fd9327886a0c3db442cb8e34e92 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 13 Feb 2003 18:35:13 +0000 Subject: [PATCH 216/513] Further edits, predestructor technique removed. [SVN r17374] --- sp_techniques.html | 83 +++++++++++++++------------------------- test/shared_ptr_test.cpp | 1 - 2 files changed, 30 insertions(+), 54 deletions(-) diff --git a/sp_techniques.html b/sp_techniques.html index 7b24efe..e523a52 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -32,7 +32,6 @@ object
    Associating arbitrary data with heterogeneous shared_ptr instances
    - Post-constructors and pre-destructors
    Using shared_ptr as a CopyConstructible mutex lock
    Using shared_ptr to wrap member function calls
    Delayed deallocation
    @@ -360,7 +359,7 @@ shared_ptr<X> make_shared_from_another(another_ptr<X> qx) instance. Example:

    void f(X * p)
     {
    -    shared_ptr<X> px(???);
    +    shared_ptr<X> px(???);
     }
     

    Inside f, we'd like to create a shared_ptr to *p.

    @@ -390,7 +389,7 @@ public: X() { - shared_ptr<X> this_(???); + shared_ptr<X> this_(???); } };
    @@ -401,8 +400,7 @@ public:

    but at construction time, px does not exist yet, and it is impossible to create another shared_ptr instance that shares ownership with it.

    -

    - Depending on context, if the inner shared_ptr this_ doesn't +

    Depending on context, if the inner shared_ptr this_ doesn't need to keep the object alive, use a null_deleter as explained here and here. If X is supposed to always live on the heap, and be managed by a shared_ptr, @@ -463,7 +461,7 @@ public: virtual shared_ptr<X> getX() { - shared_ptr<X> px(???); + shared_ptr<X> px(???); return px; } }; @@ -500,8 +498,7 @@ public:

    The library now includes a helper class template enable_shared_from_this that can be used to encapsulate the solution:

    -
    -class impl: public X, public Y, public enable_shared_from_this<impl>
    +		
    class impl: public X, public Y, public enable_shared_from_this<impl>
     {
     public:
     
    @@ -536,8 +533,8 @@ handle createProcess()
     }
     

    Using shared_ptr to execute code on block exit

    -

    It is possible to use shared_ptr<void> to automatically - execute cleanup code when control leaves a scope.

    +

    shared_ptr<void> can automatically execute cleanup code when + control leaves a scope.

    • Executing f(p), where p is a pointer:
    @@ -546,16 +543,16 @@ handle createProcess()
    • Executing arbitrary code: f(x, y):
    -
        shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
    +		
        shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
     

    For a more thorough treatment, see the article "Simplify Your Exception-Safe Code" by Andrei Alexandrescu and Petru Marginean, available online at http://www.cuj.com/experts/1812/alexandr.htm?topic=experts.

    Using shared_ptr<void> to hold an arbitrary object

    -

    It is possible to use shared_ptr<void> as a generic object - pointer similar to void*. When a shared_ptr<void> - instance constructed as:

    +

    shared_ptr<void> can act as a generic object pointer similar + to void*. When a shared_ptr<void> instance + constructed as:

        shared_ptr<void> pv(new X);
     

    is destroyed, it will correctly dispose of the X object by @@ -566,7 +563,10 @@ handle createProcess() static_pointer_cast.

    Associating arbitrary data with heterogeneous shared_ptr instances

    -

    [...]

    +

    shared_ptr and weak_ptr support operator< + comparisons required by standard associative containers such as std::map. + This can be used to non-intrusively associate arbitrary data with objects + managed by shared_ptr:

    typedef int Data;
     
     std::map< shared_ptr<void>, Data > userData;
    @@ -577,38 +577,11 @@ shared_ptr<int> pi(new int(3));
     
     userData[px] = 42;
     userData[pi] = 91;
    -
    -

    Post-constructors and pre-destructors

    -

    [...]

    -
    class X
    -{
    -public:
    -
    -    X();
    -    virtual void postconstructor();
    -    virtual void predestructor() throw();
    -    ~X() throw();
    -
    -    struct deleter
    -    {
    -        void operator()(X * p)
    -        {
    -             p->predestructor();
    -             delete p;
    -        }
    -    }
    -
    -    static shared_ptr<X> create()
    -    {
    -        shared_ptr<X> px(new X, X::deleter());
    -        px->postconstructor(); // can throw
    -        return px;
    -    }
    -};
     

    Using shared_ptr as a CopyConstructible mutex lock

    -

    [Sometimes it's necessary to return a mutex lock from a function. A noncopyable - lock cannot be used.]

    +

    Sometimes it's necessary to return a mutex lock from a function, and a + noncopyable lock cannot be returned by value. It is possible to use shared_ptr + as a mutex lock:

    class mutex
     {
     public:
    @@ -623,7 +596,8 @@ shared_ptr<mutex> lock(mutex & m)
         return shared_ptr<mutex>(&m, mem_fn(&mutex::unlock));
     }
     
    -

    [Or to encapsulate it in a dedicated class:]

    +

    Better yet, the shared_ptr instance acting as a lock can be + encapsulated in a dedicated shared_lock class:

    class shared_lock
     {
     private:
    @@ -635,11 +609,11 @@ public:
         template<class Mutex> explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&Mutex::unlock)) {}
     };
     
    -

    [Usage:]

    +

    shared_lock can now be used as:

        shared_lock lock(m);
     
    -

    [Note that shared_lock is not templated on the mutex type, thanks - to shared_ptr<void>'s ability to hide type information.]

    +

    Note that shared_lock is not templated on the mutex type, thanks to + shared_ptr<void>'s ability to hide type information.

    Using shared_ptr to wrap member function calls

    [http://www.research.att.com/~bs/wrapper.pdf]

    template<class T> class pointer
    @@ -686,8 +660,8 @@ int main()
     }
     

    Delayed deallocation

    -

    [In some situations, a single px.reset() can trigger an expensive - deallocation in a performance-critical region.]

    +

    In some situations, a single px.reset() can trigger an expensive + deallocation in a performance-critical region:

    class X; // ~X is expensive
     
     class Y
    @@ -702,7 +676,9 @@ public:
         }
     };
     
    -

    [Solution 1]

    +

    The solution is to postpone the potential deallocation by moving px + to a dedicated free list that can be periodically emptied when performance and + response times are not an issue:

    vector< shared_ptr<void> > free_list;
     
     class Y
    @@ -720,7 +696,8 @@ public:
     
     // periodically invoke free_list.clear() when convenient
     
    -

    [Solution 2, as above, but use a delayed deleter]

    +

    Another variation is to move the free list logic to the construction point by + using a delayed deleter:

    struct delayed_deleter
     {
         template<class T> void operator()(T * p)
    diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp
    index 447dd9c..fd18e45 100644
    --- a/test/shared_ptr_test.cpp
    +++ b/test/shared_ptr_test.cpp
    @@ -3154,7 +3154,6 @@ int main()
         n_spt_intrusive::test();
         n_spt_another_sp::test();
         n_spt_shared_from_this::test();
    -//  n_spt_post_constructors::test();
         n_spt_wrap::test();
     
         return boost::report_errors();
    
    From 300f8f7b9a2e336db61beacc30fd2010120b37fc Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Thu, 13 Feb 2003 19:07:20 +0000
    Subject: [PATCH 217/513] Finished Techniques page, added links to it.
    
    [SVN r17380]
    ---
     shared_ptr.htm     |  7 ++++---
     smart_ptr.htm      |  2 ++
     sp_techniques.html | 11 +++++++----
     3 files changed, 13 insertions(+), 7 deletions(-)
    
    diff --git a/shared_ptr.htm b/shared_ptr.htm
    index 4e5f561..809ceb3 100644
    --- a/shared_ptr.htm
    +++ b/shared_ptr.htm
    @@ -16,7 +16,8 @@
     			Handle/Body Idiom
    Thread Safety
    Frequently Asked Questions
    - Smart Pointer Timings

    + Smart Pointer Timings
    + Programming Techniques

    Introduction

    The shared_ptr class template stores a pointer to a dynamically allocated object, typically with a C++ new-expression . The object pointed to is @@ -390,8 +391,8 @@ q = p; many of the implicit conversion pitfalls.

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

    + to be declared in conditions when using dynamic_pointer_cast + or weak_ptr::lock.]

    swap

    void swap(shared_ptr & b); // never throws
    diff --git a/smart_ptr.htm b/smart_ptr.htm index ddf5e39..9327c9f 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -68,6 +68,8 @@ versions of the smart pointer implementation.

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

    +

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

    Common Requirements

    These smart pointer class templates have a template parameter, T, which specifies the type of the object pointed to by the smart pointer. The behavior diff --git a/sp_techniques.html b/sp_techniques.html index e523a52..a157f0b 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -1,12 +1,12 @@ - Smart pointer programming techniques + Smart Pointer Programming Techniques

    c++boost.gif (8819 bytes)Smart - pointer programming techniques

    + Pointer Programming Techniques

    Using incomplete classes for implementation hiding
    The "Pimpl" idiom
    Using abstract classes for implementation hiding
    @@ -615,7 +615,10 @@ public:

    Note that shared_lock is not templated on the mutex type, thanks to shared_ptr<void>'s ability to hide type information.

    Using shared_ptr to wrap member function calls

    -

    [http://www.research.att.com/~bs/wrapper.pdf]

    +

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

    template<class T> class pointer
     {
     private:
    @@ -631,7 +634,7 @@ public:
         shared_ptr<T> operator->() const
         {
             p_->prefix();
    -        return shared_ptr<T>(p_, mem_fn(&T::suffix));
    +        return shared_ptr<T>(p_, mem_fn(&T::suffix));
         }
     };
     
    
    From deab8ca1bb050c0a784220a7dc3cf38d61ddcd99 Mon Sep 17 00:00:00 2001
    From: Peter Dimov 
    Date: Fri, 14 Feb 2003 10:55:20 +0000
    Subject: [PATCH 218/513] Added link to enable_shared_from_this.html.
    
    [SVN r17397]
    ---
     sp_techniques.html | 15 ++++++++-------
     1 file changed, 8 insertions(+), 7 deletions(-)
    
    diff --git a/sp_techniques.html b/sp_techniques.html
    index a157f0b..826195f 100644
    --- a/sp_techniques.html
    +++ b/sp_techniques.html
    @@ -359,7 +359,7 @@ shared_ptr<X> make_shared_from_another(another_ptr<X> qx)
     			instance. Example:

    void f(X * p)
     {
    -    shared_ptr<X> px(???);
    +    shared_ptr<X> px(???);
     }
     

    Inside f, we'd like to create a shared_ptr to *p.

    @@ -389,7 +389,7 @@ public: X() { - shared_ptr<X> this_(???); + shared_ptr<X> this_(???); } };
    @@ -461,7 +461,7 @@ public: virtual shared_ptr<X> getX() { - shared_ptr<X> px(???); + shared_ptr<X> px(???); return px; } }; @@ -496,8 +496,9 @@ public: } }; -

    The library now includes a helper class template enable_shared_from_this - that can be used to encapsulate the solution:

    +

    The library now includes a helper class template + enable_shared_from_this that can be used to encapsulate the + solution:

    class impl: public X, public Y, public enable_shared_from_this<impl>
     {
     public:
    @@ -751,9 +752,9 @@ public:
     			all weak pointers will automatically expire.


    $Date$

    -

    Copyright İ 2003 Peter Dimov. Permission to copy, use, modify, sell and +

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

    + warranty, and with no claim as to its suitability for any purpose.

    From e760759414628ecb50afb3c2211330ca261e412a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 28 Mar 2003 12:27:55 +0000 Subject: [PATCH 219/513] Fixed a copy/assignment issue. [SVN r18122] --- include/boost/enable_shared_from_this.hpp | 19 ++++++++++ test/shared_from_this_test.cpp | 46 +++++++++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 4dfdab6..d3f8ab8 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -24,6 +24,25 @@ namespace boost template class enable_shared_from_this { +protected: + + enable_shared_from_this() + { + } + + enable_shared_from_this(enable_shared_from_this const &) + { + } + + enable_shared_from_this & operator=(enable_shared_from_this const &) + { + return *this; + } + + ~enable_shared_from_this() + { + } + public: shared_ptr shared_from_this() diff --git a/test/shared_from_this_test.cpp b/test/shared_from_this_test.cpp index d5dbe6e..2b40363 100644 --- a/test/shared_from_this_test.cpp +++ b/test/shared_from_this_test.cpp @@ -67,18 +67,20 @@ void test() } void test2(); +void test3(); int main() { test(); test2(); + test3(); return boost::report_errors(); } -// virtual inheritance from Y to stress the implementation -// (prevents Y* -> impl* casts) +// virtual inheritance to stress the implementation +// (prevents Y* -> impl*, enable_shared_from_this* -> impl* casts) -class impl: public X, public virtual Y, public boost::enable_shared_from_this +class impl: public X, public virtual Y, public virtual boost::enable_shared_from_this { public: @@ -110,3 +112,41 @@ void test2() { boost::shared_ptr pi(static_cast(0)); } + +// + +struct V: public boost::enable_shared_from_this +{ +}; + +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)); + + V v2(*p); + + try + { + boost::shared_ptr r = v2.shared_from_this(); + BOOST_ERROR("v2.shared_from_this() failed to throw"); + } + catch(boost::bad_weak_ptr const &) + { + } + + try + { + *p = V(); + boost::shared_ptr r = p->shared_from_this(); + BOOST_TEST(p == r); + BOOST_TEST(!(p < r) && !(r < p)); + } + catch(boost::bad_weak_ptr const &) + { + BOOST_ERROR("p->shared_from_this() threw bad_weak_ptr after *p = V()"); + } +} From bc00d5fa1a3ddc39d85393ac20b22fcdb97db7f4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 16 May 2003 12:11:17 +0000 Subject: [PATCH 220/513] Fixed bool conversions for Sun 5.3 [SVN r18419] --- include/boost/intrusive_ptr.hpp | 17 +++++++++++++++++ include/boost/scoped_array.hpp | 20 ++++++++++++++++++++ include/boost/scoped_ptr.hpp | 18 ++++++++++++++++++ include/boost/shared_array.hpp | 18 ++++++++++++++++++ include/boost/shared_ptr.hpp | 17 +++++++++++++++++ 5 files changed, 90 insertions(+) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 3b988a8..57e8c87 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -119,6 +119,21 @@ public: return p_; } +#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return p_ != 0; + } + +private: + + operator int () const; + +public: + +#else + typedef T * (intrusive_ptr::*unspecified_bool_type) () const; operator unspecified_bool_type () const @@ -126,6 +141,8 @@ public: return p_ == 0? 0: &intrusive_ptr::get; } +#endif + // operator! is a Borland-specific workaround bool operator! () const { diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index abd75ad..fd770bc 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -15,6 +15,9 @@ #include #include #include // in case ptrdiff_t not in std + +#include + #include // for std::ptrdiff_t namespace boost @@ -83,6 +86,21 @@ public: // implicit conversion to "bool" +#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return ptr != 0; + } + +private: + + operator int () const; + +public: + +#else + typedef T * (this_type::*unspecified_bool_type)() const; operator unspecified_bool_type() const // never throws @@ -90,6 +108,8 @@ public: return ptr == 0? 0: &this_type::get; } +#endif + bool operator! () const // never throws { return ptr == 0; diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 19396a5..5c07ebd 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -14,6 +14,7 @@ #include #include +#include #ifndef BOOST_NO_AUTO_PTR # include // for std::auto_ptr @@ -102,6 +103,21 @@ public: // implicit conversion to "bool" +#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return ptr != 0; + } + +private: + + operator int () const; + +public: + +#else + typedef T * (this_type::*unspecified_bool_type)() const; operator unspecified_bool_type() const // never throws @@ -109,6 +125,8 @@ public: return ptr == 0? 0: &this_type::get; } +#endif + bool operator! () const // never throws { return ptr == 0; diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index 992bdee..68420a2 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -25,6 +25,7 @@ #include #include +#include #include // for std::ptrdiff_t #include // for std::swap @@ -94,6 +95,21 @@ public: // implicit conversion to "bool" +#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return px != 0; + } + +private: + + operator int () const; + +public: + +#else + typedef T * (this_type::*unspecified_bool_type)() const; operator unspecified_bool_type() const // never throws @@ -101,6 +117,8 @@ public: return px == 0? 0: &this_type::get; } +#endif + bool operator! () const // never throws { return px == 0; diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index e66373a..0040fb4 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -246,6 +246,21 @@ public: // implicit conversion to "bool" +#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return px != 0; + } + +private: + + operator int () const; + +public: + +#else + typedef T * (this_type::*unspecified_bool_type)() const; operator unspecified_bool_type() const // never throws @@ -253,6 +268,8 @@ public: return px == 0? 0: &this_type::get; } +#endif + // operator! is redundant, but some compilers need it bool operator! () const // never throws From d091ee85c01c60db7f69c13181d4272a84ceb269 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 23 May 2003 13:46:07 +0000 Subject: [PATCH 221/513] Turns out Sun CC doesn't like operator int(). [SVN r18512] --- include/boost/intrusive_ptr.hpp | 6 ------ include/boost/scoped_array.hpp | 6 ------ include/boost/scoped_ptr.hpp | 6 ------ include/boost/shared_array.hpp | 6 ------ include/boost/shared_ptr.hpp | 6 ------ 5 files changed, 30 deletions(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 57e8c87..6135bb6 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -126,12 +126,6 @@ public: return p_ != 0; } -private: - - operator int () const; - -public: - #else typedef T * (intrusive_ptr::*unspecified_bool_type) () const; diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index fd770bc..6d33a56 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -93,12 +93,6 @@ public: return ptr != 0; } -private: - - operator int () const; - -public: - #else typedef T * (this_type::*unspecified_bool_type)() const; diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 5c07ebd..464822b 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -110,12 +110,6 @@ public: return ptr != 0; } -private: - - operator int () const; - -public: - #else typedef T * (this_type::*unspecified_bool_type)() const; diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index 68420a2..5ee8ff7 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -102,12 +102,6 @@ public: return px != 0; } -private: - - operator int () const; - -public: - #else typedef T * (this_type::*unspecified_bool_type)() const; diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 0040fb4..8cb6d1e 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -253,12 +253,6 @@ public: return px != 0; } -private: - - operator int () const; - -public: - #else typedef T * (this_type::*unspecified_bool_type)() const; From 77c629b6e4219939942d028fa473ea0f32bda24e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 28 May 2003 13:51:35 +0000 Subject: [PATCH 222/513] smart_ptr.hpp now includes all smart pointer headers for convenience. [SVN r18588] --- include/boost/smart_ptr.hpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index 4ff62e7..a142883 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -1,10 +1,11 @@ // // smart_ptr.hpp // -// For compatibility, this header includes the headers for the four "classic" -// smart pointer class templates. +// For convenience, this header includes the rest of the smart +// pointer library headers. // // Copyright (c) 1998-2002 boost.org +// Copyright (c) 2003 Peter Dimov // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. @@ -14,7 +15,15 @@ // http://www.boost.org/libs/smart_ptr/smart_ptr.htm // -#include +#include + +#include #include #include #include + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) +# include +# include +# include +#endif From 11cddbbb45caa42967f7eb3e39ec5908102b8e40 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 9 Jun 2003 18:25:41 +0000 Subject: [PATCH 223/513] Minor fix, scoped_ptr in the intro should've been shared_ptr. [SVN r18745] --- index.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.htm b/index.htm index 2c775ac..3dcdabd 100644 --- a/index.htm +++ b/index.htm @@ -18,7 +18,7 @@

    Smart Pointer Library

    The smart pointer library includes five smart pointer class templates. Smart pointers ease the management of memory dynamically allocated with C++ new - expressions. In addition, scoped_ptr can ease the management of memory + expressions. In addition, shared_ptr can ease the management of memory dynamically allocated in other ways.

    • From 889cb6bee6f097479596047e3acf9ee52a7ebff1 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 12 Jun 2003 17:09:24 +0000 Subject: [PATCH 224/513] -Wundef fixes. [SVN r18788] --- include/boost/detail/atomic_count.hpp | 4 ++-- include/boost/detail/atomic_count_win32.hpp | 4 ++-- include/boost/detail/lightweight_mutex.hpp | 4 ++-- include/boost/detail/lwm_irix.hpp | 4 ---- include/boost/detail/lwm_linux.hpp | 4 ---- include/boost/detail/lwm_nop.hpp | 4 ++-- include/boost/detail/lwm_pthreads.hpp | 4 ++-- include/boost/detail/lwm_win32.hpp | 4 ++-- include/boost/detail/lwm_win32_cs.hpp | 4 ++-- include/boost/detail/shared_count.hpp | 4 ++-- include/boost/intrusive_ptr.hpp | 4 ++-- include/boost/scoped_array.hpp | 2 +- include/boost/scoped_ptr.hpp | 2 +- include/boost/shared_array.hpp | 2 +- include/boost/shared_ptr.hpp | 4 ++-- 15 files changed, 23 insertions(+), 31 deletions(-) diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 5321232..decb95d 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -1,8 +1,8 @@ #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED #define BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED -#if _MSC_VER >= 1020 -#pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once #endif // diff --git a/include/boost/detail/atomic_count_win32.hpp b/include/boost/detail/atomic_count_win32.hpp index 0f00c43..8f9ad7f 100644 --- a/include/boost/detail/atomic_count_win32.hpp +++ b/include/boost/detail/atomic_count_win32.hpp @@ -1,8 +1,8 @@ #ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED #define BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED -#if _MSC_VER >= 1020 -#pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once #endif // diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index 1310da3..91a338a 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -1,8 +1,8 @@ #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED #define BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED -#if _MSC_VER >= 1020 -#pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once #endif // diff --git a/include/boost/detail/lwm_irix.hpp b/include/boost/detail/lwm_irix.hpp index 2a55161..6e5e57f 100644 --- a/include/boost/detail/lwm_irix.hpp +++ b/include/boost/detail/lwm_irix.hpp @@ -1,10 +1,6 @@ #ifndef BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED #define BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED -#if _MSC_VER >= 1020 -#pragma once -#endif - // // boost/detail/lwm_irix.hpp // diff --git a/include/boost/detail/lwm_linux.hpp b/include/boost/detail/lwm_linux.hpp index 62d8e64..e4c23c3 100644 --- a/include/boost/detail/lwm_linux.hpp +++ b/include/boost/detail/lwm_linux.hpp @@ -1,10 +1,6 @@ #ifndef BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED #define BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED -#if _MSC_VER >= 1020 -#pragma once -#endif - // // boost/detail/lwm_linux.hpp // diff --git a/include/boost/detail/lwm_nop.hpp b/include/boost/detail/lwm_nop.hpp index 671a5b0..d07ff1d 100644 --- a/include/boost/detail/lwm_nop.hpp +++ b/include/boost/detail/lwm_nop.hpp @@ -1,8 +1,8 @@ #ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED #define BOOST_DETAIL_LWM_NOP_HPP_INCLUDED -#if _MSC_VER >= 1020 -#pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once #endif // diff --git a/include/boost/detail/lwm_pthreads.hpp b/include/boost/detail/lwm_pthreads.hpp index 8ee5550..1f5f2c9 100644 --- a/include/boost/detail/lwm_pthreads.hpp +++ b/include/boost/detail/lwm_pthreads.hpp @@ -1,8 +1,8 @@ #ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED #define BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED -#if _MSC_VER >= 1020 -#pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once #endif // diff --git a/include/boost/detail/lwm_win32.hpp b/include/boost/detail/lwm_win32.hpp index 6d37068..d60c8b6 100644 --- a/include/boost/detail/lwm_win32.hpp +++ b/include/boost/detail/lwm_win32.hpp @@ -1,8 +1,8 @@ #ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED #define BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED -#if _MSC_VER >= 1020 -#pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once #endif // diff --git a/include/boost/detail/lwm_win32_cs.hpp b/include/boost/detail/lwm_win32_cs.hpp index 8b40ae9..0a03588 100644 --- a/include/boost/detail/lwm_win32_cs.hpp +++ b/include/boost/detail/lwm_win32_cs.hpp @@ -1,8 +1,8 @@ #ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED #define BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED -#if _MSC_VER >= 1020 -#pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once #endif // diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 417071c..3ade9f9 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -1,8 +1,8 @@ #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED #define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED -#if _MSC_VER >= 1020 -#pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once #endif // diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 6135bb6..9d713a8 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -119,7 +119,7 @@ public: return p_; } -#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) operator bool () const { @@ -235,7 +235,7 @@ template std::ostream & operator<< (std::ostream & os, intrusive_ptr #else -# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT) +# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT) // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL using std::basic_ostream; template basic_ostream & operator<< (basic_ostream & os, intrusive_ptr const & p) diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index 6d33a56..1930f20 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -86,7 +86,7 @@ public: // implicit conversion to "bool" -#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) operator bool () const { diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 464822b..429d295 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -103,7 +103,7 @@ public: // implicit conversion to "bool" -#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) operator bool () const { diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index 5ee8ff7..2009efd 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -95,7 +95,7 @@ public: // implicit conversion to "bool" -#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) operator bool () const { diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 8cb6d1e..d33eb77 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -246,7 +246,7 @@ public: // implicit conversion to "bool" -#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) operator bool () const { @@ -398,7 +398,7 @@ template std::ostream & operator<< (std::ostream & os, shared_ptr co #else -# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT) +# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT) // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL using std::basic_ostream; template basic_ostream & operator<< (basic_ostream & os, shared_ptr const & p) From 6dbec7621d6d7c99547f5ed1c493193fdb3ac5e3 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 18 Jun 2003 16:03:09 +0000 Subject: [PATCH 225/513] Detect the VC6 STL, not VC6 itself (for Intel) [SVN r18837] --- test/shared_ptr_test.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp index fd18e45..95e34d3 100644 --- a/test/shared_ptr_test.cpp +++ b/test/shared_ptr_test.cpp @@ -817,6 +817,10 @@ void weak_ptr_constructor() } } +#if defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB < 306) +# define BOOST_OLD_AUTO_PTR +#endif + void auto_ptr_constructor() { { @@ -940,7 +944,7 @@ void auto_ptr_constructor() BOOST_TEST(pi.unique()); BOOST_TEST(*pi == 7); -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) +#if !defined(BOOST_OLD_AUTO_PTR) BOOST_TEST(p.get() == 0); #endif } @@ -956,7 +960,7 @@ void auto_ptr_constructor() BOOST_TEST(pi.unique()); BOOST_TEST(*pi == 7); -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) +#if !defined(BOOST_OLD_AUTO_PTR) BOOST_TEST(p.get() == 0); #endif } @@ -971,7 +975,7 @@ void auto_ptr_constructor() BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) +#if !defined(BOOST_OLD_AUTO_PTR) BOOST_TEST(p.get() == 0); #endif } @@ -986,7 +990,7 @@ void auto_ptr_constructor() BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) +#if !defined(BOOST_OLD_AUTO_PTR) BOOST_TEST(p.get() == 0); #endif } @@ -1004,7 +1008,7 @@ void auto_ptr_constructor() BOOST_TEST(px.unique()); BOOST_TEST(X::instances == 1); -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) +#if !defined(BOOST_OLD_AUTO_PTR) BOOST_TEST(p.get() == 0); #endif } @@ -1022,7 +1026,7 @@ void auto_ptr_constructor() BOOST_TEST(px.unique()); BOOST_TEST(X::instances == 1); -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) +#if !defined(BOOST_OLD_AUTO_PTR) BOOST_TEST(p.get() == 0); #endif } @@ -1040,7 +1044,7 @@ void auto_ptr_constructor() BOOST_TEST(pv.unique()); BOOST_TEST(X::instances == 1); -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) +#if !defined(BOOST_OLD_AUTO_PTR) BOOST_TEST(p.get() == 0); #endif } @@ -1058,7 +1062,7 @@ void auto_ptr_constructor() BOOST_TEST(pv.unique()); BOOST_TEST(X::instances == 1); -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) +#if !defined(BOOST_OLD_AUTO_PTR) BOOST_TEST(p.get() == 0); #endif } @@ -1078,7 +1082,7 @@ void auto_ptr_constructor() BOOST_TEST(X::instances == 1); BOOST_TEST(Y::instances == 1); -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) +#if !defined(BOOST_OLD_AUTO_PTR) BOOST_TEST(p.get() == 0); #endif } @@ -1098,7 +1102,7 @@ void auto_ptr_constructor() BOOST_TEST(X::instances == 1); BOOST_TEST(Y::instances == 1); -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) +#if !defined(BOOST_OLD_AUTO_PTR) BOOST_TEST(p.get() == 0); #endif } @@ -1407,7 +1411,7 @@ void auto_ptr_assignment() BOOST_TEST(p1.get() == p); BOOST_TEST(p1.use_count() == 1); -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) +#if !defined(BOOST_OLD_AUTO_PTR) BOOST_TEST(p3.get() == 0); #endif @@ -1436,7 +1440,7 @@ void auto_ptr_assignment() BOOST_TEST(p1.get() == p); BOOST_TEST(p1.use_count() == 1); -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) +#if !defined(BOOST_OLD_AUTO_PTR) BOOST_TEST(p3.get() == 0); #endif @@ -1473,7 +1477,7 @@ void auto_ptr_assignment() BOOST_TEST(X::instances == 1); BOOST_TEST(Y::instances == 1); -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) +#if !defined(BOOST_OLD_AUTO_PTR) BOOST_TEST(p3.get() == 0); #endif From dcdbaf1e570032104cc2e87eacb00391a061e408 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 2 Jul 2003 11:54:40 +0000 Subject: [PATCH 226/513] A binary compatible 'null' lightweight_mutex for Win32 added. [SVN r18916] --- include/boost/detail/lightweight_mutex.hpp | 16 ++++-- include/boost/detail/lwm_win32_nt.hpp | 64 ++++++++++++++++++++++ include/boost/detail/shared_count.hpp | 2 +- 3 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 include/boost/detail/lwm_win32_nt.hpp diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index 91a338a..961227e 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -8,7 +8,7 @@ // // boost/detail/lightweight_mutex.hpp - lightweight mutex // -// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd. // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. @@ -64,15 +64,23 @@ // shared_ptr_timing_test.cpp will compile succesfully with a stub do-nothing // pthreads library, since it doesn't create any threads. -#ifndef BOOST_HAS_THREADS -# include +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(BOOST_LWM_USE_CRITICAL_SECTION) && !defined(BOOST_LWM_USE_PTHREADS) +# define BOOST_LWM_WIN32 +#endif + +#if !defined(BOOST_HAS_THREADS) +# if defined(BOOST_LWM_WIN32) +# include +# else +# include +# endif #elif defined(BOOST_LWM_USE_SPINLOCK) && defined(BOOST_USE_ASM_ATOMIC_H) # include #elif defined(BOOST_LWM_USE_CRITICAL_SECTION) # include #elif defined(BOOST_LWM_USE_PTHREADS) # include -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +#elif defined(BOOST_LWM_WIN32) # include #elif defined(BOOST_LWM_USE_SPINLOCK) && defined(__sgi) # include diff --git a/include/boost/detail/lwm_win32_nt.hpp b/include/boost/detail/lwm_win32_nt.hpp new file mode 100644 index 0000000..39e49e2 --- /dev/null +++ b/include/boost/detail/lwm_win32_nt.hpp @@ -0,0 +1,64 @@ +#ifndef BOOST_DETAIL_LWM_WIN32_NT_HPP_INCLUDED +#define BOOST_DETAIL_LWM_WIN32_NT_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/lwm_win32_nt.hpp +// +// Copyright (c) 2002, 2003 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// "No threads" version of lwm_win32.hpp; binary compatible but no-op. +// + +namespace boost +{ + +namespace detail +{ + +class lightweight_mutex +{ +private: + + long l_; + + lightweight_mutex(lightweight_mutex const &); + lightweight_mutex & operator=(lightweight_mutex const &); + +public: + + lightweight_mutex(): l_(0) + { + } + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock + { + private: + + scoped_lock(scoped_lock const &); + scoped_lock & operator=(scoped_lock const &); + + public: + + explicit scoped_lock(lightweight_mutex &) + { + } + }; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LWM_WIN32_NT_HPP_INCLUDED diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 3ade9f9..19e6ff2 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -187,7 +187,7 @@ private: long use_count_; long weak_count_; -#if defined(BOOST_HAS_THREADS) +#if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32) mutable mutex_type mtx_; #endif }; From 794de98cd14b2ab834ff3b9b7d5afccb90cebaa1 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 11 Jul 2003 17:03:56 +0000 Subject: [PATCH 227/513] #include added. [SVN r19065] --- include/boost/intrusive_ptr.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 9d713a8..24af067 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -14,6 +14,8 @@ // See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation. // +#include + #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash # pragma warning(push) # pragma warning(disable:4284) // odd return type for operator-> From 7c36a640aed653c082fe9c8a1942aa5d5eb4543f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 15 Jul 2003 12:18:40 +0000 Subject: [PATCH 228/513] add_ref split to add_ref_copy and add_ref_lock to eliminate the redundant use_count_ == 0 check. [SVN r19126] --- include/boost/detail/shared_count.hpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 19e6ff2..143a5a5 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -115,7 +115,16 @@ public: virtual void * get_deleter(std::type_info const & ti) = 0; - void add_ref() + void add_ref_copy() + { +#if defined(BOOST_HAS_THREADS) + mutex_type::scoped_lock lock(mtx_); +#endif + ++use_count_; + ++weak_count_; + } + + void add_ref_lock() { #if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); @@ -384,7 +393,7 @@ public: , id_(shared_count_id) #endif { - if(pi_ != 0) pi_->add_ref(); + if(pi_ != 0) pi_->add_ref_copy(); } explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 @@ -392,7 +401,7 @@ public: shared_count & operator= (shared_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; - if(tmp != 0) tmp->add_ref(); + if(tmp != 0) tmp->add_ref_copy(); if(pi_ != 0) pi_->release(); pi_ = tmp; @@ -532,7 +541,7 @@ inline shared_count::shared_count(weak_count const & r): pi_(r.pi_) { if(pi_ != 0) { - pi_->add_ref(); + pi_->add_ref_lock(); } else { From 192970b3b88744816ef5fd4426f5f4bc4ebed06d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 16 Jul 2003 11:51:12 +0000 Subject: [PATCH 229/513] const_pointer_cast added. [SVN r19147] --- include/boost/intrusive_ptr.hpp | 5 ++++ include/boost/shared_ptr.hpp | 21 +++++++++++++ intrusive_ptr.html | 10 +++++++ shared_ptr.htm | 18 ++++++++++++ test/shared_ptr_test.cpp | 52 +++++++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 24af067..06e43fb 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -220,6 +220,11 @@ template intrusive_ptr static_pointer_cast(intrusive_ptr return static_cast(p.get()); } +template intrusive_ptr const_pointer_cast(intrusive_ptr const & p) +{ + return const_cast(p.get()); +} + template intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & p) { return dynamic_cast(p.get()); diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index d33eb77..6663cde 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -48,6 +48,7 @@ namespace detail { struct static_cast_tag {}; +struct const_cast_tag {}; struct dynamic_cast_tag {}; struct polymorphic_cast_tag {}; @@ -68,6 +69,16 @@ template<> struct shared_ptr_traits typedef void reference; }; +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + #endif // enable_shared_from_this support @@ -158,6 +169,11 @@ public: { } + template + shared_ptr(shared_ptr const & r, detail::const_cast_tag): px(const_cast(r.px)), pn(r.pn) + { + } + template shared_ptr(shared_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) { @@ -351,6 +367,11 @@ template shared_ptr static_pointer_cast(shared_ptr const return shared_ptr(r, detail::static_cast_tag()); } +template shared_ptr const_pointer_cast(shared_ptr const & r) +{ + return shared_ptr(r, detail::const_cast_tag()); +} + template shared_ptr dynamic_pointer_cast(shared_ptr const & r) { return shared_ptr(r, detail::dynamic_cast_tag()); diff --git a/intrusive_ptr.html b/intrusive_ptr.html index 22bbc0c..66c1401 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -100,6 +100,9 @@ template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r); // never throws + template<class T, class U> + intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r); // never throws + template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r); // never throws @@ -250,6 +253,13 @@ intrusive_ptr & operator=(T * r);

    Returns: intrusive_ptr<T>(static_cast<T*>(r.get())).

    Throws: nothing.

    +

    const_pointer_cast

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

    Returns: intrusive_ptr<T>(const_cast<T*>(r.get())).

    +

    Throws: nothing.

    +

    dynamic_pointer_cast

    template<class T, class U>
       intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r);
    diff --git a/shared_ptr.htm b/shared_ptr.htm index 809ceb3..196b777 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -142,6 +142,9 @@ void bad() template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws + template<class T, class U> + shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws + template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r); // never throws @@ -473,6 +476,21 @@ q = p;

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

    +

    const_pointer_cast

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

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

    +

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

    +

    Throws: nothing.

    +

    Notes: the seemingly equivalent expression

    +

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

    +

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

    +

    dynamic_pointer_cast

    template<class T, class U>
       shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r);
    diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp index 95e34d3..9e3bf10 100644 --- a/test/shared_ptr_test.cpp +++ b/test/shared_ptr_test.cpp @@ -2375,6 +2375,57 @@ void test() } // namespace n_static_cast +namespace n_const_cast +{ + +struct X; + +void test() +{ + { + boost::shared_ptr px; + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px2.get() == 0); + } + + { + boost::shared_ptr px; + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px2.get() == 0); + } + + { + boost::shared_ptr px; + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px2.get() == 0); + } + + { + boost::shared_ptr px(new int); + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + BOOST_TEST(px.use_count() == 2); + BOOST_TEST(px2.use_count() == 2); + } + + { + boost::shared_ptr px(new int); + + boost::shared_ptr px2 = boost::const_pointer_cast(px); + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(!(px < px2 || px2 < px)); + BOOST_TEST(px.use_count() == 2); + BOOST_TEST(px2.use_count() == 2); + } +} + +} // namespace n_const_cast + namespace n_dynamic_cast { @@ -3141,6 +3192,7 @@ int main() n_swap::test(); n_comparison::test(); n_static_cast::test(); + n_const_cast::test(); n_dynamic_cast::test(); n_map::test(); From 2d4eb9240136e47474ce492ec524af96beabffb6 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 16 Jul 2003 11:54:49 +0000 Subject: [PATCH 230/513] get_deleter fix for EDG 2.38 [SVN r19148] --- include/boost/shared_ptr.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 6663cde..f2b4689 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -435,9 +435,10 @@ template std::basic_ostream & operator<< (std:: // get_deleter (experimental) -#if defined(__GNUC__) && (__GNUC__ < 3) +#if (defined(__GNUC__) && (__GNUC__ < 3)) || (defined(__EDG_VERSION__) && (__EDG_VERSION__ <= 238)) // g++ 2.9x doesn't allow static_cast(void *) +// apparently EDG 2.38 also doesn't accept it template D * get_deleter(shared_ptr const & p) { From b4ec0e90fb45544087e91ec4a198e4ae2f6ba16e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 21 Jul 2003 14:17:03 +0000 Subject: [PATCH 231/513] Switched weak_count_ from #shared+#weak to #weak+(#shared != 0); thanks to Alexander Terekhov and Ben Hutchings [SVN r19246] --- include/boost/detail/shared_count.hpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 143a5a5..b4e2db2 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -121,7 +121,6 @@ public: mutex_type::scoped_lock lock(mtx_); #endif ++use_count_; - ++weak_count_; } void add_ref_lock() @@ -129,9 +128,8 @@ public: #if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif - if(use_count_ == 0 && weak_count_ != 0) boost::throw_exception(boost::bad_weak_ptr()); + if(use_count_ == 0) boost::throw_exception(boost::bad_weak_ptr()); ++use_count_; - ++weak_count_; } void release() // nothrow @@ -142,11 +140,7 @@ public: #endif long new_use_count = --use_count_; - if(new_use_count != 0) - { - --weak_count_; - return; - } + if(new_use_count != 0) return; } dispose(); @@ -191,10 +185,8 @@ private: sp_counted_base(sp_counted_base const &); sp_counted_base & operator= (sp_counted_base const &); - // inv: use_count_ <= weak_count_ - - long use_count_; - long weak_count_; + long use_count_; // #shared + long weak_count_; // #weak + (#shared != 0) #if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32) mutable mutex_type mtx_; From f2c54396447321900bd49d35c1688c9809125637 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 8 Sep 2003 12:26:02 +0000 Subject: [PATCH 232/513] 'volatile' fixes. [SVN r19961] --- include/boost/shared_ptr.hpp | 2 +- test/shared_ptr_test.cpp | 37 ++++++++++++++++++++++++++---------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index f2b4689..8720a2c 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -88,7 +88,7 @@ template void sp_enable_shared_from_this(boost::enable_shared_ if(pe != 0) pe->_internal_weak_this._internal_assign(px, pn); } -inline void sp_enable_shared_from_this(void const *, void const *, shared_count const &) +inline void sp_enable_shared_from_this(void const volatile *, void const volatile *, shared_count const &) { } diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp index 9e3bf10..3e36c24 100644 --- a/test/shared_ptr_test.cpp +++ b/test/shared_ptr_test.cpp @@ -123,10 +123,31 @@ private: long Y::instances = 0; +template void pc0_test(T * p) +{ + BOOST_TEST(p == 0); + boost::shared_ptr pt(p); + BOOST_TEST(pt? false: true); + BOOST_TEST(!pt); + BOOST_TEST(pt.get() == 0); + BOOST_TEST(pt.use_count() == 1); + BOOST_TEST(pt.unique()); +} + void pointer_constructor() { + pc0_test(static_cast(0)); + +#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) + + pc0_test(static_cast(0)); + pc0_test(static_cast(0)); + pc0_test(static_cast(0)); + +#endif + { - boost::shared_ptr pi(static_cast(0)); + boost::shared_ptr pi(static_cast(0)); BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); @@ -135,7 +156,7 @@ void pointer_constructor() } { - boost::shared_ptr pi(static_cast(0)); + boost::shared_ptr pi(static_cast(0)); BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); @@ -161,14 +182,10 @@ void pointer_constructor() BOOST_TEST(pv.unique()); } - { - boost::shared_ptr px(static_cast(0)); - BOOST_TEST(px? false: true); - BOOST_TEST(!px); - BOOST_TEST(px.get() == 0); - BOOST_TEST(px.use_count() == 1); - BOOST_TEST(px.unique()); - } + pc0_test(static_cast(0)); + pc0_test(static_cast(0)); + pc0_test(static_cast(0)); + pc0_test(static_cast(0)); { boost::shared_ptr px(static_cast(0)); From debd953d8f10f4e800f115c5cf4d525102b5ea6f Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 8 Sep 2003 17:38:49 +0000 Subject: [PATCH 233/513] Use the import rule [SVN r19968] --- test/Jamfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/Jamfile b/test/Jamfile index df8c543..80ecab9 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -11,8 +11,7 @@ subproject libs/smart_ptr/test ; # bring in rules for testing -SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; -include testing.jam ; +import testing ; # Make tests run by default. DEPENDS all : smart_ptr ; From 106a6d58d4d07550249eaf12f7467a8111fe8e67 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 12 Sep 2003 17:09:29 +0000 Subject: [PATCH 234/513] Change license message to reference Boost Software License [SVN r20038] --- example/scoped_ptr_example.cpp | 9 +++------ example/scoped_ptr_example.hpp | 9 +++------ example/scoped_ptr_example_test.cpp | 9 +++------ example/shared_ptr_example.cpp | 9 +++------ example/shared_ptr_example2.cpp | 9 +++------ example/shared_ptr_example2.hpp | 9 +++------ example/shared_ptr_example2_test.cpp | 9 +++------ test/smart_ptr_test.cpp | 30 ++++++++++++++-------------- 8 files changed, 36 insertions(+), 57 deletions(-) diff --git a/example/scoped_ptr_example.cpp b/example/scoped_ptr_example.cpp index b15356b..ea1917d 100644 --- a/example/scoped_ptr_example.cpp +++ b/example/scoped_ptr_example.cpp @@ -1,12 +1,9 @@ // Boost scoped_ptr_example implementation file -----------------------------// -// (C) Copyright Beman Dawes 2001. Permission to copy, -// use, modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided "as is" -// without express or implied warranty, and with no claim as to its -// suitability for any purpose. +// Copyright Beman Dawes 2001. +// See accompanying license for terms and conditions of use. -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/smart_ptr for documentation. #include "scoped_ptr_example.hpp" #include diff --git a/example/scoped_ptr_example.hpp b/example/scoped_ptr_example.hpp index 14c1c6b..2747121 100644 --- a/example/scoped_ptr_example.hpp +++ b/example/scoped_ptr_example.hpp @@ -1,12 +1,9 @@ // Boost scoped_ptr_example header file ------------------------------------// -// (C) Copyright Beman Dawes 2001. Permission to copy, -// use, modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided "as is" -// without express or implied warranty, and with no claim as to its -// suitability for any purpose. +// Copyright Beman Dawes 2001. +// See accompanying license for terms and conditions of use. -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/smart_ptr for documentation. #include #include diff --git a/example/scoped_ptr_example_test.cpp b/example/scoped_ptr_example_test.cpp index 4037997..e880d31 100644 --- a/example/scoped_ptr_example_test.cpp +++ b/example/scoped_ptr_example_test.cpp @@ -1,12 +1,9 @@ // Boost scoped_ptr_example_test main program -------------------------------// -// (C) Copyright Beman Dawes 2001. Permission to copy, -// use, modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided "as is" -// without express or implied warranty, and with no claim as to its -// suitability for any purpose. +// Copyright Beman Dawes 2001. +// See accompanying license for terms and conditions of use. -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/smart_ptr for documentation. #include "scoped_ptr_example.hpp" diff --git a/example/shared_ptr_example.cpp b/example/shared_ptr_example.cpp index 4db8fc6..04a564e 100644 --- a/example/shared_ptr_example.cpp +++ b/example/shared_ptr_example.cpp @@ -1,12 +1,9 @@ // Boost shared_ptr_example.cpp --------------------------------------------// -// (C) Copyright Beman Dawes 2001. Permission to copy, -// use, modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided "as is" -// without express or implied warranty, and with no claim as to its -// suitability for any purpose. +// Copyright Beman Dawes 2001. +// See accompanying license for terms and conditions of use. -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/smart_ptr for documentation. // Revision History // 21 May 01 Initial complete version (Beman Dawes) diff --git a/example/shared_ptr_example2.cpp b/example/shared_ptr_example2.cpp index cbf69ec..5f0d797 100644 --- a/example/shared_ptr_example2.cpp +++ b/example/shared_ptr_example2.cpp @@ -1,12 +1,9 @@ // Boost shared_ptr_example2 implementation file -----------------------------// -// (C) Copyright Beman Dawes 2001. Permission to copy, -// use, modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided "as is" -// without express or implied warranty, and with no claim as to its -// suitability for any purpose. +// Copyright Beman Dawes 2001. +// See accompanying license for terms and conditions of use. -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/smart_ptr for documentation. #include "shared_ptr_example2.hpp" #include diff --git a/example/shared_ptr_example2.hpp b/example/shared_ptr_example2.hpp index bb9050e..1aa3ea8 100644 --- a/example/shared_ptr_example2.hpp +++ b/example/shared_ptr_example2.hpp @@ -1,12 +1,9 @@ // Boost shared_ptr_example2 header file -----------------------------------// -// (C) Copyright Beman Dawes 2001. Permission to copy, -// use, modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided "as is" -// without express or implied warranty, and with no claim as to its -// suitability for any purpose. +// Copyright Beman Dawes 2001. +// See accompanying license for terms and conditions of use. -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/smart_ptr for documentation. #include diff --git a/example/shared_ptr_example2_test.cpp b/example/shared_ptr_example2_test.cpp index a03511e..e5d4d89 100644 --- a/example/shared_ptr_example2_test.cpp +++ b/example/shared_ptr_example2_test.cpp @@ -1,12 +1,9 @@ // Boost shared_ptr_example2_test main program ------------------------------// -// (C) Copyright Beman Dawes 2001. Permission to copy, -// use, modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided "as is" -// without express or implied warranty, and with no claim as to its -// suitability for any purpose. +// Copyright Beman Dawes 2001. +// See accompanying license for terms and conditions of use. -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/smart_ptr for documentation. #include "shared_ptr_example2.hpp" diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp index 26924f0..28e22a1 100644 --- a/test/smart_ptr_test.cpp +++ b/test/smart_ptr_test.cpp @@ -1,3 +1,18 @@ +// smart pointer test program ----------------------------------------------// + +// Copyright Beman Dawes 1998, 1999. +// See accompanying license for terms and conditions of use. + +// See http://www.boost.org/libs/smart_ptr for documentation. + +// Revision History +// 24 May 01 use Boost test library for error detection, reporting, add tests +// for operations on incomplete types (Beman Dawes) +// 29 Nov 99 added std::swap and associative container tests (Darin Adler) +// 25 Sep 99 added swap tests +// 20 Jul 99 header name changed to .hpp +// 20 Apr 99 additional error tests added. + #if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) # pragma warning(disable: 4786) // identifier truncated in debug info # pragma warning(disable: 4710) // function not inlined @@ -9,21 +24,6 @@ # pragma warn -8092 // template argument passed to 'find' is not an iterator #endif -// smart pointer test program ----------------------------------------------// - -// (C) Copyright Beman Dawes 1998, 1999. Permission to copy, use, modify, sell -// and distribute this software is granted provided this copyright notice -// appears in all copies. This software is provided "as is" without express or -// implied warranty, and with no claim as to its suitability for any purpose. - -// Revision History -// 24 May 01 use Boost test library for error detection, reporting, add tests -// for operations on incomplete types (Beman Dawes) -// 29 Nov 99 added std::swap and associative container tests (Darin Adler) -// 25 Sep 99 added swap tests -// 20 Jul 99 header name changed to .hpp -// 20 Apr 99 additional error tests added. - #include #include #include From d6c4633e89e452162f1d802e85a18b872054844d Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Tue, 30 Sep 2003 07:42:34 +0000 Subject: [PATCH 235/513] Add V2 Jamfile [SVN r20223] --- test/Jamfile.v2 | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 test/Jamfile.v2 diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 new file mode 100644 index 0000000..8fe0637 --- /dev/null +++ b/test/Jamfile.v2 @@ -0,0 +1,36 @@ +# Boost.SmartPtr Library test Jamfile +# +# Copyright (c) 2003 Peter Dimov +# Copyright (c) 2003 Dave Abrahams +# +# Permission to copy, use, modify, sell and distribute this software +# is granted provided this copyright notice appears in all copies. +# This software is provided "as is" without express or implied +# warranty, and with no claim as to its suitability for any purpose. + +# bring in rules for testing +import testing ; + +{ + test-suite "smart_ptr" + : [ run smart_ptr_test.cpp ] + [ run shared_ptr_basic_test.cpp : : : :-Wno-non-virtual-dtor ] + [ run shared_ptr_test.cpp : : : gcc:-Wno-non-virtual-dtor ] + [ run weak_ptr_test.cpp ] + [ run shared_from_this_test.cpp : : : gcc:-Wno-non-virtual-dtor ] + [ run get_deleter_test.cpp ] + [ run intrusive_ptr_test.cpp ] + [ compile-fail shared_ptr_assign_fail.cpp ] + ; + + # this one is too slow to run unless explicitly requested, and ALL + # tests are run by default when this file is subincluded from + # boost/status, so it's guarded from that case. It will only be + # built from this directory when the targets "test" (all tests) or + # "shared_ptr_alloc_test" are requested. + #!!! + #if [ in-invocation-subdir ] + #{ + # run shared_ptr_alloc_test.cpp ; + #} +} From 96f572b19ba3de7004b4cbf2af9c5a9414d97bcb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 1 Oct 2003 11:12:15 +0000 Subject: [PATCH 236/513] Switched unspecified_bool_type to data member pointer. [SVN r20238] --- include/boost/intrusive_ptr.hpp | 4 ++-- include/boost/scoped_array.hpp | 4 ++-- include/boost/scoped_ptr.hpp | 4 ++-- include/boost/shared_array.hpp | 4 ++-- include/boost/shared_ptr.hpp | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 06e43fb..b612864 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -130,11 +130,11 @@ public: #else - typedef T * (intrusive_ptr::*unspecified_bool_type) () const; + typedef T * this_type::*unspecified_bool_type; operator unspecified_bool_type () const { - return p_ == 0? 0: &intrusive_ptr::get; + return p_ == 0? 0: &this_type::p_; } #endif diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index 1930f20..08155e9 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -95,11 +95,11 @@ public: #else - typedef T * (this_type::*unspecified_bool_type)() const; + typedef T * this_type::*unspecified_bool_type; operator unspecified_bool_type() const // never throws { - return ptr == 0? 0: &this_type::get; + return ptr == 0? 0: &this_type::ptr; } #endif diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 429d295..da4aeef 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -112,11 +112,11 @@ public: #else - typedef T * (this_type::*unspecified_bool_type)() const; + typedef T * this_type::*unspecified_bool_type; operator unspecified_bool_type() const // never throws { - return ptr == 0? 0: &this_type::get; + return ptr == 0? 0: &this_type::ptr; } #endif diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index 2009efd..b380879 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -104,11 +104,11 @@ public: #else - typedef T * (this_type::*unspecified_bool_type)() const; + typedef T * this_type::*unspecified_bool_type; operator unspecified_bool_type() const // never throws { - return px == 0? 0: &this_type::get; + return px == 0? 0: &this_type::px; } #endif diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 8720a2c..f7d80ae 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -271,11 +271,11 @@ public: #else - typedef T * (this_type::*unspecified_bool_type)() const; + typedef T * this_type::*unspecified_bool_type; operator unspecified_bool_type() const // never throws { - return px == 0? 0: &this_type::get; + return px == 0? 0: &this_type::px; } #endif From 26a93f224e23cd76b8108f20086e6f4eb12546fb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 1 Oct 2003 11:13:04 +0000 Subject: [PATCH 237/513] Changed index.htm to redirect to smart_ptr.htm [SVN r20239] --- index.htm | 56 +++++++------------------------------------------------ 1 file changed, 7 insertions(+), 49 deletions(-) diff --git a/index.htm b/index.htm index 3dcdabd..e2e191f 100644 --- a/index.htm +++ b/index.htm @@ -1,51 +1,9 @@ - - - - Boost Smart Pointer Library - - - - - - - - - - - -
    c++boost.gif (8819 bytes)HomeLibrariesPeopleFAQMore
    -

    Smart Pointer Library

    -

    The smart pointer library includes five smart pointer class templates. Smart - pointers ease the management of memory dynamically allocated with C++ new - expressions. In addition, shared_ptr can ease the management of memory - dynamically allocated in other ways.

    - -
    -

    $Date$

    - + + + + +Automatic redirection failed, please go to +smart_ptr.htm. + From feff6e40ea4de1013e3e11fda95e3eb0f04322b9 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 2 Oct 2003 17:49:06 +0000 Subject: [PATCH 238/513] Use conforming is_class for EDG compilers Make is_enum work for class types which are convertible to anything at all (on many compilers). smart_ptr library workarounds for __MWERKS__ (must use member function pointer for unspecified_bool_type). [SVN r20244] --- include/boost/scoped_array.hpp | 10 +++++++++- include/boost/scoped_ptr.hpp | 9 ++++++++- include/boost/shared_array.hpp | 10 +++++++++- include/boost/shared_ptr.hpp | 10 +++++++++- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index 08155e9..e5919a4 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -93,7 +93,15 @@ public: return ptr != 0; } -#else +#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; diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index da4aeef..c36cace 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -110,8 +110,15 @@ public: return ptr != 0; } -#else +#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 diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index b380879..5e943d9 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -102,7 +102,15 @@ public: return px != 0; } -#else +#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 px == 0? 0: &this_type::get; + } + +#else typedef T * this_type::*unspecified_bool_type; diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index f7d80ae..d4b44e6 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -269,7 +269,15 @@ public: return px != 0; } -#else +#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 px == 0? 0: &this_type::get; + } + +#else typedef T * this_type::*unspecified_bool_type; From 15d6b2aace7e130f325f93fa3a162fb243091964 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 9 Oct 2003 14:14:26 +0000 Subject: [PATCH 239/513] CWPro8 workaround [SVN r20323] --- include/boost/intrusive_ptr.hpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index b612864..7db6dcf 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -128,7 +128,15 @@ public: return p_ != 0; } -#else +#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; From 09c8685181e0a33c0c54cee60c06bb6eac22dfee Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 27 Nov 2003 16:58:23 +0000 Subject: [PATCH 240/513] Fixed a VC7 'regression' (pointers to volatile cannot be deleted) [SVN r20977] --- test/shared_ptr_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp index 3e36c24..a129613 100644 --- a/test/shared_ptr_test.cpp +++ b/test/shared_ptr_test.cpp @@ -138,7 +138,7 @@ void pointer_constructor() { pc0_test(static_cast(0)); -#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) +#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1300) pc0_test(static_cast(0)); pc0_test(static_cast(0)); From 93d69af60aa6e5027cd42b4b82361fc6edcfb901 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 28 Nov 2003 15:35:21 +0000 Subject: [PATCH 241/513] _MSC_VER use clarified. [SVN r20992] --- include/boost/detail/atomic_count.hpp | 2 ++ include/boost/detail/atomic_count_win32.hpp | 2 ++ include/boost/detail/lightweight_mutex.hpp | 2 ++ include/boost/detail/lwm_nop.hpp | 2 ++ include/boost/detail/lwm_pthreads.hpp | 2 ++ include/boost/detail/lwm_win32.hpp | 2 ++ include/boost/detail/lwm_win32_cs.hpp | 2 ++ include/boost/detail/shared_count.hpp | 2 ++ test/intrusive_ptr_test.cpp | 10 +++++++++- test/shared_from_this_test.cpp | 4 +++- test/shared_ptr_assign_fail.cpp | 4 +++- test/shared_ptr_basic_test.cpp | 16 ++++++++++++++++ test/shared_ptr_mt_test.cpp | 4 +++- test/shared_ptr_test.cpp | 10 +++++++++- test/shared_ptr_timing_test.cpp | 4 +++- test/smart_ptr_test.cpp | 10 +++++++++- test/weak_ptr_test.cpp | 10 +++++++++- 17 files changed, 80 insertions(+), 8 deletions(-) diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index decb95d..da4fc69 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -1,6 +1,8 @@ #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED #define BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED +// MS compatible compilers support #pragma once + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif diff --git a/include/boost/detail/atomic_count_win32.hpp b/include/boost/detail/atomic_count_win32.hpp index 8f9ad7f..c8a4681 100644 --- a/include/boost/detail/atomic_count_win32.hpp +++ b/include/boost/detail/atomic_count_win32.hpp @@ -1,6 +1,8 @@ #ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED #define BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED +// MS compatible compilers support #pragma once + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index 961227e..9155940 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -1,6 +1,8 @@ #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED #define BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED +// MS compatible compilers support #pragma once + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif diff --git a/include/boost/detail/lwm_nop.hpp b/include/boost/detail/lwm_nop.hpp index d07ff1d..fdc0a3d 100644 --- a/include/boost/detail/lwm_nop.hpp +++ b/include/boost/detail/lwm_nop.hpp @@ -1,6 +1,8 @@ #ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED #define BOOST_DETAIL_LWM_NOP_HPP_INCLUDED +// MS compatible compilers support #pragma once + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif diff --git a/include/boost/detail/lwm_pthreads.hpp b/include/boost/detail/lwm_pthreads.hpp index 1f5f2c9..79ea5a7 100644 --- a/include/boost/detail/lwm_pthreads.hpp +++ b/include/boost/detail/lwm_pthreads.hpp @@ -1,6 +1,8 @@ #ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED #define BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED +// MS compatible compilers support #pragma once + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif diff --git a/include/boost/detail/lwm_win32.hpp b/include/boost/detail/lwm_win32.hpp index d60c8b6..2228231 100644 --- a/include/boost/detail/lwm_win32.hpp +++ b/include/boost/detail/lwm_win32.hpp @@ -1,6 +1,8 @@ #ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED #define BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED +// MS compatible compilers support #pragma once + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif diff --git a/include/boost/detail/lwm_win32_cs.hpp b/include/boost/detail/lwm_win32_cs.hpp index 0a03588..c4547de 100644 --- a/include/boost/detail/lwm_win32_cs.hpp +++ b/include/boost/detail/lwm_win32_cs.hpp @@ -1,6 +1,8 @@ #ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED #define BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED +// MS compatible compilers support #pragma once + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index b4e2db2..2d14179 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -1,6 +1,8 @@ #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED #define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED +// MS compatible compilers support #pragma once + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif diff --git a/test/intrusive_ptr_test.cpp b/test/intrusive_ptr_test.cpp index f780d19..f8f305c 100644 --- a/test/intrusive_ptr_test.cpp +++ b/test/intrusive_ptr_test.cpp @@ -1,4 +1,7 @@ -#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) +#include + +#if defined(BOOST_MSVC) + #pragma warning(disable: 4786) // identifier truncated in debug info #pragma warning(disable: 4710) // function not inlined #pragma warning(disable: 4711) // function selected for automatic inline expansion @@ -6,6 +9,11 @@ #pragma warning(disable: 4355) // 'this' : used in base member initializer list #pragma warning(disable: 4511) // copy constructor could not be generated #pragma warning(disable: 4512) // assignment operator could not be generated + +#if (BOOST_MSVC >= 1310) +#pragma warning(disable: 4675) // resolved overload found with Koenig lookup +#endif + #endif // diff --git a/test/shared_from_this_test.cpp b/test/shared_from_this_test.cpp index 2b40363..be40fc9 100644 --- a/test/shared_from_this_test.cpp +++ b/test/shared_from_this_test.cpp @@ -1,4 +1,6 @@ -#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) +#include + +#if defined(BOOST_MSVC) #pragma warning(disable: 4786) // identifier truncated in debug info #pragma warning(disable: 4710) // function not inlined #pragma warning(disable: 4711) // function selected for automatic inline expansion diff --git a/test/shared_ptr_assign_fail.cpp b/test/shared_ptr_assign_fail.cpp index 993769a..4b6cc86 100644 --- a/test/shared_ptr_assign_fail.cpp +++ b/test/shared_ptr_assign_fail.cpp @@ -1,4 +1,6 @@ -#if defined(_MSC_VER) && !defined(__ICL) +#include + +#if defined(BOOST_MSVC) #pragma warning(disable: 4786) // identifier truncated in debug info #pragma warning(disable: 4710) // function not inlined #pragma warning(disable: 4711) // function selected for automatic inline expansion diff --git a/test/shared_ptr_basic_test.cpp b/test/shared_ptr_basic_test.cpp index 1b9c3cc..da8e902 100644 --- a/test/shared_ptr_basic_test.cpp +++ b/test/shared_ptr_basic_test.cpp @@ -1,3 +1,19 @@ +#include + +#if defined(BOOST_MSVC) + +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#pragma warning(disable: 4355) // 'this' : used in base member initializer list + +#if (BOOST_MSVC >= 1310) +#pragma warning(disable: 4675) // resolved overload found with Koenig lookup +#endif + +#endif + // // shared_ptr_basic_test.cpp // diff --git a/test/shared_ptr_mt_test.cpp b/test/shared_ptr_mt_test.cpp index ec9d790..a70158f 100644 --- a/test/shared_ptr_mt_test.cpp +++ b/test/shared_ptr_mt_test.cpp @@ -1,4 +1,6 @@ -#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) +#include + +#if defined(BOOST_MSVC) #pragma warning(disable: 4786) // identifier truncated in debug info #pragma warning(disable: 4710) // function not inlined #pragma warning(disable: 4711) // function selected for automatic inline expansion diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp index a129613..8d3c7cc 100644 --- a/test/shared_ptr_test.cpp +++ b/test/shared_ptr_test.cpp @@ -1,9 +1,17 @@ -#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) +#include + +#if defined(BOOST_MSVC) + #pragma warning(disable: 4786) // identifier truncated in debug info #pragma warning(disable: 4710) // function not inlined #pragma warning(disable: 4711) // function selected for automatic inline expansion #pragma warning(disable: 4514) // unreferenced inline removed #pragma warning(disable: 4355) // 'this' : used in base member initializer list + +#if (BOOST_MSVC >= 1310) +#pragma warning(disable: 4675) // resolved overload found with Koenig lookup +#endif + #endif // diff --git a/test/shared_ptr_timing_test.cpp b/test/shared_ptr_timing_test.cpp index d42b960..612ac39 100644 --- a/test/shared_ptr_timing_test.cpp +++ b/test/shared_ptr_timing_test.cpp @@ -1,4 +1,6 @@ -#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) +#include + +#if defined(BOOST_MSVC) #pragma warning(disable: 4786) // identifier truncated in debug info #pragma warning(disable: 4710) // function not inlined #pragma warning(disable: 4711) // function selected for automatic inline expansion diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp index 28e22a1..4baa92d 100644 --- a/test/smart_ptr_test.cpp +++ b/test/smart_ptr_test.cpp @@ -13,11 +13,19 @@ // 20 Jul 99 header name changed to .hpp // 20 Apr 99 additional error tests added. -#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) +#include + +#if defined(BOOST_MSVC) + # pragma warning(disable: 4786) // identifier truncated in debug info # pragma warning(disable: 4710) // function not inlined # pragma warning(disable: 4711) // function selected for automatic inline expansion # pragma warning(disable: 4514) // unreferenced inline removed + +#if (BOOST_MSVC >= 1310) +# pragma warning(disable: 4675) // resolved overload found with Koenig lookup +#endif + #endif #ifdef __BORLANDC__ diff --git a/test/weak_ptr_test.cpp b/test/weak_ptr_test.cpp index 098d32d..8e8e534 100644 --- a/test/weak_ptr_test.cpp +++ b/test/weak_ptr_test.cpp @@ -1,9 +1,17 @@ -#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) +#include + +#if defined(BOOST_MSVC) + #pragma warning(disable: 4786) // identifier truncated in debug info #pragma warning(disable: 4710) // function not inlined #pragma warning(disable: 4711) // function selected for automatic inline expansion #pragma warning(disable: 4514) // unreferenced inline removed #pragma warning(disable: 4355) // 'this' : used in base member initializer list + +#if (BOOST_MSVC >= 1310) +#pragma warning(disable: 4675) // resolved overload found with Koenig lookup +#endif + #endif // From 7fb399b3bb9c70cb75ce47534dfc60339c7e16b4 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 11 Dec 2003 23:31:15 +0000 Subject: [PATCH 242/513] index.htm renamed index.html [SVN r21231] --- index.htm => index.html | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename index.htm => index.html (100%) diff --git a/index.htm b/index.html similarity index 100% rename from index.htm rename to index.html From 53cc52127bda021bb545f0ff2b37fcbc593046ef Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 10 Feb 2004 23:17:12 +0000 Subject: [PATCH 243/513] Self-assignment optimization [SVN r22233] --- include/boost/detail/shared_count.hpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 2d14179..a9ba4d2 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -395,9 +395,13 @@ public: shared_count & operator= (shared_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; - if(tmp != 0) tmp->add_ref_copy(); - if(pi_ != 0) pi_->release(); - pi_ = tmp; + + if(tmp != pi_) + { + if(tmp != 0) tmp->add_ref_copy(); + if(pi_ != 0) pi_->release(); + pi_ = tmp; + } return *this; } From c48f05dcb40453fb1a2366d17be6c33e1ea7628c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 16 Feb 2004 18:50:07 +0000 Subject: [PATCH 244/513] enable_shared_from_this is now const-tolerant. [SVN r22298] --- include/boost/enable_shared_from_this.hpp | 2 +- include/boost/shared_ptr.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index d3f8ab8..affed6f 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -60,7 +60,7 @@ public: } typedef T _internal_element_type; // for bcc 5.5.1 - weak_ptr<_internal_element_type> _internal_weak_this; + mutable weak_ptr<_internal_element_type> _internal_weak_this; }; } // namespace boost diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index d4b44e6..a5e4adf 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -83,9 +83,9 @@ template<> struct shared_ptr_traits // enable_shared_from_this support -template void sp_enable_shared_from_this(boost::enable_shared_from_this * pe, Y * px, shared_count const & pn) +template void sp_enable_shared_from_this(boost::enable_shared_from_this const * pe, Y const * px, shared_count const & pn) { - if(pe != 0) pe->_internal_weak_this._internal_assign(px, pn); + if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); } inline void sp_enable_shared_from_this(void const volatile *, void const volatile *, shared_count const &) From 1346982b8074934c0574f85b2981b35d587aa94a Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Thu, 10 Jun 2004 12:31:20 +0000 Subject: [PATCH 245/513] Fix a typo [SVN r23077] --- test/Jamfile.v2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 8fe0637..688cb2e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -14,7 +14,7 @@ import testing ; { test-suite "smart_ptr" : [ run smart_ptr_test.cpp ] - [ run shared_ptr_basic_test.cpp : : : :-Wno-non-virtual-dtor ] + [ run shared_ptr_basic_test.cpp : : : gcc:-Wno-non-virtual-dtor ] [ run shared_ptr_test.cpp : : : gcc:-Wno-non-virtual-dtor ] [ run weak_ptr_test.cpp ] [ run shared_from_this_test.cpp : : : gcc:-Wno-non-virtual-dtor ] From e1bd18f6a6f1da557c6a1886a014d9628fe56c9d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 27 Jun 2004 15:09:46 +0000 Subject: [PATCH 246/513] Made value_ mutable to enable operator long() const to compile [SVN r23208] --- include/boost/detail/atomic_count_gcc.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/atomic_count_gcc.hpp b/include/boost/detail/atomic_count_gcc.hpp index c3d29a8..b4a46ce 100644 --- a/include/boost/detail/atomic_count_gcc.hpp +++ b/include/boost/detail/atomic_count_gcc.hpp @@ -51,7 +51,7 @@ private: atomic_count(atomic_count const &); atomic_count & operator=(atomic_count const &); - _Atomic_word value_; + mutable _Atomic_word value_; }; } // namespace detail From 7361e476b848e9fafa8382fc192c58414aef32f9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 27 Jun 2004 15:40:29 +0000 Subject: [PATCH 247/513] Fixed operator-- [SVN r23210] --- include/boost/detail/atomic_count_gcc.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/atomic_count_gcc.hpp b/include/boost/detail/atomic_count_gcc.hpp index b4a46ce..8761b80 100644 --- a/include/boost/detail/atomic_count_gcc.hpp +++ b/include/boost/detail/atomic_count_gcc.hpp @@ -38,7 +38,7 @@ public: long operator--() { - return !__exchange_and_add(&value_, -1); + return __exchange_and_add(&value_, -1) - 1; } operator long() const From 9c67a59d43f5f92ba98eb5e3ee4a62409be1fc94 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 6 Jul 2004 10:52:06 +0000 Subject: [PATCH 248/513] Fixed lwm_gcc, had the same bug as atomic_count_gcc (Tyson Whitehead) [SVN r23367] --- include/boost/detail/lwm_gcc.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/detail/lwm_gcc.hpp b/include/boost/detail/lwm_gcc.hpp index bf8a09a..a77b26d 100644 --- a/include/boost/detail/lwm_gcc.hpp +++ b/include/boost/detail/lwm_gcc.hpp @@ -37,7 +37,7 @@ private: public: - lightweight_mutex(): a_(1) + lightweight_mutex(): a_(0) { } @@ -57,16 +57,16 @@ public: explicit scoped_lock(lightweight_mutex & m): m_(m) { - while( !__exchange_and_add(&m_.a_, -1) ) + while( __exchange_and_add(&m_.a_, 1) ) { - __atomic_add(&m_.a_, 1); + __atomic_add(&m_.a_, -1); sched_yield(); } } ~scoped_lock() { - __atomic_add(&m_.a_, 1); + __atomic_add(&m_.a_, -1); } }; }; From 366d2666d404f41f4a23a9b520033c0eac5313d9 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Sun, 25 Jul 2004 12:01:00 +0000 Subject: [PATCH 249/513] Licence update [SVN r24031] --- example/scoped_ptr_example.cpp | 6 ++++-- example/scoped_ptr_example.hpp | 6 ++++-- example/scoped_ptr_example_test.cpp | 6 ++++-- example/shared_ptr_example.cpp | 6 ++++-- example/shared_ptr_example2.cpp | 6 ++++-- example/shared_ptr_example2.hpp | 6 ++++-- example/shared_ptr_example2_test.cpp | 6 ++++-- 7 files changed, 28 insertions(+), 14 deletions(-) diff --git a/example/scoped_ptr_example.cpp b/example/scoped_ptr_example.cpp index ea1917d..3dcfbb1 100644 --- a/example/scoped_ptr_example.cpp +++ b/example/scoped_ptr_example.cpp @@ -1,7 +1,9 @@ // Boost scoped_ptr_example implementation file -----------------------------// -// Copyright Beman Dawes 2001. -// See accompanying license for terms and conditions of use. +// Copyright Beman Dawes 2001. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + // See http://www.boost.org/libs/smart_ptr for documentation. diff --git a/example/scoped_ptr_example.hpp b/example/scoped_ptr_example.hpp index 2747121..0d9c603 100644 --- a/example/scoped_ptr_example.hpp +++ b/example/scoped_ptr_example.hpp @@ -1,7 +1,9 @@ // Boost scoped_ptr_example header file ------------------------------------// -// Copyright Beman Dawes 2001. -// See accompanying license for terms and conditions of use. +// Copyright Beman Dawes 2001. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + // See http://www.boost.org/libs/smart_ptr for documentation. diff --git a/example/scoped_ptr_example_test.cpp b/example/scoped_ptr_example_test.cpp index e880d31..26b3a18 100644 --- a/example/scoped_ptr_example_test.cpp +++ b/example/scoped_ptr_example_test.cpp @@ -1,7 +1,9 @@ // Boost scoped_ptr_example_test main program -------------------------------// -// Copyright Beman Dawes 2001. -// See accompanying license for terms and conditions of use. +// Copyright Beman Dawes 2001. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + // See http://www.boost.org/libs/smart_ptr for documentation. diff --git a/example/shared_ptr_example.cpp b/example/shared_ptr_example.cpp index 04a564e..c3b1f3b 100644 --- a/example/shared_ptr_example.cpp +++ b/example/shared_ptr_example.cpp @@ -1,7 +1,9 @@ // Boost shared_ptr_example.cpp --------------------------------------------// -// Copyright Beman Dawes 2001. -// See accompanying license for terms and conditions of use. +// Copyright Beman Dawes 2001. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + // See http://www.boost.org/libs/smart_ptr for documentation. diff --git a/example/shared_ptr_example2.cpp b/example/shared_ptr_example2.cpp index 5f0d797..fdefc8d 100644 --- a/example/shared_ptr_example2.cpp +++ b/example/shared_ptr_example2.cpp @@ -1,7 +1,9 @@ // Boost shared_ptr_example2 implementation file -----------------------------// -// Copyright Beman Dawes 2001. -// See accompanying license for terms and conditions of use. +// Copyright Beman Dawes 2001. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + // See http://www.boost.org/libs/smart_ptr for documentation. diff --git a/example/shared_ptr_example2.hpp b/example/shared_ptr_example2.hpp index 1aa3ea8..5ca7a07 100644 --- a/example/shared_ptr_example2.hpp +++ b/example/shared_ptr_example2.hpp @@ -1,7 +1,9 @@ // Boost shared_ptr_example2 header file -----------------------------------// -// Copyright Beman Dawes 2001. -// See accompanying license for terms and conditions of use. +// Copyright Beman Dawes 2001. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + // See http://www.boost.org/libs/smart_ptr for documentation. diff --git a/example/shared_ptr_example2_test.cpp b/example/shared_ptr_example2_test.cpp index e5d4d89..2702cb8 100644 --- a/example/shared_ptr_example2_test.cpp +++ b/example/shared_ptr_example2_test.cpp @@ -1,7 +1,9 @@ // Boost shared_ptr_example2_test main program ------------------------------// -// Copyright Beman Dawes 2001. -// See accompanying license for terms and conditions of use. +// Copyright Beman Dawes 2001. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + // See http://www.boost.org/libs/smart_ptr for documentation. From cb6cb636f7ef37f0db20c9a26d8435a52de6298c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 26 Jul 2004 00:32:12 +0000 Subject: [PATCH 250/513] Converted to Boost Software License, Version 1.0 [SVN r24055] --- include/boost/detail/atomic_count.hpp | 7 +++---- include/boost/detail/atomic_count_linux.hpp | 7 +++---- include/boost/detail/atomic_count_pthreads.hpp | 7 +++---- include/boost/detail/atomic_count_win32.hpp | 7 +++---- include/boost/detail/lightweight_mutex.hpp | 7 +++---- include/boost/detail/lwm_linux.hpp | 7 +++---- include/boost/detail/lwm_nop.hpp | 7 +++---- include/boost/detail/lwm_pthreads.hpp | 7 +++---- include/boost/detail/lwm_win32.hpp | 7 +++---- include/boost/detail/lwm_win32_cs.hpp | 7 +++---- include/boost/detail/lwm_win32_nt.hpp | 7 +++---- include/boost/detail/shared_count.hpp | 7 +++---- include/boost/enable_shared_from_this.hpp | 7 +++---- include/boost/get_pointer.hpp | 9 ++++----- include/boost/intrusive_ptr.hpp | 7 +++---- include/boost/weak_ptr.hpp | 7 +++---- src/sp_collector.cpp | 7 +++---- src/sp_debug_hooks.cpp | 7 +++---- test/collector_test.cpp | 7 +++---- test/get_deleter_test.cpp | 7 +++---- test/intrusive_ptr_test.cpp | 7 +++---- test/shared_from_this_test.cpp | 7 +++---- test/shared_ptr_alloc_test.cpp | 7 +++---- test/shared_ptr_assign_fail.cpp | 7 +++---- test/shared_ptr_basic_test.cpp | 7 +++---- test/shared_ptr_mt_test.cpp | 7 +++---- test/shared_ptr_test.cpp | 7 +++---- test/shared_ptr_timing_test.cpp | 7 +++---- test/weak_ptr_test.cpp | 7 +++---- 29 files changed, 88 insertions(+), 117 deletions(-) diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index da4fc69..3ad92b1 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -12,10 +12,9 @@ // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // // typedef boost::detail::atomic_count; // diff --git a/include/boost/detail/atomic_count_linux.hpp b/include/boost/detail/atomic_count_linux.hpp index 1a69cec..e0b0dda 100644 --- a/include/boost/detail/atomic_count_linux.hpp +++ b/include/boost/detail/atomic_count_linux.hpp @@ -6,10 +6,9 @@ // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // // diff --git a/include/boost/detail/atomic_count_pthreads.hpp b/include/boost/detail/atomic_count_pthreads.hpp index 0f8c663..7ed055f 100644 --- a/include/boost/detail/atomic_count_pthreads.hpp +++ b/include/boost/detail/atomic_count_pthreads.hpp @@ -6,10 +6,9 @@ // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include diff --git a/include/boost/detail/atomic_count_win32.hpp b/include/boost/detail/atomic_count_win32.hpp index c8a4681..0dfa3f3 100644 --- a/include/boost/detail/atomic_count_win32.hpp +++ b/include/boost/detail/atomic_count_win32.hpp @@ -12,10 +12,9 @@ // // Copyright (c) 2001, 2002, 2003 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #ifdef BOOST_USE_WINDOWS_H diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index 9155940..22e0f54 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -12,10 +12,9 @@ // // Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd. // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // // typedef boost::detail::lightweight_mutex; // diff --git a/include/boost/detail/lwm_linux.hpp b/include/boost/detail/lwm_linux.hpp index e4c23c3..f0cfb7f 100644 --- a/include/boost/detail/lwm_linux.hpp +++ b/include/boost/detail/lwm_linux.hpp @@ -6,10 +6,9 @@ // // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // // diff --git a/include/boost/detail/lwm_nop.hpp b/include/boost/detail/lwm_nop.hpp index fdc0a3d..c73ab68 100644 --- a/include/boost/detail/lwm_nop.hpp +++ b/include/boost/detail/lwm_nop.hpp @@ -12,10 +12,9 @@ // // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // namespace boost diff --git a/include/boost/detail/lwm_pthreads.hpp b/include/boost/detail/lwm_pthreads.hpp index 79ea5a7..a5bf75b 100644 --- a/include/boost/detail/lwm_pthreads.hpp +++ b/include/boost/detail/lwm_pthreads.hpp @@ -12,10 +12,9 @@ // // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include diff --git a/include/boost/detail/lwm_win32.hpp b/include/boost/detail/lwm_win32.hpp index 2228231..8496ed8 100644 --- a/include/boost/detail/lwm_win32.hpp +++ b/include/boost/detail/lwm_win32.hpp @@ -12,10 +12,9 @@ // // Copyright (c) 2002, 2003 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #ifdef BOOST_USE_WINDOWS_H diff --git a/include/boost/detail/lwm_win32_cs.hpp b/include/boost/detail/lwm_win32_cs.hpp index c4547de..4ee0a71 100644 --- a/include/boost/detail/lwm_win32_cs.hpp +++ b/include/boost/detail/lwm_win32_cs.hpp @@ -12,10 +12,9 @@ // // Copyright (c) 2002, 2003 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #ifdef BOOST_USE_WINDOWS_H diff --git a/include/boost/detail/lwm_win32_nt.hpp b/include/boost/detail/lwm_win32_nt.hpp index 39e49e2..216e636 100644 --- a/include/boost/detail/lwm_win32_nt.hpp +++ b/include/boost/detail/lwm_win32_nt.hpp @@ -10,10 +10,9 @@ // // Copyright (c) 2002, 2003 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // // "No threads" version of lwm_win32.hpp; binary compatible but no-op. // diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index a9ba4d2..86d8e4b 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -12,10 +12,9 @@ // // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index affed6f..0cf7854 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -6,10 +6,9 @@ // // Copyright (c) 2002 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html // diff --git a/include/boost/get_pointer.hpp b/include/boost/get_pointer.hpp index 09091e4..17d11b8 100644 --- a/include/boost/get_pointer.hpp +++ b/include/boost/get_pointer.hpp @@ -1,8 +1,7 @@ -// Copyright Peter Dimov and David Abrahams 2002. Permission to copy, -// use, modify, sell and distribute this software is granted provided -// this copyright notice appears in all copies of the source. This -// software is provided "as is" without express or implied warranty, -// and with no claim as to its suitability for any purpose. +// Copyright Peter Dimov and David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) #ifndef GET_POINTER_DWA20021219_HPP # define GET_POINTER_DWA20021219_HPP diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 7db6dcf..7efbade 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -6,10 +6,9 @@ // // Copyright (c) 2001, 2002 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation. // diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index d44b201..c238500 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -6,10 +6,9 @@ // // Copyright (c) 2001, 2002, 2003 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation. // diff --git a/src/sp_collector.cpp b/src/sp_collector.cpp index 42fd16c..6f933c2 100644 --- a/src/sp_collector.cpp +++ b/src/sp_collector.cpp @@ -3,10 +3,9 @@ // // Copyright (c) 2002, 2003 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) diff --git a/src/sp_debug_hooks.cpp b/src/sp_debug_hooks.cpp index 1f6be5f..3193936 100644 --- a/src/sp_debug_hooks.cpp +++ b/src/sp_debug_hooks.cpp @@ -3,10 +3,9 @@ // // Copyright (c) 2002, 2003 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) diff --git a/test/collector_test.cpp b/test/collector_test.cpp index 89fd208..062b557 100644 --- a/test/collector_test.cpp +++ b/test/collector_test.cpp @@ -3,10 +3,9 @@ // // Copyright (c) 2003 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include diff --git a/test/get_deleter_test.cpp b/test/get_deleter_test.cpp index 94d6dd4..8bed379 100644 --- a/test/get_deleter_test.cpp +++ b/test/get_deleter_test.cpp @@ -3,10 +3,9 @@ // // Copyright (c) 2002 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include diff --git a/test/intrusive_ptr_test.cpp b/test/intrusive_ptr_test.cpp index f8f305c..51429ae 100644 --- a/test/intrusive_ptr_test.cpp +++ b/test/intrusive_ptr_test.cpp @@ -21,10 +21,9 @@ // // Copyright (c) 2002, 2003 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include diff --git a/test/shared_from_this_test.cpp b/test/shared_from_this_test.cpp index be40fc9..5107cb1 100644 --- a/test/shared_from_this_test.cpp +++ b/test/shared_from_this_test.cpp @@ -12,10 +12,9 @@ // // Copyright (c) 2002, 2003 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // diff --git a/test/shared_ptr_alloc_test.cpp b/test/shared_ptr_alloc_test.cpp index 6eed3c3..0dedc37 100644 --- a/test/shared_ptr_alloc_test.cpp +++ b/test/shared_ptr_alloc_test.cpp @@ -3,10 +3,9 @@ // // Copyright (c) 2002, 2003 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include diff --git a/test/shared_ptr_assign_fail.cpp b/test/shared_ptr_assign_fail.cpp index 4b6cc86..c2820e0 100644 --- a/test/shared_ptr_assign_fail.cpp +++ b/test/shared_ptr_assign_fail.cpp @@ -12,10 +12,9 @@ // // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include diff --git a/test/shared_ptr_basic_test.cpp b/test/shared_ptr_basic_test.cpp index da8e902..f699848 100644 --- a/test/shared_ptr_basic_test.cpp +++ b/test/shared_ptr_basic_test.cpp @@ -19,10 +19,9 @@ // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include diff --git a/test/shared_ptr_mt_test.cpp b/test/shared_ptr_mt_test.cpp index a70158f..3ac1f97 100644 --- a/test/shared_ptr_mt_test.cpp +++ b/test/shared_ptr_mt_test.cpp @@ -12,10 +12,9 @@ // // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp index 8d3c7cc..2f852ea 100644 --- a/test/shared_ptr_test.cpp +++ b/test/shared_ptr_test.cpp @@ -19,10 +19,9 @@ // // Copyright (c) 2002, 2003 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include diff --git a/test/shared_ptr_timing_test.cpp b/test/shared_ptr_timing_test.cpp index 612ac39..79e62ff 100644 --- a/test/shared_ptr_timing_test.cpp +++ b/test/shared_ptr_timing_test.cpp @@ -12,10 +12,9 @@ // // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include diff --git a/test/weak_ptr_test.cpp b/test/weak_ptr_test.cpp index 8e8e534..347cd01 100644 --- a/test/weak_ptr_test.cpp +++ b/test/weak_ptr_test.cpp @@ -19,10 +19,9 @@ // // Copyright (c) 2002, 2003 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include From c7abff00991b4df6203ba6f75bfc17652c62e25e Mon Sep 17 00:00:00 2001 From: John Maddock Date: Tue, 10 Aug 2004 10:34:20 +0000 Subject: [PATCH 251/513] Updated Beman Dawes' licence statement to use the new prefered form of words. [SVN r24370] --- test/smart_ptr_test.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp index 4baa92d..27cba2b 100644 --- a/test/smart_ptr_test.cpp +++ b/test/smart_ptr_test.cpp @@ -1,7 +1,8 @@ // smart pointer test program ----------------------------------------------// -// Copyright Beman Dawes 1998, 1999. -// See accompanying license for terms and conditions of use. +// Copyright Beman Dawes 1998, 1999. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/smart_ptr for documentation. From 858cefbfe872401885786cc94ec2965e754b7815 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Wed, 11 Aug 2004 10:59:33 +0000 Subject: [PATCH 252/513] Removed boost.org copyright assignments, and reverted to orginal author (as based on cvs history). [SVN r24402] --- include/boost/smart_ptr.hpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp index a142883..98e0894 100644 --- a/include/boost/smart_ptr.hpp +++ b/include/boost/smart_ptr.hpp @@ -4,13 +4,9 @@ // For convenience, this header includes the rest of the smart // pointer library headers. // -// Copyright (c) 1998-2002 boost.org -// Copyright (c) 2003 Peter Dimov -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Copyright (c) 2003 Peter Dimov Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // http://www.boost.org/libs/smart_ptr/smart_ptr.htm // From 6b00a555428fab93bc5c86590bb249789eedbc68 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 19 Aug 2004 15:19:17 +0000 Subject: [PATCH 253/513] License updates [SVN r24597] --- include/boost/detail/atomic_count_gcc.hpp | 7 +++---- include/boost/detail/lwm_gcc.hpp | 7 +++---- include/boost/detail/shared_array_nmt.hpp | 7 +++---- include/boost/detail/shared_ptr_nmt.hpp | 7 +++---- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/include/boost/detail/atomic_count_gcc.hpp b/include/boost/detail/atomic_count_gcc.hpp index 8761b80..9fa661f 100644 --- a/include/boost/detail/atomic_count_gcc.hpp +++ b/include/boost/detail/atomic_count_gcc.hpp @@ -11,10 +11,9 @@ // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2002 Lars Gullik Bjĝnnes // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include diff --git a/include/boost/detail/lwm_gcc.hpp b/include/boost/detail/lwm_gcc.hpp index a77b26d..e64ef7d 100644 --- a/include/boost/detail/lwm_gcc.hpp +++ b/include/boost/detail/lwm_gcc.hpp @@ -11,10 +11,9 @@ // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2002 Lars Gullik Bjĝnnes // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include diff --git a/include/boost/detail/shared_array_nmt.hpp b/include/boost/detail/shared_array_nmt.hpp index 8e9b727..13ca6ac 100644 --- a/include/boost/detail/shared_array_nmt.hpp +++ b/include/boost/detail/shared_array_nmt.hpp @@ -7,10 +7,9 @@ // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. // Copyright (c) 2001, 2002 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation. // diff --git a/include/boost/detail/shared_ptr_nmt.hpp b/include/boost/detail/shared_ptr_nmt.hpp index 14fbe65..0780e30 100644 --- a/include/boost/detail/shared_ptr_nmt.hpp +++ b/include/boost/detail/shared_ptr_nmt.hpp @@ -7,10 +7,9 @@ // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. // Copyright (c) 2001, 2002 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. // From ef51f6a1de7d93bf2ecf6df93218cd6f00772b3f Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 19 Aug 2004 15:23:47 +0000 Subject: [PATCH 254/513] License update [SVN r24598] --- include/boost/scoped_array.hpp | 7 +++---- include/boost/scoped_ptr.hpp | 7 +++---- include/boost/shared_array.hpp | 7 +++---- include/boost/shared_ptr.hpp | 7 +++---- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index e5919a4..667dfff 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -4,10 +4,9 @@ // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. // Copyright (c) 2001, 2002 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // // http://www.boost.org/libs/smart_ptr/scoped_array.htm // diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index c36cace..651deed 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -4,10 +4,9 @@ // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. // Copyright (c) 2001, 2002 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // // http://www.boost.org/libs/smart_ptr/scoped_ptr.htm // diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index 5e943d9..9216e89 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -7,10 +7,9 @@ // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. // Copyright (c) 2001, 2002 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation. // diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index a5e4adf..ae89ecc 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -7,10 +7,9 @@ // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. // Copyright (c) 2001, 2002, 2003 Peter Dimov // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. // From 27be736b8faa67864913daa7d9ce768872c04524 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 24 Aug 2004 16:27:31 +0000 Subject: [PATCH 255/513] Fixed sp_enable_shared_from_this to not use void cv * since this breaks function types. [SVN r24718] --- include/boost/shared_ptr.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index ae89ecc..0a3bf6d 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -82,12 +82,12 @@ template<> struct shared_ptr_traits // enable_shared_from_this support -template void sp_enable_shared_from_this(boost::enable_shared_from_this const * pe, Y const * px, shared_count const & pn) +template void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this const * pe, Y const * px ) { if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); } -inline void sp_enable_shared_from_this(void const volatile *, void const volatile *, shared_count const &) +inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) { } @@ -123,7 +123,7 @@ public: template explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter()) // Y must be complete { - detail::sp_enable_shared_from_this(p, p, pn); + detail::sp_enable_shared_from_this( pn, p, p ); } // @@ -134,7 +134,7 @@ public: template shared_ptr(Y * p, D d): px(p), pn(p, d) { - detail::sp_enable_shared_from_this(p, p, pn); + detail::sp_enable_shared_from_this( pn, p, p ); } // generated copy constructor, assignment, destructor are fine... @@ -198,7 +198,7 @@ public: { Y * tmp = r.get(); pn = detail::shared_count(r); - detail::sp_enable_shared_from_this(tmp, tmp, pn); + detail::sp_enable_shared_from_this( pn, tmp, tmp ); } #endif From 1bc58ea8611b2097405bbc37da78f74fdd44caea Mon Sep 17 00:00:00 2001 From: John Maddock Date: Sun, 29 Aug 2004 10:29:46 +0000 Subject: [PATCH 256/513] Updated to use the BSL (using permissions supplied in more/blanket-permission.txt) [SVN r24804] --- include/boost/detail/lwm_irix.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/boost/detail/lwm_irix.hpp b/include/boost/detail/lwm_irix.hpp index 6e5e57f..cfc304b 100644 --- a/include/boost/detail/lwm_irix.hpp +++ b/include/boost/detail/lwm_irix.hpp @@ -7,10 +7,9 @@ // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2002 Dan Gohman // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // #include From c81be1e2e70c5e0e83069f458e60a86f2e1f77ad Mon Sep 17 00:00:00 2001 From: Aleksey Gurtovoy Date: Tue, 5 Oct 2004 15:45:52 +0000 Subject: [PATCH 257/513] c++boost.gif -> boost.png replacement [SVN r25573] --- compatibility.htm | 2 +- enable_shared_from_this.html | 2 +- intrusive_ptr.html | 2 +- scoped_array.htm | 2 +- scoped_ptr.htm | 2 +- shared_array.htm | 2 +- shared_ptr.htm | 2 +- smart_ptr.htm | 2 +- smarttests.htm | 2 +- sp_techniques.html | 2 +- weak_ptr.htm | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/compatibility.htm b/compatibility.htm index fb4d0a5..6d7af92 100644 --- a/compatibility.htm +++ b/compatibility.htm @@ -9,7 +9,7 @@ -

    c++boost.gif (8819 bytes)Smart +

    boost.png (6897 bytes)Smart Pointer Changes

    The February 2002 change to the Boost smart pointers introduced a number diff --git a/enable_shared_from_this.html b/enable_shared_from_this.html index 8ff0a73..8d6a6e3 100644 --- a/enable_shared_from_this.html +++ b/enable_shared_from_this.html @@ -8,7 +8,7 @@
    - c++boost.gif (8819 bytes) + boost.png (6897 bytes)

    enable_shared_from_this.hpp

    diff --git a/intrusive_ptr.html b/intrusive_ptr.html index 66c1401..c0ddfeb 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -5,7 +5,7 @@ -

    c++boost.gif (8819 bytes)intrusive_ptr +

    boost.png (6897 bytes)intrusive_ptr class template

    Introduction
    diff --git a/scoped_array.htm b/scoped_array.htm index 9fef424..2e1081c 100644 --- a/scoped_array.htm +++ b/scoped_array.htm @@ -5,7 +5,7 @@ -

    c++boost.gif (8819 bytes)scoped_array +

    boost.png (6897 bytes)scoped_array class template

    The scoped_array class template stores a pointer to a dynamically allocated array. (Dynamically allocated arrays are allocated with the C++ new[] diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 4a15223..881c402 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -5,7 +5,7 @@ -

    c++boost.gif (8819 bytes)scoped_ptr +

    boost.png (6897 bytes)scoped_ptr class template

    The scoped_ptr class template stores a pointer to a dynamically allocated object. (Dynamically allocated objects are allocated with the C++ new expression.) diff --git a/shared_array.htm b/shared_array.htm index f4d5f04..337f131 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -5,7 +5,7 @@ -

    c++boost.gif (8819 bytes)shared_array +

    boost.png (6897 bytes)shared_array class template

    The shared_array class template stores a pointer to a dynamically allocated array. (Dynamically allocated array are allocated with the C++ new[] diff --git a/shared_ptr.htm b/shared_ptr.htm index 196b777..3422166 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -5,7 +5,7 @@ -

    c++boost.gif (8819 bytes)shared_ptr +

    boost.png (6897 bytes)shared_ptr class template

    Introduction
    Best Practices
    diff --git a/smart_ptr.htm b/smart_ptr.htm index 9327c9f..2ff8dd2 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -5,7 +5,7 @@ -

    c++boost.gif (8819 bytes)Smart +

    boost.png (6897 bytes)Smart Pointers

    Introduction
    Common Requirements
    diff --git a/smarttests.htm b/smarttests.htm index 04a4381..e7cedff 100644 --- a/smarttests.htm +++ b/smarttests.htm @@ -9,7 +9,7 @@ -

    c++boost.gif (8819 bytes)Smart Pointer Timings

    +

    boost.png (6897 bytes)Smart Pointer Timings

    In late January 2000, Mark Borgerding put forward a suggestion to boost for a new design of smart pointer whereby an intrusive doubly linked list is used diff --git a/sp_techniques.html b/sp_techniques.html index 826195f..ea48db9 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -5,7 +5,7 @@ -

    c++boost.gif (8819 bytes)Smart +

    boost.png (6897 bytes)Smart Pointer Programming Techniques

    Using incomplete classes for implementation hiding
    The "Pimpl" idiom
    diff --git a/weak_ptr.htm b/weak_ptr.htm index fb9f44f..e5ccc11 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -5,7 +5,7 @@ -

    c++boost.gif (8819 bytes)weak_ptr +

    boost.png (6897 bytes)weak_ptr class template

    Introduction
    Synopsis
    From 8f317492ee506214a6830dc0f41da84e59ab2759 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 22 Nov 2004 12:32:35 +0000 Subject: [PATCH 258/513] Outdated comment removed (Jonathan Wakely) [SVN r26272] --- include/boost/detail/shared_count.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 86d8e4b..7125905 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -247,7 +247,7 @@ private: public: - // pre: initial_use_count <= initial_weak_count, d(p) must not throw + // pre: d(p) must not throw sp_counted_base_impl(P p, D d): ptr(p), del(d) { From e5c1e12a66a75eba1c77f99733ef6b6492078024 Mon Sep 17 00:00:00 2001 From: Aleksey Gurtovoy Date: Sun, 28 Nov 2004 04:44:21 +0000 Subject: [PATCH 259/513] merge RC_1_32_0 fixes [SVN r26333] --- scoped_ptr.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 881c402..f3a0155 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -115,7 +115,7 @@ class MyClass { int add_one() { return ++*ptr; } }; -void main() +int main() { boost::scoped_ptr<Shoe> x(new Shoe); MyClass my_instance; From 5616a1a87231217e449ed9f05792250bc9df4448 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 13 Jan 2005 13:45:59 +0000 Subject: [PATCH 260/513] Added note on BOOST_MEM_FN_ENABLE_STDCALL. [SVN r26687] --- sp_techniques.html | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sp_techniques.html b/sp_techniques.html index ea48db9..816047f 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -272,6 +272,9 @@ shared_ptr<X> createX() single reference created in make_shared_from_COM. Weak pointers created from pw will be invalidated when the last shared_ptr is destroyed, regardless of whether the COM object itself is still alive.

    +

    As explained in the mem_fn documentation, + you need to #define + BOOST_MEM_FN_ENABLE_STDCALL first.

    Using a shared_ptr to hold a pointer to an object with an embedded reference count

    This is a generalization of the above technique. The example assumes that the @@ -753,8 +756,8 @@ public:


    $Date$

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

    + distribute this document is granted provided this copyright notice appears in + all copies. This document is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose.

    From 7d59d29ad18f118bcd6806c19b72c48e65cd4f6d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 4 Feb 2005 16:28:50 +0000 Subject: [PATCH 261/513] HP aCC fix for get_deleter (Jaroslav Gresula) [SVN r27092] --- include/boost/shared_ptr.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 0a3bf6d..474bf4f 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -442,10 +442,12 @@ template std::basic_ostream & operator<< (std:: // get_deleter (experimental) -#if (defined(__GNUC__) && (__GNUC__ < 3)) || (defined(__EDG_VERSION__) && (__EDG_VERSION__ <= 238)) +#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ + ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ + ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) ) // g++ 2.9x doesn't allow static_cast(void *) -// apparently EDG 2.38 also doesn't accept it +// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it template D * get_deleter(shared_ptr const & p) { From 42a739b357db75cb9c827a4c0b2d25d84f009899 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 4 Feb 2005 16:39:44 +0000 Subject: [PATCH 262/513] Fixed nonportable elision assumption. [SVN r27093] --- test/weak_ptr_test.cpp | 115 +++++++++++++++++++++++++++++++++-------- 1 file changed, 93 insertions(+), 22 deletions(-) diff --git a/test/weak_ptr_test.cpp b/test/weak_ptr_test.cpp index 347cd01..7213794 100644 --- a/test/weak_ptr_test.cpp +++ b/test/weak_ptr_test.cpp @@ -17,7 +17,7 @@ // // weak_ptr_test.cpp // -// Copyright (c) 2002, 2003 Peter Dimov +// Copyright (c) 2002-2005 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -500,7 +500,7 @@ void test() namespace n_assignment { -template void copy_assignment(boost::shared_ptr sp) +template void copy_assignment(boost::shared_ptr & sp) { BOOST_TEST(sp.unique()); @@ -611,7 +611,7 @@ void conversion_assignment() } } -template void shared_ptr_assignment(boost::shared_ptr sp, T * = 0) +template void shared_ptr_assignment(boost::shared_ptr & sp, T * = 0) { BOOST_TEST(sp.unique()); @@ -644,18 +644,62 @@ template void shared_ptr_assignment(boost::shared_ptr sp, T void test() { - copy_assignment(boost::shared_ptr(new int)); - copy_assignment(boost::shared_ptr(new X)); - copy_assignment(boost::shared_ptr(new int)); - copy_assignment(create_incomplete()); + { + boost::shared_ptr p( new int ); + copy_assignment( p ); + } + + { + boost::shared_ptr p( new X ); + copy_assignment( p ); + } + + { + boost::shared_ptr p( new int ); + copy_assignment( p ); + } + + { + boost::shared_ptr p = create_incomplete(); + copy_assignment( p ); + } + conversion_assignment(); - shared_ptr_assignment(boost::shared_ptr(new int)); - shared_ptr_assignment(boost::shared_ptr(new int)); - shared_ptr_assignment(boost::shared_ptr(new X)); - shared_ptr_assignment(boost::shared_ptr(new X)); - shared_ptr_assignment(boost::shared_ptr(new int)); - shared_ptr_assignment(create_incomplete()); - shared_ptr_assignment(create_incomplete()); + + { + boost::shared_ptr p( new int ); + shared_ptr_assignment( p ); + } + + { + boost::shared_ptr p( new int ); + shared_ptr_assignment( p ); + } + + { + boost::shared_ptr p( new X ); + shared_ptr_assignment( p ); + } + + { + boost::shared_ptr p( new X ); + shared_ptr_assignment( p ); + } + + { + boost::shared_ptr p( new int ); + shared_ptr_assignment( p ); + } + + { + boost::shared_ptr p = create_incomplete(); + shared_ptr_assignment( p ); + } + + { + boost::shared_ptr p = create_incomplete(); + shared_ptr_assignment( p ); + } } } // namespace n_assignment @@ -663,7 +707,7 @@ void test() namespace n_reset { -template void test2(boost::shared_ptr sp, T * = 0) +template void test2( boost::shared_ptr & sp, T * = 0 ) { BOOST_TEST(sp.unique()); @@ -697,13 +741,40 @@ template void test2(boost::shared_ptr sp, T * = 0) void test() { - test2(boost::shared_ptr(new int)); - test2(boost::shared_ptr(new int)); - test2(boost::shared_ptr(new X)); - test2(boost::shared_ptr(new X)); - test2(boost::shared_ptr(new int)); - test2(create_incomplete()); - test2(create_incomplete()); + { + boost::shared_ptr p( new int ); + test2( p ); + } + + { + boost::shared_ptr p( new int ); + test2( p ); + } + + { + boost::shared_ptr p( new X ); + test2( p ); + } + + { + boost::shared_ptr p( new X ); + test2( p ); + } + + { + boost::shared_ptr p( new int ); + test2( p ); + } + + { + boost::shared_ptr p = create_incomplete(); + test2( p ); + } + + { + boost::shared_ptr p = create_incomplete(); + test2( p ); + } } } // namespace n_reset From b07447aa6e8627dd4908a9a030876dcb6c0d9f9c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 15 Mar 2005 16:02:01 +0000 Subject: [PATCH 263/513] BCB 6.4 still needs option -pc (reported by Pavel Vozenilek) [SVN r27672] --- include/boost/detail/shared_count.hpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 7125905..cc50165 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -58,14 +58,13 @@ void sp_array_destructor_hook(void * px); #endif -// The standard library that comes with Borland C++ 5.5.1 +// The standard library that comes with Borland C++ 5.5.1, 5.6.4 // defines std::exception and its members as having C calling // convention (-pc). When the definition of bad_weak_ptr // is compiled with -ps, the compiler issues an error. -// Hence, the temporary #pragma option -pc below. The version -// check is deliberately conservative. +// Hence, the temporary #pragma option -pc below. -#if defined(__BORLANDC__) && __BORLANDC__ == 0x551 +#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564 # pragma option push -pc #endif @@ -79,7 +78,7 @@ public: } }; -#if defined(__BORLANDC__) && __BORLANDC__ == 0x551 +#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564 # pragma option pop #endif From c830315dff123379b8e9f5edb5d24a824b5500d8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 17 Mar 2005 22:45:11 +0000 Subject: [PATCH 264/513] Refactored shared_count.hpp into bad_weak_ptr.hpp, sp_counted_base.hpp [SVN r27725] --- include/boost/detail/bad_weak_ptr.hpp | 59 +++++++++ include/boost/detail/shared_count.hpp | 148 +---------------------- include/boost/detail/sp_counted_base.hpp | 143 ++++++++++++++++++++++ 3 files changed, 207 insertions(+), 143 deletions(-) create mode 100644 include/boost/detail/bad_weak_ptr.hpp create mode 100644 include/boost/detail/sp_counted_base.hpp diff --git a/include/boost/detail/bad_weak_ptr.hpp b/include/boost/detail/bad_weak_ptr.hpp new file mode 100644 index 0000000..a08d7b1 --- /dev/null +++ b/include/boost/detail/bad_weak_ptr.hpp @@ -0,0 +1,59 @@ +#ifndef BOOST_BAD_WEAK_PTR_HPP_INCLUDED +#define BOOST_BAD_WEAK_PTR_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/bad_weak_ptr.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +#ifdef __BORLANDC__ +# pragma warn -8026 // Functions with excep. spec. are not expanded inline +#endif + +namespace boost +{ + +// The standard library that comes with Borland C++ 5.5.1, 5.6.4 +// defines std::exception and its members as having C calling +// convention (-pc). When the definition of bad_weak_ptr +// is compiled with -ps, the compiler issues an error. +// Hence, the temporary #pragma option -pc below. + +#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564 +# pragma option push -pc +#endif + +class bad_weak_ptr: public std::exception +{ +public: + + virtual char const * what() const throw() + { + return "boost::bad_weak_ptr"; + } +}; + +#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564 +# pragma option pop +#endif + +} // namespace boost + +#ifdef __BORLANDC__ +# pragma warn .8026 // Functions with excep. spec. are not expanded inline +#endif + +#endif // #ifndef BOOST_BAD_WEAK_PTR_HPP_INCLUDED diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index cc50165..afc4e78 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -11,6 +11,7 @@ // detail/shared_count.hpp // // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -25,7 +26,8 @@ #include #include -#include +#include +#include #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) #include @@ -33,13 +35,11 @@ #include // std::auto_ptr, std::allocator #include // std::less -#include // std::exception #include // std::bad_alloc #include // std::type_info in get_deleter #include // std::size_t #ifdef __BORLANDC__ -# pragma warn -8026 // Functions with excep. spec. are not expanded inline # pragma warn -8027 // Functions containing try are not expanded inline #endif @@ -57,142 +57,9 @@ void sp_array_destructor_hook(void * px); #endif - -// The standard library that comes with Borland C++ 5.5.1, 5.6.4 -// defines std::exception and its members as having C calling -// convention (-pc). When the definition of bad_weak_ptr -// is compiled with -ps, the compiler issues an error. -// Hence, the temporary #pragma option -pc below. - -#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564 -# pragma option push -pc -#endif - -class bad_weak_ptr: public std::exception -{ -public: - - virtual char const * what() const throw() - { - return "boost::bad_weak_ptr"; - } -}; - -#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564 -# pragma option pop -#endif - namespace detail { -class sp_counted_base -{ -private: - - typedef detail::lightweight_mutex mutex_type; - -public: - - sp_counted_base(): use_count_(1), weak_count_(1) - { - } - - virtual ~sp_counted_base() // nothrow - { - } - - // dispose() is called when use_count_ drops to zero, to release - // the resources managed by *this. - - virtual void dispose() = 0; // nothrow - - // destruct() is called when weak_count_ drops to zero. - - virtual void destruct() // nothrow - { - delete this; - } - - virtual void * get_deleter(std::type_info const & ti) = 0; - - void add_ref_copy() - { -#if defined(BOOST_HAS_THREADS) - mutex_type::scoped_lock lock(mtx_); -#endif - ++use_count_; - } - - void add_ref_lock() - { -#if defined(BOOST_HAS_THREADS) - mutex_type::scoped_lock lock(mtx_); -#endif - if(use_count_ == 0) boost::throw_exception(boost::bad_weak_ptr()); - ++use_count_; - } - - void release() // nothrow - { - { -#if defined(BOOST_HAS_THREADS) - mutex_type::scoped_lock lock(mtx_); -#endif - long new_use_count = --use_count_; - - if(new_use_count != 0) return; - } - - dispose(); - weak_release(); - } - - void weak_add_ref() // nothrow - { -#if defined(BOOST_HAS_THREADS) - mutex_type::scoped_lock lock(mtx_); -#endif - ++weak_count_; - } - - void weak_release() // nothrow - { - long new_weak_count; - - { -#if defined(BOOST_HAS_THREADS) - mutex_type::scoped_lock lock(mtx_); -#endif - new_weak_count = --weak_count_; - } - - if(new_weak_count == 0) - { - destruct(); - } - } - - long use_count() const // nothrow - { -#if defined(BOOST_HAS_THREADS) - mutex_type::scoped_lock lock(mtx_); -#endif - return use_count_; - } - -private: - - sp_counted_base(sp_counted_base const &); - sp_counted_base & operator= (sp_counted_base const &); - - long use_count_; // #shared - long weak_count_; // #weak + (#shared != 0) - -#if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32) - mutable mutex_type mtx_; -#endif -}; - #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) template void cbi_call_constructor_hook(sp_counted_base * pn, T * px, checked_deleter const &, int) @@ -535,13 +402,9 @@ inline shared_count::shared_count(weak_count const & r): pi_(r.pi_) , id_(shared_count_id) #endif { - if(pi_ != 0) + if( pi_ == 0 || !pi_->add_ref_lock() ) { - pi_->add_ref_lock(); - } - else - { - boost::throw_exception(boost::bad_weak_ptr()); + boost::throw_exception( boost::bad_weak_ptr() ); } } @@ -551,7 +414,6 @@ inline shared_count::shared_count(weak_count const & r): pi_(r.pi_) #ifdef __BORLANDC__ # pragma warn .8027 // Functions containing try are not expanded inline -# pragma warn .8026 // Functions with excep. spec. are not expanded inline #endif #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp new file mode 100644 index 0000000..194bc1f --- /dev/null +++ b/include/boost/detail/sp_counted_base.hpp @@ -0,0 +1,143 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include + +#include + +namespace boost +{ + +namespace detail +{ + +class sp_counted_base +{ +private: + + typedef detail::lightweight_mutex mutex_type; + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + long use_count_; // #shared + long weak_count_; // #weak + (#shared != 0) + +#if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32) + mutable mutex_type mtx_; +#endif + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( std::type_info const & ti ) = 0; + + void add_ref_copy() + { +#if defined(BOOST_HAS_THREADS) + mutex_type::scoped_lock lock(mtx_); +#endif + ++use_count_; + } + + bool add_ref_lock() // true on success + { +#if defined(BOOST_HAS_THREADS) + mutex_type::scoped_lock lock(mtx_); +#endif + if( use_count_ == 0 ) return false; + ++use_count_; + return true; + } + + void release() // nothrow + { + { +#if defined(BOOST_HAS_THREADS) + mutex_type::scoped_lock lock(mtx_); +#endif + long new_use_count = --use_count_; + + if( new_use_count != 0 ) return; + } + + dispose(); + weak_release(); + } + + void weak_add_ref() // nothrow + { +#if defined(BOOST_HAS_THREADS) + mutex_type::scoped_lock lock(mtx_); +#endif + ++weak_count_; + } + + void weak_release() // nothrow + { + long new_weak_count; + + { +#if defined(BOOST_HAS_THREADS) + mutex_type::scoped_lock lock(mtx_); +#endif + new_weak_count = --weak_count_; + } + + if( new_weak_count == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { +#if defined(BOOST_HAS_THREADS) + mutex_type::scoped_lock lock(mtx_); +#endif + return use_count_; + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED From b0eb65b433b9be9c0a223b39681d4b471465720f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 17 Mar 2005 23:05:26 +0000 Subject: [PATCH 265/513] Refactored sp_counted_impl.hpp out of shared_count.hpp [SVN r27726] --- include/boost/detail/shared_count.hpp | 127 +---------------- include/boost/detail/sp_counted_impl.hpp | 167 +++++++++++++++++++++++ 2 files changed, 171 insertions(+), 123 deletions(-) create mode 100644 include/boost/detail/sp_counted_impl.hpp diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index afc4e78..106428d 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) #include @@ -37,7 +38,6 @@ #include // std::less #include // std::bad_alloc #include // std::type_info in get_deleter -#include // std::size_t #ifdef __BORLANDC__ # pragma warn -8027 // Functions containing try are not expanded inline @@ -46,126 +46,11 @@ namespace boost { -// Debug hooks - -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - -void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn); -void sp_array_constructor_hook(void * px); -void sp_scalar_destructor_hook(void * px, std::size_t size, void * pn); -void sp_array_destructor_hook(void * px); - -#endif - namespace detail { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) -template void cbi_call_constructor_hook(sp_counted_base * pn, T * px, checked_deleter const &, int) -{ - boost::sp_scalar_constructor_hook(px, sizeof(T), pn); -} - -template void cbi_call_constructor_hook(sp_counted_base *, T * px, checked_array_deleter const &, int) -{ - boost::sp_array_constructor_hook(px); -} - -template void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long) -{ -} - -template void cbi_call_destructor_hook(sp_counted_base * pn, T * px, checked_deleter const &, int) -{ - boost::sp_scalar_destructor_hook(px, sizeof(T), pn); -} - -template void cbi_call_destructor_hook(sp_counted_base *, T * px, checked_array_deleter const &, int) -{ - boost::sp_array_destructor_hook(px); -} - -template void cbi_call_destructor_hook(sp_counted_base *, P const &, D const &, long) -{ -} - -#endif - -// -// Borland's Codeguard trips up over the -Vx- option here: -// -#ifdef __CODEGUARD__ -# pragma option push -Vx- -#endif - -template class sp_counted_base_impl: public sp_counted_base -{ -private: - - P ptr; // copy constructor must not throw - D del; // copy constructor must not throw - - sp_counted_base_impl(sp_counted_base_impl const &); - sp_counted_base_impl & operator= (sp_counted_base_impl const &); - - typedef sp_counted_base_impl this_type; - -public: - - // pre: d(p) must not throw - - sp_counted_base_impl(P p, D d): ptr(p), del(d) - { -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - detail::cbi_call_constructor_hook(this, p, d, 0); -#endif - } - - virtual void dispose() // nothrow - { -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - detail::cbi_call_destructor_hook(this, ptr, del, 0); -#endif - del(ptr); - } - - virtual void * get_deleter(std::type_info const & ti) - { - return ti == typeid(D)? &del: 0; - } - -#if defined(BOOST_SP_USE_STD_ALLOCATOR) - - void * operator new(std::size_t) - { - return std::allocator().allocate(1, static_cast(0)); - } - - void operator delete(void * p) - { - std::allocator().deallocate(static_cast(p), 1); - } - -#endif - -#if defined(BOOST_SP_USE_QUICK_ALLOCATOR) - - void * operator new(std::size_t) - { - return quick_allocator::alloc(); - } - - void operator delete(void * p) - { - quick_allocator::dealloc(p); - } - -#endif -}; - -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - int const shared_count_id = 0x2C35F101; int const weak_count_id = 0x298C38A4; @@ -203,7 +88,7 @@ public: try { - pi_ = new sp_counted_base_impl(p, d); + pi_ = new sp_counted_impl_pd(p, d); } catch(...) { @@ -213,7 +98,7 @@ public: #else - pi_ = new sp_counted_base_impl(p, d); + pi_ = new sp_counted_impl_pd(p, d); if(pi_ == 0) { @@ -229,7 +114,7 @@ public: // auto_ptr is special cased to provide the strong guarantee template - explicit shared_count(std::auto_ptr & r): pi_(new sp_counted_base_impl< Y *, checked_deleter >(r.get(), checked_deleter())) + explicit shared_count(std::auto_ptr & r): pi_(new sp_counted_impl_pd< Y *, checked_deleter >(r.get(), checked_deleter())) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif @@ -304,10 +189,6 @@ public: } }; -#ifdef __CODEGUARD__ -# pragma option pop -#endif - class weak_count { diff --git a/include/boost/detail/sp_counted_impl.hpp b/include/boost/detail/sp_counted_impl.hpp new file mode 100644 index 0000000..8d3c8c7 --- /dev/null +++ b/include/boost/detail/sp_counted_impl.hpp @@ -0,0 +1,167 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_impl.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +#if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR) +# error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible. +#endif + +#include +#include + +#if defined(BOOST_SP_USE_QUICK_ALLOCATOR) +#include +#endif + +#include // std::allocator +#include // std::type_info in get_deleter +#include // std::size_t + +namespace boost +{ + +// Debug hooks + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn); +void sp_array_constructor_hook(void * px); +void sp_scalar_destructor_hook(void * px, std::size_t size, void * pn); +void sp_array_destructor_hook(void * px); + +#endif + +namespace detail +{ + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +template void cbi_call_constructor_hook(sp_counted_base * pn, T * px, checked_deleter const &, int) +{ + boost::sp_scalar_constructor_hook(px, sizeof(T), pn); +} + +template void cbi_call_constructor_hook(sp_counted_base *, T * px, checked_array_deleter const &, int) +{ + boost::sp_array_constructor_hook(px); +} + +template void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long) +{ +} + +template void cbi_call_destructor_hook(sp_counted_base * pn, T * px, checked_deleter const &, int) +{ + boost::sp_scalar_destructor_hook(px, sizeof(T), pn); +} + +template void cbi_call_destructor_hook(sp_counted_base *, T * px, checked_array_deleter const &, int) +{ + boost::sp_array_destructor_hook(px); +} + +template void cbi_call_destructor_hook(sp_counted_base *, P const &, D const &, long) +{ +} + +#endif + +// +// Borland's Codeguard trips up over the -Vx- option here: +// +#ifdef __CODEGUARD__ +# pragma option push -Vx- +#endif + +template class sp_counted_impl_pd: public sp_counted_base +{ +private: + + P ptr; // copy constructor must not throw + D del; // copy constructor must not throw + + sp_counted_impl_pd(sp_counted_impl_pd const &); + sp_counted_impl_pd & operator= (sp_counted_impl_pd const &); + + typedef sp_counted_impl_pd this_type; + +public: + + // pre: d(p) must not throw + + sp_counted_impl_pd(P p, D d): ptr(p), del(d) + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + detail::cbi_call_constructor_hook(this, p, d, 0); +#endif + } + + virtual void dispose() // nothrow + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + detail::cbi_call_destructor_hook(this, ptr, del, 0); +#endif + del(ptr); + } + + virtual void * get_deleter(std::type_info const & ti) + { + return ti == typeid(D)? &del: 0; + } + +#if defined(BOOST_SP_USE_STD_ALLOCATOR) + + void * operator new(std::size_t) + { + return std::allocator().allocate(1, static_cast(0)); + } + + void operator delete(void * p) + { + std::allocator().deallocate(static_cast(p), 1); + } + +#endif + +#if defined(BOOST_SP_USE_QUICK_ALLOCATOR) + + void * operator new(std::size_t) + { + return quick_allocator::alloc(); + } + + void operator delete(void * p) + { + quick_allocator::dealloc(p); + } + +#endif +}; + +#ifdef __CODEGUARD__ +# pragma option pop +#endif + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED From 09a0ba8c7537945a0cb5c2a68b57669999e1d7a4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 17 Mar 2005 23:30:47 +0000 Subject: [PATCH 266/513] sp_counted_impl_p added for the pointer constructor [SVN r27727] --- include/boost/detail/shared_count.hpp | 66 +++++++++---- include/boost/detail/sp_counted_impl.hpp | 114 +++++++++++++---------- include/boost/shared_ptr.hpp | 2 +- 3 files changed, 116 insertions(+), 66 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 106428d..133e54e 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -19,21 +19,12 @@ // #include - -#if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR) -# error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible. -#endif - #include #include #include #include #include -#if defined(BOOST_SP_USE_QUICK_ALLOCATOR) -#include -#endif - #include // std::auto_ptr, std::allocator #include // std::less #include // std::bad_alloc @@ -79,6 +70,36 @@ public: { } + template explicit shared_count( Y * p ): pi_( 0 ) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { +#ifndef BOOST_NO_EXCEPTIONS + + try + { + pi_ = new sp_counted_impl_p( p ); + } + catch(...) + { + boost::checked_delete( p ); + throw; + } + +#else + + pi_ = new sp_counted_impl_p( p ); + + if( pi_ == 0 ) + { + boost::checked_delete( p ); + boost::throw_exception( std::bad_alloc() ); + } + +#endif + } + template shared_count(P p, D d): pi_(0) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) @@ -114,11 +135,20 @@ public: // auto_ptr is special cased to provide the strong guarantee template - explicit shared_count(std::auto_ptr & r): pi_(new sp_counted_impl_pd< Y *, checked_deleter >(r.get(), checked_deleter())) + explicit shared_count( std::auto_ptr & r ): pi_( new sp_counted_impl_p( r.get() ) ) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { +#ifdef BOOST_NO_EXCEPTIONS + + if( pi_ == 0 ) + { + boost::throw_exception(std::bad_alloc()); + } + +#endif + r.release(); } @@ -126,7 +156,7 @@ public: ~shared_count() // nothrow { - if(pi_ != 0) pi_->release(); + if( pi_ != 0 ) pi_->release(); #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) id_ = 0; #endif @@ -137,7 +167,7 @@ public: , id_(shared_count_id) #endif { - if(pi_ != 0) pi_->add_ref_copy(); + if( pi_ != 0 ) pi_->add_ref_copy(); } explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 @@ -146,10 +176,10 @@ public: { sp_counted_base * tmp = r.pi_; - if(tmp != pi_) + if( tmp != pi_ ) { - if(tmp != 0) tmp->add_ref_copy(); - if(pi_ != 0) pi_->release(); + if( tmp != 0 ) tmp->add_ref_copy(); + if( pi_ != 0 ) pi_->release(); pi_ = tmp; } @@ -180,12 +210,12 @@ public: friend inline bool operator<(shared_count const & a, shared_count const & b) { - return std::less()(a.pi_, b.pi_); + return std::less()( a.pi_, b.pi_ ); } void * get_deleter(std::type_info const & ti) const { - return pi_? pi_->get_deleter(ti): 0; + return pi_? pi_->get_deleter( ti ): 0; } }; @@ -278,7 +308,7 @@ public: } }; -inline shared_count::shared_count(weak_count const & r): pi_(r.pi_) +inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ ) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif diff --git a/include/boost/detail/sp_counted_impl.hpp b/include/boost/detail/sp_counted_impl.hpp index 8d3c8c7..51093b5 100644 --- a/include/boost/detail/sp_counted_impl.hpp +++ b/include/boost/detail/sp_counted_impl.hpp @@ -38,52 +38,78 @@ namespace boost { -// Debug hooks - #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) -void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn); -void sp_array_constructor_hook(void * px); -void sp_scalar_destructor_hook(void * px, std::size_t size, void * pn); -void sp_array_destructor_hook(void * px); +void sp_scalar_constructor_hook( void * px, std::size_t size, void * pn ); +void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn ); #endif namespace detail { +template class sp_counted_impl_p: public sp_counted_base +{ +private: + + X * px_; + + sp_counted_impl_p( sp_counted_impl_p const & ); + sp_counted_impl_p & operator= ( sp_counted_impl_p const & ); + + typedef sp_counted_impl_p this_type; + +public: + + explicit sp_counted_impl_p( X * px ): px_( px ) + { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_constructor_hook( px, sizeof(X), this ); +#endif + } -template void cbi_call_constructor_hook(sp_counted_base * pn, T * px, checked_deleter const &, int) -{ - boost::sp_scalar_constructor_hook(px, sizeof(T), pn); -} + virtual void dispose() // nothrow + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_destructor_hook( px_, sizeof(X), this ); +#endif + boost::checked_delete( px_ ); + } -template void cbi_call_constructor_hook(sp_counted_base *, T * px, checked_array_deleter const &, int) -{ - boost::sp_array_constructor_hook(px); -} + virtual void * get_deleter( std::type_info const & ) + { + return 0; + } -template void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long) -{ -} +#if defined(BOOST_SP_USE_STD_ALLOCATOR) -template void cbi_call_destructor_hook(sp_counted_base * pn, T * px, checked_deleter const &, int) -{ - boost::sp_scalar_destructor_hook(px, sizeof(T), pn); -} + void * operator new( std::size_t ) + { + return std::allocator().allocate( 1, static_cast(0) ); + } -template void cbi_call_destructor_hook(sp_counted_base *, T * px, checked_array_deleter const &, int) -{ - boost::sp_array_destructor_hook(px); -} - -template void cbi_call_destructor_hook(sp_counted_base *, P const &, D const &, long) -{ -} + void operator delete( void * p ) + { + std::allocator().deallocate( static_cast(p), 1 ); + } #endif +#if defined(BOOST_SP_USE_QUICK_ALLOCATOR) + + void * operator new( std::size_t ) + { + return quick_allocator::alloc(); + } + + void operator delete( void * p ) + { + quick_allocator::dealloc( p ); + } + +#endif +}; + // // Borland's Codeguard trips up over the -Vx- option here: // @@ -98,8 +124,8 @@ private: P ptr; // copy constructor must not throw D del; // copy constructor must not throw - sp_counted_impl_pd(sp_counted_impl_pd const &); - sp_counted_impl_pd & operator= (sp_counted_impl_pd const &); + sp_counted_impl_pd( sp_counted_impl_pd const & ); + sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & ); typedef sp_counted_impl_pd this_type; @@ -107,50 +133,44 @@ public: // pre: d(p) must not throw - sp_counted_impl_pd(P p, D d): ptr(p), del(d) + sp_counted_impl_pd( P p, D d ): ptr(p), del(d) { -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - detail::cbi_call_constructor_hook(this, p, d, 0); -#endif } virtual void dispose() // nothrow { -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - detail::cbi_call_destructor_hook(this, ptr, del, 0); -#endif - del(ptr); + del( ptr ); } - virtual void * get_deleter(std::type_info const & ti) + virtual void * get_deleter( std::type_info const & ti ) { return ti == typeid(D)? &del: 0; } #if defined(BOOST_SP_USE_STD_ALLOCATOR) - void * operator new(std::size_t) + void * operator new( std::size_t ) { - return std::allocator().allocate(1, static_cast(0)); + return std::allocator().allocate( 1, static_cast(0) ); } - void operator delete(void * p) + void operator delete( void * p ) { - std::allocator().deallocate(static_cast(p), 1); + std::allocator().deallocate( static_cast(p), 1 ); } #endif #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) - void * operator new(std::size_t) + void * operator new( std::size_t ) { return quick_allocator::alloc(); } - void operator delete(void * p) + void operator delete( void * p ) { - quick_allocator::dealloc(p); + quick_allocator::dealloc( p ); } #endif diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 474bf4f..800e539 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -121,7 +121,7 @@ public: } template - explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter()) // Y must be complete + explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { detail::sp_enable_shared_from_this( pn, p, p ); } From 34953d8a458f8972004c5cfc07b2118a015073d1 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 18 Mar 2005 01:27:11 +0000 Subject: [PATCH 267/513] Split sp_counted_base into no threads (nt), win32 lock-free (w32) and pthreads (pt) [SVN r27729] --- include/boost/detail/sp_counted_base.hpp | 128 +++--------------- include/boost/detail/sp_counted_base_nt.hpp | 107 +++++++++++++++ include/boost/detail/sp_counted_base_pt.hpp | 135 +++++++++++++++++++ include/boost/detail/sp_counted_base_w32.hpp | 114 ++++++++++++++++ test/shared_ptr_mt_test.cpp | 10 +- 5 files changed, 372 insertions(+), 122 deletions(-) create mode 100644 include/boost/detail/sp_counted_base_nt.hpp create mode 100644 include/boost/detail/sp_counted_base_pt.hpp create mode 100644 include/boost/detail/sp_counted_base_w32.hpp diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index 194bc1f..0c61fdd 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -10,8 +10,7 @@ // // detail/sp_counted_base.hpp // -// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. -// Copyright 2004-2005 Peter Dimov +// Copyright 2005 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -19,125 +18,28 @@ // #include -#include -#include +#if defined( BOOST_SP_DISABLE_THREADS ) -namespace boost -{ +# include -namespace detail -{ +#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) -class sp_counted_base -{ -private: +# include - typedef detail::lightweight_mutex mutex_type; +#elif !defined( BOOST_HAS_THREADS ) - sp_counted_base( sp_counted_base const & ); - sp_counted_base & operator= ( sp_counted_base const & ); +# include - long use_count_; // #shared - long weak_count_; // #weak + (#shared != 0) +#elif defined( BOOST_HAS_PTHREADS ) + +# include + +#else + +// Use #define BOOST_DISABLE_THREADS to avoid the error +# error Unrecognized threading platform -#if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32) - mutable mutex_type mtx_; #endif -public: - - sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) - { - } - - virtual ~sp_counted_base() // nothrow - { - } - - // dispose() is called when use_count_ drops to zero, to release - // the resources managed by *this. - - virtual void dispose() = 0; // nothrow - - // destroy() is called when weak_count_ drops to zero. - - virtual void destroy() // nothrow - { - delete this; - } - - virtual void * get_deleter( std::type_info const & ti ) = 0; - - void add_ref_copy() - { -#if defined(BOOST_HAS_THREADS) - mutex_type::scoped_lock lock(mtx_); -#endif - ++use_count_; - } - - bool add_ref_lock() // true on success - { -#if defined(BOOST_HAS_THREADS) - mutex_type::scoped_lock lock(mtx_); -#endif - if( use_count_ == 0 ) return false; - ++use_count_; - return true; - } - - void release() // nothrow - { - { -#if defined(BOOST_HAS_THREADS) - mutex_type::scoped_lock lock(mtx_); -#endif - long new_use_count = --use_count_; - - if( new_use_count != 0 ) return; - } - - dispose(); - weak_release(); - } - - void weak_add_ref() // nothrow - { -#if defined(BOOST_HAS_THREADS) - mutex_type::scoped_lock lock(mtx_); -#endif - ++weak_count_; - } - - void weak_release() // nothrow - { - long new_weak_count; - - { -#if defined(BOOST_HAS_THREADS) - mutex_type::scoped_lock lock(mtx_); -#endif - new_weak_count = --weak_count_; - } - - if( new_weak_count == 0 ) - { - destroy(); - } - } - - long use_count() const // nothrow - { -#if defined(BOOST_HAS_THREADS) - mutex_type::scoped_lock lock(mtx_); -#endif - return use_count_; - } -}; - -} // namespace detail - -} // namespace boost - #endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_nt.hpp b/include/boost/detail/sp_counted_base_nt.hpp new file mode 100644 index 0000000..7a76f4a --- /dev/null +++ b/include/boost/detail/sp_counted_base_nt.hpp @@ -0,0 +1,107 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_nt.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + long use_count_; // #shared + long weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( std::type_info const & ti ) = 0; + + void add_ref_copy() + { + ++use_count_; + } + + bool add_ref_lock() // true on success + { + if( use_count_ == 0 ) return false; + ++use_count_; + return true; + } + + void release() // nothrow + { + if( --use_count_ == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + ++weak_count_; + } + + void weak_release() // nothrow + { + if( --weak_count_ == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return use_count_; + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_pt.hpp b/include/boost/detail/sp_counted_base_pt.hpp new file mode 100644 index 0000000..5fb4716 --- /dev/null +++ b/include/boost/detail/sp_counted_base_pt.hpp @@ -0,0 +1,135 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_pt.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include + +namespace boost +{ + +namespace detail +{ + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + long use_count_; // #shared + long weak_count_; // #weak + (#shared != 0) + + pthread_mutex_t m_; + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { +// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init + +#if defined(__hpux) && defined(_DECTHREADS_) + pthread_mutex_init( &m_, pthread_mutexattr_default ); +#else + pthread_mutex_init( &m_, 0 ); +#endif + } + + virtual ~sp_counted_base() // nothrow + { + pthread_mutex_destroy( &m_ ); + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( std::type_info const & ti ) = 0; + + void add_ref_copy() + { + pthread_mutex_lock( &m_ ); + ++use_count_; + pthread_mutex_unlock( &m_ ); + } + + bool add_ref_lock() // true on success + { + pthread_mutex_lock( &m_ ); + bool r = use_count_ == 0? false: ( ++use_count_, true ); + pthread_mutex_unlock( &m_ ); + return r; + } + + void release() // nothrow + { + pthread_mutex_lock( &m_ ); + long new_use_count = --use_count_; + pthread_mutex_unlock( &m_ ); + + if( new_use_count == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + pthread_mutex_lock( &m_ ); + ++weak_count_; + pthread_mutex_unlock( &m_ ); + } + + void weak_release() // nothrow + { + pthread_mutex_lock( &m_ ); + long new_weak_count = --weak_count_; + pthread_mutex_unlock( &m_ ); + + if( new_weak_count == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + pthread_mutex_lock( &m_ ); + long r = use_count_; + pthread_mutex_unlock( &m_ ); + + return r; + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_w32.hpp b/include/boost/detail/sp_counted_base_w32.hpp new file mode 100644 index 0000000..273a07f --- /dev/null +++ b/include/boost/detail/sp_counted_base_w32.hpp @@ -0,0 +1,114 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_w32.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-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) +// +// +// Lock-free algorithm by Alexander Terekhov +// + +#include +#include + +namespace boost +{ + +namespace detail +{ + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + long use_count_; // #shared + long weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( std::type_info const & ti ) = 0; + + void add_ref_copy() + { + BOOST_INTERLOCKED_INCREMENT( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + for( ;; ) + { + long tmp = static_cast< long const volatile& >( use_count_ ); + if( tmp == 0 ) return false; + if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true; + } + } + + void release() // nothrow + { + if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + BOOST_INTERLOCKED_INCREMENT( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( BOOST_INTERLOCKED_DECREMENT( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED diff --git a/test/shared_ptr_mt_test.cpp b/test/shared_ptr_mt_test.cpp index 3ac1f97..fa31894 100644 --- a/test/shared_ptr_mt_test.cpp +++ b/test/shared_ptr_mt_test.cpp @@ -143,19 +143,11 @@ void test(boost::shared_ptr const & pi) int const m = 16; // threads -#if defined(BOOST_LWM_USE_CRITICAL_SECTION) - char const * implementation = "critical section"; -#elif defined(BOOST_LWM_USE_PTHREADS) - char const * implementation = "pthread_mutex"; -#else - char const * implementation = "spinlock"; -#endif - int main() { using namespace std; // printf, clock_t, clock - printf("%s: %s, %d threads, %d iterations: ", title, implementation, m, n); + printf("%s: %d threads, %d iterations: ", title, m, n); boost::shared_ptr pi(new int(42)); From 14024e25987e33565ee55f2488cc3524daa4bf1d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 18 Mar 2005 13:04:43 +0000 Subject: [PATCH 268/513] Add a comment thanking Ben Hutchings for the #w+(#s!=0) formulation [SVN r27735] --- include/boost/detail/sp_counted_base_w32.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/boost/detail/sp_counted_base_w32.hpp b/include/boost/detail/sp_counted_base_w32.hpp index 273a07f..e84f06e 100644 --- a/include/boost/detail/sp_counted_base_w32.hpp +++ b/include/boost/detail/sp_counted_base_w32.hpp @@ -20,6 +20,9 @@ // // Lock-free algorithm by Alexander Terekhov // +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// #include #include From c6bf857f8bee764d4381b9ff0ddae7b633d3a968 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 18 Mar 2005 21:27:22 +0000 Subject: [PATCH 269/513] Made the pthread mutex mutable [SVN r27740] --- include/boost/detail/sp_counted_base_pt.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/sp_counted_base_pt.hpp b/include/boost/detail/sp_counted_base_pt.hpp index 5fb4716..191064f 100644 --- a/include/boost/detail/sp_counted_base_pt.hpp +++ b/include/boost/detail/sp_counted_base_pt.hpp @@ -37,7 +37,7 @@ private: long use_count_; // #shared long weak_count_; // #weak + (#shared != 0) - pthread_mutex_t m_; + mutable pthread_mutex_t m_; public: From adec862262044bd34e871108bedd76defad564ed Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 20 Mar 2005 15:40:30 +0000 Subject: [PATCH 270/513] atomic_count_test.cpp added. [SVN r27746] --- test/Jamfile | 1 + test/Jamfile.v2 | 1 + test/atomic_count_test.cpp | 40 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 test/atomic_count_test.cpp diff --git a/test/Jamfile b/test/Jamfile index 80ecab9..63e46cf 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -26,6 +26,7 @@ DEPENDS all : smart_ptr ; [ run get_deleter_test.cpp ] [ run intrusive_ptr_test.cpp ] [ run intrusive_ptr_test.cpp ] + [ run atomic_count_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] ; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 688cb2e..d4d7545 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -20,6 +20,7 @@ import testing ; [ run shared_from_this_test.cpp : : : gcc:-Wno-non-virtual-dtor ] [ run get_deleter_test.cpp ] [ run intrusive_ptr_test.cpp ] + [ run atomic_count_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] ; diff --git a/test/atomic_count_test.cpp b/test/atomic_count_test.cpp new file mode 100644 index 0000000..07e2e99 --- /dev/null +++ b/test/atomic_count_test.cpp @@ -0,0 +1,40 @@ +// +// astomic_count_test.cpp +// +// Copyright 2005 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include + +int main() +{ + boost::detail::atomic_count n( 4 ); + + BOOST_TEST( n == 4L ); + + ++n; + + BOOST_TEST( n == 5L ); + BOOST_TEST( --n != 0L ); + + boost::detail::atomic_count m( 0 ); + + BOOST_TEST( m == 0 ); + + ++m; + + BOOST_TEST( m == 1 ); + + ++m; + + BOOST_TEST( m == 2 ); + BOOST_TEST( --m != 0 ); + BOOST_TEST( --m == 0 ); + + return boost::report_errors(); +} From a67e505cf508343e6fe88edd02c3dc47c43795dd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 24 Mar 2005 21:29:29 +0000 Subject: [PATCH 271/513] Made use of detail/interlocked.hpp [SVN r27810] --- include/boost/detail/atomic_count_win32.hpp | 52 ++++----------------- 1 file changed, 9 insertions(+), 43 deletions(-) diff --git a/include/boost/detail/atomic_count_win32.hpp b/include/boost/detail/atomic_count_win32.hpp index 0dfa3f3..0de2537 100644 --- a/include/boost/detail/atomic_count_win32.hpp +++ b/include/boost/detail/atomic_count_win32.hpp @@ -10,16 +10,14 @@ // // boost/detail/atomic_count_win32.hpp // -// Copyright (c) 2001, 2002, 2003 Peter Dimov +// Copyright (c) 2001-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) // -#ifdef BOOST_USE_WINDOWS_H -# include -#endif +#include namespace boost { @@ -27,67 +25,35 @@ namespace boost namespace detail { -#ifndef BOOST_USE_WINDOWS_H - -#ifdef _WIN64 - -// Intel 6.0 on Win64 version, posted by Tim Fenders to [boost-users] - -extern "C" long_type __cdecl _InterlockedIncrement(long volatile *); -extern "C" long_type __cdecl _InterlockedDecrement(long volatile *); - -#pragma intrinsic(_InterlockedIncrement) -#pragma intrinsic(_InterlockedDecrement) - -inline long InterlockedIncrement(long volatile * lp) -{ - return _InterlockedIncrement(lp); -} - -inline long InterlockedDecrement(long volatile* lp) -{ - return _InterlockedDecrement(lp); -} - -#else // _WIN64 - -extern "C" __declspec(dllimport) long __stdcall InterlockedIncrement(long volatile *); -extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement(long volatile *); - -#endif // _WIN64 - -#endif // #ifndef BOOST_USE_WINDOWS_H - class atomic_count { public: - explicit atomic_count(long v): value_(v) + explicit atomic_count( long v ): value_( v ) { } long operator++() { - // Some older versions do not accept volatile - return InterlockedIncrement(const_cast(&value_)); + return BOOST_INTERLOCKED_INCREMENT( &value_ ); } long operator--() { - return InterlockedDecrement(const_cast(&value_)); + return BOOST_INTERLOCKED_DECREMENT( &value_ ); } operator long() const { - return value_; + return static_cast( value_ ); } private: - atomic_count(atomic_count const &); - atomic_count & operator=(atomic_count const &); + atomic_count( atomic_count const & ); + atomic_count & operator=( atomic_count const & ); - volatile long value_; + long value_; }; } // namespace detail From bfc0225cda130178efee9510dccea5a2265b5377 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 24 Mar 2005 21:55:24 +0000 Subject: [PATCH 272/513] Switched to atomic_count [SVN r27811] --- test/intrusive_ptr_test.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/intrusive_ptr_test.cpp b/test/intrusive_ptr_test.cpp index 51429ae..614a9cb 100644 --- a/test/intrusive_ptr_test.cpp +++ b/test/intrusive_ptr_test.cpp @@ -19,7 +19,7 @@ // // intrusive_ptr_test.cpp // -// Copyright (c) 2002, 2003 Peter Dimov +// Copyright (c) 2002-2005 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -41,7 +42,7 @@ class base { private: - long use_count_; + boost::detail::atomic_count use_count_; base(base const &); base & operator=(base const &); From 613e684b303a768fa8fe449e78489ce419db0f7e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 30 Mar 2005 22:06:25 +0000 Subject: [PATCH 273/513] shared_ptr_delete_fail.cpp added (reported by Dan Bikel) [SVN r27888] --- test/Jamfile | 3 ++- test/Jamfile.v2 | 14 ++------------ test/shared_ptr_delete_fail.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 13 deletions(-) create mode 100644 test/shared_ptr_delete_fail.cpp diff --git a/test/Jamfile b/test/Jamfile index 63e46cf..6e23b25 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -1,6 +1,6 @@ # Boost.SmartPtr Library test Jamfile # -# Copyright (c) 2003 Peter Dimov +# Copyright (c) 2003-2005 Peter Dimov # Copyright (c) 2003 Dave Abrahams # # Permission to copy, use, modify, sell and distribute this software @@ -28,6 +28,7 @@ DEPENDS all : smart_ptr ; [ run intrusive_ptr_test.cpp ] [ run atomic_count_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] + [ compile-fail shared_ptr_delete_fail.cpp ] ; # this one is too slow to run unless explicitly requested, and ALL diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d4d7545..128853e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,6 +1,6 @@ # Boost.SmartPtr Library test Jamfile # -# Copyright (c) 2003 Peter Dimov +# Copyright (c) 2003-2005 Peter Dimov # Copyright (c) 2003 Dave Abrahams # # Permission to copy, use, modify, sell and distribute this software @@ -22,16 +22,6 @@ import testing ; [ run intrusive_ptr_test.cpp ] [ run atomic_count_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] + [ compile-fail shared_ptr_delete_fail.cpp ] ; - - # this one is too slow to run unless explicitly requested, and ALL - # tests are run by default when this file is subincluded from - # boost/status, so it's guarded from that case. It will only be - # built from this directory when the targets "test" (all tests) or - # "shared_ptr_alloc_test" are requested. - #!!! - #if [ in-invocation-subdir ] - #{ - # run shared_ptr_alloc_test.cpp ; - #} } diff --git a/test/shared_ptr_delete_fail.cpp b/test/shared_ptr_delete_fail.cpp new file mode 100644 index 0000000..66cfafe --- /dev/null +++ b/test/shared_ptr_delete_fail.cpp @@ -0,0 +1,27 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// shared_ptr_delete_fail.cpp - a negative test for "delete sp;" +// +// Copyright 2005 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +int main() +{ + boost::shared_ptr p; + delete p; // must fail + return 0; +} From 3adfc7842ccd5435fe89cf086e73ecf48de411c5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 30 Mar 2005 22:52:54 +0000 Subject: [PATCH 274/513] Kill *_linux variants of atomic_count and lightweight_mutex. [SVN r27889] --- include/boost/detail/atomic_count.hpp | 7 +- include/boost/detail/atomic_count_linux.hpp | 69 ----------------- include/boost/detail/lightweight_mutex.hpp | 6 -- include/boost/detail/lwm_linux.hpp | 84 --------------------- 4 files changed, 1 insertion(+), 165 deletions(-) delete mode 100644 include/boost/detail/atomic_count_linux.hpp delete mode 100644 include/boost/detail/lwm_linux.hpp diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 3ad92b1..9985b2c 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -73,9 +73,6 @@ // are called driven by smart_ptr interface... // -// Note: atomic_count_linux.hpp has been disabled by default; see the -// comments inside for more info. - #include #ifndef BOOST_HAS_THREADS @@ -92,13 +89,11 @@ typedef long atomic_count; } -#elif defined(BOOST_USE_ASM_ATOMIC_H) -# include #elif defined(BOOST_AC_USE_PTHREADS) # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) # include -#elif defined(__GLIBCPP__) +#elif defined(__GLIBCPP__) || defined(__GLIBCXX__) # include #elif defined(BOOST_HAS_PTHREADS) # define BOOST_AC_USE_PTHREADS diff --git a/include/boost/detail/atomic_count_linux.hpp b/include/boost/detail/atomic_count_linux.hpp deleted file mode 100644 index e0b0dda..0000000 --- a/include/boost/detail/atomic_count_linux.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED -#define BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED - -// -// boost/detail/atomic_count_linux.hpp -// -// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -// -// This implementation uses . This is a kernel header; -// using kernel headers in a user program may cause a number of problems, -// and not all flavors of Linux provide the atomic instructions. -// -// This file is only provided because the performance of this implementation -// is significantly higher than the pthreads version. Use at your own risk -// (by defining BOOST_USE_ASM_ATOMIC_H.) -// - -#include - -namespace boost -{ - -namespace detail -{ - -class atomic_count -{ -public: - - explicit atomic_count(long v) - { - atomic_t init = ATOMIC_INIT(v); - value_ = init; - } - - void operator++() - { - atomic_inc(&value_); - } - - long operator--() - { - return !atomic_dec_and_test(&value_); - } - - operator long() const - { - return atomic_read(&value_); - } - -private: - - atomic_count(atomic_count const &); - atomic_count & operator=(atomic_count const &); - - atomic_t value_; -}; - -} // namespace detail - -} // namespace boost - -#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index 22e0f54..a99689e 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -49,10 +49,6 @@ // where a spinlock can be several orders of magnitude faster than a CRITICAL_SECTION. -// Note: lwm_linux.hpp has been disabled by default; see the comments -// inside for more info. - - #include // Note to implementors: if you write a platform-specific spinlock @@ -75,8 +71,6 @@ # else # include # endif -#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(BOOST_USE_ASM_ATOMIC_H) -# include #elif defined(BOOST_LWM_USE_CRITICAL_SECTION) # include #elif defined(BOOST_LWM_USE_PTHREADS) diff --git a/include/boost/detail/lwm_linux.hpp b/include/boost/detail/lwm_linux.hpp deleted file mode 100644 index f0cfb7f..0000000 --- a/include/boost/detail/lwm_linux.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED -#define BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED - -// -// boost/detail/lwm_linux.hpp -// -// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -// -// This implementation uses . This is a kernel header; -// using kernel headers in a user program may cause a number of problems, -// and not all flavors of Linux provide the atomic instructions. -// -// This file is only provided because the performance of this implementation -// is about 3.5 times higher than the pthreads version. Use at your own risk -// (by defining BOOST_USE_ASM_ATOMIC_H.) -// - -#include -#include - -namespace boost -{ - -namespace detail -{ - -class lightweight_mutex -{ -private: - - atomic_t a_; - - lightweight_mutex(lightweight_mutex const &); - lightweight_mutex & operator=(lightweight_mutex const &); - -public: - - lightweight_mutex() - { - atomic_t a = ATOMIC_INIT(1); - a_ = a; - } - - class scoped_lock; - friend class scoped_lock; - - class scoped_lock - { - private: - - lightweight_mutex & m_; - - scoped_lock(scoped_lock const &); - scoped_lock & operator=(scoped_lock const &); - - public: - - explicit scoped_lock(lightweight_mutex & m): m_(m) - { - while( !atomic_dec_and_test(&m_.a_) ) - { - atomic_inc(&m_.a_); - sched_yield(); - } - } - - ~scoped_lock() - { - atomic_inc(&m_.a_); - } - }; -}; - -} // namespace detail - -} // namespace boost - -#endif // #ifndef BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED From 8f2beee8e980bc0feda2a4c1673fbe7e0ce1d9fd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 1 Apr 2005 19:33:00 +0000 Subject: [PATCH 275/513] Link fixed. [SVN r27906] --- include/boost/detail/lightweight_mutex.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index a99689e..14aad0d 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -19,7 +19,9 @@ // typedef boost::detail::lightweight_mutex; // // boost::detail::lightweight_mutex meets a subset of the Mutex concept -// requirements: http://www.boost.org/libs/thread/doc/mutex_concept.html#Mutex +// requirements: +// +// http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex // // * Used by the smart pointer library // * Performance oriented From 0669d41076367ddd8429b50092a4141e100c57ae Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 2 Apr 2005 11:37:53 +0000 Subject: [PATCH 276/513] Atomics are in namespace __gnu_cxx for g++ 3.4+ [SVN r27929] --- include/boost/detail/atomic_count_gcc.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/boost/detail/atomic_count_gcc.hpp b/include/boost/detail/atomic_count_gcc.hpp index 9fa661f..1160e44 100644 --- a/include/boost/detail/atomic_count_gcc.hpp +++ b/include/boost/detail/atomic_count_gcc.hpp @@ -10,6 +10,7 @@ // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2002 Lars Gullik Bjĝnnes +// Copyright 2003-2005 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -24,6 +25,13 @@ namespace boost namespace detail { +#if defined(__GLIBCXX__) // g++ 3.4+ + +using __gnu_cxx::__atomic_add; +using __gnu_cxx::__exchange_and_add; + +#endif + class atomic_count { public: From 52587aaa055257c2448128149a9e67e95aaa6ebe Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 2 Apr 2005 12:00:14 +0000 Subject: [PATCH 277/513] Fixed shared_ptr_delete_fail failure on g++ 3.3 and below [SVN r27930] --- include/boost/shared_ptr.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 800e539..8d6196c 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -268,7 +268,10 @@ public: return px != 0; } -#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) +#elif \ + ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ + ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) + typedef T * (this_type::*unspecified_bool_type)() const; operator unspecified_bool_type() const // never throws From 13657c8bdaa164d4e704477cfc321a3ed637f0f5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 2 Apr 2005 12:51:17 +0000 Subject: [PATCH 278/513] lw_mutex_test added. [SVN r27931] --- test/Jamfile | 1 + test/Jamfile.v2 | 1 + test/atomic_count_test.cpp | 2 +- test/lw_mutex_test.cpp | 28 ++++++++++++++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 test/lw_mutex_test.cpp diff --git a/test/Jamfile b/test/Jamfile index 6e23b25..d4cb858 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -27,6 +27,7 @@ DEPENDS all : smart_ptr ; [ run intrusive_ptr_test.cpp ] [ run intrusive_ptr_test.cpp ] [ run atomic_count_test.cpp ] + [ run lw_mutex_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] [ compile-fail shared_ptr_delete_fail.cpp ] ; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 128853e..16c988e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -21,6 +21,7 @@ import testing ; [ run get_deleter_test.cpp ] [ run intrusive_ptr_test.cpp ] [ run atomic_count_test.cpp ] + [ run lw_mutex_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] [ compile-fail shared_ptr_delete_fail.cpp ] ; diff --git a/test/atomic_count_test.cpp b/test/atomic_count_test.cpp index 07e2e99..ecc24c0 100644 --- a/test/atomic_count_test.cpp +++ b/test/atomic_count_test.cpp @@ -1,5 +1,5 @@ // -// astomic_count_test.cpp +// atomic_count_test.cpp // // Copyright 2005 Peter Dimov // diff --git a/test/lw_mutex_test.cpp b/test/lw_mutex_test.cpp new file mode 100644 index 0000000..a47ac1e --- /dev/null +++ b/test/lw_mutex_test.cpp @@ -0,0 +1,28 @@ +// +// lw_mutex_test.cpp +// +// Copyright 2005 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +// Sanity check only + +boost::detail::lightweight_mutex m1; + +int main() +{ + boost::detail::lightweight_mutex::scoped_lock lock1( m1 ); + + boost::detail::lightweight_mutex m2; + boost::detail::lightweight_mutex m3; + + boost::detail::lightweight_mutex::scoped_lock lock2( m2 ); + boost::detail::lightweight_mutex::scoped_lock lock3( m3 ); + + return 0; +} From e0ee037e2d77bb994dcdef7105a1dafd663cf650 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 2 Apr 2005 13:12:28 +0000 Subject: [PATCH 279/513] Spinlocks removed. [SVN r27932] --- include/boost/detail/lightweight_mutex.hpp | 62 +---------- include/boost/detail/lwm_gcc.hpp | 77 ------------- include/boost/detail/lwm_irix.hpp | 73 ------------ include/boost/detail/lwm_win32.hpp | 122 --------------------- include/boost/detail/lwm_win32_nt.hpp | 63 ----------- 5 files changed, 5 insertions(+), 392 deletions(-) delete mode 100644 include/boost/detail/lwm_gcc.hpp delete mode 100644 include/boost/detail/lwm_irix.hpp delete mode 100644 include/boost/detail/lwm_win32.hpp delete mode 100644 include/boost/detail/lwm_win32_nt.hpp diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index 14aad0d..a0936cb 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -18,73 +18,21 @@ // // typedef boost::detail::lightweight_mutex; // -// boost::detail::lightweight_mutex meets a subset of the Mutex concept -// requirements: +// boost::detail::lightweight_mutex is a header-only implementation of +// a subset of the Mutex concept requirements: // // http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex // -// * Used by the smart pointer library -// * Performance oriented -// * Header-only implementation -// * Small memory footprint -// * Not a general purpose mutex, use boost::mutex, CRITICAL_SECTION or -// pthread_mutex instead. -// * Never spin in a tight lock/do-something/unlock loop, since -// lightweight_mutex does not guarantee fairness. -// * Never keep a lightweight_mutex locked for long periods. +// It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX. // -// The current implementation can use a pthread_mutex, a CRITICAL_SECTION, -// or a platform-specific spinlock. -// -// You can force a particular implementation by defining BOOST_LWM_USE_PTHREADS, -// BOOST_LWM_USE_CRITICAL_SECTION, or BOOST_LWM_USE_SPINLOCK. -// -// If neither macro has been defined, the default is to use a spinlock on Win32, -// and a pthread_mutex otherwise. -// -// Note that a spinlock is not a general synchronization primitive. In particular, -// it is not guaranteed to be a memory barrier, and it is possible to "livelock" -// if a lower-priority thread has acquired the spinlock but a higher-priority -// thread is spinning trying to acquire the same lock. -// -// For these reasons, spinlocks have been disabled by default except on Windows, -// where a spinlock can be several orders of magnitude faster than a CRITICAL_SECTION. - #include -// Note to implementors: if you write a platform-specific spinlock -// for a platform that supports pthreads, be sure to test its performance -// against the pthreads-based version using shared_ptr_timing_test.cpp and -// shared_ptr_mt_test.cpp. Custom versions are usually not worth the trouble -// _unless_ the performance gains are substantial. -// -// Be sure to compare against a "real" pthreads library; -// shared_ptr_timing_test.cpp will compile succesfully with a stub do-nothing -// pthreads library, since it doesn't create any threads. - -#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(BOOST_LWM_USE_CRITICAL_SECTION) && !defined(BOOST_LWM_USE_PTHREADS) -# define BOOST_LWM_WIN32 -#endif - #if !defined(BOOST_HAS_THREADS) -# if defined(BOOST_LWM_WIN32) -# include -# else -# include -# endif -#elif defined(BOOST_LWM_USE_CRITICAL_SECTION) +# include +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) # include -#elif defined(BOOST_LWM_USE_PTHREADS) -# include -#elif defined(BOOST_LWM_WIN32) -# include -#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(__sgi) -# include -#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(__GLIBCPP__) -# include #elif defined(BOOST_HAS_PTHREADS) -# define BOOST_LWM_USE_PTHREADS # include #else // Use #define BOOST_DISABLE_THREADS to avoid the error diff --git a/include/boost/detail/lwm_gcc.hpp b/include/boost/detail/lwm_gcc.hpp deleted file mode 100644 index e64ef7d..0000000 --- a/include/boost/detail/lwm_gcc.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef BOOST_DETAIL_LWM_GCC_HPP_INCLUDED -#define BOOST_DETAIL_LWM_GCC_HPP_INCLUDED - -// -// boost/detail/lwm_gcc.hpp -// -// lightweight_mutex for GNU libstdc++ v3 -// -// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html -// -// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. -// Copyright (c) 2002 Lars Gullik Bjĝnnes -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -#include -#include - -namespace boost -{ - -namespace detail -{ - -class lightweight_mutex -{ -private: - - _Atomic_word a_; - - lightweight_mutex(lightweight_mutex const &); - lightweight_mutex & operator=(lightweight_mutex const &); - -public: - - lightweight_mutex(): a_(0) - { - } - - class scoped_lock; - friend class scoped_lock; - - class scoped_lock - { - private: - - lightweight_mutex & m_; - - scoped_lock(scoped_lock const &); - scoped_lock & operator=(scoped_lock const &); - - public: - - explicit scoped_lock(lightweight_mutex & m): m_(m) - { - while( __exchange_and_add(&m_.a_, 1) ) - { - __atomic_add(&m_.a_, -1); - sched_yield(); - } - } - - ~scoped_lock() - { - __atomic_add(&m_.a_, -1); - } - }; -}; - -} // namespace detail - -} // namespace boost - -#endif // #ifndef BOOST_DETAIL_LWM_GCC_HPP_INCLUDED diff --git a/include/boost/detail/lwm_irix.hpp b/include/boost/detail/lwm_irix.hpp deleted file mode 100644 index cfc304b..0000000 --- a/include/boost/detail/lwm_irix.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED -#define BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED - -// -// boost/detail/lwm_irix.hpp -// -// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. -// Copyright (c) 2002 Dan Gohman -// -// Distributed under the 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 boost -{ - -namespace detail -{ - -class lightweight_mutex -{ -private: - - __uint32_t l_; - - lightweight_mutex(lightweight_mutex const &); - lightweight_mutex & operator=(lightweight_mutex const &); - -public: - - lightweight_mutex(): l_(0) - { - } - - class scoped_lock; - friend class scoped_lock; - - class scoped_lock - { - private: - - lightweight_mutex & m_; - - scoped_lock(scoped_lock const &); - scoped_lock & operator=(scoped_lock const &); - - public: - - explicit scoped_lock(lightweight_mutex & m): m_(m) - { - while( test_and_set32(&m_.l_, 1) ) - { - sched_yield(); - } - } - - ~scoped_lock() - { - m_.l_ = 0; - } - }; -}; - -} // namespace detail - -} // namespace boost - -#endif // #ifndef BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED diff --git a/include/boost/detail/lwm_win32.hpp b/include/boost/detail/lwm_win32.hpp deleted file mode 100644 index 8496ed8..0000000 --- a/include/boost/detail/lwm_win32.hpp +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED -#define BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED - -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -// -// boost/detail/lwm_win32.hpp -// -// Copyright (c) 2002, 2003 Peter Dimov -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -#ifdef BOOST_USE_WINDOWS_H -# include -#endif - -#ifdef __BORLANDC__ -# pragma warn -8027 // Functions containing while are not expanded inline -#endif - -namespace boost -{ - -namespace detail -{ - -#ifndef BOOST_USE_WINDOWS_H - -#ifdef _WIN64 - -// Intel 6.0 on Win64 version, posted by Tim Fenders to [boost-users] - -extern "C" long_type __cdecl _InterlockedExchange(long volatile *, long); - -#pragma intrinsic(_InterlockedExchange) - -inline long InterlockedExchange(long volatile* lp, long l) -{ - return _InterlockedExchange(lp, l); -} - -#else // _WIN64 - -extern "C" __declspec(dllimport) long __stdcall InterlockedExchange(long volatile *, long); - -#endif // _WIN64 - -extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long); - -#endif // #ifndef BOOST_USE_WINDOWS_H - -class lightweight_mutex -{ -private: - - long l_; - - lightweight_mutex(lightweight_mutex const &); - lightweight_mutex & operator=(lightweight_mutex const &); - -public: - - lightweight_mutex(): l_(0) - { - } - - class scoped_lock; - friend class scoped_lock; - - class scoped_lock - { - private: - - lightweight_mutex & m_; - - scoped_lock(scoped_lock const &); - scoped_lock & operator=(scoped_lock const &); - - public: - - explicit scoped_lock(lightweight_mutex & m): m_(m) - { - while( InterlockedExchange(&m_.l_, 1) ) - { - // Note: changed to Sleep(1) from Sleep(0). - // According to MSDN, Sleep(0) will never yield - // to a lower-priority thread, whereas Sleep(1) - // will. Performance seems not to be affected. - - Sleep(1); - } - } - - ~scoped_lock() - { - InterlockedExchange(&m_.l_, 0); - - // Note: adding a yield here will make - // the spinlock more fair and will increase the overall - // performance of some applications substantially in - // high contention situations, but will penalize the - // low contention / single thread case up to 5x - } - }; -}; - -} // namespace detail - -} // namespace boost - -#ifdef __BORLANDC__ -# pragma warn .8027 // Functions containing while are not expanded inline -#endif - -#endif // #ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED diff --git a/include/boost/detail/lwm_win32_nt.hpp b/include/boost/detail/lwm_win32_nt.hpp deleted file mode 100644 index 216e636..0000000 --- a/include/boost/detail/lwm_win32_nt.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef BOOST_DETAIL_LWM_WIN32_NT_HPP_INCLUDED -#define BOOST_DETAIL_LWM_WIN32_NT_HPP_INCLUDED - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -// -// boost/detail/lwm_win32_nt.hpp -// -// Copyright (c) 2002, 2003 Peter Dimov -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// "No threads" version of lwm_win32.hpp; binary compatible but no-op. -// - -namespace boost -{ - -namespace detail -{ - -class lightweight_mutex -{ -private: - - long l_; - - lightweight_mutex(lightweight_mutex const &); - lightweight_mutex & operator=(lightweight_mutex const &); - -public: - - lightweight_mutex(): l_(0) - { - } - - class scoped_lock; - friend class scoped_lock; - - class scoped_lock - { - private: - - scoped_lock(scoped_lock const &); - scoped_lock & operator=(scoped_lock const &); - - public: - - explicit scoped_lock(lightweight_mutex &) - { - } - }; -}; - -} // namespace detail - -} // namespace boost - -#endif // #ifndef BOOST_DETAIL_LWM_WIN32_NT_HPP_INCLUDED From 6046a099ba5d30a6baa79d6abef1f36c50f2c3b9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 2 Apr 2005 17:14:26 +0000 Subject: [PATCH 280/513] Added an implementation of sp_counted_base for g++/x86 [SVN r27933] --- .../boost/detail/sp_counted_base_gcc_x86.hpp | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 include/boost/detail/sp_counted_base_gcc_x86.hpp diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/detail/sp_counted_base_gcc_x86.hpp new file mode 100644 index 0000000..1792d40 --- /dev/null +++ b/include/boost/detail/sp_counted_base_gcc_x86.hpp @@ -0,0 +1,158 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_gcc_x86.hpp - g++ on 486+ or AMD64 +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-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) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include + +namespace boost +{ + +namespace detail +{ + +inline long atomic_exchange_and_add( long * pw, long dv ) +{ + // long r = *pw; + // *pw += dv; + // return r; + + long r; + + __asm__ __volatile__ + ( + "lock\n\t" + "xadd %1, %0": + "=m"( *pw ), "=r"( r ): // outputs (%0, %1) + "0"( *pw ), "1"( dv ): // inputs (%0, %1) + "memory", "cc" // clobbers + ); + + return r; +} + +inline long atomic_conditional_increment( long * pw ) +{ + // long r = *pw; + // if( r != 0 ) ++*pw; + // return r; + + long r; + + __asm__ __volatile__ + ( + "movl %0, %%eax\n\t" + "0:\n\t" + "test %%eax, %%eax\n\t" + "je 1f\n\t" + "leal 1(%%eax), %%ebx\n\t" + "lock\n\t" + "cmpxchgl %%ebx, %0\n\t" + "jne 0b\n\t" + "1:": + "=m"( *pw ), "=eax"( r ): // outputs (%0, %1) + "0"( *pw ): // input (%0) + "ebx", "memory", "cc" // clobbers + ); + + return r; +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + long use_count_; // #shared + long weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( std::type_info const & ti ) = 0; + + void add_ref_copy() + { + atomic_exchange_and_add( &use_count_, +1 ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_exchange_and_add( &use_count_, -1 ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_exchange_and_add( &weak_count_, +1 ); + } + + void weak_release() // nothrow + { + if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED From a0eb5daf750f851126d6dffb214475caae8757fc Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 2 Apr 2005 18:56:38 +0000 Subject: [PATCH 281/513] Mark eax as earlyclobber [SVN r27937] --- include/boost/detail/sp_counted_base_gcc_x86.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/detail/sp_counted_base_gcc_x86.hpp index 1792d40..235153e 100644 --- a/include/boost/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/detail/sp_counted_base_gcc_x86.hpp @@ -71,7 +71,7 @@ inline long atomic_conditional_increment( long * pw ) "cmpxchgl %%ebx, %0\n\t" "jne 0b\n\t" "1:": - "=m"( *pw ), "=eax"( r ): // outputs (%0, %1) + "=m"( *pw ), "=&eax"( r ): // outputs (%0, %1) "0"( *pw ): // input (%0) "ebx", "memory", "cc" // clobbers ); From 1942b647518522fa3ae3295f6a8e92a13137f31b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 2 Apr 2005 19:35:58 +0000 Subject: [PATCH 282/513] weak_ptr_mt_test.cpp added. [SVN r27938] --- test/weak_ptr_mt_test.cpp | 214 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 test/weak_ptr_mt_test.cpp diff --git a/test/weak_ptr_mt_test.cpp b/test/weak_ptr_mt_test.cpp new file mode 100644 index 0000000..442c591 --- /dev/null +++ b/test/weak_ptr_mt_test.cpp @@ -0,0 +1,214 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// weak_ptr_mt_test.cpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright 2005 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +// 'portable' thread framework + +class abstract_thread +{ +public: + + virtual ~abstract_thread() {} + virtual void run() = 0; +}; + +#if !defined(BOOST_HAS_PTHREADS) && defined(BOOST_HAS_WINTHREADS) + +char const * title = "Using Windows threads"; + +#include +#include + +typedef HANDLE pthread_t; + +unsigned __stdcall common_thread_routine(void * pv) +{ + abstract_thread * pt = static_cast(pv); + pt->run(); + delete pt; + return 0; +} + +int pthread_create(pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg) +{ + HANDLE h = (HANDLE)_beginthreadex(0, 0, start_routine, arg, 0, 0); + + if(h != 0) + { + *thread = h; + return 0; + } + else + { + return 1; // return errno; + } +} + +int pthread_join(pthread_t thread, void ** /*value_ptr*/) +{ + ::WaitForSingleObject(thread, INFINITE); + ::CloseHandle(thread); + return 0; +} + +#else + +char const * title = "Using POSIX threads"; + +#include + +extern "C" void * common_thread_routine(void * pv) +{ + abstract_thread * pt = static_cast(pv); + pt->run(); + delete pt; + return 0; +} + +#endif + +// + +template class thread: public abstract_thread +{ +public: + + explicit thread(F f): f_(f) + { + } + + void run() + { + f_(); + } + +private: + + F f_; +}; + +template pthread_t createThread(F f) +{ + std::auto_ptr p(new thread(f)); + + pthread_t r; + + if(pthread_create(&r, 0, common_thread_routine, p.get()) == 0) + { + p.release(); + return r; + } + + throw std::runtime_error("createThread failed."); +} + +// + +int const n = 16384; +int const k = 512; // vector size +int const m = 16; // threads + +void test( std::vector< boost::shared_ptr > & v ) +{ + using namespace std; // printf, rand + + std::vector< boost::weak_ptr > w( v.begin(), v.end() ); + + int s = 0, f = 0, r = 0; + + for( int i = 0; i < n; ++i ) + { + // randomly kill a pointer + + v[ rand() % k ].reset(); + ++s; + + for( int j = 0; j < k; ++j ) + { + if( boost::shared_ptr px = w[ j ].lock() ) + { + ++s; + + if( rand() & 4 ) + { + continue; + } + + // rebind anyway with prob. 50% for add_ref_lock() against weak_release() contention + ++f; + } + else + { + ++r; + } + + w[ j ] = v[ rand() % k ]; + } + } + + printf( "\n%d locks, %d forced rebinds, %d normal rebinds.", s, f, r ); +} + +int main() +{ + using namespace std; // printf, clock_t, clock + + printf("%s: %d threads, %d * %d iterations: ", title, m, n, k ); + + std::vector< boost::shared_ptr > v( k ); + + for( int i = 0; i < k; ++i ) + { + v[ i ].reset( new int( 0 ) ); + } + + clock_t t = clock(); + + pthread_t a[m]; + + for(int i = 0; i < m; ++i) + { + a[i] = createThread( boost::bind( test, v ) ); + } + + v.resize( 0 ); // kill original copies + + for(int j = 0; j < m; ++j) + { + pthread_join( a[j], 0 ); + } + + t = clock() - t; + + printf("\n\n%.3f seconds.\n", static_cast(t) / CLOCKS_PER_SEC); + + return 0; +} From f1a9148a439c7703f8f0c9c5ffa867b5f894baec Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Apr 2005 19:36:18 +0000 Subject: [PATCH 283/513] Constraints fixed for g++ 3.4, atomic_increment added [SVN r27958] --- .../boost/detail/sp_counted_base_gcc_x86.hpp | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/detail/sp_counted_base_gcc_x86.hpp index 235153e..18fd1e9 100644 --- a/include/boost/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/detail/sp_counted_base_gcc_x86.hpp @@ -45,13 +45,27 @@ inline long atomic_exchange_and_add( long * pw, long dv ) "lock\n\t" "xadd %1, %0": "=m"( *pw ), "=r"( r ): // outputs (%0, %1) - "0"( *pw ), "1"( dv ): // inputs (%0, %1) + "m"( *pw ), "1"( dv ): // inputs (%2, %3 == %1) "memory", "cc" // clobbers ); return r; } +inline void atomic_increment( long * pw ) +{ + //atomic_exchange_and_add( pw, 1 ); + + __asm__ + ( + "lock\n\t" + "incl %0": + "=m"( *pw ): // output (%0) + "m"( *pw ): // input (%1) + "cc" // clobbers + ); +} + inline long atomic_conditional_increment( long * pw ) { // long r = *pw; @@ -72,7 +86,7 @@ inline long atomic_conditional_increment( long * pw ) "jne 0b\n\t" "1:": "=m"( *pw ), "=&eax"( r ): // outputs (%0, %1) - "0"( *pw ): // input (%0) + "m"( *pw ): // input (%2) "ebx", "memory", "cc" // clobbers ); @@ -115,12 +129,12 @@ public: void add_ref_copy() { - atomic_exchange_and_add( &use_count_, +1 ); + atomic_increment( &use_count_ ); } bool add_ref_lock() // true on success { - return atomic_conditional_increment( &use_count_ ) != 0; + return atomic_conditional_increment( &use_count_ ) != 0; } void release() // nothrow @@ -134,7 +148,7 @@ public: void weak_add_ref() // nothrow { - atomic_exchange_and_add( &weak_count_, +1 ); + atomic_increment( &weak_count_ ); } void weak_release() // nothrow From d0656015ad0cd0894fe47eb61e9693c948732bb8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 4 Apr 2005 22:43:03 +0000 Subject: [PATCH 284/513] Fixed 'eax' to '%eax' in clobber; enabled gcc/x86 version [SVN r27965] --- include/boost/detail/sp_counted_base.hpp | 4 ++++ include/boost/detail/sp_counted_base_gcc_x86.hpp | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index 0c61fdd..2c9df7e 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -23,6 +23,10 @@ # include +#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) + +# include + #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) # include diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/detail/sp_counted_base_gcc_x86.hpp index 18fd1e9..54ab199 100644 --- a/include/boost/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/detail/sp_counted_base_gcc_x86.hpp @@ -85,9 +85,9 @@ inline long atomic_conditional_increment( long * pw ) "cmpxchgl %%ebx, %0\n\t" "jne 0b\n\t" "1:": - "=m"( *pw ), "=&eax"( r ): // outputs (%0, %1) + "=m"( *pw ), "=&%eax"( r ): // outputs (%0, %1) "m"( *pw ): // input (%2) - "ebx", "memory", "cc" // clobbers + "%ebx", "memory", "cc" // clobbers ); return r; From 319836fe7884af0956ab0684f131423043f80d40 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Apr 2005 16:04:36 +0000 Subject: [PATCH 285/513] Constraints fixed (again), volatile/memory clobber removed from conditional_inc [SVN r27983] --- include/boost/detail/sp_counted_base_gcc_x86.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/detail/sp_counted_base_gcc_x86.hpp index 54ab199..0dad672 100644 --- a/include/boost/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/detail/sp_counted_base_gcc_x86.hpp @@ -74,7 +74,7 @@ inline long atomic_conditional_increment( long * pw ) long r; - __asm__ __volatile__ + __asm__ ( "movl %0, %%eax\n\t" "0:\n\t" @@ -85,9 +85,9 @@ inline long atomic_conditional_increment( long * pw ) "cmpxchgl %%ebx, %0\n\t" "jne 0b\n\t" "1:": - "=m"( *pw ), "=&%eax"( r ): // outputs (%0, %1) + "=m"( *pw ), "=&a"( r ): // outputs (%0, %1) "m"( *pw ): // input (%2) - "%ebx", "memory", "cc" // clobbers + "ebx", "cc" // clobbers ); return r; From faa675ad6a598a2a2d56ea24243852c88aea93ca Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Apr 2005 20:29:15 +0000 Subject: [PATCH 286/513] PowerPC implementations added. [SVN r27986] --- .../boost/detail/sp_counted_base_cw_ppc.hpp | 154 +++++++++++++++ .../boost/detail/sp_counted_base_gcc_ppc.hpp | 181 ++++++++++++++++++ 2 files changed, 335 insertions(+) create mode 100644 include/boost/detail/sp_counted_base_cw_ppc.hpp create mode 100644 include/boost/detail/sp_counted_base_gcc_ppc.hpp diff --git a/include/boost/detail/sp_counted_base_cw_ppc.hpp b/include/boost/detail/sp_counted_base_cw_ppc.hpp new file mode 100644 index 0000000..f937d2a --- /dev/null +++ b/include/boost/detail/sp_counted_base_cw_ppc.hpp @@ -0,0 +1,154 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_cw_ppc.hpp - CodeWarrior on PowerPC +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-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) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include + +namespace boost +{ + +namespace detail +{ + +asm void atomic_increment( register long * pw ) +{ +loop: + + lwarx r4, 0, r3 + addi r4, r4, 1 + stwcx. r4, 0, r3 + bne- loop +} + +asm long atomic_decrement( register long * pw ) +{ + sync + +loop: + + lwarx r4, 0, r3 + addi r4, r4, -1 + stwcx. r4, 0, r3 + bne- loop + + mr r3, r4 + + isync +} + +asm long atomic_conditional_increment( register long * pw ) +{ +loop: + + lwarx r4, 0, r3 + cmpwi r4, 0 + beq done + + addi r4, r4, 1 + stwcx. r4, 0, r3 + bne- loop + +done: + + mr r3, r4 +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + long use_count_; // #shared + long weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( std::type_info const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_, -1 ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_, -1 ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/detail/sp_counted_base_gcc_ppc.hpp new file mode 100644 index 0000000..9a6b609 --- /dev/null +++ b/include/boost/detail/sp_counted_base_gcc_ppc.hpp @@ -0,0 +1,181 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_gcc_ppc.hpp - g++ on PowerPC +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-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) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include + +namespace boost +{ + +namespace detail +{ + +inline void atomic_increment( long * pw ) +{ + // ++*pw; + + long tmp; + + __asm__ + ( + "0:\n\t" + "lwarx %1, 0, %2\n\t" + "addi %1, %1, 1\n\t" + "stwcx. %1, 0, %2\n\t" + "bne- 0b": + + "=m"( *pw ), "=&b"( tmp ): + "r"( pw ): + "cc" + ); +} + +inline long atomic_decrement( long * pw ) +{ + // return --*pw; + + long rv; + + __asm__ __volatile__ + ( + "sync\n\t" + "0:\n\t" + "lwarx %1, 0, %2\n\t" + "addi %1, %1, -1\n\t" + "stwcx. %1, 0, %2\n\t" + "bne- 0b\n\t" + "isync": + + "=m"( *pw ), "=&b"( rv ): + "r"( pw ): + "memory", "cc" + ); + + return rv; +} + +inline long atomic_conditional_increment( long * pw ) +{ + // if( *pw != 0 ) ++*pw; + // return *pw; + + long rv; + + __asm__ + ( + "0:\n\t" + "lwarx %1, 0, %2\n\t" + "cmpwi %1, 0\n\t" + "beq 1f\n\t" + "addi %1, %1, 1\n\t" + "stwcx. %1, 0, %2\n\t" + "bne- 0b\n\t" + "1:": + + "=m"( *pw ), "=&b"( rv ): + "r"( pw ): + "cc" + ); + + return rv; +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + long use_count_; // #shared + long weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( std::type_info const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_, -1 ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_, -1 ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED From 361a7c3fd00e2ad99ad39b6bdd2bbe2bfb69492c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Apr 2005 20:39:56 +0000 Subject: [PATCH 287/513] PowerPC dispatch added, disabled for now. [SVN r27988] --- include/boost/detail/sp_counted_base.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index 2c9df7e..cdf57cd 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -27,6 +27,12 @@ # include +//#elif defined( __GNUC__ ) && defined( __powerpc__ ) +//# include + +//#elif defined( __MWERKS__ ) && defined( __POWERPC__ ) +//# include + #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) # include From 3ebc9b8f0b93eda01b918812c1df40c14b9139d2 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Wed, 6 Apr 2005 00:32:09 +0000 Subject: [PATCH 288/513] Remove extra argument to atomic_dcrement. [SVN r27994] --- include/boost/detail/sp_counted_base_cw_ppc.hpp | 4 ++-- include/boost/detail/sp_counted_base_gcc_ppc.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/detail/sp_counted_base_cw_ppc.hpp b/include/boost/detail/sp_counted_base_cw_ppc.hpp index f937d2a..b44178f 100644 --- a/include/boost/detail/sp_counted_base_cw_ppc.hpp +++ b/include/boost/detail/sp_counted_base_cw_ppc.hpp @@ -121,7 +121,7 @@ public: void release() // nothrow { - if( atomic_decrement( &use_count_, -1 ) == 0 ) + if( atomic_decrement( &use_count_ ) == 0 ) { dispose(); weak_release(); @@ -135,7 +135,7 @@ public: void weak_release() // nothrow { - if( atomic_decrement( &weak_count_, -1 ) == 0 ) + if( atomic_decrement( &weak_count_ ) == 0 ) { destroy(); } diff --git a/include/boost/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/detail/sp_counted_base_gcc_ppc.hpp index 9a6b609..80ef987 100644 --- a/include/boost/detail/sp_counted_base_gcc_ppc.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ppc.hpp @@ -148,7 +148,7 @@ public: void release() // nothrow { - if( atomic_decrement( &use_count_, -1 ) == 0 ) + if( atomic_decrement( &use_count_ ) == 0 ) { dispose(); weak_release(); @@ -162,7 +162,7 @@ public: void weak_release() // nothrow { - if( atomic_decrement( &weak_count_, -1 ) == 0 ) + if( atomic_decrement( &weak_count_ ) == 0 ) { destroy(); } From 13c128f98f9544d6f74515f636de65855f806ae0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 6 Apr 2005 08:15:48 +0000 Subject: [PATCH 289/513] Enabled PPC versions [SVN r28007] --- include/boost/detail/sp_counted_base.hpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index cdf57cd..1e6e58a 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -23,15 +23,21 @@ # include +#elif defined( BOOST_SP_USE_PTHREADS ) + +# include + #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) # include -//#elif defined( __GNUC__ ) && defined( __powerpc__ ) -//# include +#elif defined( __MWERKS__ ) && defined( __POWERPC__ ) -//#elif defined( __MWERKS__ ) && defined( __POWERPC__ ) -//# include +# include + +#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) ) + +# include #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) From 559056c8561d2078d75ea5d9587e382a0942c174 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 6 Apr 2005 13:34:41 +0000 Subject: [PATCH 290/513] x86-64 fixes: long -> int, lea -> mov+inc [SVN r28015] --- .../boost/detail/sp_counted_base_gcc_x86.hpp | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/detail/sp_counted_base_gcc_x86.hpp index 0dad672..51c7891 100644 --- a/include/boost/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/detail/sp_counted_base_gcc_x86.hpp @@ -32,13 +32,13 @@ namespace boost namespace detail { -inline long atomic_exchange_and_add( long * pw, long dv ) +inline int atomic_exchange_and_add( int * pw, int dv ) { - // long r = *pw; + // int r = *pw; // *pw += dv; // return r; - long r; + int r; __asm__ __volatile__ ( @@ -52,7 +52,7 @@ inline long atomic_exchange_and_add( long * pw, long dv ) return r; } -inline void atomic_increment( long * pw ) +inline void atomic_increment( int * pw ) { //atomic_exchange_and_add( pw, 1 ); @@ -66,13 +66,13 @@ inline void atomic_increment( long * pw ) ); } -inline long atomic_conditional_increment( long * pw ) +inline int atomic_conditional_increment( int * pw ) { - // long r = *pw; + // int r = *pw; // if( r != 0 ) ++*pw; // return r; - long r; + int r; __asm__ ( @@ -80,7 +80,8 @@ inline long atomic_conditional_increment( long * pw ) "0:\n\t" "test %%eax, %%eax\n\t" "je 1f\n\t" - "leal 1(%%eax), %%ebx\n\t" + "movl %%eax, %%ebx\n\t" + "incl %%ebx\n\t" "lock\n\t" "cmpxchgl %%ebx, %0\n\t" "jne 0b\n\t" @@ -100,8 +101,8 @@ private: sp_counted_base( sp_counted_base const & ); sp_counted_base & operator= ( sp_counted_base const & ); - long use_count_; // #shared - long weak_count_; // #weak + (#shared != 0) + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) public: From 6ab6b66601103378ce92ba576497cc5966b6f807 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 6 Apr 2005 13:40:34 +0000 Subject: [PATCH 291/513] One more long -> int fix [SVN r28016] --- include/boost/detail/sp_counted_base_gcc_x86.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/detail/sp_counted_base_gcc_x86.hpp index 51c7891..1c94d4f 100644 --- a/include/boost/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/detail/sp_counted_base_gcc_x86.hpp @@ -162,7 +162,7 @@ public: long use_count() const // nothrow { - return static_cast( use_count_ ); + return static_cast( use_count_ ); } }; From d24f6d3b97c8ba0ad5dcfcdb67b23b499129e6eb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 6 Apr 2005 14:12:40 +0000 Subject: [PATCH 292/513] Remove hardcoded ebx [SVN r28017] --- .../boost/detail/sp_counted_base_gcc_x86.hpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/detail/sp_counted_base_gcc_x86.hpp index 1c94d4f..0a8e189 100644 --- a/include/boost/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/detail/sp_counted_base_gcc_x86.hpp @@ -68,11 +68,11 @@ inline void atomic_increment( int * pw ) inline int atomic_conditional_increment( int * pw ) { - // int r = *pw; - // if( r != 0 ) ++*pw; - // return r; + // int rv = *pw; + // if( rv != 0 ) ++*pw; + // return rv; - int r; + int rv, tmp; __asm__ ( @@ -80,18 +80,18 @@ inline int atomic_conditional_increment( int * pw ) "0:\n\t" "test %%eax, %%eax\n\t" "je 1f\n\t" - "movl %%eax, %%ebx\n\t" - "incl %%ebx\n\t" + "movl %%eax, %2\n\t" + "incl %2\n\t" "lock\n\t" - "cmpxchgl %%ebx, %0\n\t" + "cmpxchgl %2, %0\n\t" "jne 0b\n\t" "1:": - "=m"( *pw ), "=&a"( r ): // outputs (%0, %1) - "m"( *pw ): // input (%2) - "ebx", "cc" // clobbers + "=m"( *pw ), "=&a"( rv ), "=&r"( tmp ): // outputs (%0, %1, %2) + "m"( *pw ): // input (%3) + "cc" // clobbers ); - return r; + return rv; } class sp_counted_base From 76722e125f84dca0fb38da71efdbb74f67827007 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 8 Apr 2005 10:39:28 +0000 Subject: [PATCH 293/513] Clear reservation for 970 (thanks to Miro Jurisic and Philip Koch) [SVN r28060] --- include/boost/detail/sp_counted_base_cw_ppc.hpp | 7 ++++--- include/boost/detail/sp_counted_base_gcc_ppc.hpp | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/boost/detail/sp_counted_base_cw_ppc.hpp b/include/boost/detail/sp_counted_base_cw_ppc.hpp index b44178f..b6fc68a 100644 --- a/include/boost/detail/sp_counted_base_cw_ppc.hpp +++ b/include/boost/detail/sp_counted_base_cw_ppc.hpp @@ -64,14 +64,15 @@ loop: lwarx r4, 0, r3 cmpwi r4, 0 - beq done + beq store addi r4, r4, 1 + +store: + stwcx. r4, 0, r3 bne- loop -done: - mr r3, r4 } diff --git a/include/boost/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/detail/sp_counted_base_gcc_ppc.hpp index 80ef987..29d323a 100644 --- a/include/boost/detail/sp_counted_base_gcc_ppc.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ppc.hpp @@ -90,9 +90,9 @@ inline long atomic_conditional_increment( long * pw ) "cmpwi %1, 0\n\t" "beq 1f\n\t" "addi %1, %1, 1\n\t" + "1:\n\t" "stwcx. %1, 0, %2\n\t" - "bne- 0b\n\t" - "1:": + "bne- 0b": "=m"( *pw ), "=&b"( rv ): "r"( pw ): From df1d8b27df606c8fc3822265f59870969d0b7504 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Mon, 11 Apr 2005 15:59:44 +0000 Subject: [PATCH 294/513] Make assembly functions inline to prevent multiple definitions. Required to change from function level assembly to regular functions with statement level assembly. [SVN r28133] --- include/boost/detail/sp_counted_base_cw_ppc.hpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/include/boost/detail/sp_counted_base_cw_ppc.hpp b/include/boost/detail/sp_counted_base_cw_ppc.hpp index b6fc68a..3452c9d 100644 --- a/include/boost/detail/sp_counted_base_cw_ppc.hpp +++ b/include/boost/detail/sp_counted_base_cw_ppc.hpp @@ -32,18 +32,23 @@ namespace boost namespace detail { -asm void atomic_increment( register long * pw ) +inline void atomic_increment( register long * pw ) { + asm + { loop: lwarx r4, 0, r3 addi r4, r4, 1 stwcx. r4, 0, r3 bne- loop + } } -asm long atomic_decrement( register long * pw ) +inline long atomic_decrement( register long * pw ) { + asm + { sync loop: @@ -56,10 +61,13 @@ loop: mr r3, r4 isync + } } -asm long atomic_conditional_increment( register long * pw ) +inline long atomic_conditional_increment( register long * pw ) { + asm + { loop: lwarx r4, 0, r3 @@ -74,6 +82,7 @@ store: bne- loop mr r3, r4 + } } class sp_counted_base From 4e4ec29fc983a04de0915fc39eeefef3edb47f82 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 19 Apr 2005 17:43:48 +0000 Subject: [PATCH 295/513] Added an implementation of sp_counted_base for g++/ia64. [SVN r28325] --- include/boost/detail/sp_counted_base.hpp | 4 + .../boost/detail/sp_counted_base_gcc_ia64.hpp | 157 ++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 include/boost/detail/sp_counted_base_gcc_ia64.hpp diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index 1e6e58a..48a4cfe 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -31,6 +31,10 @@ # include +#elif defined( __GNUC__ ) && defined( __ia64__ ) + +# include + #elif defined( __MWERKS__ ) && defined( __POWERPC__ ) # include diff --git a/include/boost/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/detail/sp_counted_base_gcc_ia64.hpp new file mode 100644 index 0000000..db54f6f --- /dev/null +++ b/include/boost/detail/sp_counted_base_gcc_ia64.hpp @@ -0,0 +1,157 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED + +// +// detail/sp_counted_base_gcc_ia64.hpp - g++ on IA64 +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// Copyright 2005 Ben Hutchings +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// +// Lock-free algorithm by Alexander Terekhov +// + +#include + +namespace boost +{ + +namespace detail +{ + +inline void atomic_increment( long * pw ) +{ + // ++*pw; + + long tmp; + + // No barrier is required here but fetchadd always has an acquire or + // release barrier associated with it. We choose release as it should be + // cheaper. + __asm__ ("fetchadd8.rel %0=[%2],1" : + "=r"(tmp), "=m"(*pw) : + "r"(pw)); +} + +inline long atomic_decrement( long * pw ) +{ + // return --*pw; + + long rv; + + __asm__ (" fetchadd8.rel %0=[%2],-1 ;; \n" + " cmp.eq p7,p0=1,%0 ;; \n" + "(p7) ld8.acq %0=[%2] " : + "=&r"(rv), "=m"(*pw) : + "r"(pw) : + "p7"); + + return rv; +} + +inline long atomic_conditional_increment( long * pw ) +{ + // if( *pw != 0 ) ++*pw; + // return *pw; + + long rv, tmp, tmp2; + + __asm__ ("0: ld8 %0=[%4] ;; \n" + " cmp.eq p7,p0=0,%0 ;; \n" + "(p7) br.cond.spnt 1f \n" + " mov ar.ccv=%0 \n" + " add %1=1,%0 ;; \n" + " cmpxchg8.acq %2=[%4],%1,ar.ccv ;; \n" + " cmp.ne p7,p0=%0,%2 ;; \n" + "(p7) br.cond.spnt 0b \n" + " mov %0=%1 ;; \n" + "1:" : + "=&r"(rv), "=&r"(tmp), "=&r"(tmp2), "=m"(*pw) : + "r"(pw) : + "ar.ccv", "p7"); + + return rv; +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + long use_count_; // #shared + long weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( std::type_info const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED From 8bacee46ebcc279f2b7bf228e9c7c8ca4d663d72 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Fri, 22 Apr 2005 16:36:38 +0000 Subject: [PATCH 296/513] Add x86 assembly implementation for use with CodeWarrior. Commented out initially until we can get more widespread testing for verification of performance improvements (if any). [SVN r28422] --- include/boost/detail/sp_counted_base.hpp | 4 + .../boost/detail/sp_counted_base_cw_x86.hpp | 158 ++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 include/boost/detail/sp_counted_base_cw_x86.hpp diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index 48a4cfe..6b18433 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -31,6 +31,10 @@ # include +//~ #elif defined( __MWERKS__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) + +//~ # include + #elif defined( __GNUC__ ) && defined( __ia64__ ) # include diff --git a/include/boost/detail/sp_counted_base_cw_x86.hpp b/include/boost/detail/sp_counted_base_cw_x86.hpp new file mode 100644 index 0000000..63c9fa2 --- /dev/null +++ b/include/boost/detail/sp_counted_base_cw_x86.hpp @@ -0,0 +1,158 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_cw_x86.hpp - CodeWarrion on 486+ +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// Copyright 2005 Rene Rivera +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include + +namespace boost +{ + +namespace detail +{ + +inline int atomic_exchange_and_add( int * pw, int dv ) +{ + // int r = *pw; + // *pw += dv; + // return r; + + asm + { + mov esi, [pw] + mov eax, dv + lock xadd dword ptr [esi], eax + } +} + +inline void atomic_increment( int * pw ) +{ + //atomic_exchange_and_add( pw, 1 ); + + asm + { + mov esi, [pw] + lock inc dword ptr [esi] + } +} + +inline int atomic_conditional_increment( int * pw ) +{ + // int rv = *pw; + // if( rv != 0 ) ++*pw; + // return rv; + + asm + { + mov esi, [pw] + mov eax, dword ptr [esi] + L0: + test eax, eax + je L1 + mov ebx, eax + inc ebx + lock cmpxchg dword ptr [esi], ebx + jne L0 + L1: + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( std::type_info const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_exchange_and_add( &use_count_, -1 ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED From 357f57d1473420ad5080f3abc695a6cc39e7b6e7 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 26 Apr 2005 11:08:28 +0000 Subject: [PATCH 297/513] Added a weak_ptr timing test. [SVN r28483] --- test/weak_ptr_timing_test.cpp | 85 +++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 test/weak_ptr_timing_test.cpp diff --git a/test/weak_ptr_timing_test.cpp b/test/weak_ptr_timing_test.cpp new file mode 100644 index 0000000..1c24b0a --- /dev/null +++ b/test/weak_ptr_timing_test.cpp @@ -0,0 +1,85 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// weak_ptr_timing_test.cpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright 2005 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include + +#include +#include +#include +#include + +// + +int const n = 29000; +int const k = 2048; + +void test( std::vector< boost::shared_ptr > & v ) +{ + using namespace std; // printf, rand + + std::vector< boost::weak_ptr > w( v.begin(), v.end() ); + + int s = 0, r = 0; + + for( int i = 0; i < n; ++i ) + { + // randomly kill a pointer + + v[ rand() % k ].reset(); + + for( int j = 0; j < k; ++j ) + { + if( boost::shared_ptr px = w[ j ].lock() ) + { + ++s; + } + else + { + ++r; + w[ j ] = v[ rand() % k ]; + } + } + } + + printf( "\n%d locks, %d rebinds.", s, r ); +} + +int main() +{ + using namespace std; // printf, clock_t, clock + + std::vector< boost::shared_ptr > v( k ); + + for( int i = 0; i < k; ++i ) + { + v[ i ].reset( new int( 0 ) ); + } + + clock_t t = clock(); + + test( v ); + + t = clock() - t; + + printf( "\n\n%.3f seconds.\n", static_cast( t ) / CLOCKS_PER_SEC ); + + return 0; +} From 880c2e1062622e10362df5d0cd776df9d17f3f6e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 18 May 2005 20:10:01 +0000 Subject: [PATCH 298/513] Detabified. [SVN r29039] --- .../boost/detail/sp_counted_base_gcc_ia64.hpp | 28 +++++++++---------- include/boost/detail/sp_counted_base_nt.hpp | 8 +++--- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/include/boost/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/detail/sp_counted_base_gcc_ia64.hpp index db54f6f..8016c8d 100644 --- a/include/boost/detail/sp_counted_base_gcc_ia64.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ia64.hpp @@ -34,8 +34,8 @@ inline void atomic_increment( long * pw ) // release barrier associated with it. We choose release as it should be // cheaper. __asm__ ("fetchadd8.rel %0=[%2],1" : - "=r"(tmp), "=m"(*pw) : - "r"(pw)); + "=r"(tmp), "=m"(*pw) : + "r"(pw)); } inline long atomic_decrement( long * pw ) @@ -62,18 +62,18 @@ inline long atomic_conditional_increment( long * pw ) long rv, tmp, tmp2; __asm__ ("0: ld8 %0=[%4] ;; \n" - " cmp.eq p7,p0=0,%0 ;; \n" - "(p7) br.cond.spnt 1f \n" - " mov ar.ccv=%0 \n" - " add %1=1,%0 ;; \n" - " cmpxchg8.acq %2=[%4],%1,ar.ccv ;; \n" - " cmp.ne p7,p0=%0,%2 ;; \n" - "(p7) br.cond.spnt 0b \n" - " mov %0=%1 ;; \n" - "1:" : - "=&r"(rv), "=&r"(tmp), "=&r"(tmp2), "=m"(*pw) : - "r"(pw) : - "ar.ccv", "p7"); + " cmp.eq p7,p0=0,%0 ;; \n" + "(p7) br.cond.spnt 1f \n" + " mov ar.ccv=%0 \n" + " add %1=1,%0 ;; \n" + " cmpxchg8.acq %2=[%4],%1,ar.ccv ;; \n" + " cmp.ne p7,p0=%0,%2 ;; \n" + "(p7) br.cond.spnt 0b \n" + " mov %0=%1 ;; \n" + "1:" : + "=&r"(rv), "=&r"(tmp), "=&r"(tmp2), "=m"(*pw) : + "r"(pw) : + "ar.ccv", "p7"); return rv; } diff --git a/include/boost/detail/sp_counted_base_nt.hpp b/include/boost/detail/sp_counted_base_nt.hpp index 7a76f4a..4a4401d 100644 --- a/include/boost/detail/sp_counted_base_nt.hpp +++ b/include/boost/detail/sp_counted_base_nt.hpp @@ -75,10 +75,10 @@ public: void release() // nothrow { if( --use_count_ == 0 ) - { - dispose(); - weak_release(); - } + { + dispose(); + weak_release(); + } } void weak_add_ref() // nothrow From 24c23b8064c02f4b5df24c62430c77282dfd327a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20M=2E=20L=C3=B3pez=20Mu=C3=B1oz?= Date: Tue, 24 May 2005 12:11:35 +0000 Subject: [PATCH 299/513] disabled asm implementation for ICC/IA64 [SVN r29166] --- include/boost/detail/sp_counted_base.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index 6b18433..bc170ca 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -35,7 +35,7 @@ //~ # include -#elif defined( __GNUC__ ) && defined( __ia64__ ) +#elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER ) # include From 675d09723a21c438c7d79ed309d0c738cc8116e4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 12 Jun 2005 12:58:17 +0000 Subject: [PATCH 300/513] Lock-free implementation documented, minor changes to align with TR1 [SVN r29536] --- shared_ptr.htm | 98 ++++++++++++++++++++++++-------------------------- weak_ptr.htm | 8 ++--- 2 files changed, 51 insertions(+), 55 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 3422166..0b83d1f 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -20,7 +20,7 @@ Programming Techniques

    Introduction

    The shared_ptr class template stores a pointer to a dynamically allocated - object, typically with a C++ new-expression . The object pointed to is + 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 @@ -47,6 +47,13 @@ to shared_ptr<T const>, to shared_ptr<U> where U is an accessible base of T, and to shared_ptr<void>.

    +

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

    +

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

    +

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

    Best Practices

    A simple guideline that nearly eliminates the possibility of memory leaks is: always use a named smart pointer variable to hold the result of new. @@ -154,15 +161,6 @@ void bad() template<class D, class T> D * get_deleter(shared_ptr<T> const & p); } -

    [It might be convenient to relax the requirements on shared_ptr's - signature, allowing an additional, defaulted, template parameter; the parameter - can encode the threading model, for example. This would help in detecting - possible ODR violations.

    -

    On the other hand, using shared_ptr as an argument to a - template template parameter requires an exact signature match. Metaprogramming - experts tend to deemphasize template template parameters as they are too - inflexible, but the alternative is typically an std::allocator::rebind-type - "hack".]

    Members

    element_type

    typedef T element_type;
    @@ -174,22 +172,12 @@ void bad()

    Effects: Constructs an empty shared_ptr. Empty shared_ptr objects have an unspecified use_count.

    -

    Postconditions: get() == 0.

    +

    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 - allocate memory.

    -

    There are two possible implementations, one stores 0 as a pointer to the - reference count, the other uses a single statically allocated count for all - default-constructed shared_ptrs. The second option is - difficult to achieve in the current header-only reference implementation due to - thread safety issues and initialization order, but it should not be precluded - by the specification. That's why the use_count() has been left unspecified.

    -

    A future release may enable shared_ptr construction from a - literal zero, for consistency with built-in pointers. It is not clear yet - whether this constructor should be left implicit, enabling 0 to - be used as a shorthand for shared_ptr<T>().]

    + allocate memory.]

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

    Requirements: p must be convertible to T *. Y @@ -198,8 +186,8 @@ void bad()

    Effects: Constructs a shared_ptr that owns the pointer p.

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

    -

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

    +

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

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

    Notes: p must be a pointer to an object that was @@ -226,8 +214,8 @@ void bad()

    Effects: Constructs a shared_ptr that owns the pointer p and the deleter d.

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

    -

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

    +

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

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

    Notes: When the the time comes to delete the object pointed to by p, the stored copy of d is invoked with the stored copy of p @@ -245,17 +233,10 @@ void bad()

    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.

    -

    Pass by reference is problematic since (1) pass by value conveniently changes - functions (function references) to function pointers (this has to be performed - manually otherwise and some compilers may not be able to do it) and (2) const - references don't currently (per the standard) bind to functions. This can be - solved (I think) but it requires an overload set that breaks on many compilers - due to 14.5.5.2 problems (and of course it will break on compilers that don't - do partial ordering at all.)

    -

    The main problem with pass by reference, though, 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 +

    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
    @@ -280,8 +261,8 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r); // never

    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 exception when - a resource other than memory could not be obtained.

    +

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

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

    @@ -325,12 +306,6 @@ q = p;

    both assignments may be no-ops.

    -

    [Some experts consider the note to be redundant, as it appears to essentially - mirror the "as if" rule. However, experience suggests that when C++ code is - used to describe effects, it is often misinterpreted as required - implementation. In addition, it is not entirely clear whether the "as if" rule - actually applies here, so it's better to be explicit about the possible - optimizations.]

    reset

    void reset(); // never throws
    @@ -602,11 +577,32 @@ p3.reset(new int(1)); // thread B p3.reset(new int(2)); // undefined, multiple writes -

    shared_ptr uses Boost.Config - to detect whether the implementation supports threads. If your program is - single-threaded, but your platform is autodetected by Boost.Config - as supporting multiple threads, #define BOOST_DISABLE_THREADS to - eliminate the thread safety overhead.

    +

     

    +

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

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

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

    +

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

    +

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

    Frequently Asked Questions

    Q. There are several variations of shared pointers, with different tradeoffs; why does the smart pointer library supply only a single @@ -691,7 +687,7 @@ int * p = a.release();

    $Date$

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

    diff --git a/weak_ptr.htm b/weak_ptr.htm index e5ccc11..3fcdcb7 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -145,9 +145,9 @@ template<class Y> weak_ptr & operator=(shared_ptr<Y> const &

    use_count

    long use_count() const;
    -

    Returns: if *this is empty, an unspecified - nonnegative value; otherwise, the number of shared_ptr objects that share - ownership with *this.

    +

    Returns: 0 if *this is empty; otherwise, + the number of shared_ptr objects that share ownership + with *this.

    Throws: nothing.

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

    @@ -236,7 +236,7 @@ public:

    $Date$

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

    From 8d2aeea3a87f84ee9dfb9b4bdd07ac16d429a712 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 30 Jun 2005 21:49:40 +0000 Subject: [PATCH 301/513] Moved warning 8027 suppression above the #includes [SVN r29852] --- include/boost/detail/shared_count.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 133e54e..49aca85 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -18,6 +18,10 @@ // http://www.boost.org/LICENSE_1_0.txt) // +#ifdef __BORLANDC__ +# pragma warn -8027 // Functions containing try are not expanded inline +#endif + #include #include #include @@ -30,10 +34,6 @@ #include // std::bad_alloc #include // std::type_info in get_deleter -#ifdef __BORLANDC__ -# pragma warn -8027 // Functions containing try are not expanded inline -#endif - namespace boost { From eb3d3464db44072655f6a01f8540d782b51a1e0d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 18 Jul 2005 20:33:59 +0000 Subject: [PATCH 302/513] operator< documenation fix. [SVN r30166] --- shared_ptr.htm | 28 ++++++++++++++-------------- weak_ptr.htm | 7 +++---- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 0b83d1f..fb15da1 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -50,8 +50,8 @@

    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)

    +

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

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

    Best Practices

    @@ -402,7 +402,7 @@ q = p;
  • under the equivalence relation defined by operator<, !(a < b) && !(b < a), two shared_ptr instances - are equivalent if and only if they share ownership.
  • + are equivalent if and only if they share ownership or are both empty.

    Throws: nothing.

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

    @@ -582,27 +582,27 @@ p3.reset(new int(2)); // undefined, multiple writes implementation on the following platforms:

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

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

    -

    (Defining BOOST_SP_DISABLE_THREADS in some, but not - all, 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.)

    +

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

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

    + lock-free platform-specific implementation and fall back to the generic pthread_mutex_t-based + code.

    Frequently Asked Questions

    Q. There are several variations of shared pointers, with different tradeoffs; why does the smart pointer library supply only a single diff --git a/weak_ptr.htm b/weak_ptr.htm index 3fcdcb7..e214d4a 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -145,9 +145,8 @@ template<class Y> weak_ptr & operator=(shared_ptr<Y> const &

    use_count

    long use_count() const;
    -

    Returns: 0 if *this is empty; otherwise, - the number of shared_ptr objects that share ownership - with *this.

    +

    Returns: 0 if *this is empty; otherwise, the + number of shared_ptr objects that share ownership with *this.

    Throws: nothing.

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

    @@ -189,7 +188,7 @@ template<class Y> weak_ptr & operator=(shared_ptr<Y> const &
  • under the equivalence relation defined by operator<, !(a < b) && !(b < a), two weak_ptr instances - are equivalent if and only if they share ownership.
  • + are equivalent if and only if they share ownership or are both empty.

    Throws: nothing.

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

    From 0cee41d47e1ae5ec0f97d6aa3f7d54f1e8513f5c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 21 Jul 2005 00:51:38 +0000 Subject: [PATCH 303/513] Minor documentation fix. [SVN r30190] --- shared_ptr.htm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index fb15da1..1eaf661 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -170,8 +170,7 @@ void bad()

    constructors

    shared_ptr(); // never throws
    -

    Effects: Constructs an empty shared_ptr. Empty - shared_ptr objects have an unspecified use_count.

    +

    Effects: Constructs an empty shared_ptr.

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

    Throws: nothing.

    From afc17037deeba03917c808419ae66bfc0ce3ee5e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 22 Jul 2005 23:40:53 +0000 Subject: [PATCH 304/513] Another minor documentation fix. [SVN r30224] --- shared_ptr.htm | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 1eaf661..5b7f47b 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -248,9 +248,8 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r); // never
    template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
    -

    Effects: If r is empty, constructs an empty shared_ptr; - otherwise, constructs a shared_ptr that shares ownership with r - and stores a copy of the pointer stored in r.

    +

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

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

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

    Exception safety: If an exception is thrown, the constructor has no From 0db2a884032bf06400b2d70c1d2f1069bb43dcd4 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 12 Aug 2005 13:02:37 +0000 Subject: [PATCH 305/513] Merged from 1.33.0 release [SVN r30540] --- shared_ptr.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 5b7f47b..26fd78e 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -621,7 +621,7 @@ p3.reset(new int(2)); // undefined, multiple writes 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 + based smart pointers should read Modern C++ Design by Andrei Alexandrescu.)

    Q. I am not convinced. Default parameters can be used where appropriate From 6b3f96154288e62ddbc5f122cf1a29e4e3044dbd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 15 Aug 2005 19:44:15 +0000 Subject: [PATCH 306/513] Removed explicit register use (thanks to Howard Hinnant) [SVN r30585] --- .../boost/detail/sp_counted_base_cw_ppc.hpp | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/include/boost/detail/sp_counted_base_cw_ppc.hpp b/include/boost/detail/sp_counted_base_cw_ppc.hpp index 3452c9d..c56a562 100644 --- a/include/boost/detail/sp_counted_base_cw_ppc.hpp +++ b/include/boost/detail/sp_counted_base_cw_ppc.hpp @@ -34,55 +34,61 @@ namespace detail inline void atomic_increment( register long * pw ) { + register int a; + asm { loop: - lwarx r4, 0, r3 - addi r4, r4, 1 - stwcx. r4, 0, r3 + lwarx a, 0, pw + addi a, a, 1 + stwcx. a, 0, pw bne- loop } } inline long atomic_decrement( register long * pw ) { + register int a; + asm { sync loop: - lwarx r4, 0, r3 - addi r4, r4, -1 - stwcx. r4, 0, r3 + lwarx a, 0, pw + addi a, a, -1 + stwcx. a, 0, pw bne- loop - mr r3, r4 - isync } + + return a; } inline long atomic_conditional_increment( register long * pw ) { + register int a; + asm { loop: - lwarx r4, 0, r3 - cmpwi r4, 0 + lwarx a, 0, pw + cmpwi a, 0 beq store - addi r4, r4, 1 + addi a, a, 1 store: - stwcx. r4, 0, r3 + stwcx. a, 0, pw bne- loop - - mr r3, r4 } + + return a; } class sp_counted_base From 08f517b5b0e3f73c7a92be5aec3868fb7434378e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 23 Aug 2005 21:32:42 +0000 Subject: [PATCH 307/513] Switched to 'int' because 'long' is 64 bits on PPC64 [SVN r30641] --- .../boost/detail/sp_counted_base_gcc_ppc.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/boost/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/detail/sp_counted_base_gcc_ppc.hpp index 29d323a..fc2925e 100644 --- a/include/boost/detail/sp_counted_base_gcc_ppc.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ppc.hpp @@ -32,11 +32,11 @@ namespace boost namespace detail { -inline void atomic_increment( long * pw ) +inline void atomic_increment( int * pw ) { // ++*pw; - long tmp; + int tmp; __asm__ ( @@ -52,11 +52,11 @@ inline void atomic_increment( long * pw ) ); } -inline long atomic_decrement( long * pw ) +inline int atomic_decrement( int * pw ) { // return --*pw; - long rv; + int rv; __asm__ __volatile__ ( @@ -76,12 +76,12 @@ inline long atomic_decrement( long * pw ) return rv; } -inline long atomic_conditional_increment( long * pw ) +inline int atomic_conditional_increment( int * pw ) { // if( *pw != 0 ) ++*pw; // return *pw; - long rv; + int rv; __asm__ ( @@ -109,8 +109,8 @@ private: sp_counted_base( sp_counted_base const & ); sp_counted_base & operator= ( sp_counted_base const & ); - long use_count_; // #shared - long weak_count_; // #weak + (#shared != 0) + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) public: @@ -170,7 +170,7 @@ public: long use_count() const // nothrow { - return static_cast( use_count_ ); + return static_cast( use_count_ ); } }; From ff7e0276487082d5e63f84b1fb9bdaf08646d26b Mon Sep 17 00:00:00 2001 From: John Maddock Date: Thu, 25 Aug 2005 16:27:28 +0000 Subject: [PATCH 308/513] Large patch from Ulrich Eckhardt to fix support for EVC++ 4. [SVN r30670] --- include/boost/intrusive_ptr.hpp | 2 +- include/boost/shared_ptr.hpp | 4 ++-- include/boost/weak_ptr.hpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 7efbade..dd8cc39 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -249,7 +249,7 @@ template std::ostream & operator<< (std::ostream & os, intrusive_ptr #else -# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT) +# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL using std::basic_ostream; template basic_ostream & operator<< (basic_ostream & os, intrusive_ptr const & p) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 8d6196c..baa374b 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -203,7 +203,7 @@ public: #endif -#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) template shared_ptr & operator=(shared_ptr const & r) // never throws @@ -429,7 +429,7 @@ template std::ostream & operator<< (std::ostream & os, shared_ptr co #else -# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT) +# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL using std::basic_ostream; template basic_ostream & operator<< (basic_ostream & os, shared_ptr const & p) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index c238500..a4073fc 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -69,7 +69,7 @@ public: { } -#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) template weak_ptr & operator=(weak_ptr const & r) // never throws From c6a4e93a059e74268e5eb7c26dfa90d36947f197 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 6 Sep 2005 03:28:01 +0000 Subject: [PATCH 309/513] Qualify detail references [SVN r30824] --- include/boost/shared_ptr.hpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index baa374b..f78f0fe 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -114,7 +114,7 @@ public: typedef T element_type; typedef T value_type; typedef T * pointer; - typedef typename detail::shared_ptr_traits::reference reference; + typedef typename boost::detail::shared_ptr_traits::reference reference; shared_ptr(): px(0), pn() // never throws in 1.30+ { @@ -123,7 +123,7 @@ public: template explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { - detail::sp_enable_shared_from_this( pn, p, p ); + boost::detail::sp_enable_shared_from_this( pn, p, p ); } // @@ -134,7 +134,7 @@ public: template shared_ptr(Y * p, D d): px(p), pn(p, d) { - detail::sp_enable_shared_from_this( pn, p, p ); + boost::detail::sp_enable_shared_from_this( pn, p, p ); } // generated copy constructor, assignment, destructor are fine... @@ -164,26 +164,26 @@ public: } template - shared_ptr(shared_ptr const & r, detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) + shared_ptr(shared_ptr const & r, boost::detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) { } template - shared_ptr(shared_ptr const & r, detail::const_cast_tag): px(const_cast(r.px)), pn(r.pn) + shared_ptr(shared_ptr const & r, boost::detail::const_cast_tag): px(const_cast(r.px)), pn(r.pn) { } template - shared_ptr(shared_ptr const & r, detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) + shared_ptr(shared_ptr const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) { if(px == 0) // need to allocate new counter -- the cast failed { - pn = detail::shared_count(); + pn = boost::detail::shared_count(); } } template - shared_ptr(shared_ptr const & r, detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) + shared_ptr(shared_ptr const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) { if(px == 0) { @@ -197,8 +197,8 @@ public: explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn() { Y * tmp = r.get(); - pn = detail::shared_count(r); - detail::sp_enable_shared_from_this( pn, tmp, tmp ); + pn = boost::detail::shared_count(r); + boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); } #endif @@ -337,7 +337,7 @@ private: #endif T * px; // contained pointer - detail::shared_count pn; // reference counter + boost::detail::shared_count pn; // reference counter }; // shared_ptr @@ -374,34 +374,34 @@ template inline void swap(shared_ptr & a, shared_ptr & b) template shared_ptr static_pointer_cast(shared_ptr const & r) { - return shared_ptr(r, detail::static_cast_tag()); + return shared_ptr(r, boost::detail::static_cast_tag()); } template shared_ptr const_pointer_cast(shared_ptr const & r) { - return shared_ptr(r, detail::const_cast_tag()); + return shared_ptr(r, boost::detail::const_cast_tag()); } template shared_ptr dynamic_pointer_cast(shared_ptr const & r) { - return shared_ptr(r, detail::dynamic_cast_tag()); + return shared_ptr(r, boost::detail::dynamic_cast_tag()); } // shared_*_cast names are deprecated. Use *_pointer_cast instead. template shared_ptr shared_static_cast(shared_ptr const & r) { - return shared_ptr(r, detail::static_cast_tag()); + return shared_ptr(r, boost::detail::static_cast_tag()); } template shared_ptr shared_dynamic_cast(shared_ptr const & r) { - return shared_ptr(r, detail::dynamic_cast_tag()); + return shared_ptr(r, boost::detail::dynamic_cast_tag()); } template shared_ptr shared_polymorphic_cast(shared_ptr const & r) { - return shared_ptr(r, detail::polymorphic_cast_tag()); + return shared_ptr(r, boost::detail::polymorphic_cast_tag()); } template shared_ptr shared_polymorphic_downcast(shared_ptr const & r) From 7bfddbccf6c0dff239ff52b70c740b9f4027ced1 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 25 Sep 2005 21:27:00 +0000 Subject: [PATCH 310/513] Comparison operators against a raw pointer now accept different types [SVN r31110] --- include/boost/intrusive_ptr.hpp | 8 ++++---- intrusive_ptr.html | 36 ++++++++++++++++----------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index dd8cc39..b03b901 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -174,22 +174,22 @@ template inline bool operator!=(intrusive_ptr const & a, in return a.get() != b.get(); } -template inline bool operator==(intrusive_ptr const & a, T * b) +template inline bool operator==(intrusive_ptr const & a, U * b) { return a.get() == b; } -template inline bool operator!=(intrusive_ptr const & a, T * b) +template inline bool operator!=(intrusive_ptr const & a, U * b) { return a.get() != b; } -template inline bool operator==(T * a, intrusive_ptr const & b) +template inline bool operator==(T * a, intrusive_ptr const & b) { return a == b.get(); } -template inline bool operator!=(T * a, intrusive_ptr const & b) +template inline bool operator!=(T * a, intrusive_ptr const & b) { return a != b.get(); } diff --git a/intrusive_ptr.html b/intrusive_ptr.html index c0ddfeb..8844491 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -5,8 +5,8 @@ -

    boost.png (6897 bytes)intrusive_ptr - class template

    +

    boost.png (6897 bytes)intrusive_ptr class template

    Introduction
    Synopsis
    @@ -31,11 +31,11 @@

    The main reasons to use intrusive_ptr are:

    • - Some existing frameworks or OSes provide objects with embedded reference - counts;
    • + Some existing frameworks or OSes provide objects with embedded reference + counts;
    • - The memory footprint of intrusive_ptr is the same as the - corresponding raw pointer;
    • + The memory footprint of intrusive_ptr + is the same as the corresponding raw pointer;
    • intrusive_ptr<T> can be constructed from an arbitrary raw pointer of type T *.
    @@ -196,26 +196,26 @@ intrusive_ptr & operator=(T * r);

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

    Throws: nothing.

    -
    template<class T>
    -  bool operator==(intrusive_ptr<T> const & a, T * b); // never throws
    +
    template<class T, class U>
    +  bool operator==(intrusive_ptr<T> const & a, U * b); // never throws

    Returns: a.get() == b.

    Throws: nothing.

    -
    template<class T>
    -  bool operator!=(intrusive_ptr<T> const & a, T * b); // never throws
    +
    template<class T, class U>
    +  bool operator!=(intrusive_ptr<T> const & a, U * b); // never throws

    Returns: a.get() != b.

    Throws: nothing.

    -
    template<class T>
    -  bool operator==(T * a, intrusive_ptr<T> const & b); // never throws
    +
    template<class T, class U>
    +  bool operator==(T * a, intrusive_ptr<U> const & b); // never throws

    Returns: a == b.get().

    Throws: nothing.

    -
    template<class T>
    -  bool operator!=(T * a, intrusive_ptr<T> const & b); // never throws
    +
    template<class T, class U>
    +  bool operator!=(T * a, intrusive_ptr<U> const & b); // never throws

    Returns: a != b.get().

    Throws: nothing.

    @@ -278,9 +278,9 @@ intrusive_ptr & operator=(T * r);

    $Date$

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

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

    From 235994873faff1e2c58d6adb5a56d6766a386e79 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 25 Sep 2005 21:49:08 +0000 Subject: [PATCH 311/513] Documented conversion to 'unspecified bool' [SVN r31111] --- scoped_array.htm | 30 ++++++++++++++++++------------ scoped_ptr.htm | 18 ++++++++++++------ shared_array.htm | 18 ++++++++++++------ 3 files changed, 42 insertions(+), 24 deletions(-) diff --git a/scoped_array.htm b/scoped_array.htm index 2e1081c..93b1cf9 100644 --- a/scoped_array.htm +++ b/scoped_array.htm @@ -5,8 +5,8 @@ -

    boost.png (6897 bytes)scoped_array - class template

    +

    boost.png (6897 bytes)scoped_array class template

    The scoped_array class template stores a pointer to a dynamically allocated array. (Dynamically allocated arrays are allocated with the C++ new[] expression.) The array pointed to is guaranteed to be deleted, either on @@ -14,10 +14,9 @@

    The scoped_array template is a simple solution for simple needs. It supplies a basic "resource acquisition is initialization" facility, without shared-ownership or transfer-of-ownership semantics. Both its name and - enforcement of semantics (by being - noncopyable) signal its intent to retain ownership solely within the - current scope. Because it is - noncopyable, + enforcement of semantics (by being + noncopyable) signal its intent to retain ownership solely within the + current scope. Because it is noncopyable, it is safer than shared_array for pointers which should not be copied.

    Because scoped_array is so simple, in its usual implementation every operation is as fast as a built-in array pointer and it has no more space @@ -48,6 +47,8 @@ T & operator[](std::ptrdiff_t i) const; // never throws T * get() const; // never throws + operator unspecified-bool-type() const; // never throws + void swap(scoped_array & b); // never throws }; @@ -90,6 +91,10 @@

    T * get() const; // never throws

    Returns the stored pointer. T need not be a complete type. See the smart pointer common requirements.

    +

    conversions

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

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

    swap

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

    Exchanges the contents of the two smart pointers. T need not be a @@ -101,11 +106,12 @@

    Equivalent to a.swap(b). Matches the interface of std::swap. Provided as an aid to generic programming.


    -

    Revised 09 January 2003

    +

    Revised + 09 January 2003

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

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

    - \ No newline at end of file + diff --git a/scoped_ptr.htm b/scoped_ptr.htm index f3a0155..1c6458d 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -5,8 +5,8 @@ -

    boost.png (6897 bytes)scoped_ptr - class template

    +

    boost.png (6897 bytes)scoped_ptr class template

    The scoped_ptr class template stores a pointer to a dynamically allocated object. (Dynamically allocated objects are allocated with the C++ new expression.) The object pointed to is guaranteed to be deleted, either on destruction of the scoped_ptr, @@ -48,6 +48,8 @@ T * operator->() const; // never throws T * get() const; // never throws + operator unspecified-bool-type() const; // never throws + void swap(scoped_ptr & b); // never throws }; @@ -90,6 +92,10 @@

    T * get() const; // never throws

    Returns the stored pointer. T need not be a complete type. See the smart pointer common requirements.

    +

    conversions

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

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

    swap

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

    Exchanges the contents of the two smart pointers. T need not be a @@ -150,8 +156,8 @@ Buckle my shoe

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

    -

    The scoped_ptr_example_test.cpp sample - program includes a header file, scoped_ptr_example.hpp, +

    The scoped_ptr_example_test.cpp + sample program includes a header file, scoped_ptr_example.hpp, which uses a scoped_ptr<> to an incomplete type to hide the implementation. The instantiation of member functions which require a complete type occurs in the scoped_ptr_example.cpp @@ -165,10 +171,10 @@ Buckle my shoe given context. Use std::auto_ptr where transfer of ownership is required. (supplied by Dave Abrahams)


    -

    Revised +

    Revised 09 January 2003

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

    diff --git a/shared_array.htm b/shared_array.htm index 337f131..7c61f53 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -5,8 +5,8 @@ -

    boost.png (6897 bytes)shared_array - class template

    +

    boost.png (6897 bytes)shared_array class template

    The shared_array class template stores a pointer to a dynamically allocated array. (Dynamically allocated array are allocated with the C++ new[] expression.) The object pointed to is guaranteed to be deleted when the last shared_array @@ -53,6 +53,8 @@ bool unique() const; // never throws long use_count() const; // never throws + operator unspecified-bool-type() const; // never throws + void swap(shared_array<T> & b); // never throws }; @@ -139,6 +141,10 @@ implementations of shared_array that do not use an explicit reference count, it might be removed from some future version. Thus it should be used for debugging purposes only, and not production code.

    +

    conversions

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

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

    swap

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

    Exchanges the contents of the two smart pointers. T need not be a @@ -172,9 +178,9 @@ template<class T> 09 January 2003

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

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

    From 7880720bc13a825117075e29b59d0cb5700386a8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 25 Sep 2005 21:54:19 +0000 Subject: [PATCH 312/513] Made the Boost logo link to the home page [SVN r31112] --- compatibility.htm | 188 ++++++++++++++++------------------- enable_shared_from_this.html | 5 +- intrusive_ptr.html | 2 +- shared_ptr.htm | 6 +- smart_ptr.htm | 4 +- sp_techniques.html | 4 +- weak_ptr.htm | 4 +- 7 files changed, 98 insertions(+), 115 deletions(-) diff --git a/compatibility.htm b/compatibility.htm index 6d7af92..71662ce 100644 --- a/compatibility.htm +++ b/compatibility.htm @@ -1,105 +1,89 @@ - - - - -Smart Pointer Changes - - - - -

    boost.png (6897 bytes)Smart -Pointer Changes

    - -

    The February 2002 change to the Boost smart pointers introduced a number -of changes. Since the previous version of the smart pointers was in use for -a long time, it's useful to have a detailed list of what changed from a library -user's point of view.

    - -

    Note that for compilers that don't support member templates well enough, -a separate implementation is used that lacks many of the new features and is -more like the old version.

    - -

    Features Requiring Code Changes to Take Advantage

    - -
      - -
    • The smart pointer class templates now each have their own header file. -For compatibility, the -<boost/smart_ptr.hpp> -header now includes the headers for the four classic smart pointer class templates.
    • - -
    • The weak_ptr template was added.
    • - -
    • The new shared_ptr and shared_array relax the requirement that the pointed-to object's -destructor must be visible when instantiating the shared_ptr destructor. -This makes it easier to have shared_ptr members in classes without explicit destructors.
    • - -
    • A custom deallocator can be passed in when creating a shared_ptr or shared_array.
    • - -
    • shared_static_cast and shared_dynamic_cast function templates are -provided which work for shared_ptr and weak_ptr as static_cast and -dynamic_cast do for pointers.
    • - -
    • The self-assignment misfeature has been removed from shared_ptr::reset, -although it is still present in scoped_ptr, and in std::auto_ptr. -Calling reset with a pointer to the object that's already owned by the -shared_ptr results in undefined behavior -(an assertion, or eventually a double-delete if assertions are off).
    • - -
    • The BOOST_SMART_PTR_CONVERSION feature has been removed.
    • - -
    • shared_ptr<void> is now allowed.
    • - -
    - -

    Features That Improve Robustness

    - -
      - -
    • The manipulation of use counts is now thread safe on Windows, Linux, and platforms -that support pthreads. See the -<boost/detail/atomic_count.hpp> -file for details
    • - -
    • The new shared_ptr will always delete the object using the pointer it was originally constructed with. -This prevents subtle problems that could happen if the last shared_ptr was a pointer to a sub-object -of a class that did not have a virtual destructor.
    • - -
    - -

    Implementation Details

    - -
      - -
    • Some bugs in the assignment operator implementations and in reset -have been fixed by using the "copy and swap" idiom.
    • - -
    • Assertions have been added to check preconditions of various functions; -however, since these use the new -<boost/assert.hpp> -header, the assertions are disabled by default.
    • - -
    • The partial specialization of std::less has been replaced by operator< -overloads which accomplish the same thing without relying on undefined behavior.
    • - -
    • The incorrect overload of std::swap has been replaced by boost::swap, which -has many of the same advantages for generic programming but does not violate the C++ standard.
    • - -
    - -
    - -

    Revised 1 February 2002

    - -

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

    - - - + + Smart Pointer Changes + + + +

    boost.png (6897 bytes)Smart Pointer Changes

    +

    The February 2002 change to the Boost smart pointers introduced a number of + changes. Since the previous version of the smart pointers was in use for a long + time, it's useful to have a detailed list of what changed from a library user's + point of view.

    +

    Note that for compilers that don't support member templates well enough, a + separate implementation is used that lacks many of the new features and is more + like the old version.

    +

    Features Requiring Code Changes to Take Advantage

    +
      +
    • + The smart pointer class templates now each have their own header file. For + compatibility, the <boost/smart_ptr.hpp> + header now includes the headers for the four classic smart pointer class + templates. +
    • + The weak_ptr + template was added. +
    • + The new shared_ptr and shared_array relax the requirement that + the pointed-to object's destructor must be visible when instantiating the shared_ptr + destructor. This makes it easier to have shared_ptr members in classes without + explicit destructors. +
    • + A custom deallocator can be passed in when creating a shared_ptr or shared_array. +
    • + shared_static_cast and shared_dynamic_cast function templates are + provided which work for shared_ptr and weak_ptr as static_cast + and dynamic_cast + do for pointers. +
    • + The self-assignment misfeature has been removed from shared_ptr::reset, + although it is still present in scoped_ptr, and in std::auto_ptr. + Calling reset with a pointer to the object that's already owned by the shared_ptr + results in undefined behavior (an assertion, or eventually a double-delete if + assertions are off). +
    • + The BOOST_SMART_PTR_CONVERSION + feature has been removed. +
    • + shared_ptr<void> is now allowed.
    • +
    +

    Features That Improve Robustness

    +
      +
    • + The manipulation of use counts is now thread safe on + Windows, Linux, and platforms that support pthreads. See the + <boost/detail/atomic_count.hpp> + file for details +
    • + The new shared_ptr will always delete the object using the pointer it was + originally constructed with. This prevents subtle problems that could happen if + the last shared_ptr was a pointer to a sub-object of a class that did + not have a virtual destructor.
    • +
    +

    Implementation Details

    +
      +
    • + Some bugs in the assignment operator implementations and in reset + have been fixed by using the "copy and swap" idiom. +
    • + Assertions have been added to check preconditions of various functions; + however, since these use the new <boost/assert.hpp> + header, the assertions are disabled by default. +
    • + The partial specialization of std::less has been replaced by operator< + overloads which accomplish the same thing without relying on undefined + behavior. +
    • + The incorrect overload of std::swap has been replaced by boost::swap, + which has many of the same advantages for generic programming but does not + violate the C++ standard.
    • +
    +
    +

    Revised 1 February 2002

    +

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

    + diff --git a/enable_shared_from_this.html b/enable_shared_from_this.html index 8d6a6e3..166870f 100644 --- a/enable_shared_from_this.html +++ b/enable_shared_from_this.html @@ -7,10 +7,9 @@ - - diff --git a/intrusive_ptr.html b/intrusive_ptr.html index 8844491..5d8aa48 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -5,7 +5,7 @@ -

    boost.png (6897 bytes)boost.png (6897 bytes)intrusive_ptr class template

    Introduction
    diff --git a/shared_ptr.htm b/shared_ptr.htm index 26fd78e..0cc77d2 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -5,8 +5,8 @@ -

    boost.png (6897 bytes)shared_ptr - class template

    +

    boost.png (6897 bytes)shared_ptr class template

    Introduction
    Best Practices
    Synopsis
    @@ -621,7 +621,7 @@ p3.reset(new int(2)); // undefined, multiple writes 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 + based smart pointers should read Modern C++ Design by Andrei Alexandrescu.)

    Q. I am not convinced. Default parameters can be used where appropriate diff --git a/smart_ptr.htm b/smart_ptr.htm index 2ff8dd2..14f456b 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -5,8 +5,8 @@ -

    boost.png (6897 bytes)Smart - Pointers

    +

    boost.png (6897 bytes)Smart Pointers

    Introduction
    Common Requirements
    Exception Safety
    diff --git a/sp_techniques.html b/sp_techniques.html index 816047f..d41be4b 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -5,8 +5,8 @@ -

    boost.png (6897 bytes)Smart - Pointer Programming Techniques

    +

    boost.png (6897 bytes)Smart Pointer Programming Techniques

    Using incomplete classes for implementation hiding
    The "Pimpl" idiom
    Using abstract classes for implementation hiding
    diff --git a/weak_ptr.htm b/weak_ptr.htm index e214d4a..68dc980 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -5,8 +5,8 @@ -

    boost.png (6897 bytes)weak_ptr - class template

    +

    boost.png (6897 bytes)weak_ptr class template

    Introduction
    Synopsis
    Members
    From 92a027fbebd8e858af71eaaa86810ce31210620b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 25 Sep 2005 22:00:31 +0000 Subject: [PATCH 313/513] Minor warning fix for SGI MIPSPro (Kevin Wheatley) [SVN r31113] --- include/boost/shared_ptr.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index f78f0fe..de8c112 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -87,10 +87,19 @@ template void sp_enable_shared_from_this( shared_count const & if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); } +#ifdef sgi +// Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed +# pragma set woff 3506 +#endif + inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) { } +#ifdef sgi +# pragma reset woff 3506 +#endif + } // namespace detail From 9edd3beebc5c7627aa885d498a30994f2eede1a8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 5 Nov 2005 14:33:42 +0000 Subject: [PATCH 314/513] Added a note that it's not necessary to initialize _internal_weak_this. [SVN r31565] --- sp_techniques.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sp_techniques.html b/sp_techniques.html index d41be4b..e046275 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -519,6 +519,9 @@ public: } } +

    Note that you no longer need to manually initialize the weak_ptr member + in enable_shared_from_this. + Constructing a shared_ptr to impl takes care of that.

    Using shared_ptr as a smart counted handle

    Some library interfaces use opaque handles, a variation of the incomplete class technique described above. An example:

    From 0127c06692cc4e6f86ec841a891ec1f8c19b3534 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 5 Nov 2005 14:40:29 +0000 Subject: [PATCH 315/513] Added a note that it's not necessary to initialize _internal_weak_this. [SVN r31566] --- include/boost/enable_shared_from_this.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 0cf7854..4e49f1f 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -58,6 +58,12 @@ public: return p; } +// Note: No, you don't need to initialize _internal_weak_this +// +// Please read the documentation, not the code +// +// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html + typedef T _internal_element_type; // for bcc 5.5.1 mutable weak_ptr<_internal_element_type> _internal_weak_this; }; From 25ca8551276d85840220c15f8bac80908a0907bc Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 9 Nov 2005 20:05:42 +0000 Subject: [PATCH 316/513] shared_ptr( p, d, a ) added. [SVN r31613] --- include/boost/detail/shared_count.hpp | 46 ++++++++++++++++++++++++ include/boost/detail/sp_counted_impl.hpp | 42 ++++++++++++++++++++++ include/boost/shared_ptr.hpp | 16 +++++++-- 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 49aca85..0395053 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -127,6 +127,52 @@ public: boost::throw_exception(std::bad_alloc()); } +#endif + } + + template shared_count( P p, D d, A a ): pi_( 0 ) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + typedef sp_counted_impl_pda impl_type; + typedef typename A::template rebind< impl_type >::other A2; + + A2 a2( a ); + +#ifndef BOOST_NO_EXCEPTIONS + + try + { + pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); + new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); + } + catch(...) + { + d( p ); + + if( pi_ != 0 ) + { + a2.deallocate( static_cast< impl_type* >( pi_ ), 1 ); + } + + throw; + } + +#else + + pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); + + if( pi_ != 0 ) + { + new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); + } + else + { + d( p ); + boost::throw_exception( std::bad_alloc() ); + } + #endif } diff --git a/include/boost/detail/sp_counted_impl.hpp b/include/boost/detail/sp_counted_impl.hpp index 51093b5..51557db 100644 --- a/include/boost/detail/sp_counted_impl.hpp +++ b/include/boost/detail/sp_counted_impl.hpp @@ -176,6 +176,48 @@ public: #endif }; +template class sp_counted_impl_pda: public sp_counted_base +{ +private: + + P p_; // copy constructor must not throw + D d_; // copy constructor must not throw + A a_; // copy constructor must not throw + + sp_counted_impl_pda( sp_counted_impl_pda const & ); + sp_counted_impl_pda & operator= ( sp_counted_impl_pda const & ); + + typedef sp_counted_impl_pda this_type; + +public: + + // pre: d( p ) must not throw + + sp_counted_impl_pda( P p, D d, A a ): p_( p ), d_( d ), a_( a ) + { + } + + virtual void dispose() // nothrow + { + d_( p_ ); + } + + virtual void destroy() // nothrow + { + typedef typename A::template rebind< this_type >::other A2; + + A2 a2( a_ ); + + this->~this_type(); + a2.deallocate( this, 1 ); + } + + virtual void * get_deleter( std::type_info const & ti ) + { + return ti == typeid( D )? &d_: 0; + } +}; + #ifdef __CODEGUARD__ # pragma option pop #endif diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index de8c112..cb94325 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -146,6 +146,13 @@ public: boost::detail::sp_enable_shared_from_this( pn, p, p ); } + // As above, but with allocator. A's copy constructor shall not throw. + + template shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) + { + boost::detail::sp_enable_shared_from_this( pn, p, p ); + } + // generated copy constructor, assignment, destructor are fine... // except that Borland C++ has a bug, and g++ with -Wsynth warns @@ -246,9 +253,14 @@ public: this_type(p).swap(*this); } - template void reset(Y * p, D d) + template void reset( Y * p, D d ) { - this_type(p, d).swap(*this); + this_type( p, d ).swap( *this ); + } + + template void reset( Y * p, D d, A a ) + { + this_type( p, d, a ).swap( *this ); } reference operator* () const // never throws From 239bb6d966ca254eb03260c1237a034e0d8ca811 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 11 Nov 2005 21:06:08 +0000 Subject: [PATCH 317/513] #include reorderings for Boost.TR1 [SVN r31623] --- include/boost/detail/shared_count.hpp | 2 +- include/boost/detail/sp_counted_impl.hpp | 3 +++ include/boost/shared_ptr.hpp | 3 ++- include/boost/weak_ptr.hpp | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 0395053..e139a7d 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -29,7 +29,7 @@ #include #include -#include // std::auto_ptr, std::allocator +#include // std::auto_ptr #include // std::less #include // std::bad_alloc #include // std::type_info in get_deleter diff --git a/include/boost/detail/sp_counted_impl.hpp b/include/boost/detail/sp_counted_impl.hpp index 51557db..6963f59 100644 --- a/include/boost/detail/sp_counted_impl.hpp +++ b/include/boost/detail/sp_counted_impl.hpp @@ -31,7 +31,10 @@ #include #endif +#if defined(BOOST_SP_USE_STD_ALLOCATOR) #include // std::allocator +#endif + #include // std::type_info in get_deleter #include // std::size_t diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index cb94325..08b2a95 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -20,13 +20,14 @@ #include #else +#include // for std::auto_ptr + #include #include #include #include #include -#include // for std::auto_ptr #include // for std::swap #include // for std::less #include // for std::bad_cast diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index a4073fc..cd9ee63 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -13,6 +13,8 @@ // See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation. // +#include // boost.TR1 include order fix +#include #include #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash From 3771707bb713b869b7dc46fed6a48b867efd1fa7 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 11 Nov 2005 21:07:18 +0000 Subject: [PATCH 318/513] Added a test for the custom allocator constructor/reset. [SVN r31624] --- test/Jamfile | 1 + test/Jamfile.v2 | 1 + test/shared_ptr_alloc2_test.cpp | 224 ++++++++++++++++++++++++++++++++ 3 files changed, 226 insertions(+) create mode 100644 test/shared_ptr_alloc2_test.cpp diff --git a/test/Jamfile b/test/Jamfile index d4cb858..9e92713 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -30,6 +30,7 @@ DEPENDS all : smart_ptr ; [ run lw_mutex_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] [ compile-fail shared_ptr_delete_fail.cpp ] + [ run shared_ptr_alloc2_test.cpp ] ; # this one is too slow to run unless explicitly requested, and ALL diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 16c988e..c2237e4 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -24,5 +24,6 @@ import testing ; [ run lw_mutex_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] [ compile-fail shared_ptr_delete_fail.cpp ] + [ run shared_ptr_alloc2_test.cpp ] ; } diff --git a/test/shared_ptr_alloc2_test.cpp b/test/shared_ptr_alloc2_test.cpp new file mode 100644 index 0000000..3eb3c46 --- /dev/null +++ b/test/shared_ptr_alloc2_test.cpp @@ -0,0 +1,224 @@ +#include + +// shared_ptr_alloc2_test.cpp +// +// Copyright (c) 2005 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include +#include +#include +#include + +// test_allocator + +struct test_allocator_base +{ + int id_; + + static int last_global_id_; + static int count_; + + explicit test_allocator_base( int id ): id_( id ) + { + } +}; + +int test_allocator_base::last_global_id_ = 0; +int test_allocator_base::count_ = 0; + +template class test_allocator: public test_allocator_base +{ +public: + + typedef T * pointer; + typedef T const * const_pointer; + typedef T & reference; + typedef T const & const_reference; + typedef T value_type; + typedef std::size_t size_type; + typedef ptrdiff_t difference_type; + +private: + + static T * last_pointer_; + static std::size_t last_n_; + static int last_id_; + +public: + + template struct rebind + { + typedef test_allocator other; + }; + + pointer address( reference r ) const + { + return &r; + } + + const_pointer address( const_reference s ) const + { + return &s; + } + + explicit test_allocator( int id = 0 ): test_allocator_base( id ) + { + } + + template test_allocator( test_allocator const & r ): test_allocator_base( r ) + { + } + + template test_allocator & operator=( test_allocator const & r ) + { + test_allocator_base::operator=( r ); + return *this; + } + + void deallocate( pointer p, size_type n ) + { + BOOST_TEST( p == last_pointer_ ); + BOOST_TEST( n == last_n_ ); + BOOST_TEST( id_ == last_id_ ); + + --count_; + + ::operator delete( p ); + } + + pointer allocate( size_type n, void const * ) + { + T * p = static_cast< T* >( ::operator new( n * sizeof( T ) ) ); + + last_pointer_ = p; + last_n_ = n; + last_id_ = id_; + + last_global_id_ = id_; + ++count_; + + return p; + } + + void construct( pointer p, T const & t ) + { + new( p ) T( t ); + } + + void destroy( pointer p ) + { + p->~T(); + } + + size_type max_size() const + { + return size_type( -1 ) / sizeof( T ); + } +}; + +template T * test_allocator::last_pointer_ = 0; +template std::size_t test_allocator::last_n_ = 0; +template int test_allocator::last_id_ = 0; + +template inline bool operator==( test_allocator const & a1, test_allocator const & a2 ) +{ + return a1.id_ == a2.id_; +} + +template inline bool operator!=( test_allocator const & a1, test_allocator const & a2 ) +{ + return a1.id_ != a2.id_; +} + +template<> class test_allocator: public test_allocator_base +{ +public: + + typedef void * pointer; + typedef void const * const_pointer; + typedef void value_type; + + template struct rebind + { + typedef test_allocator other; + }; + + explicit test_allocator( int id = 0 ): test_allocator_base( id ) + { + } + + template test_allocator( test_allocator const & r ): test_allocator_base( r ) + { + } + + template test_allocator & operator=( test_allocator const & r ) + { + test_allocator_base::operator=( r ); + return *this; + } +}; + +// + +struct X +{ + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const & ); + X & operator=( X const & ); +}; + +int X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + boost::shared_ptr pv( new X, boost::checked_deleter(), std::allocator() ); + + BOOST_TEST( X::instances == 1 ); + + pv.reset( new X, boost::checked_deleter(), test_allocator( 42 ) ); + + BOOST_TEST( X::instances == 1 ); + + BOOST_TEST( test_allocator_base::last_global_id_ == 42 ); + BOOST_TEST( test_allocator_base::count_ > 0 ); + + pv.reset(); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( test_allocator_base::count_ == 0 ); + + pv.reset( new X, boost::checked_deleter(), test_allocator( 43 ) ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( test_allocator_base::last_global_id_ == 43 ); + + pv.reset( new X, boost::checked_deleter(), std::allocator() ); + + BOOST_TEST( X::instances == 1 ); + + pv.reset(); + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +} From 2d25f8f036c79063016d4ce546a064a2171e5b12 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 27 Nov 2005 17:16:30 +0000 Subject: [PATCH 319/513] Qualified ptrdiff_t with std:: (fixes a failure on CW 9.4) [SVN r31790] --- test/shared_ptr_alloc2_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/shared_ptr_alloc2_test.cpp b/test/shared_ptr_alloc2_test.cpp index 3eb3c46..93f9d26 100644 --- a/test/shared_ptr_alloc2_test.cpp +++ b/test/shared_ptr_alloc2_test.cpp @@ -41,7 +41,7 @@ public: typedef T const & const_reference; typedef T value_type; typedef std::size_t size_type; - typedef ptrdiff_t difference_type; + typedef std::ptrdiff_t difference_type; private: From 90b5a3736a901873954e5a3a829a20e821535e72 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 6 Dec 2005 13:26:13 +0000 Subject: [PATCH 320/513] =?UTF-8?q?Pointer=20utilities=20added=20(proposed?= =?UTF-8?q?=20by=20Ion=20Gazta=C3=B1aga)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [SVN r31932] --- include/boost/pointer_cast.hpp | 45 +++++++++++ include/boost/pointer_to_other.hpp | 55 +++++++++++++ pointer_cast.html | 105 ++++++++++++++++++++++++ test/Jamfile | 2 + test/Jamfile.v2 | 2 + test/pointer_cast_test.cpp | 126 +++++++++++++++++++++++++++++ test/pointer_to_other_test.cpp | 74 +++++++++++++++++ 7 files changed, 409 insertions(+) create mode 100644 include/boost/pointer_cast.hpp create mode 100644 include/boost/pointer_to_other.hpp create mode 100644 pointer_cast.html create mode 100644 test/pointer_cast_test.cpp create mode 100644 test/pointer_to_other_test.cpp diff --git a/include/boost/pointer_cast.hpp b/include/boost/pointer_cast.hpp new file mode 100644 index 0000000..5a5bec0 --- /dev/null +++ b/include/boost/pointer_cast.hpp @@ -0,0 +1,45 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2005. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_POINTER_CAST_HPP +#define BOOST_POINTER_CAST_HPP + +namespace boost { + +//static_pointer_cast overload for raw pointers +template +inline T* static_pointer_cast(U *ptr) +{ + return static_cast(ptr); +} + +//dynamic_pointer_cast overload for raw pointers +template +inline T* dynamic_pointer_cast(U *ptr) +{ + return dynamic_cast(ptr); +} + +//const_pointer_cast overload for raw pointers +template +inline T* const_pointer_cast(U *ptr) +{ + return const_cast(ptr); +} + +//reinterpret_pointer_cast overload for raw pointers +template +inline T* reinterpret_pointer_cast(U *ptr) +{ + return reinterpret_cast(ptr); +} + +} // namespace boost + +#endif //BOOST_POINTER_CAST_HPP diff --git a/include/boost/pointer_to_other.hpp b/include/boost/pointer_to_other.hpp new file mode 100644 index 0000000..1cf2627 --- /dev/null +++ b/include/boost/pointer_to_other.hpp @@ -0,0 +1,55 @@ +#ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED +#define BOOST_POINTER_TO_OTHER_HPP_INCLUDED + +// +// pointer_to_other.hpp +// +// (C) Copyright Ion Gaztañaga 2005. +// Copyright (c) 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) +// +// See http://www.boost.org/libs/smart_ptr/pointer_to_other.html +// + +namespace boost +{ + +// Defines the same pointer type (raw or smart) to another pointee type + +template +struct pointer_to_other; + +template class Sp> +struct pointer_to_other< Sp, U > +{ + typedef Sp type; +}; + +template class Sp> +struct pointer_to_other< Sp, U > +{ + typedef Sp type; +}; + +template class Sp> +struct pointer_to_other< Sp, U > +{ + typedef Sp type; +}; + +template +struct pointer_to_other< T*, U > +{ + typedef U* type; +}; + +} // namespace boost + +#endif // #ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED diff --git a/pointer_cast.html b/pointer_cast.html new file mode 100644 index 0000000..8f14795 --- /dev/null +++ b/pointer_cast.html @@ -0,0 +1,105 @@ + + + + pointer_cast.hpp + + +

    C++ BoostPointer + cast functions

    +

    The pointer cast functions (boost::static_pointer_cast boost::dynamic_pointer_cast + boost::reinterpret_pointer_cast boost::const_pointer_cast) + provide a way to write generic pointer castings for raw pointers. The functions + are defined in boost/pointer_cast.hpp.

    +

    There is test/example code in pointer_cast_test.cpp.

    +

    Rationale

    +

    Boost smart pointers usually overload those functions to provide a mechanism to + emulate pointers casts. For example, boost::shared_ptr<...> implements + a static pointer cast this way:

    +
    +template<class T, class U>
    +    shared_ptr<T> static_pointer_cast(shared_ptr<U> const &r);
    +
    +

    Pointer cast functions from boost/pointer_cast.hpp + are overloads of boost::static_pointer_cast, boost::dynamic_pointer_cast, + boost::reinterpret_pointer_cast and boost::const_pointer_cast + for raw pointers. This way when developing pointer type independent classes, + for example, memory managers or shared memory compatible classes, the same code + can be used for raw and smart pointers.

    +

    Synopsis

    +
    +
    +namespace boost {
    +
    +template<class T, class U>
    +inline T* static_pointer_cast(U *ptr)
    +  { return static_cast<T*>(ptr); }
    +
    +template<class T, class U>
    +inline T* dynamic_pointer_cast(U *ptr)
    +  { return dynamic_cast<T*>(ptr); }
    +
    +template<class T, class U>
    +inline T* const_pointer_cast(U *ptr)
    +  { return const_cast<T*>(ptr); }
    +
    +template<class T, class U>
    +inline T* reinterpret_pointer_cast(U *ptr)
    +  { return reinterpret_cast<T*>(ptr); }
    +  
    +} // namespace boost
    +
    +
    +

    As you can see from the above synopsis, the pointer cast functions are just + wrappers around standard C++ cast operators.

    +

    Example

    +
    +
    +#include <boost/pointer_cast.hpp>
    +#include <boost/shared_ptr.hpp>
    +
    +class base
    +{
    +public:
    +
    +   virtual ~base()
    +   {
    +   }
    +};
    +
    +class derived: public base
    +{
    +};
    +
    +template <class BasePtr>
    +void check_if_it_is_derived(const BasePtr &ptr)
    +{
    +   assert(boost::dynamic_pointer_cast<derived>(ptr) != 0);
    +}
    +
    +int main()
    +{
    +   // Create a raw and a shared_ptr
    +
    +   base *ptr = new derived;
    +   boost::shared_ptr<base> sptr(new derived);
    +   
    +   // Check that base pointer points actually to derived class
    +
    +   check_if_it_is_derived(ptr);
    +   check_if_it_is_derived(sptr);
    +   
    +   // Ok!
    +   
    +   delete ptr;
    +   return 0;
    +}
    +
    +

    The example demonstrates how the generic pointer casts help us create pointer + independent code.

    +
    +

    Revised: $Date$

    +

    Copyright 2005 Ion Gaztañaga. Use, modification, and distribution are subject to + the Boost Software License, Version 1.0. (See accompanying file + LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)

    + + diff --git a/test/Jamfile b/test/Jamfile index 9e92713..e97bfd0 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -31,6 +31,8 @@ DEPENDS all : smart_ptr ; [ compile-fail shared_ptr_assign_fail.cpp ] [ compile-fail shared_ptr_delete_fail.cpp ] [ run shared_ptr_alloc2_test.cpp ] + [ run pointer_cast_test.cpp ] + [ compile pointer_to_other_test.cpp ] ; # this one is too slow to run unless explicitly requested, and ALL diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c2237e4..2a6e91b 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -25,5 +25,7 @@ import testing ; [ compile-fail shared_ptr_assign_fail.cpp ] [ compile-fail shared_ptr_delete_fail.cpp ] [ run shared_ptr_alloc2_test.cpp ] + [ run pointer_cast_test.cpp ] + [ compile pointer_to_other_test.cpp ] ; } diff --git a/test/pointer_cast_test.cpp b/test/pointer_cast_test.cpp new file mode 100644 index 0000000..0d5d652 --- /dev/null +++ b/test/pointer_cast_test.cpp @@ -0,0 +1,126 @@ +// +// pointer_cast_test.cpp - a test for boost/pointer_cast.hpp +// +// Copyright (c) 2005 Ion Gaztañaga +// Copyright (c) 2005 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +#include +#include +#include + +#include + +namespace +{ + +// Let's create these inheritance relationship: +// +// base base2 +// | | +// derived +// | +// derived_derived +// + +class base +{ + public: + virtual ~base(){} + int filler [5]; +}; + +class base2 +{ +public: + + virtual ~base2(){} + int filler [5]; +}; + +class derived + : public base, public base2 +{ + int filler [5]; +}; + +class derived_derived + : public derived +{ + int filler [5]; +}; + +// And now some simple check functions + +template +bool check_dynamic_pointer_cast(const BasePtr &ptr) +{ + //Check that dynamic_pointer_cast versus dynamic_cast + return + //Correct cast with dynamic_pointer_cast + boost::get_pointer(boost::dynamic_pointer_cast(ptr)) == + //Correct cast with dynamic_cast + dynamic_cast(boost::get_pointer(ptr)) + && + //Incorrect cast with dynamic_pointer_cast + boost::get_pointer(boost::dynamic_pointer_cast(ptr)) == + //Incorrect cast with dynamic_cast + dynamic_cast(boost::get_pointer(ptr)); +} + +template +bool check_static_pointer_cast(const BasePtr &ptr) +{ + return + //Cast base -> derived -> base2 using static_pointer_cast + boost::get_pointer( + boost::static_pointer_cast( + boost::static_pointer_cast(ptr))) == + //Now the same with static_cast + static_cast(static_cast(boost::get_pointer(ptr))); +} + +template +bool check_const_pointer_cast(const BasePtr &ptr) +{ + return + //Unconst and const again using const_pointer_cast + boost::get_pointer( + boost::const_pointer_cast + (boost::const_pointer_cast(ptr))) == + //Now the same with const_cast + const_cast(const_cast(boost::get_pointer(ptr))); +} + +} + +int main() +{ + { + // Try casts with shared_ptr + + boost::shared_ptr ptr(new derived); + + BOOST_TEST( check_dynamic_pointer_cast( ptr ) ); + BOOST_TEST( check_static_pointer_cast( ptr ) ); + BOOST_TEST( check_const_pointer_cast( ptr ) ); + } + + { + // Try casts with raw pointer + + boost::scoped_ptr ptr(new derived); + + BOOST_TEST( check_dynamic_pointer_cast( ptr.get() ) ); + BOOST_TEST( check_static_pointer_cast( ptr.get() ) ); + BOOST_TEST( check_const_pointer_cast( ptr.get() ) ); + } + + return boost::report_errors(); +} diff --git a/test/pointer_to_other_test.cpp b/test/pointer_to_other_test.cpp new file mode 100644 index 0000000..c2ee187 --- /dev/null +++ b/test/pointer_to_other_test.cpp @@ -0,0 +1,74 @@ +// +// pointer_to_other_test.cpp - a test for boost/pointer_to_other.hpp +// +// Copyright (c) 2005 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +#include +#include +#include +#include +#include + +#include + +template void assert_same_type( T** pt = 0, U** pu = 0 ) +{ + pt = pu; +} + +struct X; +struct Y; + +int main() +{ + // shared_ptr + + assert_same_type< boost::pointer_to_other< boost::shared_ptr, Y >::type, boost::shared_ptr >(); + assert_same_type< boost::pointer_to_other< boost::shared_ptr, void >::type, boost::shared_ptr >(); + assert_same_type< boost::pointer_to_other< boost::shared_ptr, Y >::type, boost::shared_ptr >(); + + // shared_array + + assert_same_type< boost::pointer_to_other< boost::shared_array, Y >::type, boost::shared_array >(); + assert_same_type< boost::pointer_to_other< boost::shared_array, void >::type, boost::shared_array >(); + assert_same_type< boost::pointer_to_other< boost::shared_array, Y >::type, boost::shared_array >(); + + // scoped_ptr + + assert_same_type< boost::pointer_to_other< boost::scoped_ptr, Y >::type, boost::scoped_ptr >(); + assert_same_type< boost::pointer_to_other< boost::scoped_ptr, void >::type, boost::scoped_ptr >(); + assert_same_type< boost::pointer_to_other< boost::scoped_ptr, Y >::type, boost::scoped_ptr >(); + + // scoped_array + + assert_same_type< boost::pointer_to_other< boost::scoped_array, Y >::type, boost::scoped_array >(); + assert_same_type< boost::pointer_to_other< boost::scoped_array, void >::type, boost::scoped_array >(); + assert_same_type< boost::pointer_to_other< boost::scoped_array, Y >::type, boost::scoped_array >(); + + // intrusive_ptr + + assert_same_type< boost::pointer_to_other< boost::intrusive_ptr, Y >::type, boost::intrusive_ptr >(); + assert_same_type< boost::pointer_to_other< boost::intrusive_ptr, void >::type, boost::intrusive_ptr >(); + assert_same_type< boost::pointer_to_other< boost::intrusive_ptr, Y >::type, boost::intrusive_ptr >(); + + // auto_ptr + + assert_same_type< boost::pointer_to_other< std::auto_ptr, Y >::type, std::auto_ptr >(); + assert_same_type< boost::pointer_to_other< std::auto_ptr, void >::type, std::auto_ptr >(); + assert_same_type< boost::pointer_to_other< std::auto_ptr, Y >::type, std::auto_ptr >(); + + // raw pointer + + assert_same_type< boost::pointer_to_other< X *, Y >::type, Y * >(); + assert_same_type< boost::pointer_to_other< X *, void >::type, void * >(); + assert_same_type< boost::pointer_to_other< void *, Y >::type, Y * >(); + + return 0; +} From a196f39cd01cb0d2f5f4a0676d3550c93484616b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 6 Dec 2005 23:17:32 +0000 Subject: [PATCH 321/513] Added documentation for pointer_to_other.hpp. [SVN r31941] --- pointer_to_other.html | 118 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 pointer_to_other.html diff --git a/pointer_to_other.html b/pointer_to_other.html new file mode 100644 index 0000000..369ac89 --- /dev/null +++ b/pointer_to_other.html @@ -0,0 +1,118 @@ + + + + + pointer_to_other.hpp + + +

    boost.png (6897 bytes)Header + boost/pointer_to_other.hpp

    + +

    The pointer to other utility provides a way, from a source pointer type, to obtain a + pointer of the same type to another pointee type. The utility is defined in + boost/pointer_to_other.hpp.

    + +

    There is test/example code in pointer_to_other_test.cpp.

    + +

    Contents

    + + +

    Rationale

    + +

    Many times when building pointer independent classes, like memory managers, + allocators, or containers, there is a need to define pointers generically, so that if a + template parameter represents a pointer (for example, a raw or smart pointer to an int), + we can define another pointer of the same type to another pointee (a raw or smart + pointer to a float.)

    + +
    template <class IntPtr>
    +class FloatPointerHolder
    +{   
    +   // Let's define a pointer to a float
    +   typedef typename boost::pointer_to_other
    +      <IntPtr, float>::type float_ptr_t;
    +   float_ptr_t float_ptr;
    +};
    + +

    Synopsis

    + +
    +namespace boost {
    +
    +template<class T, class U>
    +   struct pointer_to_other;
    +
    +template<class T, class U, template <class> class Sp>
    +   struct pointer_to_other< Sp<T>, U >
    +{
    +   typedef Sp<U> type;
    +};
    +
    +template<class T, class T2, class U,
    +        template <class, class> class Sp>
    +   struct pointer_to_other< Sp<T, T2>, U >
    +{
    +   typedef Sp<U, T2> type;
    +};
    +
    +template<class T, class T2, class T3, class U,
    +        template <class, class, class> class Sp>
    +struct pointer_to_other< Sp<T, T2, T3>, U >
    +{
    +   typedef Sp<U, T2, T3> type;
    +};
    +
    +template<class T, class U>
    +struct pointer_to_other< T*, U > 
    +{
    +   typedef U* type;
    +};
    +
    +} // namespace boost
    + +

    If this definitions are not correct for an specific smart pointer, we can define an + specialization of pointer_to_other.

    + +

    Example

    + +
    // Let's define a memory allocator that can
    +// work with raw and smart pointers
    +
    +#include <boost/pointer_to_other.hpp>
    +
    +template <class VoidPtr>
    +class memory_allocator
    +{
    +   // Predefine a memory_block 
    +   struct block;
    +
    +   // Define a pointer to a memory_block from a void pointer
    +   // If VoidPtr is void *, block_ptr_t is block*
    +   // If VoidPtr is smart_ptr<void>, block_ptr_t is smart_ptr<block>
    +   typedef typename boost::pointer_to_other      
    +            <VoidPtr, block>::type block_ptr_t;
    +            
    +   struct block
    +   {
    +      std::size_t size;
    +      block_ptr_t next_block;
    +   };
    +
    +   block_ptr_t free_blocks;
    +};
    + +

    As we can see, using pointer_to_other we can create pointer independent code.

    +
    +

    Last revised: $Date$

    +

    Copyright 2005 Ion Gaztañaga and Peter Dimov. + Use, modification, and distribution are subject to the + Boost Software License, Version 1.0.
    + (See accompanying file + LICENSE_1_0.txt or a copy at < + http://www.boost.org/LICENSE_1_0.txt>.)

    + + From a86b2f7fbfe22e32bb4c84c452cecf5fdd0086ec Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 15 Jan 2006 13:54:53 +0000 Subject: [PATCH 322/513] Rvalue auto_ptr support, technique by Dave Abrahams [SVN r32326] --- include/boost/shared_ptr.hpp | 48 +++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 08b2a95..50e6716 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -5,7 +5,7 @@ // shared_ptr.hpp // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. -// Copyright (c) 2001, 2002, 2003 Peter Dimov +// Copyright (c) 2001-2006 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -101,6 +101,21 @@ inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) # pragma reset woff 3506 #endif +#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) + +// rvalue auto_ptr support based on a technique by Dave Abrahams + +template< class T, class R > struct sp_enable_if_auto_ptr +{ +}; + +template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R > +{ + typedef R type; +}; + +#endif + } // namespace detail @@ -218,7 +233,20 @@ public: boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); } -#endif +#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + + template + explicit shared_ptr( Ap r, typename detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() + { + typename Ap::element_type * tmp = r.get(); + pn = boost::detail::shared_count( r ); + boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); + } + + +#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_NO_AUTO_PTR #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) @@ -235,13 +263,25 @@ public: #ifndef BOOST_NO_AUTO_PTR template - shared_ptr & operator=(std::auto_ptr & r) + shared_ptr & operator=( std::auto_ptr & r ) { this_type(r).swap(*this); return *this; } -#endif +#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + + template + typename detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r ) + { + this_type( r ).swap( *this ); + return *this; + } + + +#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_NO_AUTO_PTR void reset() // never throws in 1.30+ { From 8c256502cc82d2ad380a768eb6392f7ea596b079 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 15 Jan 2006 13:55:37 +0000 Subject: [PATCH 323/513] Added a test for rvalue auto_ptrs [SVN r32327] --- test/Jamfile | 1 + test/Jamfile.v2 | 1 + test/auto_ptr_rv_test.cpp | 111 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 test/auto_ptr_rv_test.cpp diff --git a/test/Jamfile b/test/Jamfile index e97bfd0..2bd285c 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -33,6 +33,7 @@ DEPENDS all : smart_ptr ; [ run shared_ptr_alloc2_test.cpp ] [ run pointer_cast_test.cpp ] [ compile pointer_to_other_test.cpp ] + [ run auto_ptr_rv_test.cpp ] ; # this one is too slow to run unless explicitly requested, and ALL diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 2a6e91b..0dd4e11 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -27,5 +27,6 @@ import testing ; [ run shared_ptr_alloc2_test.cpp ] [ run pointer_cast_test.cpp ] [ compile pointer_to_other_test.cpp ] + [ run auto_ptr_rv_test.cpp ] ; } diff --git a/test/auto_ptr_rv_test.cpp b/test/auto_ptr_rv_test.cpp new file mode 100644 index 0000000..d13b6ab --- /dev/null +++ b/test/auto_ptr_rv_test.cpp @@ -0,0 +1,111 @@ +// +// auto_ptr_rv_test.cpp +// +// Copyright (c) 2006 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include +#include +#include + +struct X +{ + static long instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + + static std::auto_ptr create() + { + return std::auto_ptr( new X ); + } + +private: + + X( X const & ); + X & operator=( X const & ); +}; + +long X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +} From e427716dc2be931cd7cda025ee079302b740461c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Feb 2006 19:17:33 +0000 Subject: [PATCH 324/513] Fully qualified detail:: to work around a subtle VC 7.1 problem. [SVN r32994] --- include/boost/shared_ptr.hpp | 4 ++-- include/boost/weak_ptr.hpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 50e6716..bab848d 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -236,7 +236,7 @@ public: #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) template - explicit shared_ptr( Ap r, typename detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() + explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() { typename Ap::element_type * tmp = r.get(); pn = boost::detail::shared_count( r ); @@ -272,7 +272,7 @@ public: #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) template - typename detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r ) + typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r ) { this_type( r ).swap( *this ); return *this; diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index cd9ee63..8f4230f 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -141,7 +141,7 @@ public: pn.swap(other.pn); } - void _internal_assign(T * px2, detail::shared_count const & pn2) + void _internal_assign(T * px2, boost::detail::shared_count const & pn2) { px = px2; pn = pn2; @@ -164,8 +164,8 @@ private: #endif - T * px; // contained pointer - detail::weak_count pn; // reference counter + T * px; // contained pointer + boost::detail::weak_count pn; // reference counter }; // weak_ptr From ae0a48d544387b5523e27ad1febadce9a4db19e2 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 6 Mar 2006 23:06:10 +0000 Subject: [PATCH 325/513] Removed erroneous // never throws annotations (reported by Scott Meyers) [SVN r33241] --- intrusive_ptr.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/intrusive_ptr.html b/intrusive_ptr.html index 5d8aa48..b07be5c 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -127,8 +127,8 @@

    Effects: if(p != 0 && add_ref) intrusive_ptr_add_ref(p);.

    Postconditions: get() == p.

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

    Effects: if(r.get() != 0) intrusive_ptr_add_ref(r.get());.

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

    @@ -139,8 +139,8 @@ template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r); //

    Effects: if(get() != 0) intrusive_ptr_release(get());.

    assignment

    -
    intrusive_ptr & operator=(intrusive_ptr const & r); // never throws
    -template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r); // never throws
    +		
    intrusive_ptr & operator=(intrusive_ptr const & r);
    +template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
     intrusive_ptr & operator=(T * r);

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

    From 24d1e6f8dd31b7d258b601c414111a56dc897a45 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Mar 2006 01:48:21 +0000 Subject: [PATCH 326/513] Added 'm'(*pw) inputs (thanks to Howard Hinnant) [SVN r33364] --- include/boost/detail/sp_counted_base_gcc_ia64.hpp | 6 +++--- include/boost/detail/sp_counted_base_gcc_ppc.hpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/detail/sp_counted_base_gcc_ia64.hpp index 8016c8d..efcfd11 100644 --- a/include/boost/detail/sp_counted_base_gcc_ia64.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ia64.hpp @@ -35,7 +35,7 @@ inline void atomic_increment( long * pw ) // cheaper. __asm__ ("fetchadd8.rel %0=[%2],1" : "=r"(tmp), "=m"(*pw) : - "r"(pw)); + "r"(pw), "m"( *pw )); } inline long atomic_decrement( long * pw ) @@ -48,7 +48,7 @@ inline long atomic_decrement( long * pw ) " cmp.eq p7,p0=1,%0 ;; \n" "(p7) ld8.acq %0=[%2] " : "=&r"(rv), "=m"(*pw) : - "r"(pw) : + "r"(pw), "m"( *pw ) : "p7"); return rv; @@ -72,7 +72,7 @@ inline long atomic_conditional_increment( long * pw ) " mov %0=%1 ;; \n" "1:" : "=&r"(rv), "=&r"(tmp), "=&r"(tmp2), "=m"(*pw) : - "r"(pw) : + "r"(pw), "m"( *pw ) : "ar.ccv", "p7"); return rv; diff --git a/include/boost/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/detail/sp_counted_base_gcc_ppc.hpp index fc2925e..ca5cf2b 100644 --- a/include/boost/detail/sp_counted_base_gcc_ppc.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ppc.hpp @@ -47,7 +47,7 @@ inline void atomic_increment( int * pw ) "bne- 0b": "=m"( *pw ), "=&b"( tmp ): - "r"( pw ): + "r"( pw ), "m"( *pw ): "cc" ); } @@ -69,7 +69,7 @@ inline int atomic_decrement( int * pw ) "isync": "=m"( *pw ), "=&b"( rv ): - "r"( pw ): + "r"( pw ), "m"( *pw ): "memory", "cc" ); @@ -95,7 +95,7 @@ inline int atomic_conditional_increment( int * pw ) "bne- 0b": "=m"( *pw ), "=&b"( rv ): - "r"( pw ): + "r"( pw ), "m"( *pw ): "cc" ); From 00f744bf1e10ae81bd8e620746d00d3bc1b157c9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Mar 2006 14:58:20 +0000 Subject: [PATCH 327/513] Minor rewording. [SVN r33367] --- pointer_to_other.html | 94 +++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 52 deletions(-) diff --git a/pointer_to_other.html b/pointer_to_other.html index 369ac89..e6b138c 100644 --- a/pointer_to_other.html +++ b/pointer_to_other.html @@ -1,35 +1,33 @@ - - - pointer_to_other.hpp - - -

    boost.png (6897 bytes)Header - boost/pointer_to_other.hpp

    - -

    The pointer to other utility provides a way, from a source pointer type, to obtain a - pointer of the same type to another pointee type. The utility is defined in - boost/pointer_to_other.hpp.

    - -

    There is test/example code in pointer_to_other_test.cpp.

    - -

    Contents

    - - -

    Rationale

    - -

    Many times when building pointer independent classes, like memory managers, - allocators, or containers, there is a need to define pointers generically, so that if a - template parameter represents a pointer (for example, a raw or smart pointer to an int), - we can define another pointer of the same type to another pointee (a raw or smart - pointer to a float.)

    - -
    template <class IntPtr>
    +	
    +		pointer_to_other.hpp
    +		
    +	
    +	
    +		

    boost.png (6897 bytes)Header + boost/pointer_to_other.hpp

    +

    + The pointer to other utility provides a way, given a source pointer type, + to obtain a pointer of the same type to another pointee type. The utility is + defined in boost/pointer_to_other.hpp.

    +

    There is test/example code in pointer_to_other_test.cpp.

    +

    Contents

    + +

    Rationale

    +

    When building pointer independent classes, like memory managers, allocators, or + containers, there is often a need to define pointers generically, so that if a + template parameter represents a pointer (for example, a raw or smart pointer to + an int), we can define another pointer of the same type to another pointee (a + raw or smart pointer to a float.)

    +
    template <class IntPtr>
     class FloatPointerHolder
     {   
        // Let's define a pointer to a float
    @@ -37,10 +35,8 @@ class FloatPointerHolder
           <IntPtr, float>::type float_ptr_t;
        float_ptr_t float_ptr;
     };
    - -

    Synopsis

    - -
    +		

    Synopsis

    +
     namespace boost {
     
     template<class T, class U>
    @@ -73,13 +69,10 @@ struct pointer_to_other< T*, U >
     };
     
     } // namespace boost
    - -

    If this definitions are not correct for an specific smart pointer, we can define an - specialization of pointer_to_other.

    - -

    Example

    - -
    // Let's define a memory allocator that can
    +		

    If these definitions are not correct for a specific smart pointer, we can define + a specialization of pointer_to_other.

    +

    Example

    +
    // Let's define a memory allocator that can
     // work with raw and smart pointers
     
     #include <boost/pointer_to_other.hpp>
    @@ -104,15 +97,12 @@ class memory_allocator
     
        block_ptr_t free_blocks;
     };
    - -

    As we can see, using pointer_to_other we can create pointer independent code.

    -
    -

    Last revised: $Date$

    -

    Copyright 2005 Ion Gaztañaga and Peter Dimov. - Use, modification, and distribution are subject to the - Boost Software License, Version 1.0.
    - (See accompanying file - LICENSE_1_0.txt or a copy at < - http://www.boost.org/LICENSE_1_0.txt>.)

    - +

    As we can see, using pointer_to_other we can create pointer independent code.

    +
    +

    Last revised: $Date$

    +

    Copyright 2005, 2006 Ion Gaztañaga and Peter Dimov. Use, modification, + and distribution are subject to the Boost Software License, Version 1.0.
    + (See accompanying file LICENSE_1_0.txt or a + copy at < http://www.boost.org/LICENSE_1_0.txt>.)

    + From c36e0231621d1e7f8c1ad783cdff7eaf96fe0320 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 19 Mar 2006 19:52:00 +0000 Subject: [PATCH 328/513] Documented the allocator support [SVN r33393] --- shared_ptr.htm | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 0cc77d2..71cb9c9 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -106,6 +106,7 @@ void bad() shared_ptr(); // never throws template<class Y> explicit shared_ptr(Y * p); template<class Y, class D> shared_ptr(Y * p, D d); + template<class Y, class D, class A> shared_ptr(Y * p, D d, A a); ~shared_ptr(); // never throws shared_ptr(shared_ptr const & r); // never throws @@ -120,6 +121,7 @@ void bad() void reset(); // never throws template<class Y> void reset(Y * p); template<class Y, class D> void reset(Y * p, D d); + template<class Y, class D, class A> void reset(Y * p, D d, A a); T & operator*() const; // never throws T * operator->() const; // never throws @@ -203,15 +205,20 @@ void bad() The current implementation uses a different mechanism, enable_shared_from_this, to solve the "shared_ptr from this" problem.
    ]

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

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

    Effects: Constructs a shared_ptr that owns the pointer - p and the deleter d.

    + 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 exception when a resource other than memory could not be obtained.

    @@ -317,6 +324,10 @@ q = p;

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

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

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

    +

    indirection

    T & operator*() const; // never throws
    From e38d0daaab2d0326d2733b34f13bb7cec41c879e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 22 Mar 2006 22:46:53 +0000 Subject: [PATCH 329/513] Fix issues on HP-UX (ILP32 model) [SVN r33449] --- .../boost/detail/sp_counted_base_gcc_ia64.hpp | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/include/boost/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/detail/sp_counted_base_gcc_ia64.hpp index efcfd11..7f4bd25 100644 --- a/include/boost/detail/sp_counted_base_gcc_ia64.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ia64.hpp @@ -5,7 +5,7 @@ // detail/sp_counted_base_gcc_ia64.hpp - g++ on IA64 // // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. -// Copyright 2004-2005 Peter Dimov +// Copyright 2004-2006 Peter Dimov // Copyright 2005 Ben Hutchings // // Distributed under the Boost Software License, Version 1.0. (See @@ -24,55 +24,55 @@ namespace boost namespace detail { -inline void atomic_increment( long * pw ) +inline void atomic_increment( int * pw ) { // ++*pw; - long tmp; + int tmp; // No barrier is required here but fetchadd always has an acquire or // release barrier associated with it. We choose release as it should be // cheaper. - __asm__ ("fetchadd8.rel %0=[%2],1" : + __asm__ ("fetchadd4.rel %0=%1,1" : "=r"(tmp), "=m"(*pw) : - "r"(pw), "m"( *pw )); + "m"( *pw )); } -inline long atomic_decrement( long * pw ) +inline int atomic_decrement( int * pw ) { // return --*pw; - long rv; + int rv; - __asm__ (" fetchadd8.rel %0=[%2],-1 ;; \n" + __asm__ (" fetchadd4.rel %0=%1,-1 ;; \n" " cmp.eq p7,p0=1,%0 ;; \n" - "(p7) ld8.acq %0=[%2] " : + "(p7) ld4.acq %0=%1 " : "=&r"(rv), "=m"(*pw) : - "r"(pw), "m"( *pw ) : + "m"( *pw ) : "p7"); return rv; } -inline long atomic_conditional_increment( long * pw ) +inline int atomic_conditional_increment( int * pw ) { // if( *pw != 0 ) ++*pw; // return *pw; - long rv, tmp, tmp2; + int rv, tmp, tmp2; - __asm__ ("0: ld8 %0=[%4] ;; \n" + __asm__ ("0: ld4 %0=%3 ;; \n" " cmp.eq p7,p0=0,%0 ;; \n" "(p7) br.cond.spnt 1f \n" " mov ar.ccv=%0 \n" " add %1=1,%0 ;; \n" - " cmpxchg8.acq %2=[%4],%1,ar.ccv ;; \n" + " cmpxchg4.acq %2=%3,%1,ar.ccv ;; \n" " cmp.ne p7,p0=%0,%2 ;; \n" "(p7) br.cond.spnt 0b \n" " mov %0=%1 ;; \n" "1:" : "=&r"(rv), "=&r"(tmp), "=&r"(tmp2), "=m"(*pw) : - "r"(pw), "m"( *pw ) : + "m"( *pw ) : "ar.ccv", "p7"); return rv; @@ -85,8 +85,8 @@ private: sp_counted_base( sp_counted_base const & ); sp_counted_base & operator= ( sp_counted_base const & ); - long use_count_; // #shared - long weak_count_; // #weak + (#shared != 0) + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) public: @@ -146,7 +146,7 @@ public: long use_count() const // nothrow { - return static_cast( use_count_ ); + return static_cast( use_count_ ); // TODO use ld.acq here } }; From 7ce5b55f5ca1a7a55d00d02ab0ccd9559fee09ba Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 24 Mar 2006 00:38:22 +0000 Subject: [PATCH 330/513] Fix issues on HP-UX (ILP32 model) [SVN r33464] --- .../boost/detail/sp_counted_base_gcc_ia64.hpp | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/include/boost/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/detail/sp_counted_base_gcc_ia64.hpp index efcfd11..7f4bd25 100644 --- a/include/boost/detail/sp_counted_base_gcc_ia64.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ia64.hpp @@ -5,7 +5,7 @@ // detail/sp_counted_base_gcc_ia64.hpp - g++ on IA64 // // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. -// Copyright 2004-2005 Peter Dimov +// Copyright 2004-2006 Peter Dimov // Copyright 2005 Ben Hutchings // // Distributed under the Boost Software License, Version 1.0. (See @@ -24,55 +24,55 @@ namespace boost namespace detail { -inline void atomic_increment( long * pw ) +inline void atomic_increment( int * pw ) { // ++*pw; - long tmp; + int tmp; // No barrier is required here but fetchadd always has an acquire or // release barrier associated with it. We choose release as it should be // cheaper. - __asm__ ("fetchadd8.rel %0=[%2],1" : + __asm__ ("fetchadd4.rel %0=%1,1" : "=r"(tmp), "=m"(*pw) : - "r"(pw), "m"( *pw )); + "m"( *pw )); } -inline long atomic_decrement( long * pw ) +inline int atomic_decrement( int * pw ) { // return --*pw; - long rv; + int rv; - __asm__ (" fetchadd8.rel %0=[%2],-1 ;; \n" + __asm__ (" fetchadd4.rel %0=%1,-1 ;; \n" " cmp.eq p7,p0=1,%0 ;; \n" - "(p7) ld8.acq %0=[%2] " : + "(p7) ld4.acq %0=%1 " : "=&r"(rv), "=m"(*pw) : - "r"(pw), "m"( *pw ) : + "m"( *pw ) : "p7"); return rv; } -inline long atomic_conditional_increment( long * pw ) +inline int atomic_conditional_increment( int * pw ) { // if( *pw != 0 ) ++*pw; // return *pw; - long rv, tmp, tmp2; + int rv, tmp, tmp2; - __asm__ ("0: ld8 %0=[%4] ;; \n" + __asm__ ("0: ld4 %0=%3 ;; \n" " cmp.eq p7,p0=0,%0 ;; \n" "(p7) br.cond.spnt 1f \n" " mov ar.ccv=%0 \n" " add %1=1,%0 ;; \n" - " cmpxchg8.acq %2=[%4],%1,ar.ccv ;; \n" + " cmpxchg4.acq %2=%3,%1,ar.ccv ;; \n" " cmp.ne p7,p0=%0,%2 ;; \n" "(p7) br.cond.spnt 0b \n" " mov %0=%1 ;; \n" "1:" : "=&r"(rv), "=&r"(tmp), "=&r"(tmp2), "=m"(*pw) : - "r"(pw), "m"( *pw ) : + "m"( *pw ) : "ar.ccv", "p7"); return rv; @@ -85,8 +85,8 @@ private: sp_counted_base( sp_counted_base const & ); sp_counted_base & operator= ( sp_counted_base const & ); - long use_count_; // #shared - long weak_count_; // #weak + (#shared != 0) + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) public: @@ -146,7 +146,7 @@ public: long use_count() const // nothrow { - return static_cast( use_count_ ); + return static_cast( use_count_ ); // TODO use ld.acq here } }; From 747c9a1d3e8147fe4310b193d368a7855602b078 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 29 Mar 2006 19:19:14 +0000 Subject: [PATCH 331/513] Rvalue auto_ptr constructor is no longer explicit. [SVN r33526] --- include/boost/shared_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index bab848d..46bf69b 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -236,7 +236,7 @@ public: #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) template - explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() + shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() { typename Ap::element_type * tmp = r.get(); pn = boost::detail::shared_count( r ); From 6e120f4bf177c62634c96b9d6506a9c5ca27e45a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 19 Apr 2006 21:03:18 +0000 Subject: [PATCH 332/513] Fix VC6 codegen issue (Alain Cormier) [SVN r33747] --- include/boost/detail/sp_counted_base_w32.hpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/boost/detail/sp_counted_base_w32.hpp b/include/boost/detail/sp_counted_base_w32.hpp index e84f06e..fb42c4e 100644 --- a/include/boost/detail/sp_counted_base_w32.hpp +++ b/include/boost/detail/sp_counted_base_w32.hpp @@ -25,6 +25,7 @@ // #include +#include #include namespace boost @@ -78,7 +79,19 @@ public: { long tmp = static_cast< long const volatile& >( use_count_ ); if( tmp == 0 ) return false; + +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1200 ) + + // work around a code generation bug + + long tmp2 = tmp + 1; + if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true; + +#else + if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true; + +#endif } } From 203764eb51ba0bfb0ac3ea96d23c9e9dc566bc12 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 19 Apr 2006 21:03:18 +0000 Subject: [PATCH 333/513] Fix VC6 codegen issue (Alain Cormier) [SVN r33747] --- include/boost/detail/sp_counted_base_w32.hpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/boost/detail/sp_counted_base_w32.hpp b/include/boost/detail/sp_counted_base_w32.hpp index e84f06e..fb42c4e 100644 --- a/include/boost/detail/sp_counted_base_w32.hpp +++ b/include/boost/detail/sp_counted_base_w32.hpp @@ -25,6 +25,7 @@ // #include +#include #include namespace boost @@ -78,7 +79,19 @@ public: { long tmp = static_cast< long const volatile& >( use_count_ ); if( tmp == 0 ) return false; + +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1200 ) + + // work around a code generation bug + + long tmp2 = tmp + 1; + if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true; + +#else + if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true; + +#endif } } From 75cd88112c2d976282bcbf0694a6b90b1b148839 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 15 May 2006 13:56:27 +0000 Subject: [PATCH 334/513] Workaround for MSVC 8.0 managed/unmanaged mismatch (reported by Loic Joly) [SVN r33968] --- include/boost/shared_ptr.hpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index bab848d..b1868fe 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -330,6 +330,19 @@ public: return px != 0; } +#elif defined( _MANAGED ) + + static void unspecified_bool( this_type*** ) + { + } + + typedef void (*unspecified_bool_type)( this_type*** ); + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: unspecified_bool; + } + #elif \ ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) From 4fcee64483d3934311346d3bf5b6bcdb655cdbbd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 May 2006 22:39:34 +0000 Subject: [PATCH 335/513] New, improved and more portable unspecified bool type. I hope. [SVN r33987] --- include/boost/shared_ptr.hpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 46bf69b..7f239b6 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -323,6 +323,8 @@ public: // implicit conversion to "bool" +/* + #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) operator bool () const @@ -330,6 +332,23 @@ public: return px != 0; } +#elif defined( _MANAGED ) + +*/ + + static void unspecified_bool( this_type*** ) + { + } + + typedef void (*unspecified_bool_type)( this_type*** ); + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: unspecified_bool; + } + +/* + #elif \ ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) @@ -352,6 +371,8 @@ public: #endif +*/ + // operator! is redundant, but some compilers need it bool operator! () const // never throws From ffd73c39b37af92071ae2da806a26eadb37d0e76 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 3 Jul 2006 10:02:46 +0000 Subject: [PATCH 336/513] Solaris implementation by Michael van der Westhuizen [SVN r34450] --- include/boost/detail/atomic_count_solaris.hpp | 59 +++++++++ .../boost/detail/sp_counted_base_solaris.hpp | 113 ++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 include/boost/detail/atomic_count_solaris.hpp create mode 100644 include/boost/detail/sp_counted_base_solaris.hpp diff --git a/include/boost/detail/atomic_count_solaris.hpp b/include/boost/detail/atomic_count_solaris.hpp new file mode 100644 index 0000000..8e2907f --- /dev/null +++ b/include/boost/detail/atomic_count_solaris.hpp @@ -0,0 +1,59 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED + +// +// boost/detail/atomic_count_solaris.hpp +// based on: boost/detail/atomic_count_win32.hpp +// +// Copyright (c) 2001-2005 Peter Dimov +// Copyright (c) 2006 Michael van der Westhuizen +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( uint32_t v ): value_( v ) + { + } + + long operator++() + { + return atomic_inc_32_nv( &value_ ); + } + + long operator--() + { + return atomic_dec_32_nv( &value_ ); + } + + operator uint32_t() const + { + return static_cast( value_ ); + } + +private: + + atomic_count( atomic_count const & ); + atomic_count & operator=( atomic_count const & ); + + uint32_t value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_solaris.hpp b/include/boost/detail/sp_counted_base_solaris.hpp new file mode 100644 index 0000000..c23e2e3 --- /dev/null +++ b/include/boost/detail/sp_counted_base_solaris.hpp @@ -0,0 +1,113 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED + +// +// detail/sp_counted_base_solaris.hpp +// based on: detail/sp_counted_base_w32.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// Copyright 2006 Michael van der Westhuizen +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include +#include + +namespace boost +{ + +namespace detail +{ + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + uint32_t use_count_; // #shared + uint32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( std::type_info const & ti ) = 0; + + void add_ref_copy() + { + atomic_inc_32( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + for( ;; ) + { + uint32_t tmp = static_cast< uint32_t const volatile& >( use_count_ ); + if( tmp == 0 ) return false; + if( atomic_cas_32( &use_count_, tmp, tmp + 1 ) == tmp ) return true; + } + } + + void release() // nothrow + { + if( atomic_dec_32_nv( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_inc_32( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_dec_32_nv( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED From 7e5d7011e6b8770b2e7402cc4b9ff5877285b0be Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 6 Jul 2006 12:13:25 +0000 Subject: [PATCH 337/513] Attempt to fix sun-5.8 shared_ptr_delete_fail regression [SVN r34466] --- include/boost/shared_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index b1868fe..0aaa48d 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -330,7 +330,7 @@ public: return px != 0; } -#elif defined( _MANAGED ) +#elif defined( _MANAGED ) || defined( __SUNPRO_CC ) static void unspecified_bool( this_type*** ) { From 7c477960d3ebf526fa6c9dea13470127337b25c8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 7 Jul 2006 22:48:20 +0000 Subject: [PATCH 338/513] Second try, revert to old Sun behavior for 5.8 and below [SVN r34479] --- include/boost/shared_ptr.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 0aaa48d..1924c9f 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -323,14 +323,14 @@ public: // implicit conversion to "bool" -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) operator bool () const { return px != 0; } -#elif defined( _MANAGED ) || defined( __SUNPRO_CC ) +#elif defined( _MANAGED ) static void unspecified_bool( this_type*** ) { From 8d2f7fc5efa90421e1e7351e5d19ba56342ee6ea Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 8 Jul 2006 17:44:55 +0000 Subject: [PATCH 339/513] g++/SPARC version by Piotr Wyderski, thanks to Tomas Puverle and Michael van der Westhuizen [SVN r34480] --- include/boost/detail/sp_counted_base.hpp | 6 +- .../detail/sp_counted_base_gcc_sparc.hpp | 166 ++++++++++++++++++ 2 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 include/boost/detail/sp_counted_base_gcc_sparc.hpp diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index bc170ca..d64f239 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -10,7 +10,7 @@ // // detail/sp_counted_base.hpp // -// Copyright 2005 Peter Dimov +// Copyright 2005, 2006 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -47,6 +47,10 @@ # include +#elif defined(__GNUC__) && ( defined( __sparcv8 ) || defined( __sparcv9 ) ) + +# include + #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) # include diff --git a/include/boost/detail/sp_counted_base_gcc_sparc.hpp b/include/boost/detail/sp_counted_base_gcc_sparc.hpp new file mode 100644 index 0000000..dd606f0 --- /dev/null +++ b/include/boost/detail/sp_counted_base_gcc_sparc.hpp @@ -0,0 +1,166 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_counted_base_gcc_sparc.hpp - g++ on Sparc V8+ +// +// Copyright (c) 2006 Piotr Wyderski +// Copyright (c) 2006 Tomas Puverle +// Copyright (c) 2006 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// Thanks to Michael van der Westhuizen + +#include +#include // int32_t + +namespace boost +{ + +namespace detail +{ + +inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ ) +{ + __asm__ __volatile__( "cas %0, %2, %1" + : "+m" (*dest_), "+r" (swap_) + : "r" (compare_) + : "memory" ); + + return swap_; +} + +inline int32_t atomic_fetch_and_add( int32_t * pw, int32_t dv ) +{ + // long r = *pw; + // *pw += dv; + // return r; + + for( ;; ) + { + int32_t r = *pw; + + if( __builtin_expect((compare_and_swap(pw, r, r + dv) == r), 1) ) + { + return r; + } + } +} + +inline void atomic_increment( int32_t * pw ) +{ + atomic_fetch_and_add( pw, 1 ); +} + +inline int32_t atomic_decrement( int32_t * pw ) +{ + return atomic_fetch_and_add( pw, -1 ); +} + +inline int32_t atomic_conditional_increment( int32_t * pw ) +{ + // long r = *pw; + // if( r != 0 ) ++*pw; + // return r; + + for( ;; ) + { + int32_t r = *pw; + + if( r == 0 ) + { + return r; + } + + if( __builtin_expect( ( compare_and_swap( pw, r, r + 1 ) == r ), 1 ) ) + { + return r; + } + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int32_t use_count_; // #shared + int32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( std::type_info const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return const_cast< int32_t const volatile & >( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED From 6412de1dd57d5e4bed192ec43b7f6d76b3c0a92a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 10 Jul 2006 13:17:41 +0000 Subject: [PATCH 340/513] TR1 cyclic dependency fixes. [SVN r34499] --- include/boost/shared_array.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index 9216e89..eb69c8e 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -20,6 +20,8 @@ #include #else +#include // TR1 cyclic inclusion fix + #include #include From 39551bdc1a62f9aaca0bbd95e86aa0fd9dd7638a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 11 Jul 2006 23:17:17 +0000 Subject: [PATCH 341/513] A negative test for p > q added. [SVN r34509] --- test/Jamfile | 4 ++-- test/Jamfile.v2 | 1 + test/shared_ptr_compare_fail.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 test/shared_ptr_compare_fail.cpp diff --git a/test/Jamfile b/test/Jamfile index 2bd285c..f2491a8 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -1,6 +1,6 @@ # Boost.SmartPtr Library test Jamfile # -# Copyright (c) 2003-2005 Peter Dimov +# Copyright (c) 2003-2006 Peter Dimov # Copyright (c) 2003 Dave Abrahams # # Permission to copy, use, modify, sell and distribute this software @@ -25,11 +25,11 @@ DEPENDS all : smart_ptr ; [ run shared_from_this_test.cpp : : : <*>-Wno-non-virtual-dtor ] [ run get_deleter_test.cpp ] [ run intrusive_ptr_test.cpp ] - [ run intrusive_ptr_test.cpp ] [ run atomic_count_test.cpp ] [ run lw_mutex_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] [ compile-fail shared_ptr_delete_fail.cpp ] + [ compile-fail shared_ptr_compare_fail.cpp ] [ run shared_ptr_alloc2_test.cpp ] [ run pointer_cast_test.cpp ] [ compile pointer_to_other_test.cpp ] diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0dd4e11..5e950fd 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -24,6 +24,7 @@ import testing ; [ run lw_mutex_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] [ compile-fail shared_ptr_delete_fail.cpp ] + [ compile-fail shared_ptr_compare_fail.cpp ] [ run shared_ptr_alloc2_test.cpp ] [ run pointer_cast_test.cpp ] [ compile pointer_to_other_test.cpp ] diff --git a/test/shared_ptr_compare_fail.cpp b/test/shared_ptr_compare_fail.cpp new file mode 100644 index 0000000..296af14 --- /dev/null +++ b/test/shared_ptr_compare_fail.cpp @@ -0,0 +1,27 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// shared_ptr_compare_fail.cpp - a negative test for "p > q" +// +// Copyright 2006 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +int main() +{ + boost::shared_ptr p, q; + p > q; // must fail + return 0; +} From db0969d97b78015a4a95ee80a6f5cc77316fce09 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 12 Jul 2006 12:31:28 +0000 Subject: [PATCH 342/513] TR1 cyclic inclusion fix [SVN r34512] --- include/boost/shared_array.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index 9216e89..eb69c8e 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -20,6 +20,8 @@ #include #else +#include // TR1 cyclic inclusion fix + #include #include From ebc0af9147d440cc86af764a4705961868b6d622 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Mon, 6 Nov 2006 17:10:46 +0000 Subject: [PATCH 343/513] Remove obsolete Boost.Build v1 files. [SVN r35880] --- test/Jamfile | 48 ------------------------------------------------ 1 file changed, 48 deletions(-) delete mode 100644 test/Jamfile diff --git a/test/Jamfile b/test/Jamfile deleted file mode 100644 index 2bd285c..0000000 --- a/test/Jamfile +++ /dev/null @@ -1,48 +0,0 @@ -# Boost.SmartPtr Library test Jamfile -# -# Copyright (c) 2003-2005 Peter Dimov -# Copyright (c) 2003 Dave Abrahams -# -# Permission to copy, use, modify, sell and distribute this software -# is granted provided this copyright notice appears in all copies. -# This software is provided "as is" without express or implied -# warranty, and with no claim as to its suitability for any purpose. - -subproject libs/smart_ptr/test ; - -# bring in rules for testing -import testing ; - -# Make tests run by default. -DEPENDS all : smart_ptr ; - -{ - test-suite "smart_ptr" - : [ run smart_ptr_test.cpp ] - [ run shared_ptr_basic_test.cpp : : : <*>-Wno-non-virtual-dtor ] - [ run shared_ptr_test.cpp : : : <*>-Wno-non-virtual-dtor ] - [ run weak_ptr_test.cpp ] - [ run shared_from_this_test.cpp : : : <*>-Wno-non-virtual-dtor ] - [ run get_deleter_test.cpp ] - [ run intrusive_ptr_test.cpp ] - [ run intrusive_ptr_test.cpp ] - [ run atomic_count_test.cpp ] - [ run lw_mutex_test.cpp ] - [ compile-fail shared_ptr_assign_fail.cpp ] - [ compile-fail shared_ptr_delete_fail.cpp ] - [ run shared_ptr_alloc2_test.cpp ] - [ run pointer_cast_test.cpp ] - [ compile pointer_to_other_test.cpp ] - [ run auto_ptr_rv_test.cpp ] - ; - - # this one is too slow to run unless explicitly requested, and ALL - # tests are run by default when this file is subincluded from - # boost/status, so it's guarded from that case. It will only be - # built from this directory when the targets "test" (all tests) or - # "shared_ptr_alloc_test" are requested. - if [ in-invocation-subdir ] - { - run shared_ptr_alloc_test.cpp ; - } -} From 75bc821afdce2f4a94c78c489e3204a2e9c27074 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 6 Nov 2006 17:25:59 +0000 Subject: [PATCH 344/513] Patch #1551992 (Michael Fink) [SVN r35882] --- include/boost/intrusive_ptr.hpp | 7 ++++++- include/boost/shared_ptr.hpp | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index b03b901..cd1ac11 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -249,6 +249,9 @@ template std::ostream & operator<< (std::ostream & os, intrusive_ptr #else +// in STLport's no-iostreams mode no iostream symbols can be used +#ifndef _STLP_NO_IOSTREAMS + # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL using std::basic_ostream; @@ -261,7 +264,9 @@ template std::basic_ostream & operator<< (std:: return os; } -#endif +#endif // _STLP_NO_IOSTREAMS + +#endif // __GNUC__ < 3 } // namespace boost diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 7f239b6..688d58f 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -512,6 +512,9 @@ template std::ostream & operator<< (std::ostream & os, shared_ptr co #else +// in STLport's no-iostreams mode no iostream symbols can be used +#ifndef _STLP_NO_IOSTREAMS + # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL using std::basic_ostream; @@ -524,7 +527,9 @@ template std::basic_ostream & operator<< (std:: return os; } -#endif +#endif // _STLP_NO_IOSTREAMS + +#endif // __GNUC__ < 3 // get_deleter (experimental) From 4a98c2931c0e10d63abfab65c04a70845a648216 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 6 Nov 2006 17:25:59 +0000 Subject: [PATCH 345/513] Patch #1551992 (Michael Fink) [SVN r35882] --- include/boost/intrusive_ptr.hpp | 7 ++++++- include/boost/shared_ptr.hpp | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index b03b901..cd1ac11 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -249,6 +249,9 @@ template std::ostream & operator<< (std::ostream & os, intrusive_ptr #else +// in STLport's no-iostreams mode no iostream symbols can be used +#ifndef _STLP_NO_IOSTREAMS + # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL using std::basic_ostream; @@ -261,7 +264,9 @@ template std::basic_ostream & operator<< (std:: return os; } -#endif +#endif // _STLP_NO_IOSTREAMS + +#endif // __GNUC__ < 3 } // namespace boost diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 1924c9f..9edc86f 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -504,6 +504,9 @@ template std::ostream & operator<< (std::ostream & os, shared_ptr co #else +// in STLport's no-iostreams mode no iostream symbols can be used +#ifndef _STLP_NO_IOSTREAMS + # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL using std::basic_ostream; @@ -516,7 +519,9 @@ template std::basic_ostream & operator<< (std:: return os; } -#endif +#endif // _STLP_NO_IOSTREAMS + +#endif // __GNUC__ < 3 // get_deleter (experimental) From 41d4167533beed73b28cf3695c0cfbb0b75772de Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Tue, 7 Nov 2006 19:11:57 +0000 Subject: [PATCH 346/513] Add copyright, license [SVN r35905] --- index.html | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index e2e191f..b6b39a0 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,11 @@ Automatic redirection failed, please go to -smart_ptr.htm. +smart_ptr.htm
    +

    İ Copyright Beman Dawes, 2001

    +

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

    - + \ No newline at end of file From c464a07ab103006a40227ef1f57869a8db02bed1 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Tue, 7 Nov 2006 19:27:00 +0000 Subject: [PATCH 347/513] Merged copyright and license addition [SVN r35907] --- index.html | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index e2e191f..b6b39a0 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,11 @@ Automatic redirection failed, please go to -smart_ptr.htm. +smart_ptr.htm
    +

    İ Copyright Beman Dawes, 2001

    +

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

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


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

    + Copyright İ 2002, 2003 by Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

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

    $Date$

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

    + Copyright İ 2003-2005 Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

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


    $Date$

    -

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

    +

    Copyright İ 2003 Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

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

    İ Copyright Beman Dawes, 2001

    -

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

    +smart_ptr.htm. - \ No newline at end of file + + From d889751bc0c8c36e774fd065770e739d5e792dcf Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 9 Nov 2006 20:24:23 +0000 Subject: [PATCH 352/513] License/copyright edits [SVN r35957] --- enable_shared_from_this.html | 7 +++---- index.html | 15 ++++++++------- intrusive_ptr.html | 7 +++---- sp_techniques.html | 7 +++---- test/Jamfile.v2 | 7 +++---- 5 files changed, 20 insertions(+), 23 deletions(-) diff --git a/enable_shared_from_this.html b/enable_shared_from_this.html index 166870f..3f35665 100644 --- a/enable_shared_from_this.html +++ b/enable_shared_from_this.html @@ -84,9 +84,8 @@ public:


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

    + Copyright İ 2002, 2003 by Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

    diff --git a/index.html b/index.html index b6b39a0..c7f709c 100644 --- a/index.html +++ b/index.html @@ -4,11 +4,12 @@ Automatic redirection failed, please go to -smart_ptr.htm
    -

    İ Copyright Beman Dawes, 2001

    -

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

    +smart_ptr.htm. - \ No newline at end of file + + diff --git a/intrusive_ptr.html b/intrusive_ptr.html index b07be5c..24d8c32 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -278,9 +278,8 @@ intrusive_ptr & operator=(T * r);

    $Date$

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

    + Copyright İ 2003-2005 Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

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


    $Date$

    -

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

    +

    Copyright İ 2003 Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

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

    Throws: nothing.

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

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

    +

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

    +

    Throws: nothing.

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

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

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

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

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

    +

    indirection

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

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

    Returns: *this.

    +

    reset

    +
    void reset(T * r);
    +
    +

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

    +

    indirection

    T & operator*() const; // never throws
    From 745dbedbaa233486da8c89819cd2297d98084a16 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 9 Apr 2007 22:24:37 +0000 Subject: [PATCH 362/513] Fix CW regression re strcmp, strcpy [SVN r37407] --- test/smart_ptr_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp index d38c97b..0c29c9c 100644 --- a/test/smart_ptr_test.cpp +++ b/test/smart_ptr_test.cpp @@ -40,9 +40,9 @@ #include -#include #include #include +#include class Incomplete; From 66a25bd4a953717e19c9f6598645f9a434e1b029 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 13 Apr 2007 22:04:22 +0000 Subject: [PATCH 363/513] Move support [SVN r37434] --- include/boost/shared_ptr.hpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index b6bf44c..b8072ba 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -306,6 +306,38 @@ public: #endif // BOOST_NO_AUTO_PTR +// Move support + +#if defined( BOOST_HAS_RVALUE_REFS ) + + shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws + { + pn.swap( r.pn ); + } + + template + shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws + { + pn.swap( r.pn ); + } + + shared_ptr & operator=( shared_ptr && r ) // never throws + { + px = r.px; + pn.swap( r.pn ); + return *this; + } + + template + shared_ptr & operator=( shared_ptr && r ) // never throws + { + px = r.px; + pn.swap( r.pn ); + return *this; + } + +#endif + void reset() // never throws in 1.30+ { this_type().swap(*this); From 86d3f0aba7a094ab62a13da442cdd2ca13bd7623 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 15 Apr 2007 02:47:45 +0000 Subject: [PATCH 364/513] Changed move constructors/assignments to leave the source empty [SVN r37439] --- include/boost/shared_ptr.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index b8072ba..ec38248 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -313,26 +313,26 @@ public: shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws { pn.swap( r.pn ); + r.px = 0; } template shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws { pn.swap( r.pn ); + r.px = 0; } shared_ptr & operator=( shared_ptr && r ) // never throws { - px = r.px; - pn.swap( r.pn ); + this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); return *this; } template shared_ptr & operator=( shared_ptr && r ) // never throws { - px = r.px; - pn.swap( r.pn ); + this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); return *this; } From 4d45e5b9b527c8ac3a9e8566dd671848eb276829 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 28 Apr 2007 15:49:13 +0000 Subject: [PATCH 365/513] Move tests added [SVN r37526] --- test/Jamfile | 4 +- test/Jamfile.v2 | 4 +- test/shared_ptr_move_test.cpp | 95 +++++++++++++++++++++++++++++ test/shared_ptr_rv_test.cpp | 110 ++++++++++++++++++++++++++++++++++ 4 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 test/shared_ptr_move_test.cpp create mode 100644 test/shared_ptr_rv_test.cpp diff --git a/test/Jamfile b/test/Jamfile index a28d75d..a1db7b7 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -1,6 +1,6 @@ # Boost.SmartPtr Library test Jamfile # -# Copyright (c) 2003-2006 Peter Dimov +# Copyright (c) 2003-2007 Peter Dimov # Copyright (c) 2003 Dave Abrahams # # Distributed under the Boost Software License, Version 1.0. (See @@ -34,6 +34,8 @@ DEPENDS all : smart_ptr ; [ compile pointer_to_other_test.cpp ] [ run auto_ptr_rv_test.cpp ] [ run shared_ptr_alias_test.cpp ] + [ run shared_ptr_rv_test.cpp ] + [ run shared_ptr_move_test.cpp ] ; # this one is too slow to run unless explicitly requested, and ALL diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 63708b7..2d96a46 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,6 +1,6 @@ # Boost.SmartPtr Library test Jamfile # -# Copyright (c) 2003-2005 Peter Dimov +# Copyright (c) 2003-2007 Peter Dimov # Copyright (c) 2003 Dave Abrahams # # Distributed under the Boost Software License, Version 1.0. (See @@ -29,5 +29,7 @@ import testing ; [ compile pointer_to_other_test.cpp ] [ run auto_ptr_rv_test.cpp ] [ run shared_ptr_alias_test.cpp ] + [ run shared_ptr_rv_test.cpp ] + [ run shared_ptr_move_test.cpp ] ; } diff --git a/test/shared_ptr_move_test.cpp b/test/shared_ptr_move_test.cpp new file mode 100644 index 0000000..8814d3d --- /dev/null +++ b/test/shared_ptr_move_test.cpp @@ -0,0 +1,95 @@ +// +// shared_ptr_move_test.cpp +// +// Copyright (c) 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include +#include + +struct X +{ + static long instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const & ); + X & operator=( X const & ); +}; + +long X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( new X ); + BOOST_TEST( X::instances == 1 ); + + boost::shared_ptr p2( static_cast< boost::shared_ptr && >( p ) ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + boost::shared_ptr p3( static_cast< boost::shared_ptr && >( p2 ) ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p2.get() == 0 ); + + p3.reset(); + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr p( new X ); + BOOST_TEST( X::instances == 1 ); + + boost::shared_ptr p2; + p2 = static_cast< boost::shared_ptr && >( p ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + boost::shared_ptr p3; + p3 = static_cast< boost::shared_ptr && >( p2 ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p2.get() == 0 ); + + p3.reset(); + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr p( new X ); + BOOST_TEST( X::instances == 1 ); + + boost::shared_ptr p2( new X ); + BOOST_TEST( X::instances == 2 ); + p2 = static_cast< boost::shared_ptr && >( p ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + boost::shared_ptr p3( new X ); + BOOST_TEST( X::instances == 2 ); + p3 = static_cast< boost::shared_ptr && >( p2 ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p2.get() == 0 ); + + p3.reset(); + BOOST_TEST( X::instances == 0 ); + } + + return boost::report_errors(); +} diff --git a/test/shared_ptr_rv_test.cpp b/test/shared_ptr_rv_test.cpp new file mode 100644 index 0000000..fe77259 --- /dev/null +++ b/test/shared_ptr_rv_test.cpp @@ -0,0 +1,110 @@ +// +// shared_ptr_rv_test.cpp +// +// Copyright (c) 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include +#include + +struct X +{ + static long instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + + static boost::shared_ptr create() + { + return boost::shared_ptr( new X ); + } + +private: + + X( X const & ); + X & operator=( X const & ); +}; + +long X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +} From ffba68221b86c8ed1b668099dbff86d7f414b57f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 28 Apr 2007 16:15:13 +0000 Subject: [PATCH 366/513] Use __sync intrinsics on g++ 4.1+ [SVN r37527] --- include/boost/detail/atomic_count.hpp | 2 + include/boost/detail/atomic_count_sync.hpp | 57 ++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 include/boost/detail/atomic_count_sync.hpp diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 9985b2c..823b929 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -93,6 +93,8 @@ typedef long atomic_count; # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) # include +#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) +# include #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) # include #elif defined(BOOST_HAS_PTHREADS) diff --git a/include/boost/detail/atomic_count_sync.hpp b/include/boost/detail/atomic_count_sync.hpp new file mode 100644 index 0000000..e973fb7 --- /dev/null +++ b/include/boost/detail/atomic_count_sync.hpp @@ -0,0 +1,57 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED + +// +// boost/detail/atomic_count_sync.hpp +// +// atomic_count for g++ 4.1+ +// +// http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html +// +// Copyright 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( long v ) : value_( v ) {} + + void operator++() + { + __sync_add_and_fetch( &value_, 1 ); + } + + long operator--() + { + return __sync_add_and_fetch( &value_, -1 ); + } + + operator long() const + { + return __sync_fetch_and_add( &value_, 0 ); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + mutable long value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED From f980da560a7b37d4e1dcc08284650a4577cfde22 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 28 Apr 2007 18:13:12 +0000 Subject: [PATCH 367/513] Use __sync intrinsics on g++ 4.1+ [SVN r37528] --- include/boost/detail/sp_counted_base.hpp | 4 + include/boost/detail/sp_counted_base_sync.hpp | 151 ++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 include/boost/detail/sp_counted_base_sync.hpp diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index d64f239..e9d6ac9 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -47,6 +47,10 @@ # include +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + +# include + #elif defined(__GNUC__) && ( defined( __sparcv8 ) || defined( __sparcv9 ) ) # include diff --git a/include/boost/detail/sp_counted_base_sync.hpp b/include/boost/detail/sp_counted_base_sync.hpp new file mode 100644 index 0000000..5aaa917 --- /dev/null +++ b/include/boost/detail/sp_counted_base_sync.hpp @@ -0,0 +1,151 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_counted_base_sync.hpp - g++ 4.1+ __sync intrinsics +// +// Copyright (c) 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include +#include + +namespace boost +{ + +namespace detail +{ + +#if INT_MAX >= 2147483647 + +typedef int sp_int32_t; + +#else + +typedef long sp_int32_t; + +#endif + +inline void atomic_increment( sp_int32_t * pw ) +{ + __sync_fetch_and_add( pw, 1 ); +} + +inline sp_int32_t atomic_decrement( sp_int32_t * pw ) +{ + return __sync_fetch_and_add( pw, -1 ); +} + +inline sp_int32_t atomic_conditional_increment( sp_int32_t * pw ) +{ + // long r = *pw; + // if( r != 0 ) ++*pw; + // return r; + + sp_int32_t r = *pw; + + for( ;; ) + { + if( r == 0 ) + { + return r; + } + + sp_int32_t r2 = __sync_val_compare_and_swap( pw, r, r + 1 ); + + if( r2 == r ) + { + return r; + } + else + { + r = r2; + } + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + sp_int32_t use_count_; // #shared + sp_int32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( std::type_info const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return const_cast< sp_int32_t const volatile & >( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED From 5b57eff9b880698022432c1916cf6c852844734a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 8 May 2007 20:14:38 +0000 Subject: [PATCH 368/513] atomic_count_gcc_x86 added since _sync doesn't work on i386 [SVN r37637] --- include/boost/detail/atomic_count.hpp | 14 ++++ include/boost/detail/atomic_count_gcc_x86.hpp | 84 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 include/boost/detail/atomic_count_gcc_x86.hpp diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 823b929..804fd1a 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -90,16 +90,30 @@ typedef long atomic_count; } #elif defined(BOOST_AC_USE_PTHREADS) + # include + +#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) + +# include + #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) + # include + #elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + # include + #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) + # include + #elif defined(BOOST_HAS_PTHREADS) + # define BOOST_AC_USE_PTHREADS # include + #else // Use #define BOOST_DISABLE_THREADS to avoid the error diff --git a/include/boost/detail/atomic_count_gcc_x86.hpp b/include/boost/detail/atomic_count_gcc_x86.hpp new file mode 100644 index 0000000..1312e8c --- /dev/null +++ b/include/boost/detail/atomic_count_gcc_x86.hpp @@ -0,0 +1,84 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED + +// +// boost/detail/atomic_count_gcc_x86.hpp +// +// atomic_count for g++ on 486+/AMD64 +// +// Copyright 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( long v ) : value_( static_cast< int >( v ) ) {} + + void operator++() + { + __asm__ + ( + "lock\n\t" + "incl %0": + "+m"( value_ ): // output (%0) + : // inputs + "cc" // clobbers + ); + } + + long operator--() + { + return atomic_exchange_and_add( &value_, -1 ) - 1; + } + + operator long() const + { + return atomic_exchange_and_add( &value_, 0 ); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + mutable int value_; + +private: + + static int atomic_exchange_and_add( int * pw, int dv ) + { + // int r = *pw; + // *pw += dv; + // return r; + + int r; + + __asm__ __volatile__ + ( + "lock\n\t" + "xadd %1, %0": + "+m"( *pw ), "=r"( r ): // outputs (%0, %1) + "1"( dv ): // inputs (%2 == %1) + "memory", "cc" // clobbers + ); + + return r; + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED From 94db73543872e9c3e398b9c5b05b7b954f31a6a6 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Mon, 21 May 2007 01:34:43 +0000 Subject: [PATCH 369/513] gcc-4.2+ moved atomicity.hpp from bits/ to ext/ [SVN r37728] --- include/boost/detail/atomic_count_gcc.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/boost/detail/atomic_count_gcc.hpp b/include/boost/detail/atomic_count_gcc.hpp index 1160e44..9a1820d 100644 --- a/include/boost/detail/atomic_count_gcc.hpp +++ b/include/boost/detail/atomic_count_gcc.hpp @@ -17,7 +17,11 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) +# include +#else +# include +#endif namespace boost { From 4ba37fce955295fc163e651134b9aad38d95446c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 23 May 2007 23:22:45 +0000 Subject: [PATCH 370/513] Negative test for conversion to void* [SVN r37756] --- test/Jamfile | 1 + test/Jamfile.v2 | 1 + test/shared_ptr_pv_fail.cpp | 31 +++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 test/shared_ptr_pv_fail.cpp diff --git a/test/Jamfile b/test/Jamfile index a1db7b7..b3fcac9 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -36,6 +36,7 @@ DEPENDS all : smart_ptr ; [ run shared_ptr_alias_test.cpp ] [ run shared_ptr_rv_test.cpp ] [ run shared_ptr_move_test.cpp ] + [ compile-fail shared_ptr_pv_fail.cpp ] ; # this one is too slow to run unless explicitly requested, and ALL diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 2d96a46..b980bfc 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -31,5 +31,6 @@ import testing ; [ run shared_ptr_alias_test.cpp ] [ run shared_ptr_rv_test.cpp ] [ run shared_ptr_move_test.cpp ] + [ compile-fail shared_ptr_pv_fail.cpp ] ; } diff --git a/test/shared_ptr_pv_fail.cpp b/test/shared_ptr_pv_fail.cpp new file mode 100644 index 0000000..924e657 --- /dev/null +++ b/test/shared_ptr_pv_fail.cpp @@ -0,0 +1,31 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// shared_ptr_pv_fail.cpp - a negative test for converting a shared_ptr to void* +// +// Copyright 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include + +void f( void* ) +{ +} + +int main() +{ + boost::shared_ptr p; + f( p ); // must fail + return 0; +} From ed8db8b5f20b48386a3637200b1de35d91f04bb8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 6 Jun 2007 16:39:52 +0000 Subject: [PATCH 371/513] Switched to BSL, Darin Adler has given blanket permission [SVN r37917] --- compatibility.htm | 7 +++---- scoped_array.htm | 9 ++++----- scoped_ptr.htm | 9 ++++----- shared_array.htm | 9 ++++----- shared_ptr.htm | 7 +++---- smart_ptr.htm | 9 ++++----- weak_ptr.htm | 8 +++----- 7 files changed, 25 insertions(+), 33 deletions(-) diff --git a/compatibility.htm b/compatibility.htm index 71662ce..d520bd1 100644 --- a/compatibility.htm +++ b/compatibility.htm @@ -81,9 +81,8 @@

    Revised 1 February 2002

    -

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

    +

    Copyright 2002 Darin Adler. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

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

    Revised 09 January 2003

    -

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

    +

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

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

    Revised 09 January 2003

    -

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

    +

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

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

    Revised 09 January 2003

    -

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

    +

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

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

    $Date$

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

    + Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

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


    $Date$

    -

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

    +

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Distributed under the Boost Software License, Version 1.0. See accompanying + file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt.

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

    $Date$

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

    - + Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

    From ecb41cb1506ca1ff0664e5e1346e5ce35beaba43 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 4 Jul 2007 16:35:44 +0000 Subject: [PATCH 372/513] sp_unary_addr_test added (reported by Scott French) [SVN r38137] --- include/boost/detail/sp_counted_impl.hpp | 4 +- test/Jamfile | 1 + test/Jamfile.v2 | 1 + test/sp_unary_addr_test.cpp | 62 ++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 test/sp_unary_addr_test.cpp diff --git a/include/boost/detail/sp_counted_impl.hpp b/include/boost/detail/sp_counted_impl.hpp index 6963f59..919b5dc 100644 --- a/include/boost/detail/sp_counted_impl.hpp +++ b/include/boost/detail/sp_counted_impl.hpp @@ -147,7 +147,7 @@ public: virtual void * get_deleter( std::type_info const & ti ) { - return ti == typeid(D)? &del: 0; + return ti == typeid(D)? &reinterpret_cast( del ): 0; } #if defined(BOOST_SP_USE_STD_ALLOCATOR) @@ -217,7 +217,7 @@ public: virtual void * get_deleter( std::type_info const & ti ) { - return ti == typeid( D )? &d_: 0; + return ti == typeid( D )? &reinterpret_cast( d_ ): 0; } }; diff --git a/test/Jamfile b/test/Jamfile index b3fcac9..71b5df7 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -37,6 +37,7 @@ DEPENDS all : smart_ptr ; [ run shared_ptr_rv_test.cpp ] [ run shared_ptr_move_test.cpp ] [ compile-fail shared_ptr_pv_fail.cpp ] + [ run sp_unary_addr_test.cpp ] ; # this one is too slow to run unless explicitly requested, and ALL diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index b980bfc..e6b49d7 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -32,5 +32,6 @@ import testing ; [ run shared_ptr_rv_test.cpp ] [ run shared_ptr_move_test.cpp ] [ compile-fail shared_ptr_pv_fail.cpp ] + [ run sp_unary_addr_test.cpp ] ; } diff --git a/test/sp_unary_addr_test.cpp b/test/sp_unary_addr_test.cpp new file mode 100644 index 0000000..4522640 --- /dev/null +++ b/test/sp_unary_addr_test.cpp @@ -0,0 +1,62 @@ +// +// sp_unary_addr_test.cpp +// +// Copyright (c) 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include + +struct deleter +{ +private: + + void operator& (); + void operator& () const; + +public: + + int data; + + deleter(): data( 17041 ) + { + } + + void operator()( void * ) + { + } +}; + +struct X +{ +}; + +int main() +{ + X x; + + { + boost::shared_ptr p( &x, deleter() ); + + deleter * q = boost::get_deleter( p ); + + BOOST_TEST( q != 0 ); + BOOST_TEST( q != 0 && q->data == 17041 ); + } + + { + boost::shared_ptr p( &x, deleter(), std::allocator() ); + + deleter * q = boost::get_deleter( p ); + + BOOST_TEST( q != 0 ); + BOOST_TEST( q != 0 && q->data == 17041 ); + } + + return boost::report_errors(); +} From 6646d8acd27ec4aec1e7ec79d929e4781acaac3d Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Wed, 8 Aug 2007 19:02:26 +0000 Subject: [PATCH 373/513] Remove V1 Jamfiles [SVN r38516] --- test/Jamfile | 52 ---------------------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 test/Jamfile diff --git a/test/Jamfile b/test/Jamfile deleted file mode 100644 index 71b5df7..0000000 --- a/test/Jamfile +++ /dev/null @@ -1,52 +0,0 @@ -# Boost.SmartPtr Library test Jamfile -# -# Copyright (c) 2003-2007 Peter Dimov -# Copyright (c) 2003 Dave Abrahams -# -# Distributed under the Boost Software License, Version 1.0. (See -# accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -subproject libs/smart_ptr/test ; - -# bring in rules for testing -import testing ; - -# Make tests run by default. -DEPENDS all : smart_ptr ; - -{ - test-suite "smart_ptr" - : [ run smart_ptr_test.cpp ] - [ run shared_ptr_basic_test.cpp : : : <*>-Wno-non-virtual-dtor ] - [ run shared_ptr_test.cpp : : : <*>-Wno-non-virtual-dtor ] - [ run weak_ptr_test.cpp ] - [ run shared_from_this_test.cpp : : : <*>-Wno-non-virtual-dtor ] - [ run get_deleter_test.cpp ] - [ run intrusive_ptr_test.cpp ] - [ run atomic_count_test.cpp ] - [ run lw_mutex_test.cpp ] - [ compile-fail shared_ptr_assign_fail.cpp ] - [ compile-fail shared_ptr_delete_fail.cpp ] - [ compile-fail shared_ptr_compare_fail.cpp ] - [ run shared_ptr_alloc2_test.cpp ] - [ run pointer_cast_test.cpp ] - [ compile pointer_to_other_test.cpp ] - [ run auto_ptr_rv_test.cpp ] - [ run shared_ptr_alias_test.cpp ] - [ run shared_ptr_rv_test.cpp ] - [ run shared_ptr_move_test.cpp ] - [ compile-fail shared_ptr_pv_fail.cpp ] - [ run sp_unary_addr_test.cpp ] - ; - - # this one is too slow to run unless explicitly requested, and ALL - # tests are run by default when this file is subincluded from - # boost/status, so it's guarded from that case. It will only be - # built from this directory when the targets "test" (all tests) or - # "shared_ptr_alloc_test" are requested. - if [ in-invocation-subdir ] - { - run shared_ptr_alloc_test.cpp ; - } -} From bca336bf35e98958e4d9df5841c11c7193db47eb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 26 Aug 2007 19:42:50 +0000 Subject: [PATCH 374/513] Updated the unspecified_bool_type to match shared_ptr. [SVN r38975] --- include/boost/shared_array.hpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index eb69c8e..3b82f35 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -103,7 +103,23 @@ public: return px != 0; } -#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) +#elif defined( _MANAGED ) + + static void unspecified_bool( this_type*** ) + { + } + + typedef void (*unspecified_bool_type)( this_type*** ); + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: unspecified_bool; + } + +#elif \ + ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ + ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) + typedef T * (this_type::*unspecified_bool_type)() const; operator unspecified_bool_type() const // never throws From e0ca42bb88f333ffd4d6cd029bfe3309af33b66e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 26 Aug 2007 20:34:40 +0000 Subject: [PATCH 375/513] BOOST_NO_TYPEID support (#1108). [SVN r38976] --- include/boost/detail/shared_count.hpp | 3 +- .../boost/detail/sp_counted_base_cw_ppc.hpp | 4 +- .../boost/detail/sp_counted_base_cw_x86.hpp | 4 +- .../boost/detail/sp_counted_base_gcc_ia64.hpp | 4 +- .../boost/detail/sp_counted_base_gcc_ppc.hpp | 4 +- .../detail/sp_counted_base_gcc_sparc.hpp | 4 +- .../boost/detail/sp_counted_base_gcc_x86.hpp | 4 +- include/boost/detail/sp_counted_base_nt.hpp | 4 +- include/boost/detail/sp_counted_base_pt.hpp | 4 +- .../boost/detail/sp_counted_base_solaris.hpp | 4 +- include/boost/detail/sp_counted_base_sync.hpp | 4 +- include/boost/detail/sp_counted_base_w32.hpp | 4 +- include/boost/detail/sp_counted_impl.hpp | 11 ++- include/boost/detail/sp_typeinfo.hpp | 83 +++++++++++++++++++ 14 files changed, 111 insertions(+), 30 deletions(-) create mode 100644 include/boost/detail/sp_typeinfo.hpp diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index e139a7d..085b12f 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -32,7 +32,6 @@ #include // std::auto_ptr #include // std::less #include // std::bad_alloc -#include // std::type_info in get_deleter namespace boost { @@ -259,7 +258,7 @@ public: return std::less()( a.pi_, b.pi_ ); } - void * get_deleter(std::type_info const & ti) const + void * get_deleter( sp_typeinfo const & ti ) const { return pi_? pi_->get_deleter( ti ): 0; } diff --git a/include/boost/detail/sp_counted_base_cw_ppc.hpp b/include/boost/detail/sp_counted_base_cw_ppc.hpp index c56a562..17fb736 100644 --- a/include/boost/detail/sp_counted_base_cw_ppc.hpp +++ b/include/boost/detail/sp_counted_base_cw_ppc.hpp @@ -24,7 +24,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -123,7 +123,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_cw_x86.hpp b/include/boost/detail/sp_counted_base_cw_x86.hpp index 63c9fa2..32dd02c 100644 --- a/include/boost/detail/sp_counted_base_cw_x86.hpp +++ b/include/boost/detail/sp_counted_base_cw_x86.hpp @@ -25,7 +25,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -111,7 +111,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/detail/sp_counted_base_gcc_ia64.hpp index 7f4bd25..70b2a26 100644 --- a/include/boost/detail/sp_counted_base_gcc_ia64.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ia64.hpp @@ -16,7 +16,7 @@ // Lock-free algorithm by Alexander Terekhov // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -110,7 +110,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/detail/sp_counted_base_gcc_ppc.hpp index ca5cf2b..5a488f5 100644 --- a/include/boost/detail/sp_counted_base_gcc_ppc.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ppc.hpp @@ -24,7 +24,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -134,7 +134,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_gcc_sparc.hpp b/include/boost/detail/sp_counted_base_gcc_sparc.hpp index dd606f0..c6624cf 100644 --- a/include/boost/detail/sp_counted_base_gcc_sparc.hpp +++ b/include/boost/detail/sp_counted_base_gcc_sparc.hpp @@ -19,7 +19,7 @@ // // Thanks to Michael van der Westhuizen -#include +#include "sp_typeinfo.hpp" #include // int32_t namespace boost @@ -119,7 +119,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/detail/sp_counted_base_gcc_x86.hpp index 0a8e189..7d243de 100644 --- a/include/boost/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/detail/sp_counted_base_gcc_x86.hpp @@ -24,7 +24,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -126,7 +126,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_nt.hpp b/include/boost/detail/sp_counted_base_nt.hpp index 4a4401d..626e06f 100644 --- a/include/boost/detail/sp_counted_base_nt.hpp +++ b/include/boost/detail/sp_counted_base_nt.hpp @@ -18,7 +18,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -58,7 +58,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_pt.hpp b/include/boost/detail/sp_counted_base_pt.hpp index 191064f..6e0835f 100644 --- a/include/boost/detail/sp_counted_base_pt.hpp +++ b/include/boost/detail/sp_counted_base_pt.hpp @@ -18,7 +18,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#include "sp_typeinfo.hpp" #include namespace boost @@ -69,7 +69,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_solaris.hpp b/include/boost/detail/sp_counted_base_solaris.hpp index c23e2e3..58119db 100644 --- a/include/boost/detail/sp_counted_base_solaris.hpp +++ b/include/boost/detail/sp_counted_base_solaris.hpp @@ -20,7 +20,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" #include namespace boost @@ -61,7 +61,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_sync.hpp b/include/boost/detail/sp_counted_base_sync.hpp index 5aaa917..bf2a0fb 100644 --- a/include/boost/detail/sp_counted_base_sync.hpp +++ b/include/boost/detail/sp_counted_base_sync.hpp @@ -15,7 +15,7 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt -#include +#include "sp_typeinfo.hpp" #include namespace boost @@ -104,7 +104,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_w32.hpp b/include/boost/detail/sp_counted_base_w32.hpp index fb42c4e..4328962 100644 --- a/include/boost/detail/sp_counted_base_w32.hpp +++ b/include/boost/detail/sp_counted_base_w32.hpp @@ -26,7 +26,7 @@ #include #include -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -66,7 +66,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_impl.hpp b/include/boost/detail/sp_counted_impl.hpp index 919b5dc..81f92da 100644 --- a/include/boost/detail/sp_counted_impl.hpp +++ b/include/boost/detail/sp_counted_impl.hpp @@ -35,7 +35,6 @@ #include // std::allocator #endif -#include // std::type_info in get_deleter #include // std::size_t namespace boost @@ -79,7 +78,7 @@ public: boost::checked_delete( px_ ); } - virtual void * get_deleter( std::type_info const & ) + virtual void * get_deleter( detail::sp_typeinfo const & ) { return 0; } @@ -145,9 +144,9 @@ public: del( ptr ); } - virtual void * get_deleter( std::type_info const & ti ) + virtual void * get_deleter( detail::sp_typeinfo const & ti ) { - return ti == typeid(D)? &reinterpret_cast( del ): 0; + return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast( del ): 0; } #if defined(BOOST_SP_USE_STD_ALLOCATOR) @@ -215,9 +214,9 @@ public: a2.deallocate( this, 1 ); } - virtual void * get_deleter( std::type_info const & ti ) + virtual void * get_deleter( detail::sp_typeinfo const & ti ) { - return ti == typeid( D )? &reinterpret_cast( d_ ): 0; + return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast( d_ ): 0; } }; diff --git a/include/boost/detail/sp_typeinfo.hpp b/include/boost/detail/sp_typeinfo.hpp new file mode 100644 index 0000000..e78c943 --- /dev/null +++ b/include/boost/detail/sp_typeinfo.hpp @@ -0,0 +1,83 @@ +#ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED +#define BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_typeinfo.hpp +// +// Copyright 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#if defined( BOOST_NO_TYPEID ) + +namespace boost +{ + +namespace detail +{ + +typedef void* sp_typeinfo; + +template struct sp_typeid_ +{ + static char v_; +}; + +template char sp_typeid_< T >::v_; + +template struct sp_typeid_< T const >: sp_typeid_< T > +{ +}; + +template struct sp_typeid_< T volatile >: sp_typeid_< T > +{ +}; + +template struct sp_typeid_< T const volatile >: sp_typeid_< T > +{ +}; + +} // namespace detail + +} // namespace boost + +#define BOOST_SP_TYPEID(T) (&boost::detail::sp_typeid_::v_) + +#else + +#include + +namespace boost +{ + +namespace detail +{ + +#if defined( BOOST_NO_STD_TYPEINFO ) + +typedef ::type_info sp_typeinfo; + +#else + +typedef std::type_info sp_typeinfo; + +#endif + +} // namespace detail + +} // namespace boost + +#define BOOST_SP_TYPEID(T) typeid(T) + +#endif + +#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED From b2354d0a5e96ce33ef2eb2d145198b9060bc153c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 26 Aug 2007 20:35:52 +0000 Subject: [PATCH 376/513] BOOST_NO_TYPEID support (#1108). [SVN r38977] --- include/boost/shared_ptr.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index ec38248..fca726f 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -453,9 +453,9 @@ public: return pn < rhs.pn; } - void * _internal_get_deleter(std::type_info const & ti) const + void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const { - return pn.get_deleter(ti); + return pn.get_deleter( ti ); } // Tasteless as this may seem, making all members public allows member templates @@ -594,7 +594,7 @@ template std::basic_ostream & operator<< (std:: template D * get_deleter(shared_ptr const & p) { - void const * q = p._internal_get_deleter(typeid(D)); + void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D)); return const_cast(static_cast(q)); } @@ -602,7 +602,7 @@ template D * get_deleter(shared_ptr const & p) template D * get_deleter(shared_ptr const & p) { - return static_cast(p._internal_get_deleter(typeid(D))); + return static_cast(p._internal_get_deleter(BOOST_SP_TYPEID(D))); } #endif From f5ce4dbc4cb00fe4d3574bfe1f88357c196c1656 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 11 Sep 2007 20:58:19 +0000 Subject: [PATCH 377/513] Fixes #1243 [SVN r39199] --- include/boost/detail/lightweight_mutex.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index a0936cb..e740d7f 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -30,10 +30,10 @@ #if !defined(BOOST_HAS_THREADS) # include -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -# include #elif defined(BOOST_HAS_PTHREADS) # include +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# include #else // Use #define BOOST_DISABLE_THREADS to avoid the error # error Unrecognized threading platform From 5a85c1f0f2f26e6fc3c5536ddc8d8459304fa774 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 14 Sep 2007 19:19:09 +0000 Subject: [PATCH 378/513] CINT support (Nils Krumnack) [SVN r39282] --- include/boost/shared_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index fca726f..9c1365f 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -383,7 +383,7 @@ public: // implicit conversion to "bool" -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) +#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) ) || defined(__CINT__) operator bool () const { From 9db307eda567bae43a6d48893efb85bd51dc2b50 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 20 Sep 2007 20:46:56 +0000 Subject: [PATCH 379/513] defined(__ppc) added (Daniel P Furlani) [SVN r39427] --- include/boost/detail/sp_counted_base.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index e9d6ac9..dee9966 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -43,7 +43,7 @@ # include -#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) ) +#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) # include From f49a2fb1e173d847091fd59d8472a05bfd6339b7 Mon Sep 17 00:00:00 2001 From: Boris Gubenko Date: Tue, 30 Oct 2007 12:43:47 +0000 Subject: [PATCH 380/513] add support for aC++ on HP-UX ia64 [SVN r40603] --- include/boost/detail/sp_counted_base.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index dee9966..f925a5d 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -39,6 +39,10 @@ # include +#elif defined(__HP_aCC) && defined(__ia64) + +# include + #elif defined( __MWERKS__ ) && defined( __POWERPC__ ) # include From 9e41d1f1942bbe271637ad70337dfa2c150b3bc8 Mon Sep 17 00:00:00 2001 From: Boris Gubenko Date: Tue, 30 Oct 2007 12:48:44 +0000 Subject: [PATCH 381/513] add support for aC++ on HP-UX ia64 [SVN r40604] --- .../boost/detail/sp_counted_base_acc_ia64.hpp | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 include/boost/detail/sp_counted_base_acc_ia64.hpp diff --git a/include/boost/detail/sp_counted_base_acc_ia64.hpp b/include/boost/detail/sp_counted_base_acc_ia64.hpp new file mode 100644 index 0000000..baeefaf --- /dev/null +++ b/include/boost/detail/sp_counted_base_acc_ia64.hpp @@ -0,0 +1,150 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED + +// +// detail/sp_counted_base_gcc_ia64.hpp - aC++ on HP-UX IA64 +// +// Copyright 2007 Baruch Zilber +// Copyright 2007 Boris Gubenko +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// +// Lock-free algorithm by Alexander Terekhov +// + +#include "sp_typeinfo.hpp" +#include + +namespace boost +{ + +namespace detail +{ + +inline void atomic_increment( int * pw ) +{ + // ++*pw; + + _Asm_fetchadd(_FASZ_W, _SEM_REL, pw, +1, _LDHINT_NONE); +} + +inline int atomic_decrement( int * pw ) +{ + // return --*pw; + + int r = static_cast(_Asm_fetchadd(_FASZ_W, _SEM_REL, pw, -1, _LDHINT_NONE)); + if (1 == r) + { + _Asm_mf(); + } + + return r - 1; +} + +inline int atomic_conditional_increment( int * pw ) +{ + // if( *pw != 0 ) ++*pw; + // return *pw; + + int v = *pw; + + for (;;) + { + if (0 == v) + { + return 0; + } + + _Asm_mov_to_ar(_AREG_CCV, + v, + (_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE)); + int r = static_cast(_Asm_cmpxchg(_SZ_W, _SEM_ACQ, pw, v + 1, _LDHINT_NONE)); + if (r == v) + { + return r + 1; + } + + v = r; + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); // TODO use ld.acq here + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED From 7b5beeedded2b214f9a04164e35ce2b1e70da1e2 Mon Sep 17 00:00:00 2001 From: Boris Gubenko Date: Tue, 30 Oct 2007 12:58:36 +0000 Subject: [PATCH 382/513] fix typo in comment [SVN r40605] --- include/boost/detail/sp_counted_base_acc_ia64.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/sp_counted_base_acc_ia64.hpp b/include/boost/detail/sp_counted_base_acc_ia64.hpp index baeefaf..94c015d 100644 --- a/include/boost/detail/sp_counted_base_acc_ia64.hpp +++ b/include/boost/detail/sp_counted_base_acc_ia64.hpp @@ -2,7 +2,7 @@ #define BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED // -// detail/sp_counted_base_gcc_ia64.hpp - aC++ on HP-UX IA64 +// detail/sp_counted_base_acc_ia64.hpp - aC++ on HP-UX IA64 // // Copyright 2007 Baruch Zilber // Copyright 2007 Boris Gubenko From f854829d869d4fe97fa4b9bc3c07832b53f84b6b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 2 Nov 2007 23:46:04 +0000 Subject: [PATCH 383/513] Port unspecified_bool fix for Sun 5.8 from RC_1_34 [SVN r40708] --- include/boost/shared_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 9c1365f..98393c2 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -383,7 +383,7 @@ public: // implicit conversion to "bool" -#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) ) || defined(__CINT__) +#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) ) || defined(__CINT__) operator bool () const { From e6f6ec9fa350265b96c4d0a240dcffa10d6f53f0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 7 Nov 2007 22:47:55 +0000 Subject: [PATCH 384/513] Attempt unspecified bool fix for Sun 5.7-5.9 [SVN r40914] --- include/boost/shared_ptr.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 98393c2..5e1abd8 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -383,7 +383,7 @@ public: // implicit conversion to "bool" -#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) ) || defined(__CINT__) +#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) operator bool () const { @@ -405,7 +405,8 @@ public: #elif \ ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ - ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) + ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \ + ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) ) typedef T * (this_type::*unspecified_bool_type)() const; From 5ab6b2485639fdabbd230cd93c3cbd648d32f061 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Fri, 23 Nov 2007 17:03:14 +0000 Subject: [PATCH 385/513] config, detail, filesystem, system, tools, at 41278. [SVN r41316] --- include/boost/detail/atomic_count.hpp | 16 ++ include/boost/detail/atomic_count_gcc.hpp | 6 +- include/boost/detail/atomic_count_gcc_x86.hpp | 84 +++++++++ include/boost/detail/atomic_count_solaris.hpp | 59 +++++++ include/boost/detail/atomic_count_sync.hpp | 57 ++++++ include/boost/detail/lightweight_mutex.hpp | 4 +- include/boost/detail/shared_count.hpp | 3 +- include/boost/detail/sp_counted_base.hpp | 16 +- .../boost/detail/sp_counted_base_acc_ia64.hpp | 150 ++++++++++++++++ .../boost/detail/sp_counted_base_cw_ppc.hpp | 4 +- .../boost/detail/sp_counted_base_cw_x86.hpp | 4 +- .../boost/detail/sp_counted_base_gcc_ia64.hpp | 4 +- .../boost/detail/sp_counted_base_gcc_ppc.hpp | 4 +- .../detail/sp_counted_base_gcc_sparc.hpp | 166 ++++++++++++++++++ .../boost/detail/sp_counted_base_gcc_x86.hpp | 4 +- include/boost/detail/sp_counted_base_nt.hpp | 4 +- include/boost/detail/sp_counted_base_pt.hpp | 4 +- .../boost/detail/sp_counted_base_solaris.hpp | 113 ++++++++++++ include/boost/detail/sp_counted_base_sync.hpp | 151 ++++++++++++++++ include/boost/detail/sp_counted_base_w32.hpp | 4 +- include/boost/detail/sp_counted_impl.hpp | 11 +- include/boost/detail/sp_typeinfo.hpp | 83 +++++++++ 22 files changed, 918 insertions(+), 33 deletions(-) create mode 100644 include/boost/detail/atomic_count_gcc_x86.hpp create mode 100644 include/boost/detail/atomic_count_solaris.hpp create mode 100644 include/boost/detail/atomic_count_sync.hpp create mode 100644 include/boost/detail/sp_counted_base_acc_ia64.hpp create mode 100644 include/boost/detail/sp_counted_base_gcc_sparc.hpp create mode 100644 include/boost/detail/sp_counted_base_solaris.hpp create mode 100644 include/boost/detail/sp_counted_base_sync.hpp create mode 100644 include/boost/detail/sp_typeinfo.hpp diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 9985b2c..804fd1a 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -90,14 +90,30 @@ typedef long atomic_count; } #elif defined(BOOST_AC_USE_PTHREADS) + # include + +#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) + +# include + #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) + # include + +#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + +# include + #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) + # include + #elif defined(BOOST_HAS_PTHREADS) + # define BOOST_AC_USE_PTHREADS # include + #else // Use #define BOOST_DISABLE_THREADS to avoid the error diff --git a/include/boost/detail/atomic_count_gcc.hpp b/include/boost/detail/atomic_count_gcc.hpp index 9a1820d..1160e44 100644 --- a/include/boost/detail/atomic_count_gcc.hpp +++ b/include/boost/detail/atomic_count_gcc.hpp @@ -17,11 +17,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) -# include -#else -# include -#endif +#include namespace boost { diff --git a/include/boost/detail/atomic_count_gcc_x86.hpp b/include/boost/detail/atomic_count_gcc_x86.hpp new file mode 100644 index 0000000..1312e8c --- /dev/null +++ b/include/boost/detail/atomic_count_gcc_x86.hpp @@ -0,0 +1,84 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED + +// +// boost/detail/atomic_count_gcc_x86.hpp +// +// atomic_count for g++ on 486+/AMD64 +// +// Copyright 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( long v ) : value_( static_cast< int >( v ) ) {} + + void operator++() + { + __asm__ + ( + "lock\n\t" + "incl %0": + "+m"( value_ ): // output (%0) + : // inputs + "cc" // clobbers + ); + } + + long operator--() + { + return atomic_exchange_and_add( &value_, -1 ) - 1; + } + + operator long() const + { + return atomic_exchange_and_add( &value_, 0 ); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + mutable int value_; + +private: + + static int atomic_exchange_and_add( int * pw, int dv ) + { + // int r = *pw; + // *pw += dv; + // return r; + + int r; + + __asm__ __volatile__ + ( + "lock\n\t" + "xadd %1, %0": + "+m"( *pw ), "=r"( r ): // outputs (%0, %1) + "1"( dv ): // inputs (%2 == %1) + "memory", "cc" // clobbers + ); + + return r; + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_solaris.hpp b/include/boost/detail/atomic_count_solaris.hpp new file mode 100644 index 0000000..8e2907f --- /dev/null +++ b/include/boost/detail/atomic_count_solaris.hpp @@ -0,0 +1,59 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED + +// +// boost/detail/atomic_count_solaris.hpp +// based on: boost/detail/atomic_count_win32.hpp +// +// Copyright (c) 2001-2005 Peter Dimov +// Copyright (c) 2006 Michael van der Westhuizen +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( uint32_t v ): value_( v ) + { + } + + long operator++() + { + return atomic_inc_32_nv( &value_ ); + } + + long operator--() + { + return atomic_dec_32_nv( &value_ ); + } + + operator uint32_t() const + { + return static_cast( value_ ); + } + +private: + + atomic_count( atomic_count const & ); + atomic_count & operator=( atomic_count const & ); + + uint32_t value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_sync.hpp b/include/boost/detail/atomic_count_sync.hpp new file mode 100644 index 0000000..e973fb7 --- /dev/null +++ b/include/boost/detail/atomic_count_sync.hpp @@ -0,0 +1,57 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED + +// +// boost/detail/atomic_count_sync.hpp +// +// atomic_count for g++ 4.1+ +// +// http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html +// +// Copyright 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( long v ) : value_( v ) {} + + void operator++() + { + __sync_add_and_fetch( &value_, 1 ); + } + + long operator--() + { + return __sync_add_and_fetch( &value_, -1 ); + } + + operator long() const + { + return __sync_fetch_and_add( &value_, 0 ); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + mutable long value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index a0936cb..e740d7f 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -30,10 +30,10 @@ #if !defined(BOOST_HAS_THREADS) # include -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -# include #elif defined(BOOST_HAS_PTHREADS) # include +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# include #else // Use #define BOOST_DISABLE_THREADS to avoid the error # error Unrecognized threading platform diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index e139a7d..085b12f 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -32,7 +32,6 @@ #include // std::auto_ptr #include // std::less #include // std::bad_alloc -#include // std::type_info in get_deleter namespace boost { @@ -259,7 +258,7 @@ public: return std::less()( a.pi_, b.pi_ ); } - void * get_deleter(std::type_info const & ti) const + void * get_deleter( sp_typeinfo const & ti ) const { return pi_? pi_->get_deleter( ti ): 0; } diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index bc170ca..f925a5d 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -10,7 +10,7 @@ // // detail/sp_counted_base.hpp // -// Copyright 2005 Peter Dimov +// Copyright 2005, 2006 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -39,14 +39,26 @@ # include +#elif defined(__HP_aCC) && defined(__ia64) + +# include + #elif defined( __MWERKS__ ) && defined( __POWERPC__ ) # include -#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) ) +#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) # include +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + +# include + +#elif defined(__GNUC__) && ( defined( __sparcv8 ) || defined( __sparcv9 ) ) + +# include + #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) # include diff --git a/include/boost/detail/sp_counted_base_acc_ia64.hpp b/include/boost/detail/sp_counted_base_acc_ia64.hpp new file mode 100644 index 0000000..94c015d --- /dev/null +++ b/include/boost/detail/sp_counted_base_acc_ia64.hpp @@ -0,0 +1,150 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED + +// +// detail/sp_counted_base_acc_ia64.hpp - aC++ on HP-UX IA64 +// +// Copyright 2007 Baruch Zilber +// Copyright 2007 Boris Gubenko +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// +// Lock-free algorithm by Alexander Terekhov +// + +#include "sp_typeinfo.hpp" +#include + +namespace boost +{ + +namespace detail +{ + +inline void atomic_increment( int * pw ) +{ + // ++*pw; + + _Asm_fetchadd(_FASZ_W, _SEM_REL, pw, +1, _LDHINT_NONE); +} + +inline int atomic_decrement( int * pw ) +{ + // return --*pw; + + int r = static_cast(_Asm_fetchadd(_FASZ_W, _SEM_REL, pw, -1, _LDHINT_NONE)); + if (1 == r) + { + _Asm_mf(); + } + + return r - 1; +} + +inline int atomic_conditional_increment( int * pw ) +{ + // if( *pw != 0 ) ++*pw; + // return *pw; + + int v = *pw; + + for (;;) + { + if (0 == v) + { + return 0; + } + + _Asm_mov_to_ar(_AREG_CCV, + v, + (_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE)); + int r = static_cast(_Asm_cmpxchg(_SZ_W, _SEM_ACQ, pw, v + 1, _LDHINT_NONE)); + if (r == v) + { + return r + 1; + } + + v = r; + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); // TODO use ld.acq here + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_cw_ppc.hpp b/include/boost/detail/sp_counted_base_cw_ppc.hpp index c56a562..17fb736 100644 --- a/include/boost/detail/sp_counted_base_cw_ppc.hpp +++ b/include/boost/detail/sp_counted_base_cw_ppc.hpp @@ -24,7 +24,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -123,7 +123,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_cw_x86.hpp b/include/boost/detail/sp_counted_base_cw_x86.hpp index 63c9fa2..32dd02c 100644 --- a/include/boost/detail/sp_counted_base_cw_x86.hpp +++ b/include/boost/detail/sp_counted_base_cw_x86.hpp @@ -25,7 +25,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -111,7 +111,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/detail/sp_counted_base_gcc_ia64.hpp index 7f4bd25..70b2a26 100644 --- a/include/boost/detail/sp_counted_base_gcc_ia64.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ia64.hpp @@ -16,7 +16,7 @@ // Lock-free algorithm by Alexander Terekhov // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -110,7 +110,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/detail/sp_counted_base_gcc_ppc.hpp index ca5cf2b..5a488f5 100644 --- a/include/boost/detail/sp_counted_base_gcc_ppc.hpp +++ b/include/boost/detail/sp_counted_base_gcc_ppc.hpp @@ -24,7 +24,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -134,7 +134,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_gcc_sparc.hpp b/include/boost/detail/sp_counted_base_gcc_sparc.hpp new file mode 100644 index 0000000..c6624cf --- /dev/null +++ b/include/boost/detail/sp_counted_base_gcc_sparc.hpp @@ -0,0 +1,166 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_counted_base_gcc_sparc.hpp - g++ on Sparc V8+ +// +// Copyright (c) 2006 Piotr Wyderski +// Copyright (c) 2006 Tomas Puverle +// Copyright (c) 2006 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// Thanks to Michael van der Westhuizen + +#include "sp_typeinfo.hpp" +#include // int32_t + +namespace boost +{ + +namespace detail +{ + +inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ ) +{ + __asm__ __volatile__( "cas %0, %2, %1" + : "+m" (*dest_), "+r" (swap_) + : "r" (compare_) + : "memory" ); + + return swap_; +} + +inline int32_t atomic_fetch_and_add( int32_t * pw, int32_t dv ) +{ + // long r = *pw; + // *pw += dv; + // return r; + + for( ;; ) + { + int32_t r = *pw; + + if( __builtin_expect((compare_and_swap(pw, r, r + dv) == r), 1) ) + { + return r; + } + } +} + +inline void atomic_increment( int32_t * pw ) +{ + atomic_fetch_and_add( pw, 1 ); +} + +inline int32_t atomic_decrement( int32_t * pw ) +{ + return atomic_fetch_and_add( pw, -1 ); +} + +inline int32_t atomic_conditional_increment( int32_t * pw ) +{ + // long r = *pw; + // if( r != 0 ) ++*pw; + // return r; + + for( ;; ) + { + int32_t r = *pw; + + if( r == 0 ) + { + return r; + } + + if( __builtin_expect( ( compare_and_swap( pw, r, r + 1 ) == r ), 1 ) ) + { + return r; + } + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int32_t use_count_; // #shared + int32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return const_cast< int32_t const volatile & >( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/detail/sp_counted_base_gcc_x86.hpp index 0a8e189..7d243de 100644 --- a/include/boost/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/detail/sp_counted_base_gcc_x86.hpp @@ -24,7 +24,7 @@ // formulation // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -126,7 +126,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_nt.hpp b/include/boost/detail/sp_counted_base_nt.hpp index 4a4401d..626e06f 100644 --- a/include/boost/detail/sp_counted_base_nt.hpp +++ b/include/boost/detail/sp_counted_base_nt.hpp @@ -18,7 +18,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -58,7 +58,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_pt.hpp b/include/boost/detail/sp_counted_base_pt.hpp index 191064f..6e0835f 100644 --- a/include/boost/detail/sp_counted_base_pt.hpp +++ b/include/boost/detail/sp_counted_base_pt.hpp @@ -18,7 +18,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#include "sp_typeinfo.hpp" #include namespace boost @@ -69,7 +69,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_base_solaris.hpp b/include/boost/detail/sp_counted_base_solaris.hpp new file mode 100644 index 0000000..58119db --- /dev/null +++ b/include/boost/detail/sp_counted_base_solaris.hpp @@ -0,0 +1,113 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED + +// +// detail/sp_counted_base_solaris.hpp +// based on: detail/sp_counted_base_w32.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// Copyright 2006 Michael van der Westhuizen +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include "sp_typeinfo.hpp" +#include + +namespace boost +{ + +namespace detail +{ + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + uint32_t use_count_; // #shared + uint32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_inc_32( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + for( ;; ) + { + uint32_t tmp = static_cast< uint32_t const volatile& >( use_count_ ); + if( tmp == 0 ) return false; + if( atomic_cas_32( &use_count_, tmp, tmp + 1 ) == tmp ) return true; + } + } + + void release() // nothrow + { + if( atomic_dec_32_nv( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_inc_32( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_dec_32_nv( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_sync.hpp b/include/boost/detail/sp_counted_base_sync.hpp new file mode 100644 index 0000000..bf2a0fb --- /dev/null +++ b/include/boost/detail/sp_counted_base_sync.hpp @@ -0,0 +1,151 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_counted_base_sync.hpp - g++ 4.1+ __sync intrinsics +// +// Copyright (c) 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include "sp_typeinfo.hpp" +#include + +namespace boost +{ + +namespace detail +{ + +#if INT_MAX >= 2147483647 + +typedef int sp_int32_t; + +#else + +typedef long sp_int32_t; + +#endif + +inline void atomic_increment( sp_int32_t * pw ) +{ + __sync_fetch_and_add( pw, 1 ); +} + +inline sp_int32_t atomic_decrement( sp_int32_t * pw ) +{ + return __sync_fetch_and_add( pw, -1 ); +} + +inline sp_int32_t atomic_conditional_increment( sp_int32_t * pw ) +{ + // long r = *pw; + // if( r != 0 ) ++*pw; + // return r; + + sp_int32_t r = *pw; + + for( ;; ) + { + if( r == 0 ) + { + return r; + } + + sp_int32_t r2 = __sync_val_compare_and_swap( pw, r, r + 1 ); + + if( r2 == r ) + { + return r; + } + else + { + r = r2; + } + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + sp_int32_t use_count_; // #shared + sp_int32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return const_cast< sp_int32_t const volatile & >( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_w32.hpp b/include/boost/detail/sp_counted_base_w32.hpp index fb42c4e..4328962 100644 --- a/include/boost/detail/sp_counted_base_w32.hpp +++ b/include/boost/detail/sp_counted_base_w32.hpp @@ -26,7 +26,7 @@ #include #include -#include +#include "sp_typeinfo.hpp" namespace boost { @@ -66,7 +66,7 @@ public: delete this; } - virtual void * get_deleter( std::type_info const & ti ) = 0; + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; void add_ref_copy() { diff --git a/include/boost/detail/sp_counted_impl.hpp b/include/boost/detail/sp_counted_impl.hpp index 6963f59..81f92da 100644 --- a/include/boost/detail/sp_counted_impl.hpp +++ b/include/boost/detail/sp_counted_impl.hpp @@ -35,7 +35,6 @@ #include // std::allocator #endif -#include // std::type_info in get_deleter #include // std::size_t namespace boost @@ -79,7 +78,7 @@ public: boost::checked_delete( px_ ); } - virtual void * get_deleter( std::type_info const & ) + virtual void * get_deleter( detail::sp_typeinfo const & ) { return 0; } @@ -145,9 +144,9 @@ public: del( ptr ); } - virtual void * get_deleter( std::type_info const & ti ) + virtual void * get_deleter( detail::sp_typeinfo const & ti ) { - return ti == typeid(D)? &del: 0; + return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast( del ): 0; } #if defined(BOOST_SP_USE_STD_ALLOCATOR) @@ -215,9 +214,9 @@ public: a2.deallocate( this, 1 ); } - virtual void * get_deleter( std::type_info const & ti ) + virtual void * get_deleter( detail::sp_typeinfo const & ti ) { - return ti == typeid( D )? &d_: 0; + return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast( d_ ): 0; } }; diff --git a/include/boost/detail/sp_typeinfo.hpp b/include/boost/detail/sp_typeinfo.hpp new file mode 100644 index 0000000..e78c943 --- /dev/null +++ b/include/boost/detail/sp_typeinfo.hpp @@ -0,0 +1,83 @@ +#ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED +#define BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_typeinfo.hpp +// +// Copyright 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#if defined( BOOST_NO_TYPEID ) + +namespace boost +{ + +namespace detail +{ + +typedef void* sp_typeinfo; + +template struct sp_typeid_ +{ + static char v_; +}; + +template char sp_typeid_< T >::v_; + +template struct sp_typeid_< T const >: sp_typeid_< T > +{ +}; + +template struct sp_typeid_< T volatile >: sp_typeid_< T > +{ +}; + +template struct sp_typeid_< T const volatile >: sp_typeid_< T > +{ +}; + +} // namespace detail + +} // namespace boost + +#define BOOST_SP_TYPEID(T) (&boost::detail::sp_typeid_::v_) + +#else + +#include + +namespace boost +{ + +namespace detail +{ + +#if defined( BOOST_NO_STD_TYPEINFO ) + +typedef ::type_info sp_typeinfo; + +#else + +typedef std::type_info sp_typeinfo; + +#endif + +} // namespace detail + +} // namespace boost + +#define BOOST_SP_TYPEID(T) typeid(T) + +#endif + +#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED From d2194e3b243c73bd4bcfcc2d1a2e742387a1fd3c Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sun, 25 Nov 2007 18:07:19 +0000 Subject: [PATCH 386/513] Full merge from trunk at revision 41356 of entire boost-root tree. [SVN r41369] --- include/boost/intrusive_ptr.hpp | 7 +++ include/boost/shared_array.hpp | 18 +++++++- include/boost/shared_ptr.hpp | 79 +++++++++++++++++++++++++++++---- include/boost/weak_ptr.hpp | 6 --- 4 files changed, 94 insertions(+), 16 deletions(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index cd1ac11..c4ec407 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -105,6 +105,11 @@ public: return *this; } + void reset( T * rhs ) + { + this_type( rhs ).swap( *this ); + } + T * get() const { return p_; @@ -112,11 +117,13 @@ public: T & operator*() const { + BOOST_ASSERT( p_ != 0 ); return *p_; } T * operator->() const { + BOOST_ASSERT( p_ != 0 ); return p_; } diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index eb69c8e..3b82f35 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -103,7 +103,23 @@ public: return px != 0; } -#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) +#elif defined( _MANAGED ) + + static void unspecified_bool( this_type*** ) + { + } + + typedef void (*unspecified_bool_type)( this_type*** ); + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: unspecified_bool; + } + +#elif \ + ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ + ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) + typedef T * (this_type::*unspecified_bool_type)() const; operator unspecified_bool_type() const // never throws diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 9edc86f..5e1abd8 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -5,7 +5,7 @@ // shared_ptr.hpp // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. -// Copyright (c) 2001-2006 Peter Dimov +// Copyright (c) 2001-2007 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -88,6 +88,21 @@ template void sp_enable_shared_from_this( shared_count const & if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); } +#ifdef _MANAGED + +// Avoid C4793, ... causes native code generation + +struct sp_any_pointer +{ + template sp_any_pointer( T* ) {} +}; + +inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer ) +{ +} + +#else // _MANAGED + #ifdef sgi // Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed # pragma set woff 3506 @@ -101,6 +116,8 @@ inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) # pragma reset woff 3506 #endif +#endif // _MANAGED + #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) // rvalue auto_ptr support based on a technique by Dave Abrahams @@ -195,6 +212,12 @@ public: { } + // aliasing + template< class Y > + shared_ptr( shared_ptr const & r, T * p ): px( p ), pn( r.pn ) // never throws + { + } + template shared_ptr(shared_ptr const & r, boost::detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) { @@ -236,7 +259,7 @@ public: #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) template - explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() + shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() { typename Ap::element_type * tmp = r.get(); pn = boost::detail::shared_count( r ); @@ -283,6 +306,38 @@ public: #endif // BOOST_NO_AUTO_PTR +// Move support + +#if defined( BOOST_HAS_RVALUE_REFS ) + + shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws + { + pn.swap( r.pn ); + r.px = 0; + } + + template + shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws + { + pn.swap( r.pn ); + r.px = 0; + } + + shared_ptr & operator=( shared_ptr && r ) // never throws + { + this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); + return *this; + } + + template + shared_ptr & operator=( shared_ptr && r ) // never throws + { + this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); + return *this; + } + +#endif + void reset() // never throws in 1.30+ { this_type().swap(*this); @@ -304,6 +359,11 @@ public: this_type( p, d, a ).swap( *this ); } + template void reset( shared_ptr const & r, T * p ) + { + this_type( r, p ).swap( *this ); + } + reference operator* () const // never throws { BOOST_ASSERT(px != 0); @@ -323,7 +383,7 @@ public: // implicit conversion to "bool" -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) +#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) operator bool () const { @@ -345,7 +405,8 @@ public: #elif \ ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ - ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) + ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \ + ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) ) typedef T * (this_type::*unspecified_bool_type)() const; @@ -393,9 +454,9 @@ public: return pn < rhs.pn; } - void * _internal_get_deleter(std::type_info const & ti) const + void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const { - return pn.get_deleter(ti); + return pn.get_deleter( ti ); } // Tasteless as this may seem, making all members public allows member templates @@ -523,7 +584,7 @@ template std::basic_ostream & operator<< (std:: #endif // __GNUC__ < 3 -// get_deleter (experimental) +// get_deleter #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ @@ -534,7 +595,7 @@ template std::basic_ostream & operator<< (std:: template D * get_deleter(shared_ptr const & p) { - void const * q = p._internal_get_deleter(typeid(D)); + void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D)); return const_cast(static_cast(q)); } @@ -542,7 +603,7 @@ template D * get_deleter(shared_ptr const & p) template D * get_deleter(shared_ptr const & p) { - return static_cast(p._internal_get_deleter(typeid(D))); + return static_cast(p._internal_get_deleter(BOOST_SP_TYPEID(D))); } #endif diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 8f4230f..ae606f2 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -179,12 +179,6 @@ template void swap(weak_ptr & a, weak_ptr & b) a.swap(b); } -// deprecated, provided for backward compatibility -template shared_ptr make_shared(weak_ptr const & r) -{ - return r.lock(); -} - } // namespace boost #ifdef BOOST_MSVC From dba6ebbb01b82171be97da909ebcc06d6b5f0ad5 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sun, 25 Nov 2007 18:38:02 +0000 Subject: [PATCH 387/513] Full merge from trunk at revision 41356 of entire boost-root tree. [SVN r41370] --- compatibility.htm | 7 +++-- intrusive_ptr.html | 8 +++++- scoped_array.htm | 9 +++---- scoped_ptr.htm | 9 +++---- shared_array.htm | 9 +++---- shared_ptr.htm | 20 +++++++++++--- smart_ptr.htm | 9 +++---- test/Jamfile.v2 | 8 +++++- test/smart_ptr_test.cpp | 58 ++++++++++++++++++----------------------- weak_ptr.htm | 8 +++--- 10 files changed, 78 insertions(+), 67 deletions(-) diff --git a/compatibility.htm b/compatibility.htm index 71662ce..d520bd1 100644 --- a/compatibility.htm +++ b/compatibility.htm @@ -81,9 +81,8 @@

    Revised 1 February 2002

    -

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

    +

    Copyright 2002 Darin Adler. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

    diff --git a/intrusive_ptr.html b/intrusive_ptr.html index 24d8c32..c4eb899 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -61,7 +61,8 @@ intrusive_ptr & operator=(intrusive_ptr const & r); template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r); - template<class Y> intrusive_ptr & operator=(T * r); + intrusive_ptr & operator=(T * r); + void reset(T * r); T & operator*() const; // never throws T * operator->() const; // never throws @@ -146,6 +147,11 @@ intrusive_ptr & operator=(T * r);

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

    Returns: *this.

    +

    reset

    +
    void reset(T * r);
    +
    +

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

    +

    indirection

    T & operator*() const; // never throws
    diff --git a/scoped_array.htm b/scoped_array.htm index 93b1cf9..2d03509 100644 --- a/scoped_array.htm +++ b/scoped_array.htm @@ -108,10 +108,9 @@

    Revised 09 January 2003

    -

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

    +

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

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

    Revised 09 January 2003

    -

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

    +

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

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

    Revised 09 January 2003

    -

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

    +

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

    diff --git a/shared_ptr.htm b/shared_ptr.htm index 71cb9c9..e108278 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -111,6 +111,7 @@ void bad() shared_ptr(shared_ptr const & r); // never throws template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws + template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p); // never throws template<class Y> explicit shared_ptr(weak_ptr<Y> const & r); template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r); @@ -122,6 +123,7 @@ void bad() template<class Y> void reset(Y * p); template<class Y, class D> void reset(Y * p, D d); template<class Y, class D, class A> void reset(Y * p, D d, A a); + template<class Y> void reset(shared_ptr<Y> const & r, T * p); // never throws T & operator*() const; // never throws T * operator->() const; // never throws @@ -253,6 +255,13 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r); // never r.use_count().

    Throws: nothing.

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

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

    +

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

    +

    Throws: nothing.

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

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

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

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

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

    +

    indirection

    T & operator*() const; // never throws
    @@ -696,9 +709,8 @@ int * p = a.release();

    $Date$

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

    + Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

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


    $Date$

    -

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

    +

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Distributed under the Boost Software License, Version 1.0. See accompanying + file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt.

    diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fbb1657..e6b49d7 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,6 +1,6 @@ # Boost.SmartPtr Library test Jamfile # -# Copyright (c) 2003-2005 Peter Dimov +# Copyright (c) 2003-2007 Peter Dimov # Copyright (c) 2003 Dave Abrahams # # Distributed under the Boost Software License, Version 1.0. (See @@ -23,9 +23,15 @@ import testing ; [ run lw_mutex_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] [ compile-fail shared_ptr_delete_fail.cpp ] + [ compile-fail shared_ptr_compare_fail.cpp ] [ run shared_ptr_alloc2_test.cpp ] [ run pointer_cast_test.cpp ] [ compile pointer_to_other_test.cpp ] [ run auto_ptr_rv_test.cpp ] + [ run shared_ptr_alias_test.cpp ] + [ run shared_ptr_rv_test.cpp ] + [ run shared_ptr_move_test.cpp ] + [ compile-fail shared_ptr_pv_fail.cpp ] + [ run sp_unary_addr_test.cpp ] ; } diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp index 27cba2b..0c29c9c 100644 --- a/test/smart_ptr_test.cpp +++ b/test/smart_ptr_test.cpp @@ -40,9 +40,9 @@ #include -#include #include #include +#include class Incomplete; @@ -51,12 +51,6 @@ Incomplete * get_ptr( boost::shared_ptr& incomplete ) return incomplete.get(); } -using namespace std; -using boost::scoped_ptr; -using boost::scoped_array; -using boost::shared_ptr; -using boost::shared_array; - template void ck( const T* v1, T v2 ) { BOOST_TEST( *v1 == v2 ); } @@ -72,7 +66,7 @@ class UDT { explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; } ~UDT() { --UDT_use_count; - cout << "UDT with value " << value_ << " being destroyed\n"; + std::cout << "UDT with value " << value_ << " being destroyed\n"; } long value() const { return value_; } void value( long v ) { value_ = v;; } @@ -86,16 +80,16 @@ class UDT { class Incomplete; -Incomplete * check_incomplete( scoped_ptr& incomplete ) +Incomplete * check_incomplete( boost::scoped_ptr& incomplete ) { return incomplete.get(); } -Incomplete * check_incomplete( shared_ptr& incomplete, - shared_ptr& i2 ) +Incomplete * check_incomplete( boost::shared_ptr& incomplete, + boost::shared_ptr& i2 ) { incomplete.swap(i2); - cout << incomplete.use_count() << ' ' << incomplete.unique() << '\n'; + std::cout << incomplete.use_count() << ' ' << incomplete.unique() << '\n'; return incomplete.get(); } @@ -107,7 +101,7 @@ void test() // test scoped_ptr with a built-in type long * lp = new long; - scoped_ptr sp ( lp ); + boost::scoped_ptr sp ( lp ); BOOST_TEST( sp.get() == lp ); BOOST_TEST( lp == sp.get() ); BOOST_TEST( &*sp == lp ); @@ -122,7 +116,7 @@ void test() BOOST_TEST( sp.get() == 0 ); // test scoped_ptr with a user defined type - scoped_ptr udt_sp ( new UDT( 999888777 ) ); + boost::scoped_ptr udt_sp ( new UDT( 999888777 ) ); BOOST_TEST( udt_sp->value() == 999888777 ); udt_sp.reset(); udt_sp.reset( new UDT( 111222333 ) ); @@ -132,7 +126,7 @@ void test() // test scoped_array with a build-in type char * sap = new char [ 100 ]; - scoped_array sa ( sap ); + boost::scoped_array sa ( sap ); BOOST_TEST( sa.get() == sap ); BOOST_TEST( sap == sa.get() ); @@ -152,7 +146,7 @@ void test() // test shared_ptr with a built-in type int * ip = new int; - shared_ptr cp ( ip ); + boost::shared_ptr cp ( ip ); BOOST_TEST( ip == cp.get() ); BOOST_TEST( cp.use_count() == 1 ); @@ -162,7 +156,7 @@ void test() ck( static_cast(cp.get()), 54321 ); ck( static_cast(ip), *cp ); - shared_ptr cp2 ( cp ); + boost::shared_ptr cp2 ( cp ); BOOST_TEST( ip == cp2.get() ); BOOST_TEST( cp.use_count() == 2 ); BOOST_TEST( cp2.use_count() == 2 ); @@ -172,7 +166,7 @@ void test() ck( static_cast(cp2.get()), 54321 ); ck( static_cast(ip), *cp2 ); - shared_ptr cp3 ( cp ); + boost::shared_ptr cp3 ( cp ); BOOST_TEST( cp.use_count() == 3 ); BOOST_TEST( cp2.use_count() == 3 ); BOOST_TEST( cp3.use_count() == 3 ); @@ -202,20 +196,20 @@ void test() BOOST_TEST( cp.use_count() == 3 ); BOOST_TEST( *cp == 87654 ); - shared_ptr cp4; + boost::shared_ptr cp4; swap( cp2, cp4 ); BOOST_TEST( cp4.use_count() == 3 ); BOOST_TEST( *cp4 == 87654 ); BOOST_TEST( cp2.get() == 0 ); - set< shared_ptr > scp; + std::set< boost::shared_ptr > scp; scp.insert(cp4); BOOST_TEST( scp.find(cp4) != scp.end() ); - BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr(cp4) ) ); + BOOST_TEST( scp.find(cp4) == scp.find( boost::shared_ptr(cp4) ) ); // test shared_array with a built-in type char * cap = new char [ 100 ]; - shared_array ca ( cap ); + boost::shared_array ca ( cap ); BOOST_TEST( ca.get() == cap ); BOOST_TEST( cap == ca.get() ); BOOST_TEST( &ca[0] == cap ); @@ -227,8 +221,8 @@ void test() BOOST_TEST( ca[0] == 'H' ); BOOST_TEST( ca[30] == 'h' ); - shared_array ca2 ( ca ); - shared_array ca3 ( ca2 ); + boost::shared_array ca2 ( ca ); + boost::shared_array ca3 ( ca2 ); ca[0] = 'N'; ca[4] = 'd'; @@ -246,24 +240,24 @@ void test() ca.reset(); BOOST_TEST( ca.get() == 0 ); - shared_array ca4; + boost::shared_array ca4; swap( ca3, ca4 ); BOOST_TEST( ca4.use_count() == 1 ); BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); BOOST_TEST( ca3.get() == 0 ); - set< shared_array > sca; + std::set< boost::shared_array > sca; sca.insert(ca4); BOOST_TEST( sca.find(ca4) != sca.end() ); - BOOST_TEST( sca.find(ca4) == sca.find( shared_array(ca4) ) ); + BOOST_TEST( sca.find(ca4) == sca.find( boost::shared_array(ca4) ) ); // test shared_array with user defined type - shared_array udta ( new UDT[3] ); + boost::shared_array udta ( new UDT[3] ); udta[0].value( 111 ); udta[1].value( 222 ); udta[2].value( 333 ); - shared_array udta2 ( udta ); + boost::shared_array udta2 ( udta ); BOOST_TEST( udta[0].value() == 111 ); BOOST_TEST( udta[1].value() == 222 ); @@ -280,7 +274,7 @@ void test() // test shared_ptr with a user defined type UDT * up = new UDT; - shared_ptr sup ( up ); + boost::shared_ptr sup ( up ); BOOST_TEST( up == sup.get() ); BOOST_TEST( sup.use_count() == 1 ); @@ -288,7 +282,7 @@ void test() BOOST_TEST( sup->value() == 54321 ); BOOST_TEST( up->value() == 54321 ); - shared_ptr sup2; + boost::shared_ptr sup2; sup2 = sup; BOOST_TEST( sup2->value() == 54321 ); BOOST_TEST( sup.use_count() == 2 ); @@ -298,7 +292,7 @@ void test() BOOST_TEST( sup.use_count() == 2 ); BOOST_TEST( sup2.use_count() == 2 ); - cout << "OK\n"; + std::cout << "OK\n"; new char[12345]; // deliberate memory leak to verify leaks detected } diff --git a/weak_ptr.htm b/weak_ptr.htm index 68dc980..0fa87f7 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -235,10 +235,8 @@ public:

    $Date$

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

    - + Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version + 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

    From 60ae24f4ae5d4b40a1506a0c6936ba293381da89 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sun, 25 Nov 2007 22:34:55 +0000 Subject: [PATCH 388/513] Pick up missing smart_ptr, utility, and type_traits files from full merge from trunk at revision 41356 of entire boost-root tree. [SVN r41386] --- test/shared_ptr_alias_test.cpp | 146 +++++++++++++++++++++++++++++++ test/shared_ptr_compare_fail.cpp | 27 ++++++ test/shared_ptr_move_test.cpp | 95 ++++++++++++++++++++ test/shared_ptr_pv_fail.cpp | 31 +++++++ test/shared_ptr_rv_test.cpp | 110 +++++++++++++++++++++++ test/sp_unary_addr_test.cpp | 62 +++++++++++++ 6 files changed, 471 insertions(+) create mode 100644 test/shared_ptr_alias_test.cpp create mode 100644 test/shared_ptr_compare_fail.cpp create mode 100644 test/shared_ptr_move_test.cpp create mode 100644 test/shared_ptr_pv_fail.cpp create mode 100644 test/shared_ptr_rv_test.cpp create mode 100644 test/sp_unary_addr_test.cpp diff --git a/test/shared_ptr_alias_test.cpp b/test/shared_ptr_alias_test.cpp new file mode 100644 index 0000000..83d866f --- /dev/null +++ b/test/shared_ptr_alias_test.cpp @@ -0,0 +1,146 @@ +#include + +// shared_ptr_alias_test.cpp +// +// Copyright (c) 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include +#include +#include +#include + +// + +class incomplete; + +struct X +{ + int v_; + + explicit X( int v ): v_( v ) + { + } + + ~X() + { + v_ = 0; + } +}; + +int main() +{ + { + int m = 0; + boost::shared_ptr< int > p; + boost::shared_ptr< int > p2( p, &m ); + + BOOST_TEST( p2.get() == &m ); + BOOST_TEST( p2? true: false ); + BOOST_TEST( !!p2 ); + BOOST_TEST( p2.use_count() == p.use_count() ); + BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); + + p2.reset( p, 0 ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST( p2? false: true ); + BOOST_TEST( !p2 ); + BOOST_TEST( p2.use_count() == p.use_count() ); + BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); + } + + { + int m = 0; + boost::shared_ptr< int > p( new int ); + boost::shared_ptr< int const > p2( p, &m ); + + BOOST_TEST( p2.get() == &m ); + BOOST_TEST( p2? true: false ); + BOOST_TEST( !!p2 ); + BOOST_TEST( p2.use_count() == p.use_count() ); + BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); + + boost::shared_ptr< int volatile > p3; + p2.reset( p3, 0 ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST( p2? false: true ); + BOOST_TEST( !p2 ); + BOOST_TEST( p2.use_count() == p3.use_count() ); + BOOST_TEST( !( p3 < p2 ) && !( p2 < p3 ) ); + } + + { + boost::shared_ptr< int > p( new int ); + boost::shared_ptr< void const > p2( p, 0 ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST( p2? false: true ); + BOOST_TEST( !p2 ); + BOOST_TEST( p2.use_count() == p.use_count() ); + BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); + + int m = 0; + boost::shared_ptr< void volatile > p3; + + p2.reset( p3, &m ); + + BOOST_TEST( p2.get() == &m ); + BOOST_TEST( p2? true: false ); + BOOST_TEST( !!p2 ); + BOOST_TEST( p2.use_count() == p3.use_count() ); + BOOST_TEST( !( p3 < p2 ) && !( p2 < p3 ) ); + } + + { + boost::shared_ptr< incomplete > p; + boost::shared_ptr< incomplete > p2( p, 0 ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST( p2? false: true ); + BOOST_TEST( !p2 ); + BOOST_TEST( p2.use_count() == p.use_count() ); + BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); + + p2.reset( p, 0 ); + + BOOST_TEST( p2.get() == 0 ); + BOOST_TEST( p2? false: true ); + BOOST_TEST( !p2 ); + BOOST_TEST( p2.use_count() == p.use_count() ); + BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); + } + + { + boost::shared_ptr< X > p( new X( 5 ) ); + boost::shared_ptr< int const > p2( p, &p->v_ ); + + BOOST_TEST( p2.get() == &p->v_ ); + BOOST_TEST( p2? true: false ); + BOOST_TEST( !!p2 ); + BOOST_TEST( p2.use_count() == p.use_count() ); + BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); + + p.reset(); + BOOST_TEST( *p2 == 5 ); + + boost::shared_ptr< X const > p3( new X( 8 ) ); + p2.reset( p3, &p3->v_ ); + + BOOST_TEST( p2.get() == &p3->v_ ); + BOOST_TEST( p2? true: false ); + BOOST_TEST( !!p2 ); + BOOST_TEST( p2.use_count() == p3.use_count() ); + BOOST_TEST( !( p3 < p2 ) && !( p2 < p3 ) ); + + p3.reset(); + BOOST_TEST( *p2 == 8 ); + } + + return boost::report_errors(); +} diff --git a/test/shared_ptr_compare_fail.cpp b/test/shared_ptr_compare_fail.cpp new file mode 100644 index 0000000..296af14 --- /dev/null +++ b/test/shared_ptr_compare_fail.cpp @@ -0,0 +1,27 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// shared_ptr_compare_fail.cpp - a negative test for "p > q" +// +// Copyright 2006 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +int main() +{ + boost::shared_ptr p, q; + p > q; // must fail + return 0; +} diff --git a/test/shared_ptr_move_test.cpp b/test/shared_ptr_move_test.cpp new file mode 100644 index 0000000..8814d3d --- /dev/null +++ b/test/shared_ptr_move_test.cpp @@ -0,0 +1,95 @@ +// +// shared_ptr_move_test.cpp +// +// Copyright (c) 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include +#include + +struct X +{ + static long instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const & ); + X & operator=( X const & ); +}; + +long X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( new X ); + BOOST_TEST( X::instances == 1 ); + + boost::shared_ptr p2( static_cast< boost::shared_ptr && >( p ) ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + boost::shared_ptr p3( static_cast< boost::shared_ptr && >( p2 ) ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p2.get() == 0 ); + + p3.reset(); + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr p( new X ); + BOOST_TEST( X::instances == 1 ); + + boost::shared_ptr p2; + p2 = static_cast< boost::shared_ptr && >( p ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + boost::shared_ptr p3; + p3 = static_cast< boost::shared_ptr && >( p2 ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p2.get() == 0 ); + + p3.reset(); + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr p( new X ); + BOOST_TEST( X::instances == 1 ); + + boost::shared_ptr p2( new X ); + BOOST_TEST( X::instances == 2 ); + p2 = static_cast< boost::shared_ptr && >( p ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + boost::shared_ptr p3( new X ); + BOOST_TEST( X::instances == 2 ); + p3 = static_cast< boost::shared_ptr && >( p2 ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p2.get() == 0 ); + + p3.reset(); + BOOST_TEST( X::instances == 0 ); + } + + return boost::report_errors(); +} diff --git a/test/shared_ptr_pv_fail.cpp b/test/shared_ptr_pv_fail.cpp new file mode 100644 index 0000000..924e657 --- /dev/null +++ b/test/shared_ptr_pv_fail.cpp @@ -0,0 +1,31 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// shared_ptr_pv_fail.cpp - a negative test for converting a shared_ptr to void* +// +// Copyright 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include + +void f( void* ) +{ +} + +int main() +{ + boost::shared_ptr p; + f( p ); // must fail + return 0; +} diff --git a/test/shared_ptr_rv_test.cpp b/test/shared_ptr_rv_test.cpp new file mode 100644 index 0000000..fe77259 --- /dev/null +++ b/test/shared_ptr_rv_test.cpp @@ -0,0 +1,110 @@ +// +// shared_ptr_rv_test.cpp +// +// Copyright (c) 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include +#include + +struct X +{ + static long instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + + static boost::shared_ptr create() + { + return boost::shared_ptr( new X ); + } + +private: + + X( X const & ); + X & operator=( X const & ); +}; + +long X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p( X::create() ); + BOOST_TEST( X::instances == 1 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + + p.reset(); + BOOST_TEST( X::instances == 0 ); + + p = X::create(); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +} diff --git a/test/sp_unary_addr_test.cpp b/test/sp_unary_addr_test.cpp new file mode 100644 index 0000000..4522640 --- /dev/null +++ b/test/sp_unary_addr_test.cpp @@ -0,0 +1,62 @@ +// +// sp_unary_addr_test.cpp +// +// Copyright (c) 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include + +struct deleter +{ +private: + + void operator& (); + void operator& () const; + +public: + + int data; + + deleter(): data( 17041 ) + { + } + + void operator()( void * ) + { + } +}; + +struct X +{ +}; + +int main() +{ + X x; + + { + boost::shared_ptr p( &x, deleter() ); + + deleter * q = boost::get_deleter( p ); + + BOOST_TEST( q != 0 ); + BOOST_TEST( q != 0 && q->data == 17041 ); + } + + { + boost::shared_ptr p( &x, deleter(), std::allocator() ); + + deleter * q = boost::get_deleter( p ); + + BOOST_TEST( q != 0 ); + BOOST_TEST( q != 0 && q->data == 17041 ); + } + + return boost::report_errors(); +} From b2a3c9e59df684c2d4721ae1cc1d2afbbb60141a Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 10 Feb 2008 14:56:22 +0000 Subject: [PATCH 389/513] Link to people pages on the website, as they've been removed from the download. [SVN r43209] --- smarttests.htm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/smarttests.htm b/smarttests.htm index e7cedff..1833719 100644 --- a/smarttests.htm +++ b/smarttests.htm @@ -21,10 +21,10 @@ mailing list and the tests which this page describes were performed to provide a guide for current and future investigations into smart pointer implementation strategies.

    -

    Thanks are due to Dave Abrahams, +

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

    Description

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

    Exception-specifications

    -

    Exception-specifications are not used; see +

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

    All the smart pointer templates contain member functions which can never throw exceptions, because they neither throw exceptions themselves nor call other From 4ba016d29e9bd48b3bd2f5a8a66ecc0d852d7d56 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 10 Feb 2008 16:39:38 +0000 Subject: [PATCH 391/513] Merged revisions 43206,43208-43213 via svnmerge from https://svn.boost.org/svn/boost/trunk ........ r43206 | danieljames | 2008-02-10 09:55:03 +0000 (Sun, 10 Feb 2008) | 1 line Fix some broken links. ........ r43209 | danieljames | 2008-02-10 14:56:22 +0000 (Sun, 10 Feb 2008) | 1 line Link to people pages on the website, as they've been removed from the download. ........ r43210 | danieljames | 2008-02-10 15:02:17 +0000 (Sun, 10 Feb 2008) | 1 line Point links to the pages that used to be in 'more' to the site. ........ r43212 | danieljames | 2008-02-10 16:10:16 +0000 (Sun, 10 Feb 2008) | 1 line Fix links on the home page as well. ........ r43213 | danieljames | 2008-02-10 16:21:22 +0000 (Sun, 10 Feb 2008) | 1 line Generated documentation which is no longer generated. ........ [SVN r43214] --- smart_ptr.htm | 2 +- smarttests.htm | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/smart_ptr.htm b/smart_ptr.htm index 5fb0e8d..497c63f 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -105,7 +105,7 @@ and that is thrown only by functions which are explicitly documented as possibly throwing std::bad_alloc.

    Exception-specifications

    -

    Exception-specifications are not used; see +

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

    All the smart pointer templates contain member functions which can never throw exceptions, because they neither throw exceptions themselves nor call other diff --git a/smarttests.htm b/smarttests.htm index e7cedff..1833719 100644 --- a/smarttests.htm +++ b/smarttests.htm @@ -21,10 +21,10 @@ mailing list and the tests which this page describes were performed to provide a guide for current and future investigations into smart pointer implementation strategies.

    -

    Thanks are due to Dave Abrahams, +

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

    Description

    From f596092bac04939f1f4a3d50a1d71474dc0bbff8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 19 Feb 2008 13:18:58 +0000 Subject: [PATCH 392/513] Fixes #1590. [SVN r43316] --- shared_ptr.htm | 10 +++++----- test/shared_ptr_test.cpp | 12 ++++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index e108278..a752629 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -373,8 +373,8 @@ q = p;
    long use_count() const; // never throws

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

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

    Throws: nothing.

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

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

    $Date$

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

    + Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, + Version 1.0. See accompanying file LICENSE_1_0.txt + or copy at http://www.boost.org/LICENSE_1_0.txt.

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

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

    +

    Throws: nothing.

    Example

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

    Returns: *this.

    reset

    +
    void reset();
    +
    +

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

    +
    void reset(T * r);

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

    From f0f9f72be6005f1413ce57c50ef96e45e80ce599 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 3 May 2008 22:47:35 +0000 Subject: [PATCH 453/513] sp_atomic_mt2_test.cpp added. [SVN r45094] --- test/sp_atomic_mt2_test.cpp | 247 ++++++++++++++++++++++++++++++++++++ test/sp_atomic_mt_test.cpp | 7 + 2 files changed, 254 insertions(+) create mode 100644 test/sp_atomic_mt2_test.cpp diff --git a/test/sp_atomic_mt2_test.cpp b/test/sp_atomic_mt2_test.cpp new file mode 100644 index 0000000..c865359 --- /dev/null +++ b/test/sp_atomic_mt2_test.cpp @@ -0,0 +1,247 @@ + +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +// + +static void next_value( unsigned & v ) +{ + v = v % 2? 3 * v + 1: v / 2; +} + +struct X +{ + std::vector v_; + + explicit X( std::size_t n ): v_( n ) + { + for( std::size_t i = 0; i < n; ++i ) + { + v_[ i ] = i; + } + } + + unsigned get() const + { + return std::accumulate( v_.begin(), v_.end(), 0 ); + } + + void set() + { + std::for_each( v_.begin(), v_.end(), next_value ); + } +}; + +static boost::shared_ptr ps; + +static boost::detail::lightweight_mutex lm; +static boost::shared_mutex rw; + +enum prim_type +{ + pt_mutex, + pt_rwlock, + pt_atomics +}; + +int read_access( prim_type pt ) +{ + switch( pt ) + { + case pt_mutex: + { + boost::detail::lightweight_mutex::scoped_lock lock( lm ); + return ps->get(); + } + + case pt_rwlock: + { + boost::shared_lock lock( rw ); + return ps->get(); + } + + case pt_atomics: + { + boost::shared_ptr p2 = ps.atomic_load(); + return p2->get(); + } + } +} + +void write_access( prim_type pt ) +{ + switch( pt ) + { + case pt_mutex: + { + boost::detail::lightweight_mutex::scoped_lock lock( lm ); + ps->set(); + } + break; + + case pt_rwlock: + { + boost::unique_lock lock( rw ); + ps->set(); + } + break; + + case pt_atomics: + { + boost::shared_ptr p1 = ps.atomic_load(); + + for( ;; ) + { + boost::shared_ptr p2( new X( *p1 ) ); + p2->set(); + + if( ps.atomic_compare_swap( p1, p2 ) ) break; + } + } + break; + } +} + +void worker( int k, prim_type pt, int n, int r ) +{ + ++r; + + unsigned s = 0, nr = 0, nw = 0; + + for( int i = 0; i < n; ++i ) + { + if( i % r ) + { + s += read_access( pt ); + ++nr; + } + else + { + write_access( pt ); + ++s; + ++nw; + } + } + + printf( "Worker %2d: %u:%u, %10u\n", k, nr, nw, s ); +} + +#if defined( BOOST_HAS_PTHREADS ) + char const * thmodel = "POSIX"; +#else + char const * thmodel = "Windows"; +#endif + +char const * pt_to_string( prim_type pt ) +{ + switch( pt ) + { + case pt_mutex: + + return "mutex"; + + case pt_rwlock: + + return "rwlock"; + + case pt_atomics: + + return "atomics"; + } +} + +static void handle_pt_option( std::string const & opt, prim_type & pt, prim_type pt2 ) +{ + if( opt == pt_to_string( pt2 ) ) + { + pt = pt2; + } +} + +static void handle_int_option( std::string const & opt, std::string const & prefix, int & k, int kmin, int kmax ) +{ + if( opt.substr( 0, prefix.size() ) == prefix ) + { + int v = atoi( opt.substr( prefix.size() ).c_str() ); + + if( v >= kmin && v <= kmax ) + { + k = v; + } + } +} + +int main( int ac, char const * av[] ) +{ + using namespace std; // printf, clock_t, clock + + int m = 4; // threads + int n = 10000; // vector size + int k = 1000000; // iterations + int r = 100; // read/write ratio, r:1 + + prim_type pt = pt_atomics; + + for( int i = 1; i < ac; ++i ) + { + handle_pt_option( av[i], pt, pt_mutex ); + handle_pt_option( av[i], pt, pt_rwlock ); + handle_pt_option( av[i], pt, pt_atomics ); + + handle_int_option( av[i], "n=", n, 1, INT_MAX ); + handle_int_option( av[i], "size=", n, 1, INT_MAX ); + + handle_int_option( av[i], "k=", k, 1, INT_MAX ); + handle_int_option( av[i], "iterations=", k, 1, INT_MAX ); + + handle_int_option( av[i], "m=", m, 1, INT_MAX ); + handle_int_option( av[i], "threads=", m, 1, INT_MAX ); + + handle_int_option( av[i], "r=", r, 1, INT_MAX ); + handle_int_option( av[i], "ratio=", r, 1, INT_MAX ); + } + + printf( "%s: threads=%d size=%d iterations=%d ratio=%d %s\n\n", thmodel, m, n, k, r, pt_to_string( pt ) ); + + ps.reset( new X( n ) ); + + clock_t t = clock(); + + std::vector a( m ); + + for( int i = 0; i < m; ++i ) + { + boost::detail::lw_thread_create( a[ i ], boost::bind( worker, i, pt, k, r ) ); + } + + for( int j = 0; j < m; ++j ) + { + pthread_join( a[ j ], 0 ); + } + + t = clock() - t; + + double ts = static_cast( t ) / CLOCKS_PER_SEC; + printf( "%.3f seconds, %.3f accesses per microsecond.\n", ts, m * k / ts / 1e+6 ); +} diff --git a/test/sp_atomic_mt_test.cpp b/test/sp_atomic_mt_test.cpp index bef549d..143df98 100644 --- a/test/sp_atomic_mt_test.cpp +++ b/test/sp_atomic_mt_test.cpp @@ -1,3 +1,10 @@ + +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + //#define USE_MUTEX //#define USE_RWLOCK From 2f1b1acc7a7ce6d3956fff629acc50e2cc791897 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 6 May 2008 18:58:15 +0000 Subject: [PATCH 454/513] Fix g++ 3.2 regression. [SVN r45177] --- include/boost/detail/sp_convertible.hpp | 12 ++++++++++++ include/boost/intrusive_ptr.hpp | 5 +---- include/boost/shared_ptr.hpp | 5 +---- include/boost/weak_ptr.hpp | 4 ++-- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/include/boost/detail/sp_convertible.hpp b/include/boost/detail/sp_convertible.hpp index 00463b3..798497c 100644 --- a/include/boost/detail/sp_convertible.hpp +++ b/include/boost/detail/sp_convertible.hpp @@ -17,6 +17,16 @@ #include +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( BOOST_NO_SFINAE ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ < 303 ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + namespace boost { @@ -57,4 +67,6 @@ template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_i } // namespace boost +#endif // !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + #endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 8982fe9..77a603e 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -22,10 +22,7 @@ #include #include - -#if !defined( BOOST_NO_SFINAE ) #include -#endif #include // for std::less @@ -78,7 +75,7 @@ public: #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) template -#if !defined( BOOST_NO_SFINAE ) +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) intrusive_ptr( intrusive_ptr const & rhs, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 02f2f4f..2c20ecc 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -31,10 +31,7 @@ #include #include #include - -#if !defined( BOOST_NO_SFINAE ) #include -#endif #if !defined(BOOST_SP_NO_ATOMIC_ACCESS) #include @@ -228,7 +225,7 @@ public: } template -#if !defined( BOOST_NO_SFINAE ) +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) shared_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index aadb60a..b300813 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -61,7 +61,7 @@ public: // template -#if !defined( BOOST_NO_SFINAE ) +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) weak_ptr( weak_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) @@ -76,7 +76,7 @@ public: } template -#if !defined( BOOST_NO_SFINAE ) +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) weak_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) From 4b0490c0ae03c03a4f6793b012dfdaa399d36c6e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 7 May 2008 10:15:16 +0000 Subject: [PATCH 455/513] Fix sp_convertible_test.cpp failure in C++0x mode. [SVN r45194] --- include/boost/shared_ptr.hpp | 12 ++++++++++-- test/sp_convertible_test.cpp | 5 +++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 2c20ecc..3bf00b1 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -349,7 +349,16 @@ public: } template - shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + shared_ptr( shared_ptr && r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + shared_ptr( shared_ptr && r ) + +#endif + : px( r.px ), pn() // never throws { pn.swap( r.pn ); r.px = 0; @@ -772,7 +781,6 @@ template D * get_deleter( shared_ptr const & p ) #endif } - return del; } diff --git a/test/sp_convertible_test.cpp b/test/sp_convertible_test.cpp index 165d55f..7f49e1f 100644 --- a/test/sp_convertible_test.cpp +++ b/test/sp_convertible_test.cpp @@ -59,7 +59,12 @@ int g( boost::shared_ptr ) int main() { + boost::shared_ptr p1; + BOOST_TEST( 1 == f( p1 ) ); BOOST_TEST( 1 == f( boost::shared_ptr() ) ); + + boost::shared_ptr p2; + BOOST_TEST( 4 == g( p2 ) ); BOOST_TEST( 4 == g( boost::shared_ptr() ) ); return boost::report_errors(); From d52878df885d5b3127af6f9cf87fd4f40c3e2104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 8 May 2008 19:08:38 +0000 Subject: [PATCH 456/513] Replaced non-ascii characters, ticket 1736 [SVN r45224] --- include/boost/pointer_cast.hpp | 2 +- include/boost/pointer_to_other.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/pointer_cast.hpp b/include/boost/pointer_cast.hpp index 5a5bec0..6e532eb 100644 --- a/include/boost/pointer_cast.hpp +++ b/include/boost/pointer_cast.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2005. +// (C) Copyright Ion Gaztanaga 2005. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) diff --git a/include/boost/pointer_to_other.hpp b/include/boost/pointer_to_other.hpp index 1cf2627..8516734 100644 --- a/include/boost/pointer_to_other.hpp +++ b/include/boost/pointer_to_other.hpp @@ -4,7 +4,7 @@ // // pointer_to_other.hpp // -// (C) Copyright Ion Gaztañaga 2005. +// (C) Copyright Ion Gaztanaga 2005. // Copyright (c) 2005 Peter Dimov. // // Distributed under the Boost Software License, Version 1.0. From d2610796164870db794fa3e96b4be204e1b1393b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 8 May 2008 19:22:16 +0000 Subject: [PATCH 457/513] Replaced non-ascii characters, ticket 1736 [SVN r45225] --- test/pointer_cast_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pointer_cast_test.cpp b/test/pointer_cast_test.cpp index 0d5d652..6e4620c 100644 --- a/test/pointer_cast_test.cpp +++ b/test/pointer_cast_test.cpp @@ -1,7 +1,7 @@ // // pointer_cast_test.cpp - a test for boost/pointer_cast.hpp // -// Copyright (c) 2005 Ion Gaztañaga +// Copyright (c) 2005 Ion Gaztanaga // Copyright (c) 2005 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See From 05e050abe0080528e4dec4ad8ec07f739d661391 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 13 May 2008 23:53:12 +0000 Subject: [PATCH 458/513] Disable sp_convertible for Borland 5.x. [SVN r45346] --- include/boost/detail/sp_convertible.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/detail/sp_convertible.hpp b/include/boost/detail/sp_convertible.hpp index 798497c..017217b 100644 --- a/include/boost/detail/sp_convertible.hpp +++ b/include/boost/detail/sp_convertible.hpp @@ -25,6 +25,10 @@ # define BOOST_SP_NO_SP_CONVERTIBLE #endif +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x600 ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) namespace boost From 31685fe5516eca027bd5b2d78ff4d00cb945b20e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 14 May 2008 00:21:28 +0000 Subject: [PATCH 459/513] Updated Borland workaround to properly use BOOST_NO_MEMBER_TEMPLATE_FRIENDS. [SVN r45347] --- include/boost/enable_shared_from_this.hpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 10accd6..b624ee9 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -21,10 +21,14 @@ namespace boost { +#if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) + template< class T > class enable_shared_from_this; template< class T, class Y > void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ); template< class T, class Y > void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ); +#endif + template< class T > class enable_shared_from_this { protected: @@ -78,7 +82,12 @@ private: } } -#if defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, <= 0x551 ) +#if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) + + template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ); + template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ); + +#else public: @@ -90,7 +99,8 @@ public: if( _weak_count.use_count() == 0 ) { _weak_count = owner.get_shared_count(); - }else if( !_shared_count.empty() ) + } + else if( !_shared_count.empty() ) { BOOST_ASSERT( owner.unique() ); // no weak_ptrs to owner should exist either, but there's no way to check that detail::sp_deleter_wrapper * pd = detail::basic_get_deleter( _shared_count ); @@ -101,9 +111,6 @@ public: detail::shared_count().swap( _shared_count ); } } - - template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ); - template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ); }; template< class T, class Y > inline void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ) From 83e2510ce572dc38d3e68ce6c8af293246f24da6 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Fri, 16 May 2008 11:12:32 +0000 Subject: [PATCH 460/513] Use the "no_tr1" version of : addition of Boost.Exception support to throw_exception has created new cyclic dependencies with Boost.TR1. [SVN r45422] --- include/boost/intrusive_ptr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 77a603e..338e672 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -24,7 +24,7 @@ #include #include -#include // for std::less +#include // for std::less #if !defined(BOOST_NO_IOSTREAM) #if !defined(BOOST_NO_IOSFWD) From 2bfe13c9c4fd7be06a5c5e9c6b43ed1c39c6cbb8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 19 May 2008 15:09:54 +0000 Subject: [PATCH 461/513] Renamed CRITICAL_SECTION to critical_section to avoid ambiguity. [SVN r45545] --- include/boost/detail/lwm_win32_cs.hpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/include/boost/detail/lwm_win32_cs.hpp b/include/boost/detail/lwm_win32_cs.hpp index 4ee0a71..8142069 100644 --- a/include/boost/detail/lwm_win32_cs.hpp +++ b/include/boost/detail/lwm_win32_cs.hpp @@ -29,7 +29,7 @@ namespace detail #ifndef BOOST_USE_WINDOWS_H -struct CRITICAL_SECTION +struct critical_section { struct critical_section_debug * DebugInfo; long LockCount; @@ -43,10 +43,14 @@ struct CRITICAL_SECTION #endif }; -extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(CRITICAL_SECTION *); -extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(CRITICAL_SECTION *); -extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(CRITICAL_SECTION *); -extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(CRITICAL_SECTION *); +extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(critical_section *); + +#else + +typedef ::CRITICAL_SECTION critical_section; #endif // #ifndef BOOST_USE_WINDOWS_H @@ -54,7 +58,7 @@ class lightweight_mutex { private: - CRITICAL_SECTION cs_; + critical_section cs_; lightweight_mutex(lightweight_mutex const &); lightweight_mutex & operator=(lightweight_mutex const &); From 366472fc35a1f6138abf333c8e2c20bfcc05b300 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 23 May 2008 20:29:14 +0000 Subject: [PATCH 462/513] Fix #1938 in trunk [SVN r45690] --- include/boost/detail/sp_counted_base_sync.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/detail/sp_counted_base_sync.hpp b/include/boost/detail/sp_counted_base_sync.hpp index c01c3c5..d72dac2 100644 --- a/include/boost/detail/sp_counted_base_sync.hpp +++ b/include/boost/detail/sp_counted_base_sync.hpp @@ -18,6 +18,10 @@ #include #include +#if defined( __ia64__ ) && defined( __INTEL_COMPILER ) +# include +#endif + namespace boost { From a9cd84f43d5d1d5d03e169e42b09a5c82cc3de54 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 23 May 2008 20:30:15 +0000 Subject: [PATCH 463/513] Fix #1938 in release [SVN r45691] --- include/boost/detail/sp_counted_base_sync.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/detail/sp_counted_base_sync.hpp b/include/boost/detail/sp_counted_base_sync.hpp index c01c3c5..d72dac2 100644 --- a/include/boost/detail/sp_counted_base_sync.hpp +++ b/include/boost/detail/sp_counted_base_sync.hpp @@ -18,6 +18,10 @@ #include #include +#if defined( __ia64__ ) && defined( __INTEL_COMPILER ) +# include +#endif + namespace boost { From 2a92df56f2dee5579de8bd6ca5acae6bb7d54d2a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 2 Jun 2008 20:01:30 +0000 Subject: [PATCH 464/513] #include in spinlock_sync.hpp as well. [SVN r46055] --- include/boost/detail/spinlock_sync.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/detail/spinlock_sync.hpp b/include/boost/detail/spinlock_sync.hpp index d602365..a752396 100644 --- a/include/boost/detail/spinlock_sync.hpp +++ b/include/boost/detail/spinlock_sync.hpp @@ -17,6 +17,10 @@ #include +#if defined( __ia64__ ) && defined( __INTEL_COMPILER ) +# include +#endif + namespace boost { From 866590ee97966451b1c0e9bc38a4bcdb30c7225a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 09:55:08 +0000 Subject: [PATCH 465/513] Merged 43316, 43317, 43318, 43733, 43782, 43873, 43888, 43916, 43950, 44055, 44056, 44058, 44073, 44074, 44132, 44137, 44138, 44140, 44344 from trunk to release [SVN r47339] --- include/boost/detail/shared_count.hpp | 19 +++ include/boost/detail/sp_counted_base.hpp | 4 + include/boost/detail/sp_counted_base_spin.hpp | 131 ++++++++++++++++ include/boost/detail/spinlock.hpp | 47 ++++++ include/boost/detail/spinlock_gcc_arm.hpp | 85 ++++++++++ include/boost/detail/spinlock_nt.hpp | 89 +++++++++++ include/boost/detail/spinlock_pool.hpp | 85 ++++++++++ include/boost/detail/spinlock_pt.hpp | 79 ++++++++++ include/boost/detail/spinlock_sync.hpp | 83 ++++++++++ include/boost/detail/spinlock_w32.hpp | 113 ++++++++++++++ include/boost/detail/yield_k.hpp | 145 ++++++++++++++++++ include/boost/scoped_array.hpp | 3 + include/boost/scoped_ptr.hpp | 3 + include/boost/shared_ptr.hpp | 20 +++ include/boost/weak_ptr.hpp | 26 +--- shared_ptr.htm | 11 +- test/Jamfile.v2 | 9 ++ test/esft_regtest.cpp | 136 ++++++++++++++++ test/scoped_array_eq_fail.cpp | 27 ++++ test/scoped_ptr_eq_fail.cpp | 27 ++++ test/shared_from_this_test.cpp | 3 +- test/shared_ptr_test.cpp | 12 ++ test/spinlock_pool_test.cpp | 30 ++++ test/spinlock_test.cpp | 31 ++++ test/spinlock_try_test.cpp | 46 ++++++ test/yield_k_test.cpp | 23 +++ 26 files changed, 1256 insertions(+), 31 deletions(-) create mode 100644 include/boost/detail/sp_counted_base_spin.hpp create mode 100644 include/boost/detail/spinlock.hpp create mode 100644 include/boost/detail/spinlock_gcc_arm.hpp create mode 100644 include/boost/detail/spinlock_nt.hpp create mode 100644 include/boost/detail/spinlock_pool.hpp create mode 100644 include/boost/detail/spinlock_pt.hpp create mode 100644 include/boost/detail/spinlock_sync.hpp create mode 100644 include/boost/detail/spinlock_w32.hpp create mode 100644 include/boost/detail/yield_k.hpp create mode 100644 test/esft_regtest.cpp create mode 100644 test/scoped_array_eq_fail.cpp create mode 100644 test/scoped_ptr_eq_fail.cpp create mode 100644 test/spinlock_pool_test.cpp create mode 100644 test/spinlock_test.cpp create mode 100644 test/spinlock_try_test.cpp create mode 100644 test/yield_k_test.cpp diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 085b12f..1eae671 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -46,6 +46,8 @@ int const weak_count_id = 0x298C38A4; #endif +struct sp_nothrow_tag {}; + class weak_count; class shared_count @@ -216,6 +218,7 @@ public: } explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 + shared_count( weak_count const & r, sp_nothrow_tag ); // constructs an empty *this when r.use_count() == 0 shared_count & operator= (shared_count const & r) // nothrow { @@ -248,6 +251,11 @@ public: return use_count() == 1; } + bool empty() const // nothrow + { + return pi_ == 0; + } + friend inline bool operator==(shared_count const & a, shared_count const & b) { return a.pi_ == b.pi_; @@ -364,6 +372,17 @@ inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ ) } } +inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ ) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif +{ + if( pi_ != 0 && !pi_->add_ref_lock() ) + { + pi_ = 0; + } +} + } // namespace detail } // namespace boost diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index f2e59b9..312893d 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -23,6 +23,10 @@ # include +#elif defined( BOOST_SP_USE_SPINLOCK ) + +# include + #elif defined( BOOST_SP_USE_PTHREADS ) # include diff --git a/include/boost/detail/sp_counted_base_spin.hpp b/include/boost/detail/sp_counted_base_spin.hpp new file mode 100644 index 0000000..610a468 --- /dev/null +++ b/include/boost/detail/sp_counted_base_spin.hpp @@ -0,0 +1,131 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_spin.hpp - spinlock pool atomic emulation +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include + +namespace boost +{ + +namespace detail +{ + +inline int atomic_exchange_and_add( int * pw, int dv ) +{ + spinlock_pool<1>::scoped_lock lock( pw ); + + int r = *pw; + *pw += dv; + return r; +} + +inline void atomic_increment( int * pw ) +{ + spinlock_pool<1>::scoped_lock lock( pw ); + ++*pw; +} + +inline int atomic_conditional_increment( int * pw ) +{ + spinlock_pool<1>::scoped_lock lock( pw ); + + int rv = *pw; + if( rv != 0 ) ++*pw; + return rv; +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_exchange_and_add( &use_count_, -1 ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + spinlock_pool<1>::scoped_lock lock( &use_count_ ); + return use_count_; + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED diff --git a/include/boost/detail/spinlock.hpp b/include/boost/detail/spinlock.hpp new file mode 100644 index 0000000..e273647 --- /dev/null +++ b/include/boost/detail/spinlock.hpp @@ -0,0 +1,47 @@ +#ifndef BOOST_DETAIL_SPINLOCK_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/spinlock.hpp +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// struct spinlock +// { +// void lock(); +// bool try_lock(); +// void unlock(); +// +// class scoped_lock; +// }; +// +// #define BOOST_DETAIL_SPINLOCK_INIT +// + +#include + +#if defined(__GNUC__) && defined( __arm__ ) +# include +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) +# include +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# include +#elif defined(BOOST_HAS_PTHREADS) +# include +#elif !defined(BOOST_HAS_THREADS) +# include +#else +# error Unrecognized threading platform +#endif + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_gcc_arm.hpp b/include/boost/detail/spinlock_gcc_arm.hpp new file mode 100644 index 0000000..c21163b --- /dev/null +++ b/include/boost/detail/spinlock_gcc_arm.hpp @@ -0,0 +1,85 @@ +#ifndef BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED + +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + int v_; + +public: + + bool try_lock() + { + int r; + + __asm__ __volatile__( + "swp %0, %1, [%2]": + "=&r"( r ): // outputs + "r"( 1 ), "r"( &v_ ): // inputs + "memory", "cc" ); + + return r == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + __asm__ __volatile__( "" ::: "memory" ); + *const_cast< int volatile* >( &v_ ) = 0; + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {0} + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_nt.hpp b/include/boost/detail/spinlock_nt.hpp new file mode 100644 index 0000000..f03ba08 --- /dev/null +++ b/include/boost/detail/spinlock_nt.hpp @@ -0,0 +1,89 @@ +#ifndef BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + bool locked_; + +public: + + inline bool try_lock() + { + if( locked_ ) + { + return false; + } + else + { + locked_ = true; + return true; + } + } + + inline void lock() + { + BOOST_ASSERT( !locked_ ); + locked_ = true; + } + + inline void unlock() + { + BOOST_ASSERT( locked_ ); + locked_ = false; + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT { false } + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_pool.hpp b/include/boost/detail/spinlock_pool.hpp new file mode 100644 index 0000000..92d26cb --- /dev/null +++ b/include/boost/detail/spinlock_pool.hpp @@ -0,0 +1,85 @@ +#ifndef BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/spinlock_pool.hpp +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// spinlock_pool<0> is reserved for atomic<>, when/if it arrives +// spinlock_pool<1> is reserved for shared_ptr reference counts +// spinlock_pool<2> is reserved for shared_ptr atomic access +// + +#include + +namespace boost +{ + +namespace detail +{ + +template< int I > class spinlock_pool +{ +private: + + static spinlock pool_[ 41 ]; + +public: + + static spinlock & spinlock_for( void const * pv ) + { + size_t i = reinterpret_cast< size_t >( pv ) % 41; + return pool_[ i ]; + } + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( void const * pv ): sp_( spinlock_for( pv ) ) + { + sp_.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +template< int I > spinlock spinlock_pool< I >::pool_[ 41 ] = +{ + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT +}; + +} // namespace detail +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_pt.hpp b/include/boost/detail/spinlock_pt.hpp new file mode 100644 index 0000000..dfb2d6f --- /dev/null +++ b/include/boost/detail/spinlock_pt.hpp @@ -0,0 +1,79 @@ +#ifndef BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + pthread_mutex_t v_; + +public: + + bool try_lock() + { + return pthread_mutex_trylock( &v_ ) == 0; + } + + void lock() + { + pthread_mutex_lock( &v_ ); + } + + void unlock() + { + pthread_mutex_unlock( &v_ ); + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT { PTHREAD_MUTEX_INITIALIZER } + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_sync.hpp b/include/boost/detail/spinlock_sync.hpp new file mode 100644 index 0000000..d602365 --- /dev/null +++ b/include/boost/detail/spinlock_sync.hpp @@ -0,0 +1,83 @@ +#ifndef BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + int v_; + +public: + + bool try_lock() + { + int r = __sync_lock_test_and_set( &v_, 1 ); + return r == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + __sync_lock_release( &v_ ); + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {0} + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_w32.hpp b/include/boost/detail/spinlock_w32.hpp new file mode 100644 index 0000000..76cfe8f --- /dev/null +++ b/include/boost/detail/spinlock_w32.hpp @@ -0,0 +1,113 @@ +#ifndef BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include + +// BOOST_COMPILER_FENCE + +#if defined(__INTEL_COMPILER) + +#define BOOST_COMPILER_FENCE __memory_barrier(); + +#elif defined( _MSC_VER ) && _MSC_VER >= 1310 + +extern "C" void _ReadWriteBarrier(); +#pragma intrinsic( _ReadWriteBarrier ) + +#define BOOST_COMPILER_FENCE _ReadWriteBarrier(); + +#elif defined(__GNUC__) + +#define BOOST_COMPILER_FENCE __asm__ __volatile__( "" ::: "memory" ); + +#else + +#define BOOST_COMPILER_FENCE + +#endif + +// + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + long v_; + +public: + + bool try_lock() + { + long r = BOOST_INTERLOCKED_EXCHANGE( &v_, 1 ); + + BOOST_COMPILER_FENCE + + return r == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + BOOST_COMPILER_FENCE + *const_cast< long volatile* >( &v_ ) = 0; + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {0} + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED diff --git a/include/boost/detail/yield_k.hpp b/include/boost/detail/yield_k.hpp new file mode 100644 index 0000000..d856d57 --- /dev/null +++ b/include/boost/detail/yield_k.hpp @@ -0,0 +1,145 @@ +#ifndef BOOST_DETAIL_YIELD_K_HPP_INCLUDED +#define BOOST_DETAIL_YIELD_K_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/yield_k.hpp +// +// Copyright (c) 2008 Peter Dimov +// +// void yield( unsigned k ); +// +// Typical use: +// +// for( unsigned k = 0; !try_lock(); ++k ) yield( k ); +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include + +// BOOST_SMT_PAUSE + +#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) + +extern "C" void _mm_pause(); +#pragma intrinsic( _mm_pause ) + +#define BOOST_SMT_PAUSE _mm_pause(); + +#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) + +#define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" ::: "memory" ); + +#endif + +// + +#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) + +#if defined( BOOST_USE_WINDOWS_H ) +# include +#endif + +namespace boost +{ + +namespace detail +{ + +#if !defined( BOOST_USE_WINDOWS_H ) + extern "C" void __stdcall Sleep( unsigned ms ); +#endif + +inline void yield( unsigned k ) +{ + if( k < 4 ) + { + } +#if defined( BOOST_SMT_PAUSE ) + else if( k < 16 ) + { + BOOST_SMT_PAUSE + } +#endif + else if( k < 32 ) + { + Sleep( 0 ); + } + else + { + Sleep( 1 ); + } +} + +} // namespace detail + +} // namespace boost + +#elif defined( BOOST_HAS_PTHREADS ) + +#include +#include + +namespace boost +{ + +namespace detail +{ + +inline void yield( unsigned k ) +{ + if( k < 4 ) + { + } +#if defined( BOOST_SMT_PAUSE ) + else if( k < 16 ) + { + BOOST_SMT_PAUSE + } +#endif + else if( k < 32 || k & 1 ) + { + sched_yield(); + } + else + { + struct timespec rqtp = { 0 }; + + rqtp.tv_sec = 0; + rqtp.tv_nsec = 1000; + + nanosleep( &rqtp, 0 ); + } +} + +} // namespace detail + +} // namespace boost + +#else + +namespace boost +{ + +namespace detail +{ + +inline void yield( unsigned ) +{ +} + +} // namespace detail + +} // namespace boost + +#endif + +#endif // #ifndef BOOST_DETAIL_YIELD_K_HPP_INCLUDED diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index 667dfff..fcb80f6 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -46,6 +46,9 @@ private: typedef scoped_array this_type; + void operator==( scoped_array const& ) const; + void operator!=( scoped_array const& ) const; + public: typedef T element_type; diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 651deed..279cec3 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -47,6 +47,9 @@ private: typedef scoped_ptr this_type; + void operator==( scoped_ptr const& ) const; + void operator!=( scoped_ptr const& ) const; + public: typedef T element_type; diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 5e1abd8..6f4d49a 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -31,7 +31,14 @@ #include // for std::swap #include // for std::less #include // for std::bad_cast + +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) #include // for std::basic_ostream +#else +#include +#endif +#endif #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash # pragma warning(push) @@ -207,6 +214,15 @@ public: px = r.px; } + template + shared_ptr( weak_ptr const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws + { + if( !pn.empty() ) + { + px = r.px; + } + } + template shared_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws { @@ -555,6 +571,8 @@ template inline T * get_pointer(shared_ptr const & p) // operator<< +#if !defined(BOOST_NO_IOSTREAM) + #if defined(__GNUC__) && (__GNUC__ < 3) template std::ostream & operator<< (std::ostream & os, shared_ptr const & p) @@ -584,6 +602,8 @@ template std::basic_ostream & operator<< (std:: #endif // __GNUC__ < 3 +#endif // !defined(BOOST_NO_IOSTREAM) + // get_deleter #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index ae606f2..4335738 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -93,31 +93,7 @@ public: shared_ptr lock() const // never throws { -#if defined(BOOST_HAS_THREADS) - - // optimization: avoid throw overhead - if(expired()) - { - return shared_ptr(); - } - - try - { - return shared_ptr(*this); - } - catch(bad_weak_ptr const &) - { - // Q: how can we get here? - // A: another thread may have invalidated r after the use_count test above. - return shared_ptr(); - } - -#else - - // optimization: avoid try/catch overhead when single threaded - return expired()? shared_ptr(): shared_ptr(*this); - -#endif + return shared_ptr( *this, boost::detail::sp_nothrow_tag() ); } long use_count() const // never throws diff --git a/shared_ptr.htm b/shared_ptr.htm index e108278..5b4444f 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -373,8 +373,8 @@ q = p;
    long use_count() const; // never throws

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

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

    Throws: nothing.

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

    @@ -522,6 +522,7 @@ q = p;

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

    +

    Throws: nothing.

    Example

    See shared_ptr_example.cpp for a @@ -709,8 +710,8 @@ int * p = a.release();

    $Date$

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

    + Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, + Version 1.0. See accompanying file LICENSE_1_0.txt + or copy at http://www.boost.org/LICENSE_1_0.txt.

    diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e6b49d7..7abcb6e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -33,5 +33,14 @@ import testing ; [ run shared_ptr_move_test.cpp ] [ compile-fail shared_ptr_pv_fail.cpp ] [ run sp_unary_addr_test.cpp ] + [ compile-fail scoped_ptr_eq_fail.cpp ] + [ compile-fail scoped_array_eq_fail.cpp ] + [ run esft_regtest.cpp ] + [ run yield_k_test.cpp ] + [ run yield_k_test.cpp : : : multi : yield_k_test.mt ] + [ run spinlock_test.cpp ] + [ run spinlock_try_test.cpp ] + [ run spinlock_try_test.cpp : : : multi : spinlock_try_test.mt ] + [ run spinlock_pool_test.cpp ] ; } diff --git a/test/esft_regtest.cpp b/test/esft_regtest.cpp new file mode 100644 index 0000000..0e3036c --- /dev/null +++ b/test/esft_regtest.cpp @@ -0,0 +1,136 @@ +// +// esft_regtest.cpp +// +// A regression test for enable_shared_from_this +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include +#include +#include + +class X: public boost::enable_shared_from_this< X > +{ +private: + + int destroyed_; + int deleted_; + int expected_; + +private: + + X( X const& ); + X& operator=( X const& ); + +public: + + static int instances; + +public: + + explicit X( int expected ): destroyed_( 0 ), deleted_( 0 ), expected_( expected ) + { + ++instances; + } + + ~X() + { + BOOST_TEST( deleted_ == expected_ ); + BOOST_TEST( destroyed_ == 0 ); + ++destroyed_; + --instances; + } + + typedef void (*deleter_type)( X* ); + + static void deleter( X * px ) + { + ++px->deleted_; + } + + static void deleter2( X * px ) + { + ++px->deleted_; + delete px; + } +}; + +int X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + X x( 0 ); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + std::auto_ptr px( new X( 0 ) ); + BOOST_TEST( X::instances == 1 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr px( new X( 0 ) ); + BOOST_TEST( X::instances == 1 ); + + boost::weak_ptr wp( px ); + BOOST_TEST( !wp.expired() ); + + px.reset(); + + BOOST_TEST( wp.expired() ); + } + + BOOST_TEST( X::instances == 0 ); + + { + X x( 1 ); + boost::shared_ptr px( &x, X::deleter ); + BOOST_TEST( X::instances == 1 ); + + X::deleter_type * pd = boost::get_deleter( px ); + BOOST_TEST( pd != 0 && *pd == X::deleter ); + + boost::weak_ptr wp( px ); + BOOST_TEST( !wp.expired() ); + + px.reset(); + + BOOST_TEST( wp.expired() ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr px( new X( 1 ), X::deleter2 ); + BOOST_TEST( X::instances == 1 ); + + X::deleter_type * pd = boost::get_deleter( px ); + BOOST_TEST( pd != 0 && *pd == X::deleter2 ); + + boost::weak_ptr wp( px ); + BOOST_TEST( !wp.expired() ); + + px.reset(); + + BOOST_TEST( wp.expired() ); + } + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +} diff --git a/test/scoped_array_eq_fail.cpp b/test/scoped_array_eq_fail.cpp new file mode 100644 index 0000000..6c7f214 --- /dev/null +++ b/test/scoped_array_eq_fail.cpp @@ -0,0 +1,27 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// scoped_array_eq_fail.cpp - a negative test for "p == q" +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +int main() +{ + boost::scoped_array p, q; + p == q; // must fail + return 0; +} diff --git a/test/scoped_ptr_eq_fail.cpp b/test/scoped_ptr_eq_fail.cpp new file mode 100644 index 0000000..0d6ade4 --- /dev/null +++ b/test/scoped_ptr_eq_fail.cpp @@ -0,0 +1,27 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// scoped_ptr_eq_fail.cpp - a negative test for "p == q" +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +int main() +{ + boost::scoped_ptr p, q; + p == q; // must fail + return 0; +} diff --git a/test/shared_from_this_test.cpp b/test/shared_from_this_test.cpp index 5107cb1..61515bd 100644 --- a/test/shared_from_this_test.cpp +++ b/test/shared_from_this_test.cpp @@ -133,7 +133,8 @@ void test3() try { boost::shared_ptr r = v2.shared_from_this(); - BOOST_ERROR("v2.shared_from_this() failed to throw"); + BOOST_TEST( p < r || r < p ); + BOOST_TEST( r.get() == &v2 ); } catch(boost::bad_weak_ptr const &) { diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp index 2f852ea..f697192 100644 --- a/test/shared_ptr_test.cpp +++ b/test/shared_ptr_test.cpp @@ -62,6 +62,7 @@ void default_constructor() BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 0); } { @@ -69,6 +70,7 @@ void default_constructor() BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 0); } { @@ -76,6 +78,7 @@ void default_constructor() BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 0); } } @@ -1565,6 +1568,7 @@ void plain_reset() BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 0); } { @@ -1573,6 +1577,7 @@ void plain_reset() BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 0); } { @@ -1581,6 +1586,7 @@ void plain_reset() BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); + BOOST_TEST(pi.use_count() == 0); } { @@ -1589,6 +1595,7 @@ void plain_reset() BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 0); } { @@ -1597,6 +1604,7 @@ void plain_reset() BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 0); } { @@ -1605,6 +1613,7 @@ void plain_reset() BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 0); } { @@ -1615,6 +1624,7 @@ void plain_reset() BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); + BOOST_TEST(px.use_count() == 0); BOOST_TEST(X::instances == 0); } @@ -1624,6 +1634,7 @@ void plain_reset() BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 0); } { @@ -1634,6 +1645,7 @@ void plain_reset() BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); + BOOST_TEST(pv.use_count() == 0); BOOST_TEST(X::instances == 0); } } diff --git a/test/spinlock_pool_test.cpp b/test/spinlock_pool_test.cpp new file mode 100644 index 0000000..00e7558 --- /dev/null +++ b/test/spinlock_pool_test.cpp @@ -0,0 +1,30 @@ +// +// spinlock_pool_test.cpp +// +// Copyright 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include + +// Sanity check only + +int main() +{ + int x = 0; + + { + boost::detail::spinlock_pool<0>::scoped_lock lock( &x ); + ++x; + } + + { + boost::detail::spinlock_pool<1>::scoped_lock lock( &x ); + boost::detail::spinlock_pool<2>::scoped_lock lock2( &x ); + } + + return 0; +} diff --git a/test/spinlock_test.cpp b/test/spinlock_test.cpp new file mode 100644 index 0000000..0820b96 --- /dev/null +++ b/test/spinlock_test.cpp @@ -0,0 +1,31 @@ +// +// spinlock_test.cpp +// +// Copyright 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +// Sanity check only + +static boost::detail::spinlock sp = BOOST_DETAIL_SPINLOCK_INIT; +static boost::detail::spinlock sp2 = BOOST_DETAIL_SPINLOCK_INIT; + +int main() +{ + sp.lock(); + sp2.lock(); + sp.unlock(); + sp2.unlock(); + + { + boost::detail::spinlock::scoped_lock lock( sp ); + boost::detail::spinlock::scoped_lock lock2( sp2 ); + } + + return 0; +} diff --git a/test/spinlock_try_test.cpp b/test/spinlock_try_test.cpp new file mode 100644 index 0000000..59e3390 --- /dev/null +++ b/test/spinlock_try_test.cpp @@ -0,0 +1,46 @@ +// +// spinlock_try_test.cpp +// +// Copyright 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include + +// Sanity check only + +static boost::detail::spinlock sp = BOOST_DETAIL_SPINLOCK_INIT; +static boost::detail::spinlock sp2 = BOOST_DETAIL_SPINLOCK_INIT; + +int main() +{ + BOOST_TEST( sp.try_lock() ); + BOOST_TEST( !sp.try_lock() ); + BOOST_TEST( sp2.try_lock() ); + BOOST_TEST( !sp.try_lock() ); + BOOST_TEST( !sp2.try_lock() ); + sp.unlock(); + sp2.unlock(); + + sp.lock(); + BOOST_TEST( !sp.try_lock() ); + sp2.lock(); + BOOST_TEST( !sp.try_lock() ); + BOOST_TEST( !sp2.try_lock() ); + sp.unlock(); + sp2.unlock(); + + { + boost::detail::spinlock::scoped_lock lock( sp ); + BOOST_TEST( !sp.try_lock() ); + boost::detail::spinlock::scoped_lock lock2( sp2 ); + BOOST_TEST( !sp.try_lock() ); + BOOST_TEST( !sp2.try_lock() ); + } + + return boost::report_errors(); +} diff --git a/test/yield_k_test.cpp b/test/yield_k_test.cpp new file mode 100644 index 0000000..1e6ab13 --- /dev/null +++ b/test/yield_k_test.cpp @@ -0,0 +1,23 @@ +// +// yield_k_test.cpp +// +// Copyright 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +// Sanity check only + +int main() +{ + for( unsigned k = 0; k < 256; ++k ) + { + boost::detail::yield( k ); + } + + return 0; +} From 0fd94d6d5649aa3f990ed7e303f9fba43934545b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 10:17:08 +0000 Subject: [PATCH 466/513] Updated sp_counted_base.hpp to trunk version; takes care of 44369, 44441. [SVN r47340] --- include/boost/detail/sp_counted_base.hpp | 29 ++++-------------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index 312893d..6d733d0 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -20,65 +20,46 @@ #include #if defined( BOOST_SP_DISABLE_THREADS ) - # include #elif defined( BOOST_SP_USE_SPINLOCK ) - # include #elif defined( BOOST_SP_USE_PTHREADS ) - # include -#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) +#elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 ) +# include +#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) # include -//~ #elif defined( __MWERKS__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) - -//~ # include - #elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER ) - # include #elif defined(__HP_aCC) && defined(__ia64) - # include #elif defined( __MWERKS__ ) && defined( __POWERPC__ ) - # include #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) - # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined(__arm__) && !defined(__hppa) - +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) # include #elif defined(__GNUC__) && ( defined( __sparcv8 ) || defined( __sparcv9 ) ) - # include #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) - # include #elif !defined( BOOST_HAS_THREADS ) - # include -#elif defined( BOOST_HAS_PTHREADS ) - -# include - #else - -// Use #define BOOST_DISABLE_THREADS to avoid the error -# error Unrecognized threading platform +# include #endif From 774a8d330cc4ccf0000c30e28216a9318a82f6e0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 10:41:24 +0000 Subject: [PATCH 467/513] Merged 44595, 44638, 44707, 44711, 44728 from trunk to release [SVN r47341] --- include/boost/detail/shared_count.hpp | 27 +++-- include/boost/detail/yield_k.hpp | 6 +- include/boost/shared_ptr.hpp | 8 +- test/shared_ptr_mt_test.cpp | 143 +++++--------------------- test/weak_ptr_mt_test.cpp | 132 ++++-------------------- 5 files changed, 76 insertions(+), 240 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 1eae671..2745649 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -28,8 +28,11 @@ #include #include #include - -#include // std::auto_ptr +// In order to avoid circular dependencies with Boost.TR1 +// we make sure that our include of doesn't try to +// pull in the TR1 headers: that's why we use this header +// rather than including directly: +#include // std::auto_ptr #include // std::less #include // std::bad_alloc @@ -321,9 +324,13 @@ public: weak_count & operator= (shared_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; - if(tmp != 0) tmp->weak_add_ref(); - if(pi_ != 0) pi_->weak_release(); - pi_ = tmp; + + if( tmp != pi_ ) + { + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); + pi_ = tmp; + } return *this; } @@ -331,9 +338,13 @@ public: weak_count & operator= (weak_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; - if(tmp != 0) tmp->weak_add_ref(); - if(pi_ != 0) pi_->weak_release(); - pi_ = tmp; + + if( tmp != pi_ ) + { + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); + pi_ = tmp; + } return *this; } diff --git a/include/boost/detail/yield_k.hpp b/include/boost/detail/yield_k.hpp index d856d57..0d964a7 100644 --- a/include/boost/detail/yield_k.hpp +++ b/include/boost/detail/yield_k.hpp @@ -111,7 +111,11 @@ inline void yield( unsigned k ) } else { - struct timespec rqtp = { 0 }; + // g++ -Wextra warns on {} or {0} + struct timespec rqtp = { 0, 0 }; + + // POSIX says that timespec has tv_sec and tv_nsec + // But it doesn't guarantee order or placement rqtp.tv_sec = 0; rqtp.tv_nsec = 1000; diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 6f4d49a..b6af46d 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -20,7 +20,11 @@ #include #else -#include // for std::auto_ptr +// In order to avoid circular dependencies with Boost.TR1 +// we make sure that our include of doesn't try to +// pull in the TR1 headers: that's why we use this header +// rather than including directly: +#include // std::auto_ptr #include #include @@ -573,7 +577,7 @@ template inline T * get_pointer(shared_ptr const & p) #if !defined(BOOST_NO_IOSTREAM) -#if defined(__GNUC__) && (__GNUC__ < 3) +#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) template std::ostream & operator<< (std::ostream & os, shared_ptr const & p) { diff --git a/test/shared_ptr_mt_test.cpp b/test/shared_ptr_mt_test.cpp index fa31894..50a9f51 100644 --- a/test/shared_ptr_mt_test.cpp +++ b/test/shared_ptr_mt_test.cpp @@ -7,167 +7,76 @@ #pragma warning(disable: 4514) // unreferenced inline removed #endif -// // shared_ptr_mt_test.cpp - tests shared_ptr with multiple threads // // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2008 Peter Dimov // -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt #include #include #include -#include -#include #include #include -// 'portable' thread framework - -class abstract_thread -{ -public: - - virtual ~abstract_thread() {} - virtual void run() = 0; -}; - -#if !defined(BOOST_HAS_PTHREADS) && defined(BOOST_HAS_WINTHREADS) - -char const * title = "Using Windows threads"; - -#include -#include - -typedef HANDLE pthread_t; - -unsigned __stdcall common_thread_routine(void * pv) -{ - abstract_thread * pt = static_cast(pv); - pt->run(); - delete pt; - return 0; -} - -int pthread_create(pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg) -{ - HANDLE h = (HANDLE)_beginthreadex(0, 0, start_routine, arg, 0, 0); - - if(h != 0) - { - *thread = h; - return 0; - } - else - { - return 1; // return errno; - } -} - -int pthread_join(pthread_t thread, void ** /*value_ptr*/) -{ - ::WaitForSingleObject(thread, INFINITE); - ::CloseHandle(thread); - return 0; -} - -#else - -char const * title = "Using POSIX threads"; - -#include - -extern "C" void * common_thread_routine(void * pv) -{ - abstract_thread * pt = static_cast(pv); - pt->run(); - delete pt; - return 0; -} - -#endif - -// - -template class thread: public abstract_thread -{ -public: - - explicit thread(F f): f_(f) - { - } - - void run() - { - f_(); - } - -private: - - F f_; -}; - -template pthread_t createThread(F f) -{ - std::auto_ptr p(new thread(f)); - - pthread_t r; - - if(pthread_create(&r, 0, common_thread_routine, p.get()) == 0) - { - p.release(); - return r; - } - - throw std::runtime_error("createThread failed."); -} +#include // int const n = 1024 * 1024; -void test(boost::shared_ptr const & pi) +void test( boost::shared_ptr const & pi ) { std::vector< boost::shared_ptr > v; - for(int i = 0; i < n; ++i) + for( int i = 0; i < n; ++i ) { - v.push_back(pi); + v.push_back( pi ); } } int const m = 16; // threads +#if defined( BOOST_HAS_PTHREADS ) + +char const * thmodel = "POSIX"; + +#else + +char const * thmodel = "Windows"; + +#endif + int main() { using namespace std; // printf, clock_t, clock - printf("%s: %d threads, %d iterations: ", title, m, n); + printf( "Using %s threads: %d threads, %d iterations: ", thmodel, m, n ); - boost::shared_ptr pi(new int(42)); + boost::shared_ptr pi( new int(42) ); clock_t t = clock(); - pthread_t a[m]; + pthread_t a[ m ]; - for(int i = 0; i < m; ++i) + for( int i = 0; i < m; ++i ) { - a[i] = createThread( boost::bind(test, pi) ); + boost::detail::lw_thread_create( a[ i ], boost::bind( test, pi ) ); } - for(int j = 0; j < m; ++j) + for( int j = 0; j < m; ++j ) { - pthread_join(a[j], 0); + pthread_join( a[j], 0 ); } t = clock() - t; - printf("\n\n%.3f seconds.\n", static_cast(t) / CLOCKS_PER_SEC); + printf( "\n\n%.3f seconds.\n", static_cast(t) / CLOCKS_PER_SEC ); return 0; } diff --git a/test/weak_ptr_mt_test.cpp b/test/weak_ptr_mt_test.cpp index 442c591..04439e6 100644 --- a/test/weak_ptr_mt_test.cpp +++ b/test/weak_ptr_mt_test.cpp @@ -7,128 +7,26 @@ #pragma warning(disable: 4514) // unreferenced inline removed #endif -// // weak_ptr_mt_test.cpp // // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. -// Copyright 2005 Peter Dimov -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright 2005, 2008 Peter Dimov // +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt #include #include #include #include -#include -#include #include #include #include -// 'portable' thread framework - -class abstract_thread -{ -public: - - virtual ~abstract_thread() {} - virtual void run() = 0; -}; - -#if !defined(BOOST_HAS_PTHREADS) && defined(BOOST_HAS_WINTHREADS) - -char const * title = "Using Windows threads"; - -#include -#include - -typedef HANDLE pthread_t; - -unsigned __stdcall common_thread_routine(void * pv) -{ - abstract_thread * pt = static_cast(pv); - pt->run(); - delete pt; - return 0; -} - -int pthread_create(pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg) -{ - HANDLE h = (HANDLE)_beginthreadex(0, 0, start_routine, arg, 0, 0); - - if(h != 0) - { - *thread = h; - return 0; - } - else - { - return 1; // return errno; - } -} - -int pthread_join(pthread_t thread, void ** /*value_ptr*/) -{ - ::WaitForSingleObject(thread, INFINITE); - ::CloseHandle(thread); - return 0; -} - -#else - -char const * title = "Using POSIX threads"; - -#include - -extern "C" void * common_thread_routine(void * pv) -{ - abstract_thread * pt = static_cast(pv); - pt->run(); - delete pt; - return 0; -} - -#endif - -// - -template class thread: public abstract_thread -{ -public: - - explicit thread(F f): f_(f) - { - } - - void run() - { - f_(); - } - -private: - - F f_; -}; - -template pthread_t createThread(F f) -{ - std::auto_ptr p(new thread(f)); - - pthread_t r; - - if(pthread_create(&r, 0, common_thread_routine, p.get()) == 0) - { - p.release(); - return r; - } - - throw std::runtime_error("createThread failed."); -} +#include // @@ -177,11 +75,21 @@ void test( std::vector< boost::shared_ptr > & v ) printf( "\n%d locks, %d forced rebinds, %d normal rebinds.", s, f, r ); } +#if defined( BOOST_HAS_PTHREADS ) + +char const * thmodel = "POSIX"; + +#else + +char const * thmodel = "Windows"; + +#endif + int main() { using namespace std; // printf, clock_t, clock - printf("%s: %d threads, %d * %d iterations: ", title, m, n, k ); + printf("Using %s threads: %d threads, %d * %d iterations: ", thmodel, m, n, k ); std::vector< boost::shared_ptr > v( k ); @@ -192,16 +100,16 @@ int main() clock_t t = clock(); - pthread_t a[m]; + pthread_t a[ m ]; - for(int i = 0; i < m; ++i) + for( int i = 0; i < m; ++i ) { - a[i] = createThread( boost::bind( test, v ) ); + boost::detail::lw_thread_create( a[ i ], boost::bind( test, v ) ); } v.resize( 0 ); // kill original copies - for(int j = 0; j < m; ++j) + for( int j = 0; j < m; ++j ) { pthread_join( a[j], 0 ); } From 1bc4f16ff8d2985472103a661e0f0af0c9cc30ce Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 10:45:56 +0000 Subject: [PATCH 468/513] Update esft_regtest.cpp to trunk HEAD; takes care of 43829, 43856, 44775. [SVN r47342] --- test/esft_regtest.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/test/esft_regtest.cpp b/test/esft_regtest.cpp index 0e3036c..cc180a2 100644 --- a/test/esft_regtest.cpp +++ b/test/esft_regtest.cpp @@ -16,6 +16,7 @@ #include #include #include +#include class X: public boost::enable_shared_from_this< X > { @@ -65,7 +66,7 @@ public: int X::instances = 0; -int main() +void test() { BOOST_TEST( X::instances == 0 ); @@ -131,6 +132,90 @@ int main() } BOOST_TEST( X::instances == 0 ); +} + +struct V: public boost::enable_shared_from_this +{ + virtual ~V() {} + std::string m_; +}; + +struct V2 +{ + virtual ~V2() {} + std::string m2_; +}; + +struct W: V2, V +{ +}; + +void test2() +{ + boost::shared_ptr p( new W ); +} + +void test3() +{ + V * p = new W; + boost::shared_ptr pv( p ); + BOOST_TEST( pv.get() == p ); + BOOST_TEST( pv.use_count() == 1 ); +} + +struct null_deleter +{ + void operator()( void const* ) const {} +}; + +void test4() +{ + boost::shared_ptr pv( new V ); + boost::shared_ptr pv2( pv.get(), null_deleter() ); + BOOST_TEST( pv2.get() == pv.get() ); + BOOST_TEST( pv2.use_count() == 1 ); +} + +void test5() +{ + V v; + + boost::shared_ptr p1( &v, null_deleter() ); + BOOST_TEST( p1.get() == &v ); + BOOST_TEST( p1.use_count() == 1 ); + + try + { + p1->shared_from_this(); + } + catch( ... ) + { + BOOST_ERROR( "p1->shared_from_this() failed" ); + } + + p1.reset(); + + boost::shared_ptr p2( &v, null_deleter() ); + BOOST_TEST( p2.get() == &v ); + BOOST_TEST( p2.use_count() == 1 ); + + try + { + p2->shared_from_this(); + } + catch( ... ) + { + BOOST_ERROR( "p2->shared_from_this() failed" ); + } +} + +int main() +{ + test(); + test2(); + test3(); + test4(); + test5(); return boost::report_errors(); } From 07b4c179801682648aefdbbf10d546d999c7197e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 11:37:16 +0000 Subject: [PATCH 469/513] Merged 44979, 45068, 45085, 45089, 45177, 45194, 45346, 45422, 45545, 46055 from trunk to release [SVN r47345] --- include/boost/detail/lwm_win32_cs.hpp | 16 +- include/boost/detail/shared_count.hpp | 9 +- include/boost/detail/sp_convertible.hpp | 76 +++++ include/boost/detail/spinlock_sync.hpp | 4 + include/boost/detail/spinlock_w32.hpp | 2 +- include/boost/detail/yield_k.hpp | 2 +- include/boost/intrusive_ptr.hpp | 35 +- include/boost/make_shared.hpp | 433 ++++++++++++++++++++++++ include/boost/shared_ptr.hpp | 23 +- include/boost/weak_ptr.hpp | 22 +- intrusive_ptr.html | 6 + test/Jamfile.v2 | 5 + test/allocate_shared_test.cpp | 189 +++++++++++ test/ip_convertible_test.cpp | 54 +++ test/make_shared_test.cpp | 189 +++++++++++ test/smart_ptr_test.cpp | 4 + test/sp_convertible_test.cpp | 71 ++++ test/sp_unary_addr_test.cpp | 5 + test/wp_convertible_test.cpp | 68 ++++ 19 files changed, 1196 insertions(+), 17 deletions(-) create mode 100644 include/boost/detail/sp_convertible.hpp create mode 100644 include/boost/make_shared.hpp create mode 100644 test/allocate_shared_test.cpp create mode 100644 test/ip_convertible_test.cpp create mode 100644 test/make_shared_test.cpp create mode 100644 test/sp_convertible_test.cpp create mode 100644 test/wp_convertible_test.cpp diff --git a/include/boost/detail/lwm_win32_cs.hpp b/include/boost/detail/lwm_win32_cs.hpp index 4ee0a71..8142069 100644 --- a/include/boost/detail/lwm_win32_cs.hpp +++ b/include/boost/detail/lwm_win32_cs.hpp @@ -29,7 +29,7 @@ namespace detail #ifndef BOOST_USE_WINDOWS_H -struct CRITICAL_SECTION +struct critical_section { struct critical_section_debug * DebugInfo; long LockCount; @@ -43,10 +43,14 @@ struct CRITICAL_SECTION #endif }; -extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(CRITICAL_SECTION *); -extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(CRITICAL_SECTION *); -extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(CRITICAL_SECTION *); -extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(CRITICAL_SECTION *); +extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(critical_section *); + +#else + +typedef ::CRITICAL_SECTION critical_section; #endif // #ifndef BOOST_USE_WINDOWS_H @@ -54,7 +58,7 @@ class lightweight_mutex { private: - CRITICAL_SECTION cs_; + critical_section cs_; lightweight_mutex(lightweight_mutex const &); lightweight_mutex & operator=(lightweight_mutex const &); diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 2745649..8f13777 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -104,11 +104,18 @@ public: #endif } - template shared_count(P p, D d): pi_(0) +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) + template shared_count( Y * p, D d ): pi_(0) +#else + template shared_count( P p, D d ): pi_(0) +#endif #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif { +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) + typedef Y* P; +#endif #ifndef BOOST_NO_EXCEPTIONS try diff --git a/include/boost/detail/sp_convertible.hpp b/include/boost/detail/sp_convertible.hpp new file mode 100644 index 0000000..017217b --- /dev/null +++ b/include/boost/detail/sp_convertible.hpp @@ -0,0 +1,76 @@ +#ifndef BOOST_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED +#define BOOST_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_convertible.hpp +// +// Copyright 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( BOOST_NO_SFINAE ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ < 303 ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x600 ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + +namespace boost +{ + +namespace detail +{ + +template< class Y, class T > struct sp_convertible +{ + typedef char (&yes) [1]; + typedef char (&no) [2]; + + static yes f( T* ); + static no f( ... ); + + enum _vt { value = sizeof( f( (Y*)0 ) ) == sizeof(yes) }; +}; + +struct sp_empty +{ +}; + +template< bool > struct sp_enable_if_convertible_impl; + +template<> struct sp_enable_if_convertible_impl +{ + typedef sp_empty type; +}; + +template<> struct sp_enable_if_convertible_impl +{ +}; + +template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_if_convertible_impl< sp_convertible< Y, T >::value > +{ +}; + +} // namespace detail + +} // namespace boost + +#endif // !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + +#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_sync.hpp b/include/boost/detail/spinlock_sync.hpp index d602365..a752396 100644 --- a/include/boost/detail/spinlock_sync.hpp +++ b/include/boost/detail/spinlock_sync.hpp @@ -17,6 +17,10 @@ #include +#if defined( __ia64__ ) && defined( __INTEL_COMPILER ) +# include +#endif + namespace boost { diff --git a/include/boost/detail/spinlock_w32.hpp b/include/boost/detail/spinlock_w32.hpp index 76cfe8f..aa416c3 100644 --- a/include/boost/detail/spinlock_w32.hpp +++ b/include/boost/detail/spinlock_w32.hpp @@ -33,7 +33,7 @@ extern "C" void _ReadWriteBarrier(); #elif defined(__GNUC__) -#define BOOST_COMPILER_FENCE __asm__ __volatile__( "" ::: "memory" ); +#define BOOST_COMPILER_FENCE __asm__ __volatile__( "" : : : "memory" ); #else diff --git a/include/boost/detail/yield_k.hpp b/include/boost/detail/yield_k.hpp index 0d964a7..d97542d 100644 --- a/include/boost/detail/yield_k.hpp +++ b/include/boost/detail/yield_k.hpp @@ -36,7 +36,7 @@ extern "C" void _mm_pause(); #elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) -#define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" ::: "memory" ); +#define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" ); #endif diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index c4ec407..338e672 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -22,9 +22,17 @@ #include #include +#include -#include // for std::less +#include // for std::less + +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) #include // for std::basic_ostream +#else +#include +#endif +#endif namespace boost @@ -66,9 +74,19 @@ public: #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) - template intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.get()) + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + intrusive_ptr( intrusive_ptr const & rhs, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + intrusive_ptr( intrusive_ptr const & rhs ) + +#endif + : p_( rhs.get() ) { - if(p_ != 0) intrusive_ptr_add_ref(p_); + if( p_ != 0 ) intrusive_ptr_add_ref( p_ ); } #endif @@ -105,6 +123,11 @@ public: return *this; } + void reset() + { + this_type().swap( *this ); + } + void reset( T * rhs ) { this_type( rhs ).swap( *this ); @@ -246,7 +269,9 @@ template intrusive_ptr dynamic_pointer_cast(intrusive_ptr std::ostream & operator<< (std::ostream & os, intrusive_ptr const & p) { @@ -275,6 +300,8 @@ template std::basic_ostream & operator<< (std:: #endif // __GNUC__ < 3 +#endif // !defined(BOOST_NO_IOSTREAM) + } // namespace boost #ifdef BOOST_MSVC diff --git a/include/boost/make_shared.hpp b/include/boost/make_shared.hpp new file mode 100644 index 0000000..cc3685b --- /dev/null +++ b/include/boost/make_shared.hpp @@ -0,0 +1,433 @@ +#ifndef BOOST_MAKE_SHARED_HPP_INCLUDED +#define BOOST_MAKE_SHARED_HPP_INCLUDED + +// make_shared.hpp +// +// Copyright (c) 2007, 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// See http://www.boost.org/libs/smart_ptr/make_shared.html +// for documentation. + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + +namespace detail +{ + +template< std::size_t N, std::size_t A > struct sp_aligned_storage +{ + union type + { + char data_[ N ]; + typename boost::type_with_alignment< A >::type align_; + }; +}; + +template< class T > class sp_ms_deleter +{ +private: + + typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type; + + bool initialized_; + storage_type storage_; + +private: + + void destroy() + { + if( initialized_ ) + { + reinterpret_cast< T* >( storage_.data_ )->~T(); + initialized_ = false; + } + } + +public: + + sp_ms_deleter(): initialized_( false ) + { + } + + ~sp_ms_deleter() + { + destroy(); + } + + void operator()( T * ) + { + destroy(); + } + + void * address() + { + return storage_.data_; + } + + void set_initialized() + { + initialized_ = true; + } +}; + +template< class T > T forward( T t ) +{ + return t; +} + +} // namespace detail + +// Zero-argument versions +// +// Used even when variadic templates are available because of the new T() vs new T issue + +template< class T > boost::shared_ptr< T > make_shared() +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T(); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T(); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) + +// Variadic templates, rvalue reference + +template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && ... args ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( detail::forward( args )... ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Args && ... args ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( detail::forward( args )... ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +#else + +// C++03 version + +template< class T, class A1 > +boost::shared_ptr< T > make_shared( A1 const & a1 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +#endif + +} // namespace boost + +#endif // #ifndef BOOST_MAKE_SHARED_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index b6af46d..5a172b9 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include // for std::swap #include // for std::less @@ -228,7 +229,16 @@ public: } template - shared_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + shared_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + shared_ptr( shared_ptr const & r ) + +#endif + : px( r.px ), pn( r.pn ) // never throws { } @@ -337,7 +347,16 @@ public: } template - shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + shared_ptr( shared_ptr && r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + shared_ptr( shared_ptr && r ) + +#endif + : px( r.px ), pn() // never throws { pn.swap( r.pn ); r.px = 0; diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 4335738..b300813 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -61,13 +61,31 @@ public: // template - weak_ptr(weak_ptr const & r): pn(r.pn) // never throws +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + weak_ptr( weak_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + weak_ptr( weak_ptr const & r ) + +#endif + : pn(r.pn) // never throws { px = r.lock().get(); } template - weak_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + weak_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + weak_ptr( shared_ptr const & r ) + +#endif + : px( r.px ), pn( r.pn ) // never throws { } diff --git a/intrusive_ptr.html b/intrusive_ptr.html index c4eb899..16097dd 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -62,6 +62,8 @@ intrusive_ptr & operator=(intrusive_ptr const & r); template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r); intrusive_ptr & operator=(T * r); + + void reset(); void reset(T * r); T & operator*() const; // never throws @@ -148,6 +150,10 @@ intrusive_ptr & operator=(T * r);

    Returns: *this.

    reset

    +
    void reset();
    +
    +

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

    +
    void reset(T * r);

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

    diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7abcb6e..955b282 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -42,5 +42,10 @@ import testing ; [ run spinlock_try_test.cpp ] [ run spinlock_try_test.cpp : : : multi : spinlock_try_test.mt ] [ run spinlock_pool_test.cpp ] + [ run make_shared_test.cpp ] + [ run sp_convertible_test.cpp ] + [ run wp_convertible_test.cpp ] + [ run ip_convertible_test.cpp ] + [ run allocate_shared_test.cpp ] ; } diff --git a/test/allocate_shared_test.cpp b/test/allocate_shared_test.cpp new file mode 100644 index 0000000..71ee948 --- /dev/null +++ b/test/allocate_shared_test.cpp @@ -0,0 +1,189 @@ +// allocate_shared_test.cpp +// +// Copyright (c) 2007, 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +class X +{ +private: + + X( X const & ); + X & operator=( X const & ); + +public: + + static int instances; + + int v; + + explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 ) + { + ++instances; + } + + ~X() + { + --instances; + } +}; + +int X::instances = 0; + +int main() +{ + { + boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator() ); + + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( *pi == 0 ); + } + + { + boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator(), 5 ); + + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( *pi == 5 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator() ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 0 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7, 8 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + return boost::report_errors(); +} diff --git a/test/ip_convertible_test.cpp b/test/ip_convertible_test.cpp new file mode 100644 index 0000000..081f7b0 --- /dev/null +++ b/test/ip_convertible_test.cpp @@ -0,0 +1,54 @@ +#include + +// wp_convertible_test.cpp +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include +#include + +// + +struct W +{ +}; + +void intrusive_ptr_add_ref( W* ) +{ +} + +void intrusive_ptr_release( W* ) +{ +} + +struct X: public virtual W +{ +}; + +struct Y: public virtual W +{ +}; + +struct Z: public X +{ +}; + +int f( boost::intrusive_ptr ) +{ + return 1; +} + +int f( boost::intrusive_ptr ) +{ + return 2; +} + +int main() +{ + BOOST_TEST( 1 == f( boost::intrusive_ptr() ) ); + return boost::report_errors(); +} diff --git a/test/make_shared_test.cpp b/test/make_shared_test.cpp new file mode 100644 index 0000000..9930e31 --- /dev/null +++ b/test/make_shared_test.cpp @@ -0,0 +1,189 @@ +// make_shared_test.cpp +// +// Copyright (c) 2007, 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +class X +{ +private: + + X( X const & ); + X & operator=( X const & ); + +public: + + static int instances; + + int v; + + explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 ) + { + ++instances; + } + + ~X() + { + --instances; + } +}; + +int X::instances = 0; + +int main() +{ + { + boost::shared_ptr< int > pi = boost::make_shared< int >(); + + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( *pi == 0 ); + } + + { + boost::shared_ptr< int > pi = boost::make_shared< int >( 5 ); + + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( *pi == 5 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > pi = boost::make_shared< X >(); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 0 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + { + boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + boost::weak_ptr wp( pi ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 ); + + pi.reset(); + + BOOST_TEST( X::instances == 0 ); + } + + return boost::report_errors(); +} diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp index 0c29c9c..8832deb 100644 --- a/test/smart_ptr_test.cpp +++ b/test/smart_ptr_test.cpp @@ -196,6 +196,10 @@ void test() BOOST_TEST( cp.use_count() == 3 ); BOOST_TEST( *cp == 87654 ); +#if defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) + using boost::swap; +#endif + boost::shared_ptr cp4; swap( cp2, cp4 ); BOOST_TEST( cp4.use_count() == 3 ); diff --git a/test/sp_convertible_test.cpp b/test/sp_convertible_test.cpp new file mode 100644 index 0000000..7f49e1f --- /dev/null +++ b/test/sp_convertible_test.cpp @@ -0,0 +1,71 @@ +#include + +// sp_convertible_test.cpp +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include +#include + +// + +class incomplete; + +struct X +{ +}; + +struct Y +{ +}; + +struct Z: public X +{ +}; + +int f( boost::shared_ptr ) +{ + return 1; +} + +int f( boost::shared_ptr ) +{ + return 2; +} + +int f( boost::shared_ptr ) +{ + return 3; +} + +int g( boost::shared_ptr ) +{ + return 4; +} + +int g( boost::shared_ptr ) +{ + return 5; +} + +int g( boost::shared_ptr ) +{ + return 6; +} + +int main() +{ + boost::shared_ptr p1; + BOOST_TEST( 1 == f( p1 ) ); + BOOST_TEST( 1 == f( boost::shared_ptr() ) ); + + boost::shared_ptr p2; + BOOST_TEST( 4 == g( p2 ) ); + BOOST_TEST( 4 == g( boost::shared_ptr() ) ); + + return boost::report_errors(); +} diff --git a/test/sp_unary_addr_test.cpp b/test/sp_unary_addr_test.cpp index 4522640..a4007a2 100644 --- a/test/sp_unary_addr_test.cpp +++ b/test/sp_unary_addr_test.cpp @@ -49,6 +49,9 @@ int main() BOOST_TEST( q != 0 && q->data == 17041 ); } +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) +#else + { boost::shared_ptr p( &x, deleter(), std::allocator() ); @@ -58,5 +61,7 @@ int main() BOOST_TEST( q != 0 && q->data == 17041 ); } +#endif + return boost::report_errors(); } diff --git a/test/wp_convertible_test.cpp b/test/wp_convertible_test.cpp new file mode 100644 index 0000000..cceacda --- /dev/null +++ b/test/wp_convertible_test.cpp @@ -0,0 +1,68 @@ +#include + +// wp_convertible_test.cpp +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include +#include + +// + +class incomplete; + +struct X +{ +}; + +struct Y +{ +}; + +struct Z: public X +{ +}; + +int f( boost::weak_ptr ) +{ + return 1; +} + +int f( boost::weak_ptr ) +{ + return 2; +} + +int f( boost::weak_ptr ) +{ + return 3; +} + +int g( boost::weak_ptr ) +{ + return 4; +} + +int g( boost::weak_ptr ) +{ + return 5; +} + +int g( boost::weak_ptr ) +{ + return 6; +} + +int main() +{ + BOOST_TEST( 1 == f( boost::weak_ptr() ) ); + BOOST_TEST( 1 == f( boost::shared_ptr() ) ); + BOOST_TEST( 4 == g( boost::weak_ptr() ) ); + BOOST_TEST( 4 == g( boost::shared_ptr() ) ); + + return boost::report_errors(); +} From f884c53bd685682aeaf31b4bc51525b0055bc7b4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 11:41:20 +0000 Subject: [PATCH 470/513] Updated spinlock_pool.hpp from trunk HEAD; takes care of 45069. [SVN r47346] --- include/boost/detail/spinlock_pool.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/detail/spinlock_pool.hpp b/include/boost/detail/spinlock_pool.hpp index 92d26cb..a264b1a 100644 --- a/include/boost/detail/spinlock_pool.hpp +++ b/include/boost/detail/spinlock_pool.hpp @@ -21,7 +21,9 @@ // spinlock_pool<2> is reserved for shared_ptr atomic access // +#include #include +#include namespace boost { @@ -39,7 +41,7 @@ public: static spinlock & spinlock_for( void const * pv ) { - size_t i = reinterpret_cast< size_t >( pv ) % 41; + std::size_t i = reinterpret_cast< std::size_t >( pv ) % 41; return pool_[ i ]; } From 034c12d2442389d6d89bccf81b0319e4ef683e63 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 11:57:45 +0000 Subject: [PATCH 471/513] Merged 44636, 44640, 45094 (atomic access) from trunk to release. [SVN r47349] --- include/boost/memory_order.hpp | 35 +++++ include/boost/shared_ptr.hpp | 64 +++++++++ test/Jamfile.v2 | 1 + test/sp_atomic_mt2_test.cpp | 247 +++++++++++++++++++++++++++++++++ test/sp_atomic_mt_test.cpp | 191 +++++++++++++++++++++++++ test/sp_atomic_test.cpp | 87 ++++++++++++ 6 files changed, 625 insertions(+) create mode 100644 include/boost/memory_order.hpp create mode 100644 test/sp_atomic_mt2_test.cpp create mode 100644 test/sp_atomic_mt_test.cpp create mode 100644 test/sp_atomic_test.cpp diff --git a/include/boost/memory_order.hpp b/include/boost/memory_order.hpp new file mode 100644 index 0000000..be5a9ce --- /dev/null +++ b/include/boost/memory_order.hpp @@ -0,0 +1,35 @@ +#ifndef BOOST_MEMORY_ORDER_HPP_INCLUDED +#define BOOST_MEMORY_ORDER_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// boost/memory_order.hpp +// +// Defines enum boost::memory_order per the C++0x working draft +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +namespace boost +{ + +enum memory_order +{ + memory_order_relaxed = 0, + memory_order_acquire = 1, + memory_order_release = 2, + memory_order_acq_rel = 3, // acquire | release + memory_order_seq_cst = 7, // acq_rel | 4 +}; + +} // namespace boost + +#endif // #ifndef BOOST_MEMORY_ORDER_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 5a172b9..394e30c 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -33,6 +33,11 @@ #include #include +#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) +#include +#include +#endif + #include // for std::swap #include // for std::less #include // for std::bad_cast @@ -498,6 +503,65 @@ public: return pn.get_deleter( ti ); } + // atomic access + +#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) + + shared_ptr atomic_load( memory_order /*mo*/ = memory_order_seq_cst ) const + { + boost::detail::spinlock_pool<2>::scoped_lock lock( this ); + return *this; + } + + void atomic_store( shared_ptr r, memory_order /*mo*/ = memory_order_seq_cst ) + { + boost::detail::spinlock_pool<2>::scoped_lock lock( this ); + swap( r ); + } + + shared_ptr atomic_swap( shared_ptr r, memory_order /*mo*/ = memory_order_seq_cst ) + { + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( this ); + + sp.lock(); + swap( r ); + sp.unlock(); + + return r; // return std::move(r) + } + + bool atomic_compare_swap( shared_ptr & v, shared_ptr w ) + { + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( this ); + + sp.lock(); + + if( px == v.px && pn == v.pn ) + { + swap( w ); + + sp.unlock(); + + return true; + } + else + { + shared_ptr tmp( *this ); + + sp.unlock(); + + tmp.swap( v ); + return false; + } + } + + inline bool atomic_compare_swap( shared_ptr & v, shared_ptr w, memory_order /*success*/, memory_order /*failure*/ ) + { + return atomic_compare_swap( v, w ); // std::move( w ) + } + +#endif + // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 955b282..5f68e20 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -47,5 +47,6 @@ import testing ; [ run wp_convertible_test.cpp ] [ run ip_convertible_test.cpp ] [ run allocate_shared_test.cpp ] + [ run sp_atomic_test.cpp ] ; } diff --git a/test/sp_atomic_mt2_test.cpp b/test/sp_atomic_mt2_test.cpp new file mode 100644 index 0000000..c865359 --- /dev/null +++ b/test/sp_atomic_mt2_test.cpp @@ -0,0 +1,247 @@ + +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +// + +static void next_value( unsigned & v ) +{ + v = v % 2? 3 * v + 1: v / 2; +} + +struct X +{ + std::vector v_; + + explicit X( std::size_t n ): v_( n ) + { + for( std::size_t i = 0; i < n; ++i ) + { + v_[ i ] = i; + } + } + + unsigned get() const + { + return std::accumulate( v_.begin(), v_.end(), 0 ); + } + + void set() + { + std::for_each( v_.begin(), v_.end(), next_value ); + } +}; + +static boost::shared_ptr ps; + +static boost::detail::lightweight_mutex lm; +static boost::shared_mutex rw; + +enum prim_type +{ + pt_mutex, + pt_rwlock, + pt_atomics +}; + +int read_access( prim_type pt ) +{ + switch( pt ) + { + case pt_mutex: + { + boost::detail::lightweight_mutex::scoped_lock lock( lm ); + return ps->get(); + } + + case pt_rwlock: + { + boost::shared_lock lock( rw ); + return ps->get(); + } + + case pt_atomics: + { + boost::shared_ptr p2 = ps.atomic_load(); + return p2->get(); + } + } +} + +void write_access( prim_type pt ) +{ + switch( pt ) + { + case pt_mutex: + { + boost::detail::lightweight_mutex::scoped_lock lock( lm ); + ps->set(); + } + break; + + case pt_rwlock: + { + boost::unique_lock lock( rw ); + ps->set(); + } + break; + + case pt_atomics: + { + boost::shared_ptr p1 = ps.atomic_load(); + + for( ;; ) + { + boost::shared_ptr p2( new X( *p1 ) ); + p2->set(); + + if( ps.atomic_compare_swap( p1, p2 ) ) break; + } + } + break; + } +} + +void worker( int k, prim_type pt, int n, int r ) +{ + ++r; + + unsigned s = 0, nr = 0, nw = 0; + + for( int i = 0; i < n; ++i ) + { + if( i % r ) + { + s += read_access( pt ); + ++nr; + } + else + { + write_access( pt ); + ++s; + ++nw; + } + } + + printf( "Worker %2d: %u:%u, %10u\n", k, nr, nw, s ); +} + +#if defined( BOOST_HAS_PTHREADS ) + char const * thmodel = "POSIX"; +#else + char const * thmodel = "Windows"; +#endif + +char const * pt_to_string( prim_type pt ) +{ + switch( pt ) + { + case pt_mutex: + + return "mutex"; + + case pt_rwlock: + + return "rwlock"; + + case pt_atomics: + + return "atomics"; + } +} + +static void handle_pt_option( std::string const & opt, prim_type & pt, prim_type pt2 ) +{ + if( opt == pt_to_string( pt2 ) ) + { + pt = pt2; + } +} + +static void handle_int_option( std::string const & opt, std::string const & prefix, int & k, int kmin, int kmax ) +{ + if( opt.substr( 0, prefix.size() ) == prefix ) + { + int v = atoi( opt.substr( prefix.size() ).c_str() ); + + if( v >= kmin && v <= kmax ) + { + k = v; + } + } +} + +int main( int ac, char const * av[] ) +{ + using namespace std; // printf, clock_t, clock + + int m = 4; // threads + int n = 10000; // vector size + int k = 1000000; // iterations + int r = 100; // read/write ratio, r:1 + + prim_type pt = pt_atomics; + + for( int i = 1; i < ac; ++i ) + { + handle_pt_option( av[i], pt, pt_mutex ); + handle_pt_option( av[i], pt, pt_rwlock ); + handle_pt_option( av[i], pt, pt_atomics ); + + handle_int_option( av[i], "n=", n, 1, INT_MAX ); + handle_int_option( av[i], "size=", n, 1, INT_MAX ); + + handle_int_option( av[i], "k=", k, 1, INT_MAX ); + handle_int_option( av[i], "iterations=", k, 1, INT_MAX ); + + handle_int_option( av[i], "m=", m, 1, INT_MAX ); + handle_int_option( av[i], "threads=", m, 1, INT_MAX ); + + handle_int_option( av[i], "r=", r, 1, INT_MAX ); + handle_int_option( av[i], "ratio=", r, 1, INT_MAX ); + } + + printf( "%s: threads=%d size=%d iterations=%d ratio=%d %s\n\n", thmodel, m, n, k, r, pt_to_string( pt ) ); + + ps.reset( new X( n ) ); + + clock_t t = clock(); + + std::vector a( m ); + + for( int i = 0; i < m; ++i ) + { + boost::detail::lw_thread_create( a[ i ], boost::bind( worker, i, pt, k, r ) ); + } + + for( int j = 0; j < m; ++j ) + { + pthread_join( a[ j ], 0 ); + } + + t = clock() - t; + + double ts = static_cast( t ) / CLOCKS_PER_SEC; + printf( "%.3f seconds, %.3f accesses per microsecond.\n", ts, m * k / ts / 1e+6 ); +} diff --git a/test/sp_atomic_mt_test.cpp b/test/sp_atomic_mt_test.cpp new file mode 100644 index 0000000..143df98 --- /dev/null +++ b/test/sp_atomic_mt_test.cpp @@ -0,0 +1,191 @@ + +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +//#define USE_MUTEX +//#define USE_RWLOCK + +#include + +#include +#include + +#if defined( USE_RWLOCK ) +#include +#include +#endif + +#include +#include +#include + +#include +#include + +// + +int const n = 1024 * 1024; + +struct X +{ + int v_; // version + + unsigned a_; + unsigned b_; + + X(): v_( 0 ), a_( 1 ), b_( 1 ) + { + } + + int get() const + { + return a_ * 7 + b_ * 11; + } + + void set() + { + int tmp = get(); + + b_ = a_; + a_ = tmp; + + ++v_; + } +}; + +static boost::shared_ptr ps( new X ); + +static boost::detail::lightweight_mutex lm; + +#if defined( USE_RWLOCK ) +static boost::shared_mutex rw; +#endif + +static int tr = 0; + +void reader( int r ) +{ + int k = 0; + unsigned s = 0; + + for( int i = 0; i < n; ++k ) + { +#if defined( USE_MUTEX ) + + boost::detail::lightweight_mutex::scoped_lock lock( lm ); + + s += ps->get(); + + BOOST_TEST( ps->v_ >= i ); + i = ps->v_; + +#elif defined( USE_RWLOCK ) + + boost::shared_lock lock( rw ); + + s += ps->get(); + + BOOST_TEST( ps->v_ >= i ); + i = ps->v_; + +#else + + boost::shared_ptr p2 = ps.atomic_load(); + + s += p2->get(); + + BOOST_TEST( p2->v_ >= i ); + i = p2->v_; + +#endif + } + + printf( "Reader %d: %9d iterations (%6.3fx), %u\n", r, k, (double)k / n, s ); + + boost::detail::lightweight_mutex::scoped_lock lock( lm ); + tr += k; +} + +void writer() +{ + for( int i = 0; i < n; ++i ) + { +#if defined( USE_MUTEX ) + + boost::detail::lightweight_mutex::scoped_lock lock( lm ); + + BOOST_TEST( ps->v_ == i ); + ps->set(); + +#elif defined( USE_RWLOCK ) + + boost::unique_lock lock( rw ); + + BOOST_TEST( ps->v_ == i ); + ps->set(); + +#else + + boost::shared_ptr p2( new X( *ps ) ); + + BOOST_TEST( p2->v_ == i ); + p2->set(); + + ps.atomic_store( p2 ); + +#endif + } +} + +#if defined( BOOST_HAS_PTHREADS ) + char const * thmodel = "POSIX"; +#else + char const * thmodel = "Windows"; +#endif + +int const mr = 8; // reader threads +int const mw = 1; // writer thread + +#if defined( USE_MUTEX ) + char const * prim = "mutex"; +#elif defined( USE_RWLOCK ) + char const * prim = "rwlock"; +#else + char const * prim = "atomics"; +#endif + +int main() +{ + using namespace std; // printf, clock_t, clock + + printf( "Using %s threads: %dR + %dW threads, %d iterations, %s\n\n", thmodel, mr, mw, n, prim ); + + clock_t t = clock(); + + pthread_t a[ mr+mw ]; + + for( int i = 0; i < mr; ++i ) + { + boost::detail::lw_thread_create( a[ i ], boost::bind( reader, i ) ); + } + + for( int i = mr; i < mr+mw; ++i ) + { + boost::detail::lw_thread_create( a[ i ], writer ); + } + + for( int j = 0; j < mr+mw; ++j ) + { + pthread_join( a[ j ], 0 ); + } + + t = clock() - t; + + double ts = static_cast( t ) / CLOCKS_PER_SEC; + printf( "%.3f seconds, %.3f reads per microsecond.\n", ts, tr / ts / 1e+6 ); + + return boost::report_errors(); +} diff --git a/test/sp_atomic_test.cpp b/test/sp_atomic_test.cpp new file mode 100644 index 0000000..c1113da --- /dev/null +++ b/test/sp_atomic_test.cpp @@ -0,0 +1,87 @@ +#include + +// sp_atomic_test.cpp +// +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + + +#include +#include + +// + +struct X +{ +}; + +#define BOOST_TEST_SP_EQ( p, q ) BOOST_TEST( p == q && !( p < q ) && !( q < p ) ) + +int main() +{ + boost::shared_ptr px( new X ); + + { + boost::shared_ptr p2 = px.atomic_load(); + BOOST_TEST_SP_EQ( p2, px ); + + boost::shared_ptr px2( new X ); + px.atomic_store( px2 ); + BOOST_TEST_SP_EQ( px, px2 ); + + p2 = px.atomic_load(); + BOOST_TEST_SP_EQ( p2, px ); + BOOST_TEST_SP_EQ( p2, px2 ); + + boost::shared_ptr px3( new X ); + boost::shared_ptr p3 = px.atomic_swap( px3 ); + BOOST_TEST_SP_EQ( p3, px2 ); + BOOST_TEST_SP_EQ( px, px3 ); + + boost::shared_ptr px4( new X ); + boost::shared_ptr cmp; + + bool r = px.atomic_compare_swap( cmp, px4 ); + BOOST_TEST( !r ); + BOOST_TEST_SP_EQ( px, px3 ); + BOOST_TEST_SP_EQ( cmp, px3 ); + + r = px.atomic_compare_swap( cmp, px4 ); + BOOST_TEST( r ); + BOOST_TEST_SP_EQ( px, px4 ); + } + + // + + px.reset(); + + { + boost::shared_ptr p2 = px.atomic_load( boost::memory_order_acquire ); + BOOST_TEST_SP_EQ( p2, px ); + + boost::shared_ptr px2( new X ); + px.atomic_store( px2, boost::memory_order_release ); + BOOST_TEST_SP_EQ( px, px2 ); + + boost::shared_ptr p3 = px.atomic_swap( boost::shared_ptr(), boost::memory_order_acq_rel ); + BOOST_TEST_SP_EQ( p3, px2 ); + BOOST_TEST_SP_EQ( px, p2 ); + + boost::shared_ptr px4( new X ); + boost::shared_ptr cmp( px2 ); + + bool r = px.atomic_compare_swap( cmp, px4, boost::memory_order_acquire, boost::memory_order_relaxed ); + BOOST_TEST( !r ); + BOOST_TEST_SP_EQ( px, p2 ); + BOOST_TEST_SP_EQ( cmp, p2 ); + + r = px.atomic_compare_swap( cmp, px4, boost::memory_order_release, boost::memory_order_acquire ); + BOOST_TEST( r ); + BOOST_TEST_SP_EQ( px, px4 ); + } + + return boost::report_errors(); +} From 1b49f08cb8e8b80933ead2ade5ae95daf67a40b9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 12:21:19 +0000 Subject: [PATCH 472/513] Merged 44686 from trunk to release. [SVN r47350] --- include/boost/memory_order.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/memory_order.hpp b/include/boost/memory_order.hpp index be5a9ce..2524e8a 100644 --- a/include/boost/memory_order.hpp +++ b/include/boost/memory_order.hpp @@ -27,7 +27,7 @@ enum memory_order memory_order_acquire = 1, memory_order_release = 2, memory_order_acq_rel = 3, // acquire | release - memory_order_seq_cst = 7, // acq_rel | 4 + memory_order_seq_cst = 7 // acq_rel | 4 }; } // namespace boost From 31d0c48f1810dfecb1e7af5199c658118c8bc879 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 14:47:13 +0000 Subject: [PATCH 473/513] Merged 45224, 45225 from trunk to release. [SVN r47355] --- include/boost/pointer_cast.hpp | 2 +- include/boost/pointer_to_other.hpp | 2 +- test/pointer_cast_test.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/pointer_cast.hpp b/include/boost/pointer_cast.hpp index 5a5bec0..6e532eb 100644 --- a/include/boost/pointer_cast.hpp +++ b/include/boost/pointer_cast.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2005. +// (C) Copyright Ion Gaztanaga 2005. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) diff --git a/include/boost/pointer_to_other.hpp b/include/boost/pointer_to_other.hpp index 1cf2627..8516734 100644 --- a/include/boost/pointer_to_other.hpp +++ b/include/boost/pointer_to_other.hpp @@ -4,7 +4,7 @@ // // pointer_to_other.hpp // -// (C) Copyright Ion Gaztañaga 2005. +// (C) Copyright Ion Gaztanaga 2005. // Copyright (c) 2005 Peter Dimov. // // Distributed under the Boost Software License, Version 1.0. diff --git a/test/pointer_cast_test.cpp b/test/pointer_cast_test.cpp index 0d5d652..6e4620c 100644 --- a/test/pointer_cast_test.cpp +++ b/test/pointer_cast_test.cpp @@ -1,7 +1,7 @@ // // pointer_cast_test.cpp - a test for boost/pointer_cast.hpp // -// Copyright (c) 2005 Ion Gaztañaga +// Copyright (c) 2005 Ion Gaztanaga // Copyright (c) 2005 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See From 991b02b03e97ac8e29b076e280fb50056fbab6fa Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 15:16:31 +0000 Subject: [PATCH 474/513] Whitespace fix. [SVN r47356] --- include/boost/shared_ptr.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 394e30c..ef0d398 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -419,7 +419,7 @@ public: BOOST_ASSERT(px != 0); return px; } - + T * get() const // never throws { return px; @@ -453,13 +453,13 @@ public: ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) ) typedef T * (this_type::*unspecified_bool_type)() const; - + operator unspecified_bool_type() const // never throws { return px == 0? 0: &this_type::get; } -#else +#else typedef T * this_type::*unspecified_bool_type; @@ -679,7 +679,7 @@ using std::basic_ostream; template basic_ostream & operator<< (basic_ostream & os, shared_ptr const & p) # else template std::basic_ostream & operator<< (std::basic_ostream & os, shared_ptr const & p) -# endif +# endif { os << p.get(); return os; @@ -719,7 +719,7 @@ template D * get_deleter(shared_ptr const & p) #ifdef BOOST_MSVC # pragma warning(pop) -#endif +#endif #endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) From 77ab95317165f72ed473c45370532ba84909d95a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 16:07:20 +0000 Subject: [PATCH 475/513] Updated atomic access syntax to match N2674 and the WD. [SVN r47357] --- include/boost/shared_ptr.hpp | 139 +++++++++++++++++++++-------------- test/sp_atomic_mt2_test.cpp | 6 +- test/sp_atomic_mt_test.cpp | 4 +- test/sp_atomic_test.cpp | 22 +++--- 4 files changed, 98 insertions(+), 73 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 3bf00b1..e1704ea 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -5,7 +5,7 @@ // shared_ptr.hpp // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. -// Copyright (c) 2001-2007 Peter Dimov +// Copyright (c) 2001-2008 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -516,65 +516,11 @@ public: return pn < rhs.pn; } - // atomic access - -#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) - - shared_ptr atomic_load( memory_order /*mo*/ = memory_order_seq_cst ) const + bool _internal_equiv( shared_ptr const & r ) const { - boost::detail::spinlock_pool<2>::scoped_lock lock( this ); - return *this; + return px == r.px && pn == r.pn; } - void atomic_store( shared_ptr r, memory_order /*mo*/ = memory_order_seq_cst ) - { - boost::detail::spinlock_pool<2>::scoped_lock lock( this ); - swap( r ); - } - - shared_ptr atomic_swap( shared_ptr r, memory_order /*mo*/ = memory_order_seq_cst ) - { - boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( this ); - - sp.lock(); - swap( r ); - sp.unlock(); - - return r; // return std::move(r) - } - - bool atomic_compare_swap( shared_ptr & v, shared_ptr w ) - { - boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( this ); - - sp.lock(); - - if( px == v.px && pn == v.pn ) - { - swap( w ); - - sp.unlock(); - - return true; - } - else - { - shared_ptr tmp( *this ); - - sp.unlock(); - - tmp.swap( v ); - return false; - } - } - - inline bool atomic_compare_swap( shared_ptr & v, shared_ptr w, memory_order /*success*/, memory_order /*failure*/ ) - { - return atomic_compare_swap( v, w ); // std::move( w ) - } - -#endif - // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) @@ -784,6 +730,85 @@ template D * get_deleter( shared_ptr const & p ) return del; } +// atomic access + +#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) + +template inline bool atomic_is_lock_free( shared_ptr const * /*p*/ ) +{ + return false; +} + +template shared_ptr atomic_load( shared_ptr const * p ) +{ + boost::detail::spinlock_pool<2>::scoped_lock lock( p ); + return *p; +} + +template inline shared_ptr atomic_load_explicit( shared_ptr const * p, memory_order /*mo*/ ) +{ + return atomic_load( p ); +} + +template void atomic_store( shared_ptr * p, shared_ptr r ) +{ + boost::detail::spinlock_pool<2>::scoped_lock lock( p ); + p->swap( r ); +} + +template inline void atomic_store_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) +{ + atomic_store( p, r ); // std::move( r ) +} + +template shared_ptr atomic_exchange( shared_ptr * p, shared_ptr r ) +{ + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); + + sp.lock(); + p->swap( r ); + sp.unlock(); + + return r; // return std::move( r ) +} + +template shared_ptr atomic_exchange_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) +{ + return atomic_exchange( p, r ); // std::move( r ) +} + +template bool atomic_compare_exchange( shared_ptr * p, shared_ptr * v, shared_ptr w ) +{ + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); + + sp.lock(); + + if( p->_internal_equiv( *v ) ) + { + p->swap( w ); + + sp.unlock(); + + return true; + } + else + { + shared_ptr tmp( *p ); + + sp.unlock(); + + tmp.swap( *v ); + return false; + } +} + +template inline bool atomic_compare_exchange_explicit( shared_ptr * p, shared_ptr * v, shared_ptr w, memory_order /*success*/, memory_order /*failure*/ ) +{ + return atomic_compare_exchange( p, v, w ); // std::move( w ) +} + +#endif + } // namespace boost #ifdef BOOST_MSVC diff --git a/test/sp_atomic_mt2_test.cpp b/test/sp_atomic_mt2_test.cpp index c865359..6a2e44e 100644 --- a/test/sp_atomic_mt2_test.cpp +++ b/test/sp_atomic_mt2_test.cpp @@ -83,7 +83,7 @@ int read_access( prim_type pt ) case pt_atomics: { - boost::shared_ptr p2 = ps.atomic_load(); + boost::shared_ptr p2 = boost::atomic_load( &ps ); return p2->get(); } } @@ -109,14 +109,14 @@ void write_access( prim_type pt ) case pt_atomics: { - boost::shared_ptr p1 = ps.atomic_load(); + boost::shared_ptr p1 = boost::atomic_load( &ps ); for( ;; ) { boost::shared_ptr p2( new X( *p1 ) ); p2->set(); - if( ps.atomic_compare_swap( p1, p2 ) ) break; + if( boost::atomic_compare_exchange( &ps, &p1, p2 ) ) break; } } break; diff --git a/test/sp_atomic_mt_test.cpp b/test/sp_atomic_mt_test.cpp index 143df98..0f0bf68 100644 --- a/test/sp_atomic_mt_test.cpp +++ b/test/sp_atomic_mt_test.cpp @@ -93,7 +93,7 @@ void reader( int r ) #else - boost::shared_ptr p2 = ps.atomic_load(); + boost::shared_ptr p2 = boost::atomic_load( &ps ); s += p2->get(); @@ -134,7 +134,7 @@ void writer() BOOST_TEST( p2->v_ == i ); p2->set(); - ps.atomic_store( p2 ); + boost::atomic_store( &ps, p2 ); #endif } diff --git a/test/sp_atomic_test.cpp b/test/sp_atomic_test.cpp index c1113da..c8c3586 100644 --- a/test/sp_atomic_test.cpp +++ b/test/sp_atomic_test.cpp @@ -25,31 +25,31 @@ int main() boost::shared_ptr px( new X ); { - boost::shared_ptr p2 = px.atomic_load(); + boost::shared_ptr p2 = boost::atomic_load( &px ); BOOST_TEST_SP_EQ( p2, px ); boost::shared_ptr px2( new X ); - px.atomic_store( px2 ); + boost::atomic_store( &px, px2 ); BOOST_TEST_SP_EQ( px, px2 ); - p2 = px.atomic_load(); + p2 = boost::atomic_load( &px ); BOOST_TEST_SP_EQ( p2, px ); BOOST_TEST_SP_EQ( p2, px2 ); boost::shared_ptr px3( new X ); - boost::shared_ptr p3 = px.atomic_swap( px3 ); + boost::shared_ptr p3 = boost::atomic_exchange( &px, px3 ); BOOST_TEST_SP_EQ( p3, px2 ); BOOST_TEST_SP_EQ( px, px3 ); boost::shared_ptr px4( new X ); boost::shared_ptr cmp; - bool r = px.atomic_compare_swap( cmp, px4 ); + bool r = boost::atomic_compare_exchange( &px, &cmp, px4 ); BOOST_TEST( !r ); BOOST_TEST_SP_EQ( px, px3 ); BOOST_TEST_SP_EQ( cmp, px3 ); - r = px.atomic_compare_swap( cmp, px4 ); + r = boost::atomic_compare_exchange( &px, &cmp, px4 ); BOOST_TEST( r ); BOOST_TEST_SP_EQ( px, px4 ); } @@ -59,26 +59,26 @@ int main() px.reset(); { - boost::shared_ptr p2 = px.atomic_load( boost::memory_order_acquire ); + boost::shared_ptr p2 = boost::atomic_load_explicit( &px, boost::memory_order_acquire ); BOOST_TEST_SP_EQ( p2, px ); boost::shared_ptr px2( new X ); - px.atomic_store( px2, boost::memory_order_release ); + boost::atomic_store_explicit( &px, px2, boost::memory_order_release ); BOOST_TEST_SP_EQ( px, px2 ); - boost::shared_ptr p3 = px.atomic_swap( boost::shared_ptr(), boost::memory_order_acq_rel ); + boost::shared_ptr p3 = boost::atomic_exchange_explicit( &px, boost::shared_ptr(), boost::memory_order_acq_rel ); BOOST_TEST_SP_EQ( p3, px2 ); BOOST_TEST_SP_EQ( px, p2 ); boost::shared_ptr px4( new X ); boost::shared_ptr cmp( px2 ); - bool r = px.atomic_compare_swap( cmp, px4, boost::memory_order_acquire, boost::memory_order_relaxed ); + bool r = boost::atomic_compare_exchange_explicit( &px, &cmp, px4, boost::memory_order_acquire, boost::memory_order_relaxed ); BOOST_TEST( !r ); BOOST_TEST_SP_EQ( px, p2 ); BOOST_TEST_SP_EQ( cmp, p2 ); - r = px.atomic_compare_swap( cmp, px4, boost::memory_order_release, boost::memory_order_acquire ); + r = boost::atomic_compare_exchange_explicit( &px, &cmp, px4, boost::memory_order_release, boost::memory_order_acquire ); BOOST_TEST( r ); BOOST_TEST_SP_EQ( px, px4 ); } From 556b9fe563a73e0f710c5992bada5eef7cd5c921 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jul 2008 16:18:05 +0000 Subject: [PATCH 476/513] Merge 47357 (atomic access N2674 edits) from trunk to release. [SVN r47358] --- include/boost/shared_ptr.hpp | 139 +++++++++++++++++++++-------------- test/sp_atomic_mt2_test.cpp | 6 +- test/sp_atomic_mt_test.cpp | 4 +- test/sp_atomic_test.cpp | 22 +++--- 4 files changed, 98 insertions(+), 73 deletions(-) diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index ef0d398..ad2bc17 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -5,7 +5,7 @@ // shared_ptr.hpp // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. -// Copyright (c) 2001-2007 Peter Dimov +// Copyright (c) 2001-2008 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -503,65 +503,11 @@ public: return pn.get_deleter( ti ); } - // atomic access - -#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) - - shared_ptr atomic_load( memory_order /*mo*/ = memory_order_seq_cst ) const + bool _internal_equiv( shared_ptr const & r ) const { - boost::detail::spinlock_pool<2>::scoped_lock lock( this ); - return *this; + return px == r.px && pn == r.pn; } - void atomic_store( shared_ptr r, memory_order /*mo*/ = memory_order_seq_cst ) - { - boost::detail::spinlock_pool<2>::scoped_lock lock( this ); - swap( r ); - } - - shared_ptr atomic_swap( shared_ptr r, memory_order /*mo*/ = memory_order_seq_cst ) - { - boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( this ); - - sp.lock(); - swap( r ); - sp.unlock(); - - return r; // return std::move(r) - } - - bool atomic_compare_swap( shared_ptr & v, shared_ptr w ) - { - boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( this ); - - sp.lock(); - - if( px == v.px && pn == v.pn ) - { - swap( w ); - - sp.unlock(); - - return true; - } - else - { - shared_ptr tmp( *this ); - - sp.unlock(); - - tmp.swap( v ); - return false; - } - } - - inline bool atomic_compare_swap( shared_ptr & v, shared_ptr w, memory_order /*success*/, memory_order /*failure*/ ) - { - return atomic_compare_swap( v, w ); // std::move( w ) - } - -#endif - // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) @@ -715,6 +661,85 @@ template D * get_deleter(shared_ptr const & p) #endif +// atomic access + +#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) + +template inline bool atomic_is_lock_free( shared_ptr const * /*p*/ ) +{ + return false; +} + +template shared_ptr atomic_load( shared_ptr const * p ) +{ + boost::detail::spinlock_pool<2>::scoped_lock lock( p ); + return *p; +} + +template inline shared_ptr atomic_load_explicit( shared_ptr const * p, memory_order /*mo*/ ) +{ + return atomic_load( p ); +} + +template void atomic_store( shared_ptr * p, shared_ptr r ) +{ + boost::detail::spinlock_pool<2>::scoped_lock lock( p ); + p->swap( r ); +} + +template inline void atomic_store_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) +{ + atomic_store( p, r ); // std::move( r ) +} + +template shared_ptr atomic_exchange( shared_ptr * p, shared_ptr r ) +{ + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); + + sp.lock(); + p->swap( r ); + sp.unlock(); + + return r; // return std::move( r ) +} + +template shared_ptr atomic_exchange_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) +{ + return atomic_exchange( p, r ); // std::move( r ) +} + +template bool atomic_compare_exchange( shared_ptr * p, shared_ptr * v, shared_ptr w ) +{ + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); + + sp.lock(); + + if( p->_internal_equiv( *v ) ) + { + p->swap( w ); + + sp.unlock(); + + return true; + } + else + { + shared_ptr tmp( *p ); + + sp.unlock(); + + tmp.swap( *v ); + return false; + } +} + +template inline bool atomic_compare_exchange_explicit( shared_ptr * p, shared_ptr * v, shared_ptr w, memory_order /*success*/, memory_order /*failure*/ ) +{ + return atomic_compare_exchange( p, v, w ); // std::move( w ) +} + +#endif + } // namespace boost #ifdef BOOST_MSVC diff --git a/test/sp_atomic_mt2_test.cpp b/test/sp_atomic_mt2_test.cpp index c865359..6a2e44e 100644 --- a/test/sp_atomic_mt2_test.cpp +++ b/test/sp_atomic_mt2_test.cpp @@ -83,7 +83,7 @@ int read_access( prim_type pt ) case pt_atomics: { - boost::shared_ptr p2 = ps.atomic_load(); + boost::shared_ptr p2 = boost::atomic_load( &ps ); return p2->get(); } } @@ -109,14 +109,14 @@ void write_access( prim_type pt ) case pt_atomics: { - boost::shared_ptr p1 = ps.atomic_load(); + boost::shared_ptr p1 = boost::atomic_load( &ps ); for( ;; ) { boost::shared_ptr p2( new X( *p1 ) ); p2->set(); - if( ps.atomic_compare_swap( p1, p2 ) ) break; + if( boost::atomic_compare_exchange( &ps, &p1, p2 ) ) break; } } break; diff --git a/test/sp_atomic_mt_test.cpp b/test/sp_atomic_mt_test.cpp index 143df98..0f0bf68 100644 --- a/test/sp_atomic_mt_test.cpp +++ b/test/sp_atomic_mt_test.cpp @@ -93,7 +93,7 @@ void reader( int r ) #else - boost::shared_ptr p2 = ps.atomic_load(); + boost::shared_ptr p2 = boost::atomic_load( &ps ); s += p2->get(); @@ -134,7 +134,7 @@ void writer() BOOST_TEST( p2->v_ == i ); p2->set(); - ps.atomic_store( p2 ); + boost::atomic_store( &ps, p2 ); #endif } diff --git a/test/sp_atomic_test.cpp b/test/sp_atomic_test.cpp index c1113da..c8c3586 100644 --- a/test/sp_atomic_test.cpp +++ b/test/sp_atomic_test.cpp @@ -25,31 +25,31 @@ int main() boost::shared_ptr px( new X ); { - boost::shared_ptr p2 = px.atomic_load(); + boost::shared_ptr p2 = boost::atomic_load( &px ); BOOST_TEST_SP_EQ( p2, px ); boost::shared_ptr px2( new X ); - px.atomic_store( px2 ); + boost::atomic_store( &px, px2 ); BOOST_TEST_SP_EQ( px, px2 ); - p2 = px.atomic_load(); + p2 = boost::atomic_load( &px ); BOOST_TEST_SP_EQ( p2, px ); BOOST_TEST_SP_EQ( p2, px2 ); boost::shared_ptr px3( new X ); - boost::shared_ptr p3 = px.atomic_swap( px3 ); + boost::shared_ptr p3 = boost::atomic_exchange( &px, px3 ); BOOST_TEST_SP_EQ( p3, px2 ); BOOST_TEST_SP_EQ( px, px3 ); boost::shared_ptr px4( new X ); boost::shared_ptr cmp; - bool r = px.atomic_compare_swap( cmp, px4 ); + bool r = boost::atomic_compare_exchange( &px, &cmp, px4 ); BOOST_TEST( !r ); BOOST_TEST_SP_EQ( px, px3 ); BOOST_TEST_SP_EQ( cmp, px3 ); - r = px.atomic_compare_swap( cmp, px4 ); + r = boost::atomic_compare_exchange( &px, &cmp, px4 ); BOOST_TEST( r ); BOOST_TEST_SP_EQ( px, px4 ); } @@ -59,26 +59,26 @@ int main() px.reset(); { - boost::shared_ptr p2 = px.atomic_load( boost::memory_order_acquire ); + boost::shared_ptr p2 = boost::atomic_load_explicit( &px, boost::memory_order_acquire ); BOOST_TEST_SP_EQ( p2, px ); boost::shared_ptr px2( new X ); - px.atomic_store( px2, boost::memory_order_release ); + boost::atomic_store_explicit( &px, px2, boost::memory_order_release ); BOOST_TEST_SP_EQ( px, px2 ); - boost::shared_ptr p3 = px.atomic_swap( boost::shared_ptr(), boost::memory_order_acq_rel ); + boost::shared_ptr p3 = boost::atomic_exchange_explicit( &px, boost::shared_ptr(), boost::memory_order_acq_rel ); BOOST_TEST_SP_EQ( p3, px2 ); BOOST_TEST_SP_EQ( px, p2 ); boost::shared_ptr px4( new X ); boost::shared_ptr cmp( px2 ); - bool r = px.atomic_compare_swap( cmp, px4, boost::memory_order_acquire, boost::memory_order_relaxed ); + bool r = boost::atomic_compare_exchange_explicit( &px, &cmp, px4, boost::memory_order_acquire, boost::memory_order_relaxed ); BOOST_TEST( !r ); BOOST_TEST_SP_EQ( px, p2 ); BOOST_TEST_SP_EQ( cmp, p2 ); - r = px.atomic_compare_swap( cmp, px4, boost::memory_order_release, boost::memory_order_acquire ); + r = boost::atomic_compare_exchange_explicit( &px, &cmp, px4, boost::memory_order_release, boost::memory_order_acquire ); BOOST_TEST( r ); BOOST_TEST_SP_EQ( px, px4 ); } From 8c7954a53a7aa8652bdb364e9e4f5d89fe4885c8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 23 Jul 2008 20:04:52 +0000 Subject: [PATCH 477/513] Untabify. [SVN r47736] --- test/spinlock_pool_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spinlock_pool_test.cpp b/test/spinlock_pool_test.cpp index 00e7558..c1ce2b3 100644 --- a/test/spinlock_pool_test.cpp +++ b/test/spinlock_pool_test.cpp @@ -17,7 +17,7 @@ int main() int x = 0; { - boost::detail::spinlock_pool<0>::scoped_lock lock( &x ); + boost::detail::spinlock_pool<0>::scoped_lock lock( &x ); ++x; } From 6ba78f76f609fddace8882b20cfc8b4f5036f052 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 23 Jul 2008 20:47:47 +0000 Subject: [PATCH 478/513] Merge 47736 from trunk (untabify). [SVN r47739] --- test/spinlock_pool_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spinlock_pool_test.cpp b/test/spinlock_pool_test.cpp index 00e7558..c1ce2b3 100644 --- a/test/spinlock_pool_test.cpp +++ b/test/spinlock_pool_test.cpp @@ -17,7 +17,7 @@ int main() int x = 0; { - boost::detail::spinlock_pool<0>::scoped_lock lock( &x ); + boost::detail::spinlock_pool<0>::scoped_lock lock( &x ); ++x; } From e3b9389a245fc8e27af3140539fb330550dbdc5f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:17:29 +0000 Subject: [PATCH 479/513] Fix #2338. [SVN r48832] --- src/sp_collector.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sp_collector.cpp b/src/sp_collector.cpp index 6f933c2..bb69ae8 100644 --- a/src/sp_collector.cpp +++ b/src/sp_collector.cpp @@ -104,6 +104,8 @@ static void find_unreachable_objects_impl(map_type const & m, map2_type & m2) BOOST_ASSERT(p->use_count() != 0); // there should be no inactive counts in the map + m2[ i->first ]; + scan_and_count(i->second.first, i->second.second, m, m2); } @@ -121,7 +123,7 @@ static void find_unreachable_objects_impl(map_type const & m, map2_type & m2) if(p->use_count() != i->second) open.push_back(p); } - std::cout << "... " << m2.size() << " objects in open.\n"; + std::cout << "... " << open.size() << " objects in open.\n"; for(open_type::iterator j = open.begin(); j != open.end(); ++j) { From a97cd2d0cc39594fbee056b4408ca1bc72848f3a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:21:56 +0000 Subject: [PATCH 480/513] Fix #2337. [SVN r48833] --- include/boost/detail/atomic_count_sync.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/detail/atomic_count_sync.hpp b/include/boost/detail/atomic_count_sync.hpp index e973fb7..676d3f9 100644 --- a/include/boost/detail/atomic_count_sync.hpp +++ b/include/boost/detail/atomic_count_sync.hpp @@ -15,6 +15,10 @@ // http://www.boost.org/LICENSE_1_0.txt) // +#if defined( __ia64__ ) && defined( __INTEL_COMPILER ) +# include +#endif + namespace boost { From 2b2557933889470a1123d1cbb75c0327116f39cb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:31:13 +0000 Subject: [PATCH 481/513] Fix #2310. [SVN r48834] --- include/boost/detail/spinlock.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/detail/spinlock.hpp b/include/boost/detail/spinlock.hpp index e273647..8a73999 100644 --- a/include/boost/detail/spinlock.hpp +++ b/include/boost/detail/spinlock.hpp @@ -30,9 +30,9 @@ #include -#if defined(__GNUC__) && defined( __arm__ ) +#if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ ) # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include From 2fb567b3f2a0af74ad2275815b559ec220c9b5e5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:37:13 +0000 Subject: [PATCH 482/513] Fix #2336. [SVN r48835] --- include/boost/detail/atomic_count.hpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 804fd1a..b731fcc 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -90,23 +90,18 @@ typedef long atomic_count; } #elif defined(BOOST_AC_USE_PTHREADS) - # include #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) - # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) - # include -#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) - +#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) # include #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) - # include #elif defined(BOOST_HAS_PTHREADS) From 6175baf858dada6cc5276dc2b02b9797afd50038 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:43:14 +0000 Subject: [PATCH 483/513] Fix #2000. [SVN r48836] --- include/boost/detail/atomic_count.hpp | 2 +- include/boost/detail/sp_counted_base.hpp | 2 +- include/boost/detail/spinlock.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index b731fcc..c53a63b 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -98,7 +98,7 @@ typedef long atomic_count; #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) # include -#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) +#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # include #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index 6d733d0..d576a49 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -46,7 +46,7 @@ #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # include #elif defined(__GNUC__) && ( defined( __sparcv8 ) || defined( __sparcv9 ) ) diff --git a/include/boost/detail/spinlock.hpp b/include/boost/detail/spinlock.hpp index 8a73999..d4e5bce 100644 --- a/include/boost/detail/spinlock.hpp +++ b/include/boost/detail/spinlock.hpp @@ -32,7 +32,7 @@ #if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ ) # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include From f5990cab6590df57bbab982122caa0ea7842024f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:49:18 +0000 Subject: [PATCH 484/513] Fix #1758. V9 is the default for g++ 4.2 or later, on 4.1 and earlier do not attempt to use CAS on V8. [SVN r48837] --- include/boost/detail/sp_counted_base.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index d576a49..c25a57f 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -49,7 +49,7 @@ #elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # include -#elif defined(__GNUC__) && ( defined( __sparcv8 ) || defined( __sparcv9 ) ) +#elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) ) # include #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) From 774332f85acc11f32964e6a3bd7f6d66cfd24cef Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:53:53 +0000 Subject: [PATCH 485/513] Fix #2263. See also [48835]. [SVN r48838] --- include/boost/detail/spinlock.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/spinlock.hpp b/include/boost/detail/spinlock.hpp index d4e5bce..346fb3c 100644 --- a/include/boost/detail/spinlock.hpp +++ b/include/boost/detail/spinlock.hpp @@ -32,7 +32,7 @@ #if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ ) # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include From 395766e2d376169c1f1dcb72c8179fdb585c9549 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 17 Sep 2008 22:59:07 +0000 Subject: [PATCH 486/513] Fix #2315. [SVN r48839] --- shared_array.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared_array.htm b/shared_array.htm index 87bf61e..320a54a 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -47,7 +47,7 @@ void reset(T * p = 0); template<class D> void reset(T * p, D d); - T & operator[](std::ptrdiff_t i) const() const; // never throws + T & operator[](std::ptrdiff_t i) const; // never throws T * get() const; // never throws bool unique() const; // never throws From 6e804e64b82b371ece78cfc297b1d0fa39aa51b4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 28 Sep 2008 15:05:17 +0000 Subject: [PATCH 487/513] Merge 48832-48840 from trunk. [SVN r48989] --- include/boost/detail/atomic_count.hpp | 7 +------ include/boost/detail/atomic_count_sync.hpp | 4 ++++ include/boost/detail/sp_counted_base.hpp | 4 ++-- include/boost/detail/spinlock.hpp | 4 ++-- shared_array.htm | 2 +- src/sp_collector.cpp | 4 +++- 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index 804fd1a..c53a63b 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -90,23 +90,18 @@ typedef long atomic_count; } #elif defined(BOOST_AC_USE_PTHREADS) - # include #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) - # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) - # include -#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) - +#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # include #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) - # include #elif defined(BOOST_HAS_PTHREADS) diff --git a/include/boost/detail/atomic_count_sync.hpp b/include/boost/detail/atomic_count_sync.hpp index e973fb7..676d3f9 100644 --- a/include/boost/detail/atomic_count_sync.hpp +++ b/include/boost/detail/atomic_count_sync.hpp @@ -15,6 +15,10 @@ // http://www.boost.org/LICENSE_1_0.txt) // +#if defined( __ia64__ ) && defined( __INTEL_COMPILER ) +# include +#endif + namespace boost { diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/detail/sp_counted_base.hpp index 6d733d0..c25a57f 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/detail/sp_counted_base.hpp @@ -46,10 +46,10 @@ #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # include -#elif defined(__GNUC__) && ( defined( __sparcv8 ) || defined( __sparcv9 ) ) +#elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) ) # include #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) diff --git a/include/boost/detail/spinlock.hpp b/include/boost/detail/spinlock.hpp index e273647..346fb3c 100644 --- a/include/boost/detail/spinlock.hpp +++ b/include/boost/detail/spinlock.hpp @@ -30,9 +30,9 @@ #include -#if defined(__GNUC__) && defined( __arm__ ) +#if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ ) # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include diff --git a/shared_array.htm b/shared_array.htm index 87bf61e..320a54a 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -47,7 +47,7 @@ void reset(T * p = 0); template<class D> void reset(T * p, D d); - T & operator[](std::ptrdiff_t i) const() const; // never throws + T & operator[](std::ptrdiff_t i) const; // never throws T * get() const; // never throws bool unique() const; // never throws diff --git a/src/sp_collector.cpp b/src/sp_collector.cpp index 6f933c2..bb69ae8 100644 --- a/src/sp_collector.cpp +++ b/src/sp_collector.cpp @@ -104,6 +104,8 @@ static void find_unreachable_objects_impl(map_type const & m, map2_type & m2) BOOST_ASSERT(p->use_count() != 0); // there should be no inactive counts in the map + m2[ i->first ]; + scan_and_count(i->second.first, i->second.second, m, m2); } @@ -121,7 +123,7 @@ static void find_unreachable_objects_impl(map_type const & m, map2_type & m2) if(p->use_count() != i->second) open.push_back(p); } - std::cout << "... " << m2.size() << " objects in open.\n"; + std::cout << "... " << open.size() << " objects in open.\n"; for(open_type::iterator j = open.begin(); j != open.end(); ++j) { From ed79000ea832a1bc2d0dfcf7ec1e6ffb72fc707c Mon Sep 17 00:00:00 2001 From: Nicola Musatti Date: Mon, 6 Oct 2008 20:17:18 +0000 Subject: [PATCH 488/513] Patch from Ticket #2342 [SVN r49153] --- include/boost/detail/sp_convertible.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/sp_convertible.hpp b/include/boost/detail/sp_convertible.hpp index 017217b..2c1539b 100644 --- a/include/boost/detail/sp_convertible.hpp +++ b/include/boost/detail/sp_convertible.hpp @@ -25,7 +25,7 @@ # define BOOST_SP_NO_SP_CONVERTIBLE #endif -#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x600 ) +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ <= 0x610 ) # define BOOST_SP_NO_SP_CONVERTIBLE #endif From 6f91ea87c34add9108acfebe2e349d15f90596a5 Mon Sep 17 00:00:00 2001 From: Nicola Musatti Date: Mon, 13 Oct 2008 19:22:17 +0000 Subject: [PATCH 489/513] CodeGear patch. Fixes #2342 [SVN r49320] --- include/boost/detail/sp_convertible.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/sp_convertible.hpp b/include/boost/detail/sp_convertible.hpp index 017217b..2c1539b 100644 --- a/include/boost/detail/sp_convertible.hpp +++ b/include/boost/detail/sp_convertible.hpp @@ -25,7 +25,7 @@ # define BOOST_SP_NO_SP_CONVERTIBLE #endif -#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x600 ) +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ <= 0x610 ) # define BOOST_SP_NO_SP_CONVERTIBLE #endif From d9b9921d236f43d3d1f01521224ae044d0845b71 Mon Sep 17 00:00:00 2001 From: "Michael A. Jackson" Date: Sat, 1 Nov 2008 13:15:41 +0000 Subject: [PATCH 490/513] Continuing merge of CMake build system files into trunk with the encouragement of Doug Gregor [SVN r49510] --- CMakeLists.txt | 30 ++++++++++++++++++++++++++++++ module.cmake | 1 + test/CMakeLists.txt | 15 +++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 module.cmake create mode 100644 test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..abe2fc7 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,30 @@ +#---------------------------------------------------------------------------- +# This file was automatically generated from the original CMakeLists.txt file +# Add a variable to hold the headers for the library +set (lib_headers + enable_shared_from_this.hpp + pointer_cast.hpp + scoped_array.hpp + scoped_ptr.hpp + shared_array.hpp + shared_ptr.hpp + weak_ptr.hpp +) + +# Add a library target to the build system +boost_library_project( + smart_ptr + # SRCDIRS + TESTDIRS test + HEADERS ${lib_headers} + # DOCDIRS + DESCRIPTION "Five smart pointer class templates." + MODULARIZED + AUTHORS "Greg Colvin" + "Beman Dawes " + "Peter Dimov " + "Darin Adler" + # MAINTAINERS +) + + diff --git a/module.cmake b/module.cmake new file mode 100644 index 0000000..d83266c --- /dev/null +++ b/module.cmake @@ -0,0 +1 @@ +boost_module(smart_ptr DEPENDS utility) \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..67eee62 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,15 @@ +boost_test_run(smart_ptr_test) +boost_test_run(shared_ptr_basic_test) +boost_test_run(shared_ptr_test) +boost_test_run(weak_ptr_test) +boost_test_run(shared_from_this_test) +boost_test_run(get_deleter_test) +boost_test_run(intrusive_ptr_test) +boost_test_run(atomic_count_test) +boost_test_run(lw_mutex_test) +boost_test_compile_fail(shared_ptr_assign_fail) +boost_test_compile_fail(shared_ptr_delete_fail) +boost_test_run(shared_ptr_alloc2_test) +boost_test_run(pointer_cast_test) +boost_test_compile(pointer_to_other_test) +boost_test_run(auto_ptr_rv_test) From c40b30664750da870f97be7c616e6c4ba5186f20 Mon Sep 17 00:00:00 2001 From: "Michael A. Jackson" Date: Fri, 7 Nov 2008 17:02:56 +0000 Subject: [PATCH 491/513] Updating CMake files to latest trunk. Added dependency information for regression tests and a few new macros for internal use. [SVN r49627] --- test/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 67eee62..7ddae31 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,3 +1,6 @@ +boost_additional_test_dependencies(tokenizer BOOST_DEPENDS test intrusive) + + boost_test_run(smart_ptr_test) boost_test_run(shared_ptr_basic_test) boost_test_run(shared_ptr_test) From 55583ac7490bcbfcf9f33d7fd7a23787adda2e4c Mon Sep 17 00:00:00 2001 From: "Troy D. Straszheim" Date: Sat, 24 Jan 2009 18:57:20 +0000 Subject: [PATCH 492/513] merge of cmake build files from trunk per beman [SVN r50756] --- CMakeLists.txt | 30 ++++++++++++++++++++++++++++++ module.cmake | 1 + test/CMakeLists.txt | 18 ++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 module.cmake create mode 100644 test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..abe2fc7 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,30 @@ +#---------------------------------------------------------------------------- +# This file was automatically generated from the original CMakeLists.txt file +# Add a variable to hold the headers for the library +set (lib_headers + enable_shared_from_this.hpp + pointer_cast.hpp + scoped_array.hpp + scoped_ptr.hpp + shared_array.hpp + shared_ptr.hpp + weak_ptr.hpp +) + +# Add a library target to the build system +boost_library_project( + smart_ptr + # SRCDIRS + TESTDIRS test + HEADERS ${lib_headers} + # DOCDIRS + DESCRIPTION "Five smart pointer class templates." + MODULARIZED + AUTHORS "Greg Colvin" + "Beman Dawes " + "Peter Dimov " + "Darin Adler" + # MAINTAINERS +) + + diff --git a/module.cmake b/module.cmake new file mode 100644 index 0000000..d83266c --- /dev/null +++ b/module.cmake @@ -0,0 +1 @@ +boost_module(smart_ptr DEPENDS utility) \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..7ddae31 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,18 @@ +boost_additional_test_dependencies(tokenizer BOOST_DEPENDS test intrusive) + + +boost_test_run(smart_ptr_test) +boost_test_run(shared_ptr_basic_test) +boost_test_run(shared_ptr_test) +boost_test_run(weak_ptr_test) +boost_test_run(shared_from_this_test) +boost_test_run(get_deleter_test) +boost_test_run(intrusive_ptr_test) +boost_test_run(atomic_count_test) +boost_test_run(lw_mutex_test) +boost_test_compile_fail(shared_ptr_assign_fail) +boost_test_compile_fail(shared_ptr_delete_fail) +boost_test_run(shared_ptr_alloc2_test) +boost_test_run(pointer_cast_test) +boost_test_compile(pointer_to_other_test) +boost_test_run(auto_ptr_rv_test) From a2c5208b8ec20988759bc2505e0cf2e62e61fdfd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 28 Feb 2009 19:59:56 +0000 Subject: [PATCH 493/513] Sync shared_count.hpp with trunk. [SVN r51484] --- include/boost/detail/shared_count.hpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 8f13777..9e9b1ba 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -28,6 +28,7 @@ #include #include #include +#include // In order to avoid circular dependencies with Boost.TR1 // we make sure that our include of doesn't try to // pull in the TR1 headers: that's why we use this header @@ -227,6 +228,18 @@ public: if( pi_ != 0 ) pi_->add_ref_copy(); } +#if defined( BOOST_HAS_RVALUE_REFS ) + + shared_count(shared_count && r): pi_(r.pi_) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + r.pi_ = 0; + } + +#endif + explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 shared_count( weak_count const & r, sp_nothrow_tag ); // constructs an empty *this when r.use_count() == 0 @@ -368,6 +381,11 @@ public: return pi_ != 0? pi_->use_count(): 0; } + bool empty() const // nothrow + { + return pi_ == 0; + } + friend inline bool operator==(weak_count const & a, weak_count const & b) { return a.pi_ == b.pi_; From 13f91c15f030ebcc1eca28e7bdd4d439b97d4771 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 28 Feb 2009 20:02:12 +0000 Subject: [PATCH 494/513] Sync enable_shared_from_this.hpp and shared_ptr.hpp with release. [SVN r51485] --- include/boost/enable_shared_from_this.hpp | 95 +++--------- include/boost/shared_ptr.hpp | 177 +++++++--------------- 2 files changed, 71 insertions(+), 201 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index b624ee9..4e49f1f 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -13,23 +13,15 @@ // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html // -#include +#include #include #include -#include +#include namespace boost { -#if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) - -template< class T > class enable_shared_from_this; -template< class T, class Y > void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ); -template< class T, class Y > void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ); - -#endif - -template< class T > class enable_shared_from_this +template class enable_shared_from_this { protected: @@ -46,89 +38,36 @@ protected: return *this; } -// virtual destructor because we need a vtable for dynamic_cast from base to derived to work - virtual ~enable_shared_from_this() + ~enable_shared_from_this() { - BOOST_ASSERT( _shared_count.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist } public: shared_ptr shared_from_this() { - init_weak_once(); - T * p = dynamic_cast( this ); - return shared_ptr( detail::shared_count( _weak_count ), p ); + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(p.get() == this); + return p; } shared_ptr shared_from_this() const { - init_weak_once(); - T const * p = dynamic_cast( this ); - return shared_ptr( detail::shared_count( _weak_count ), p ); + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(p.get() == this); + return p; } -private: +// Note: No, you don't need to initialize _internal_weak_this +// +// Please read the documentation, not the code +// +// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html - mutable detail::weak_count _weak_count; - mutable detail::shared_count _shared_count; - - void init_weak_once() const - { - if( _weak_count.empty() ) - { - detail::shared_count( (void*)0, detail::sp_deleter_wrapper() ).swap( _shared_count ); - _weak_count = _shared_count; - } - } - -#if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) - - template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ); - template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ); - -#else - -public: - -#endif - - template - void sp_accept_owner( shared_ptr & owner ) const - { - if( _weak_count.use_count() == 0 ) - { - _weak_count = owner.get_shared_count(); - } - else if( !_shared_count.empty() ) - { - BOOST_ASSERT( owner.unique() ); // no weak_ptrs to owner should exist either, but there's no way to check that - detail::sp_deleter_wrapper * pd = detail::basic_get_deleter( _shared_count ); - BOOST_ASSERT( pd != 0 ); - pd->set_deleter( owner.get_shared_count() ); - - owner.reset( _shared_count, owner.get() ); - detail::shared_count().swap( _shared_count ); - } - } + typedef T _internal_element_type; // for bcc 5.5.1 + mutable weak_ptr<_internal_element_type> _internal_weak_this; }; -template< class T, class Y > inline void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ) -{ - if( pe != 0 ) - { - pe->sp_accept_owner( *ptr ); - } -} - -template< class T, class Y > inline void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ) -{ - if( pe != 0 ) - { - pe->sp_accept_owner( *ptr ); - } -} - } // namespace boost #endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index e1704ea..ad2bc17 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -58,8 +58,8 @@ namespace boost { -template class shared_ptr; template class weak_ptr; +template class enable_shared_from_this; namespace detail { @@ -98,6 +98,43 @@ template<> struct shared_ptr_traits #endif +// enable_shared_from_this support + +template void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this const * pe, Y const * px ) +{ + if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); +} + +#ifdef _MANAGED + +// Avoid C4793, ... causes native code generation + +struct sp_any_pointer +{ + template sp_any_pointer( T* ) {} +}; + +inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer ) +{ +} + +#else // _MANAGED + +#ifdef sgi +// Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed +# pragma set woff 3506 +#endif + +inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) +{ +} + +#ifdef sgi +# pragma reset woff 3506 +#endif + +#endif // _MANAGED + #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) // rvalue auto_ptr support based on a technique by Dave Abrahams @@ -109,38 +146,12 @@ template< class T, class R > struct sp_enable_if_auto_ptr template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R > { typedef R type; -}; +}; #endif } // namespace detail -// sp_accept_owner - -#ifdef _MANAGED - -// Avoid C4793, ... causes native code generation - -struct sp_any_pointer -{ - template sp_any_pointer( T* ) {} -}; - -inline void sp_accept_owner( sp_any_pointer, sp_any_pointer ) -{ -} - -inline void sp_accept_owner( sp_any_pointer, sp_any_pointer, sp_any_pointer ) -{ -} - -#else // _MANAGED - -inline void sp_accept_owner( ... ) -{ -} - -#endif // _MANAGED // // shared_ptr @@ -171,7 +182,7 @@ public: template explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { - sp_accept_owner( this, p ); + boost::detail::sp_enable_shared_from_this( pn, p, p ); } // @@ -180,18 +191,16 @@ public: // shared_ptr will release p by calling d(p) // - template shared_ptr( Y * p, D d ): px( p ), pn( p, d ) + template shared_ptr(Y * p, D d): px(p), pn(p, d) { - D * pd = static_cast( pn.get_deleter( BOOST_SP_TYPEID(D) ) ); - sp_accept_owner( this, p, pd ); + boost::detail::sp_enable_shared_from_this( pn, p, p ); } // As above, but with allocator. A's copy constructor shall not throw. template shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) { - D * pd = static_cast( pn.get_deleter( BOOST_SP_TYPEID(D) ) ); - sp_accept_owner( this, p, pd ); + boost::detail::sp_enable_shared_from_this( pn, p, p ); } // generated copy constructor, assignment, destructor are fine... @@ -238,10 +247,6 @@ public: { } - shared_ptr( detail::shared_count const & c, T * p ): px( p ), pn( c ) // never throws - { - } - // aliasing template< class Y > shared_ptr( shared_ptr const & r, T * p ): px( p ), pn( r.pn ) // never throws @@ -283,8 +288,7 @@ public: { Y * tmp = r.get(); pn = boost::detail::shared_count(r); - - sp_accept_owner( this, tmp ); + boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); } #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) @@ -294,8 +298,7 @@ public: { typename Ap::element_type * tmp = r.get(); pn = boost::detail::shared_count( r ); - - sp_accept_owner( this, tmp ); + boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); } @@ -364,10 +367,6 @@ public: r.px = 0; } - shared_ptr(detail::shared_count && c, T * p): px(p), pn( static_cast< detail::shared_count && >( c ) ) // never throws - { - } - shared_ptr & operator=( shared_ptr && r ) // never throws { this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); @@ -409,18 +408,6 @@ public: this_type( r, p ).swap( *this ); } - void reset( detail::shared_count const & c, T * p ) - { - this_type( c, p ).swap( *this ); - } - -#if defined( BOOST_HAS_RVALUE_REFS ) - void reset( detail::shared_count && c, T * p ) - { - this_type( static_cast< detail::shared_count && >( c ), p ).swap( *this ); - } -#endif - reference operator* () const // never throws { BOOST_ASSERT(px != 0); @@ -506,16 +493,16 @@ public: pn.swap(other.pn); } - detail::shared_count const & get_shared_count() const // never throws - { - return pn; - } - template bool _internal_less(shared_ptr const & rhs) const { return pn < rhs.pn; } + void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const + { + return pn.get_deleter( ti ); + } + bool _internal_equiv( shared_ptr const & r ) const { return px == r.px && pn == r.pn; @@ -652,8 +639,6 @@ template std::basic_ostream & operator<< (std:: // get_deleter -namespace detail -{ #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) ) @@ -661,75 +646,21 @@ namespace detail // g++ 2.9x doesn't allow static_cast(void *) // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it -template D * basic_get_deleter(shared_count const & c) +template D * get_deleter(shared_ptr const & p) { - void const * q = c.get_deleter(BOOST_SP_TYPEID(D)); + void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D)); return const_cast(static_cast(q)); } #else -template D * basic_get_deleter(shared_count const & c) +template D * get_deleter(shared_ptr const & p) { - return static_cast(c.get_deleter(BOOST_SP_TYPEID(D))); + return static_cast(p._internal_get_deleter(BOOST_SP_TYPEID(D))); } #endif -class sp_deleter_wrapper -{ - detail::shared_count _deleter; -public: - sp_deleter_wrapper() - {} - void set_deleter(shared_count const &deleter) - { - _deleter = deleter; - } - void operator()(const void *) - { - BOOST_ASSERT(_deleter.use_count() <= 1); - detail::shared_count().swap( _deleter ); - } - template -#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) - D* get_deleter( D* ) const -#else - D* get_deleter() const -#endif - { - return boost::detail::basic_get_deleter(_deleter); - } -}; - -} // namespace detail - -template D * get_deleter( shared_ptr const & p ) -{ - D *del = detail::basic_get_deleter( p.get_shared_count() ); - - if( del == 0 ) - { - detail::sp_deleter_wrapper *del_wrapper = detail::basic_get_deleter(p.get_shared_count()); - -#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) - - if( del_wrapper ) del = del_wrapper->get_deleter( (D*)0 ); - -#elif defined( __GNUC__ ) && BOOST_WORKAROUND( __GNUC__, < 4 ) - - if( del_wrapper ) del = del_wrapper->::boost::detail::sp_deleter_wrapper::get_deleter(); - -#else - - if( del_wrapper ) del = del_wrapper->get_deleter(); - -#endif - } - - return del; -} - // atomic access #if !defined(BOOST_SP_NO_ATOMIC_ACCESS) From 10f6ff8b77db528ca6ca6896b6786cba87956745 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 28 Feb 2009 21:08:25 +0000 Subject: [PATCH 495/513] Sync smart_ptr/test/Jamfile.v2 with release. [SVN r51486] --- test/Jamfile.v2 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 8520861..5f68e20 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -36,19 +36,17 @@ import testing ; [ compile-fail scoped_ptr_eq_fail.cpp ] [ compile-fail scoped_array_eq_fail.cpp ] [ run esft_regtest.cpp ] - [ run esft_constructor_test.cpp ] [ run yield_k_test.cpp ] [ run yield_k_test.cpp : : : multi : yield_k_test.mt ] [ run spinlock_test.cpp ] [ run spinlock_try_test.cpp ] [ run spinlock_try_test.cpp : : : multi : spinlock_try_test.mt ] [ run spinlock_pool_test.cpp ] - [ run sp_accept_owner_test.cpp ] - [ run sp_atomic_test.cpp ] [ run make_shared_test.cpp ] [ run sp_convertible_test.cpp ] [ run wp_convertible_test.cpp ] [ run ip_convertible_test.cpp ] [ run allocate_shared_test.cpp ] + [ run sp_atomic_test.cpp ] ; } From 0da6902267567d27056b2bd67540f2a819bbec11 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 1 Mar 2009 16:00:42 +0000 Subject: [PATCH 496/513] Move smart_ptr into boost/smart_ptr/*.hpp (refs #2239). [SVN r51509] --- include/boost/detail/atomic_count.hpp | 106 +-- include/boost/detail/lightweight_mutex.hpp | 28 +- include/boost/enable_shared_from_this.hpp | 63 +- include/boost/intrusive_ptr.hpp | 301 +------ include/boost/make_shared.hpp | 418 +--------- include/boost/scoped_array.hpp | 124 +-- include/boost/scoped_ptr.hpp | 146 +--- include/boost/shared_array.hpp | 176 +--- include/boost/shared_ptr.hpp | 734 +---------------- .../{detail => smart_ptr}/bad_weak_ptr.hpp | 8 +- .../boost/smart_ptr/detail/atomic_count.hpp | 119 +++ .../detail/atomic_count_gcc.hpp | 6 +- .../detail/atomic_count_gcc_x86.hpp | 6 +- .../detail/atomic_count_pthreads.hpp | 6 +- .../detail/atomic_count_solaris.hpp | 6 +- .../detail/atomic_count_sync.hpp | 6 +- .../detail/atomic_count_win32.hpp | 6 +- .../smart_ptr/detail/lightweight_mutex.hpp | 42 + .../boost/{ => smart_ptr}/detail/lwm_nop.hpp | 6 +- .../{ => smart_ptr}/detail/lwm_pthreads.hpp | 6 +- .../{ => smart_ptr}/detail/lwm_win32_cs.hpp | 6 +- .../smart_ptr/detail/quick_allocator.hpp | 198 +++++ .../detail/shared_array_nmt.hpp | 8 +- .../{ => smart_ptr}/detail/shared_count.hpp | 12 +- .../{ => smart_ptr}/detail/shared_ptr_nmt.hpp | 8 +- .../{ => smart_ptr}/detail/sp_convertible.hpp | 6 +- .../detail/sp_counted_base.hpp | 34 +- .../detail/sp_counted_base_acc_ia64.hpp | 6 +- .../detail/sp_counted_base_cw_ppc.hpp | 6 +- .../detail/sp_counted_base_cw_x86.hpp | 6 +- .../detail/sp_counted_base_gcc_ia64.hpp | 6 +- .../detail/sp_counted_base_gcc_ppc.hpp | 6 +- .../detail/sp_counted_base_gcc_sparc.hpp | 6 +- .../detail/sp_counted_base_gcc_x86.hpp | 6 +- .../detail/sp_counted_base_nt.hpp | 6 +- .../detail/sp_counted_base_pt.hpp | 6 +- .../detail/sp_counted_base_solaris.hpp | 6 +- .../detail/sp_counted_base_spin.hpp | 8 +- .../detail/sp_counted_base_sync.hpp | 6 +- .../detail/sp_counted_base_w32.hpp | 6 +- .../detail/sp_counted_impl.hpp | 10 +- .../boost/{ => smart_ptr}/detail/spinlock.hpp | 16 +- .../detail/spinlock_gcc_arm.hpp | 8 +- .../{ => smart_ptr}/detail/spinlock_nt.hpp | 6 +- .../{ => smart_ptr}/detail/spinlock_pool.hpp | 8 +- .../{ => smart_ptr}/detail/spinlock_pt.hpp | 6 +- .../{ => smart_ptr}/detail/spinlock_sync.hpp | 8 +- .../{ => smart_ptr}/detail/spinlock_w32.hpp | 8 +- .../boost/{ => smart_ptr}/detail/yield_k.hpp | 8 +- .../smart_ptr/enable_shared_from_this.hpp | 73 ++ include/boost/smart_ptr/intrusive_ptr.hpp | 311 ++++++++ include/boost/smart_ptr/make_shared.hpp | 433 ++++++++++ include/boost/smart_ptr/scoped_array.hpp | 138 ++++ include/boost/smart_ptr/scoped_ptr.hpp | 160 ++++ include/boost/smart_ptr/shared_array.hpp | 193 +++++ include/boost/smart_ptr/shared_ptr.hpp | 751 ++++++++++++++++++ include/boost/smart_ptr/weak_ptr.hpp | 182 +++++ include/boost/weak_ptr.hpp | 172 +--- test/spinlock_pool_test.cpp | 2 +- 59 files changed, 2770 insertions(+), 2388 deletions(-) rename include/boost/{detail => smart_ptr}/bad_weak_ptr.hpp (86%) create mode 100644 include/boost/smart_ptr/detail/atomic_count.hpp rename include/boost/{ => smart_ptr}/detail/atomic_count_gcc.hpp (85%) rename include/boost/{ => smart_ptr}/detail/atomic_count_gcc_x86.hpp (87%) rename include/boost/{ => smart_ptr}/detail/atomic_count_pthreads.hpp (88%) rename include/boost/{ => smart_ptr}/detail/atomic_count_solaris.hpp (82%) rename include/boost/{ => smart_ptr}/detail/atomic_count_sync.hpp (83%) rename include/boost/{ => smart_ptr}/detail/atomic_count_win32.hpp (83%) create mode 100644 include/boost/smart_ptr/detail/lightweight_mutex.hpp rename include/boost/{ => smart_ptr}/detail/lwm_nop.hpp (76%) rename include/boost/{ => smart_ptr}/detail/lwm_pthreads.hpp (88%) rename include/boost/{ => smart_ptr}/detail/lwm_win32_cs.hpp (91%) create mode 100644 include/boost/smart_ptr/detail/quick_allocator.hpp rename include/boost/{ => smart_ptr}/detail/shared_array_nmt.hpp (92%) rename include/boost/{ => smart_ptr}/detail/shared_count.hpp (96%) rename include/boost/{ => smart_ptr}/detail/shared_ptr_nmt.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_convertible.hpp (89%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base.hpp (57%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_acc_ia64.hpp (92%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_cw_ppc.hpp (92%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_cw_x86.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_gcc_ia64.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_gcc_ppc.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_gcc_sparc.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_gcc_x86.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_nt.hpp (90%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_pt.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_solaris.hpp (91%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_spin.hpp (90%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_sync.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_base_w32.hpp (93%) rename include/boost/{ => smart_ptr}/detail/sp_counted_impl.hpp (94%) rename include/boost/{ => smart_ptr}/detail/spinlock.hpp (70%) rename include/boost/{ => smart_ptr}/detail/spinlock_gcc_arm.hpp (84%) rename include/boost/{ => smart_ptr}/detail/spinlock_nt.hpp (87%) rename include/boost/{ => smart_ptr}/detail/spinlock_pool.hpp (91%) rename include/boost/{ => smart_ptr}/detail/spinlock_pt.hpp (86%) rename include/boost/{ => smart_ptr}/detail/spinlock_sync.hpp (84%) rename include/boost/{ => smart_ptr}/detail/spinlock_w32.hpp (88%) rename include/boost/{ => smart_ptr}/detail/yield_k.hpp (92%) create mode 100644 include/boost/smart_ptr/enable_shared_from_this.hpp create mode 100644 include/boost/smart_ptr/intrusive_ptr.hpp create mode 100644 include/boost/smart_ptr/make_shared.hpp create mode 100644 include/boost/smart_ptr/scoped_array.hpp create mode 100644 include/boost/smart_ptr/scoped_ptr.hpp create mode 100644 include/boost/smart_ptr/shared_array.hpp create mode 100644 include/boost/smart_ptr/shared_ptr.hpp create mode 100644 include/boost/smart_ptr/weak_ptr.hpp diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp index c53a63b..5411c7a 100644 --- a/include/boost/detail/atomic_count.hpp +++ b/include/boost/detail/atomic_count.hpp @@ -12,108 +12,10 @@ // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// typedef boost::detail::atomic_count; -// -// atomic_count a(n); -// -// (n is convertible to long) -// -// Effects: Constructs an atomic_count with an initial value of n -// -// a; -// -// Returns: (long) the current value of a -// -// ++a; -// -// Effects: Atomically increments the value of a -// Returns: nothing -// -// --a; -// -// Effects: Atomically decrements the value of a -// Returns: (long) zero if the new value of a is zero, -// unspecified non-zero value otherwise (usually the new value) -// -// Important note: when --a returns zero, it must act as a -// read memory barrier (RMB); i.e. the calling thread must -// have a synchronized view of the memory -// -// On Intel IA-32 (x86) memory is always synchronized, so this -// is not a problem. -// -// On many architectures the atomic instructions already act as -// a memory barrier. -// -// This property is necessary for proper reference counting, since -// a thread can update the contents of a shared object, then -// release its reference, and another thread may immediately -// release the last reference causing object destruction. -// -// The destructor needs to have a synchronized view of the -// object to perform proper cleanup. -// -// Original example by Alexander Terekhov: -// -// Given: -// -// - a mutable shared object OBJ; -// - two threads THREAD1 and THREAD2 each holding -// a private smart_ptr object pointing to that OBJ. -// -// t1: THREAD1 updates OBJ (thread-safe via some synchronization) -// and a few cycles later (after "unlock") destroys smart_ptr; -// -// t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization -// with respect to shared mutable object OBJ; OBJ destructors -// are called driven by smart_ptr interface... -// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt -#include - -#ifndef BOOST_HAS_THREADS - -namespace boost -{ - -namespace detail -{ - -typedef long atomic_count; - -} - -} - -#elif defined(BOOST_AC_USE_PTHREADS) -# include - -#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) -# include - -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -# include - -#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) -# include - -#elif defined(__GLIBCPP__) || defined(__GLIBCXX__) -# include - -#elif defined(BOOST_HAS_PTHREADS) - -# define BOOST_AC_USE_PTHREADS -# include - -#else - -// Use #define BOOST_DISABLE_THREADS to avoid the error -#error Unrecognized threading platform - -#endif +#include #endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp index e740d7f..b7a7f6d 100644 --- a/include/boost/detail/lightweight_mutex.hpp +++ b/include/boost/detail/lightweight_mutex.hpp @@ -12,31 +12,11 @@ // // Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd. // -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// typedef boost::detail::lightweight_mutex; -// -// boost::detail::lightweight_mutex is a header-only implementation of -// a subset of the Mutex concept requirements: -// -// http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex -// -// It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX. +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt // -#include - -#if !defined(BOOST_HAS_THREADS) -# include -#elif defined(BOOST_HAS_PTHREADS) -# include -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -# include -#else -// Use #define BOOST_DISABLE_THREADS to avoid the error -# error Unrecognized threading platform -#endif +#include #endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 4e49f1f..b1bb63d 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -6,68 +6,13 @@ // // Copyright (c) 2002 Peter Dimov // -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt // // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html // -#include -#include -#include -#include - -namespace boost -{ - -template class enable_shared_from_this -{ -protected: - - enable_shared_from_this() - { - } - - enable_shared_from_this(enable_shared_from_this const &) - { - } - - enable_shared_from_this & operator=(enable_shared_from_this const &) - { - return *this; - } - - ~enable_shared_from_this() - { - } - -public: - - shared_ptr shared_from_this() - { - shared_ptr p(_internal_weak_this); - BOOST_ASSERT(p.get() == this); - return p; - } - - shared_ptr shared_from_this() const - { - shared_ptr p(_internal_weak_this); - BOOST_ASSERT(p.get() == this); - return p; - } - -// Note: No, you don't need to initialize _internal_weak_this -// -// Please read the documentation, not the code -// -// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html - - typedef T _internal_element_type; // for bcc 5.5.1 - mutable weak_ptr<_internal_element_type> _internal_weak_this; -}; - -} // namespace boost +#include #endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp index 338e672..63036dc 100644 --- a/include/boost/intrusive_ptr.hpp +++ b/include/boost/intrusive_ptr.hpp @@ -6,306 +6,13 @@ // // Copyright (c) 2001, 2002 Peter Dimov // -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt // // See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation. // -#include - -#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash -# pragma warning(push) -# pragma warning(disable:4284) // odd return type for operator-> -#endif - -#include -#include -#include - -#include // for std::less - -#if !defined(BOOST_NO_IOSTREAM) -#if !defined(BOOST_NO_IOSFWD) -#include // for std::basic_ostream -#else -#include -#endif -#endif - - -namespace boost -{ - -// -// intrusive_ptr -// -// A smart pointer that uses intrusive reference counting. -// -// Relies on unqualified calls to -// -// void intrusive_ptr_add_ref(T * p); -// void intrusive_ptr_release(T * p); -// -// (p != 0) -// -// The object is responsible for destroying itself. -// - -template class intrusive_ptr -{ -private: - - typedef intrusive_ptr this_type; - -public: - - typedef T element_type; - - intrusive_ptr(): p_(0) - { - } - - intrusive_ptr(T * p, bool add_ref = true): p_(p) - { - if(p_ != 0 && add_ref) intrusive_ptr_add_ref(p_); - } - -#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) - - template -#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) - - intrusive_ptr( intrusive_ptr const & rhs, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) - -#else - - intrusive_ptr( intrusive_ptr const & rhs ) - -#endif - : p_( rhs.get() ) - { - if( p_ != 0 ) intrusive_ptr_add_ref( p_ ); - } - -#endif - - intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_) - { - if(p_ != 0) intrusive_ptr_add_ref(p_); - } - - ~intrusive_ptr() - { - if(p_ != 0) intrusive_ptr_release(p_); - } - -#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) - - template intrusive_ptr & operator=(intrusive_ptr const & rhs) - { - this_type(rhs).swap(*this); - return *this; - } - -#endif - - intrusive_ptr & operator=(intrusive_ptr const & rhs) - { - this_type(rhs).swap(*this); - return *this; - } - - intrusive_ptr & operator=(T * rhs) - { - this_type(rhs).swap(*this); - return *this; - } - - void reset() - { - this_type().swap( *this ); - } - - void reset( T * rhs ) - { - this_type( rhs ).swap( *this ); - } - - T * get() const - { - return p_; - } - - T & operator*() const - { - BOOST_ASSERT( p_ != 0 ); - return *p_; - } - - T * operator->() const - { - BOOST_ASSERT( p_ != 0 ); - return p_; - } - -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) - - operator bool () const - { - return p_ != 0; - } - -#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return p_ == 0? 0: &this_type::get; - } - -#else - - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type () const - { - return p_ == 0? 0: &this_type::p_; - } - -#endif - - // operator! is a Borland-specific workaround - bool operator! () const - { - return p_ == 0; - } - - void swap(intrusive_ptr & rhs) - { - T * tmp = p_; - p_ = rhs.p_; - rhs.p_ = tmp; - } - -private: - - T * p_; -}; - -template inline bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) -{ - return a.get() == b.get(); -} - -template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) -{ - return a.get() != b.get(); -} - -template inline bool operator==(intrusive_ptr const & a, U * b) -{ - return a.get() == b; -} - -template inline bool operator!=(intrusive_ptr const & a, U * b) -{ - return a.get() != b; -} - -template inline bool operator==(T * a, intrusive_ptr const & b) -{ - return a == b.get(); -} - -template inline bool operator!=(T * a, intrusive_ptr const & b) -{ - return a != b.get(); -} - -#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 - -// Resolve the ambiguity between our op!= and the one in rel_ops - -template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) -{ - return a.get() != b.get(); -} - -#endif - -template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) -{ - return std::less()(a.get(), b.get()); -} - -template void swap(intrusive_ptr & lhs, intrusive_ptr & rhs) -{ - lhs.swap(rhs); -} - -// mem_fn support - -template T * get_pointer(intrusive_ptr const & p) -{ - return p.get(); -} - -template intrusive_ptr static_pointer_cast(intrusive_ptr const & p) -{ - return static_cast(p.get()); -} - -template intrusive_ptr const_pointer_cast(intrusive_ptr const & p) -{ - return const_cast(p.get()); -} - -template intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & p) -{ - return dynamic_cast(p.get()); -} - -// operator<< - -#if !defined(BOOST_NO_IOSTREAM) - -#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) - -template std::ostream & operator<< (std::ostream & os, intrusive_ptr const & p) -{ - os << p.get(); - return os; -} - -#else - -// in STLport's no-iostreams mode no iostream symbols can be used -#ifndef _STLP_NO_IOSTREAMS - -# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) -// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL -using std::basic_ostream; -template basic_ostream & operator<< (basic_ostream & os, intrusive_ptr const & p) -# else -template std::basic_ostream & operator<< (std::basic_ostream & os, intrusive_ptr const & p) -# endif -{ - os << p.get(); - return os; -} - -#endif // _STLP_NO_IOSTREAMS - -#endif // __GNUC__ < 3 - -#endif // !defined(BOOST_NO_IOSTREAM) - -} // namespace boost - -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif +#include #endif // #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED diff --git a/include/boost/make_shared.hpp b/include/boost/make_shared.hpp index cc3685b..c04938f 100644 --- a/include/boost/make_shared.hpp +++ b/include/boost/make_shared.hpp @@ -12,422 +12,6 @@ // See http://www.boost.org/libs/smart_ptr/make_shared.html // for documentation. -#include -#include -#include -#include -#include -#include - -namespace boost -{ - -namespace detail -{ - -template< std::size_t N, std::size_t A > struct sp_aligned_storage -{ - union type - { - char data_[ N ]; - typename boost::type_with_alignment< A >::type align_; - }; -}; - -template< class T > class sp_ms_deleter -{ -private: - - typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type; - - bool initialized_; - storage_type storage_; - -private: - - void destroy() - { - if( initialized_ ) - { - reinterpret_cast< T* >( storage_.data_ )->~T(); - initialized_ = false; - } - } - -public: - - sp_ms_deleter(): initialized_( false ) - { - } - - ~sp_ms_deleter() - { - destroy(); - } - - void operator()( T * ) - { - destroy(); - } - - void * address() - { - return storage_.data_; - } - - void set_initialized() - { - initialized_ = true; - } -}; - -template< class T > T forward( T t ) -{ - return t; -} - -} // namespace detail - -// Zero-argument versions -// -// Used even when variadic templates are available because of the new T() vs new T issue - -template< class T > boost::shared_ptr< T > make_shared() -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T(); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T(); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) - -// Variadic templates, rvalue reference - -template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && ... args ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( detail::forward( args )... ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Args && ... args ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( detail::forward( args )... ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -#else - -// C++03 version - -template< class T, class A1 > -boost::shared_ptr< T > make_shared( A1 const & a1 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2, class A3 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2, class A3 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2, class A3, class A4 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2, class A3, class A4 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5, class A6 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > -boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > -boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 ) -{ - boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); - - detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); - - void * pv = pd->address(); - - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); - pd->set_initialized(); - - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); -} - -#endif - -} // namespace boost +#include #endif // #ifndef BOOST_MAKE_SHARED_HPP_INCLUDED diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index fcb80f6..c02fa31 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -11,128 +11,6 @@ // http://www.boost.org/libs/smart_ptr/scoped_array.htm // -#include -#include -#include // in case ptrdiff_t not in std - -#include - -#include // for std::ptrdiff_t - -namespace boost -{ - -// Debug hooks - -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - -void sp_array_constructor_hook(void * p); -void sp_array_destructor_hook(void * p); - -#endif - -// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to -// is guaranteed, either on destruction of the scoped_array or via an explicit -// reset(). Use shared_array or std::vector if your needs are more complex. - -template class scoped_array // noncopyable -{ -private: - - T * ptr; - - scoped_array(scoped_array const &); - scoped_array & operator=(scoped_array const &); - - typedef scoped_array this_type; - - void operator==( scoped_array const& ) const; - void operator!=( scoped_array const& ) const; - -public: - - typedef T element_type; - - explicit scoped_array(T * p = 0) : ptr(p) // never throws - { -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_array_constructor_hook(ptr); -#endif - } - - ~scoped_array() // never throws - { -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_array_destructor_hook(ptr); -#endif - boost::checked_array_delete(ptr); - } - - void reset(T * p = 0) // never throws - { - BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors - this_type(p).swap(*this); - } - - T & operator[](std::ptrdiff_t i) const // never throws - { - BOOST_ASSERT(ptr != 0); - BOOST_ASSERT(i >= 0); - return ptr[i]; - } - - T * get() const // never throws - { - return ptr; - } - - // implicit conversion to "bool" - -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) - - operator bool () const - { - return ptr != 0; - } - -#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return ptr == 0? 0: &this_type::get; - } - -#else - - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type() const // never throws - { - return ptr == 0? 0: &this_type::ptr; - } - -#endif - - bool operator! () const // never throws - { - return ptr == 0; - } - - void swap(scoped_array & b) // never throws - { - T * tmp = b.ptr; - b.ptr = ptr; - ptr = tmp; - } - -}; - -template inline void swap(scoped_array & a, scoped_array & b) // never throws -{ - a.swap(b); -} - -} // namespace boost +#include #endif // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp index 279cec3..cb916da 100644 --- a/include/boost/scoped_ptr.hpp +++ b/include/boost/scoped_ptr.hpp @@ -11,150 +11,6 @@ // http://www.boost.org/libs/smart_ptr/scoped_ptr.htm // -#include -#include -#include - -#ifndef BOOST_NO_AUTO_PTR -# include // for std::auto_ptr -#endif - -namespace boost -{ - -// Debug hooks - -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - -void sp_scalar_constructor_hook(void * p); -void sp_scalar_destructor_hook(void * p); - -#endif - -// scoped_ptr mimics a built-in pointer except that it guarantees deletion -// of the object pointed to, either on destruction of the scoped_ptr or via -// an explicit reset(). scoped_ptr is a simple solution for simple needs; -// use shared_ptr or std::auto_ptr if your needs are more complex. - -template class scoped_ptr // noncopyable -{ -private: - - T * ptr; - - scoped_ptr(scoped_ptr const &); - scoped_ptr & operator=(scoped_ptr const &); - - typedef scoped_ptr this_type; - - void operator==( scoped_ptr const& ) const; - void operator!=( scoped_ptr const& ) const; - -public: - - typedef T element_type; - - explicit scoped_ptr(T * p = 0): ptr(p) // never throws - { -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_scalar_constructor_hook(ptr); -#endif - } - -#ifndef BOOST_NO_AUTO_PTR - - explicit scoped_ptr(std::auto_ptr p): ptr(p.release()) // never throws - { -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_scalar_constructor_hook(ptr); -#endif - } - -#endif - - ~scoped_ptr() // never throws - { -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_scalar_destructor_hook(ptr); -#endif - boost::checked_delete(ptr); - } - - void reset(T * p = 0) // never throws - { - BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors - this_type(p).swap(*this); - } - - T & operator*() const // never throws - { - BOOST_ASSERT(ptr != 0); - return *ptr; - } - - T * operator->() const // never throws - { - BOOST_ASSERT(ptr != 0); - return ptr; - } - - T * get() const // never throws - { - return ptr; - } - - // implicit conversion to "bool" - -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) - - operator bool () const - { - return ptr != 0; - } - -#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return ptr == 0? 0: &this_type::get; - } - -#else - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type() const // never throws - { - return ptr == 0? 0: &this_type::ptr; - } - -#endif - - bool operator! () const // never throws - { - return ptr == 0; - } - - void swap(scoped_ptr & b) // never throws - { - T * tmp = b.ptr; - b.ptr = ptr; - ptr = tmp; - } -}; - -template inline void swap(scoped_ptr & a, scoped_ptr & b) // never throws -{ - a.swap(b); -} - -// get_pointer(p) is a generic way to say p.get() - -template inline T * get_pointer(scoped_ptr const & p) -{ - return p.get(); -} - -} // namespace boost +#include #endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp index 3b82f35..0700ce4 100644 --- a/include/boost/shared_array.hpp +++ b/include/boost/shared_array.hpp @@ -14,180 +14,6 @@ // See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation. // -#include // for broken compiler workarounds - -#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) -#include -#else - -#include // TR1 cyclic inclusion fix - -#include -#include - -#include -#include - -#include // for std::ptrdiff_t -#include // for std::swap -#include // for std::less - -namespace boost -{ - -// -// shared_array -// -// shared_array extends shared_ptr to arrays. -// The array pointed to is deleted when the last shared_array pointing to it -// is destroyed or reset. -// - -template class shared_array -{ -private: - - // Borland 5.5.1 specific workarounds - typedef checked_array_deleter deleter; - typedef shared_array this_type; - -public: - - typedef T element_type; - - explicit shared_array(T * p = 0): px(p), pn(p, deleter()) - { - } - - // - // Requirements: D's copy constructor must not throw - // - // shared_array will release p by calling d(p) - // - - template shared_array(T * p, D d): px(p), pn(p, d) - { - } - -// generated copy constructor, assignment, destructor are fine - - void reset(T * p = 0) - { - BOOST_ASSERT(p == 0 || p != px); - this_type(p).swap(*this); - } - - template void reset(T * p, D d) - { - this_type(p, d).swap(*this); - } - - T & operator[] (std::ptrdiff_t i) const // never throws - { - BOOST_ASSERT(px != 0); - BOOST_ASSERT(i >= 0); - return px[i]; - } - - T * get() const // never throws - { - return px; - } - - // implicit conversion to "bool" - -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) - - operator bool () const - { - return px != 0; - } - -#elif defined( _MANAGED ) - - static void unspecified_bool( this_type*** ) - { - } - - typedef void (*unspecified_bool_type)( this_type*** ); - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: unspecified_bool; - } - -#elif \ - ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ - ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) - - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: &this_type::get; - } - -#else - - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: &this_type::px; - } - -#endif - - bool operator! () const // never throws - { - return px == 0; - } - - bool unique() const // never throws - { - return pn.unique(); - } - - long use_count() const // never throws - { - return pn.use_count(); - } - - void swap(shared_array & other) // never throws - { - std::swap(px, other.px); - pn.swap(other.pn); - } - -private: - - T * px; // contained pointer - detail::shared_count pn; // reference counter - -}; // shared_array - -template inline bool operator==(shared_array const & a, shared_array const & b) // never throws -{ - return a.get() == b.get(); -} - -template inline bool operator!=(shared_array const & a, shared_array const & b) // never throws -{ - return a.get() != b.get(); -} - -template inline bool operator<(shared_array const & a, shared_array const & b) // never throws -{ - return std::less()(a.get(), b.get()); -} - -template void swap(shared_array & a, shared_array & b) // never throws -{ - a.swap(b); -} - -} // namespace boost - -#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#include #endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index ad2bc17..d31978c 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -14,738 +14,6 @@ // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. // -#include // for broken compiler workarounds - -#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) -#include -#else - -// In order to avoid circular dependencies with Boost.TR1 -// we make sure that our include of doesn't try to -// pull in the TR1 headers: that's why we use this header -// rather than including directly: -#include // std::auto_ptr - -#include -#include -#include -#include -#include -#include - -#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) -#include -#include -#endif - -#include // for std::swap -#include // for std::less -#include // for std::bad_cast - -#if !defined(BOOST_NO_IOSTREAM) -#if !defined(BOOST_NO_IOSFWD) -#include // for std::basic_ostream -#else -#include -#endif -#endif - -#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash -# pragma warning(push) -# pragma warning(disable:4284) // odd return type for operator-> -#endif - -namespace boost -{ - -template class weak_ptr; -template class enable_shared_from_this; - -namespace detail -{ - -struct static_cast_tag {}; -struct const_cast_tag {}; -struct dynamic_cast_tag {}; -struct polymorphic_cast_tag {}; - -template struct shared_ptr_traits -{ - typedef T & reference; -}; - -template<> struct shared_ptr_traits -{ - typedef void reference; -}; - -#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) - -template<> struct shared_ptr_traits -{ - typedef void reference; -}; - -template<> struct shared_ptr_traits -{ - typedef void reference; -}; - -template<> struct shared_ptr_traits -{ - typedef void reference; -}; - -#endif - -// enable_shared_from_this support - -template void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this const * pe, Y const * px ) -{ - if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); -} - -#ifdef _MANAGED - -// Avoid C4793, ... causes native code generation - -struct sp_any_pointer -{ - template sp_any_pointer( T* ) {} -}; - -inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer ) -{ -} - -#else // _MANAGED - -#ifdef sgi -// Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed -# pragma set woff 3506 -#endif - -inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) -{ -} - -#ifdef sgi -# pragma reset woff 3506 -#endif - -#endif // _MANAGED - -#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) - -// rvalue auto_ptr support based on a technique by Dave Abrahams - -template< class T, class R > struct sp_enable_if_auto_ptr -{ -}; - -template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R > -{ - typedef R type; -}; - -#endif - -} // namespace detail - - -// -// shared_ptr -// -// An enhanced relative of scoped_ptr with reference counted copy semantics. -// The object pointed to is deleted when the last shared_ptr pointing to it -// is destroyed or reset. -// - -template class shared_ptr -{ -private: - - // Borland 5.5.1 specific workaround - typedef shared_ptr this_type; - -public: - - typedef T element_type; - typedef T value_type; - typedef T * pointer; - typedef typename boost::detail::shared_ptr_traits::reference reference; - - shared_ptr(): px(0), pn() // never throws in 1.30+ - { - } - - template - explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete - { - boost::detail::sp_enable_shared_from_this( pn, p, p ); - } - - // - // Requirements: D's copy constructor must not throw - // - // shared_ptr will release p by calling d(p) - // - - template shared_ptr(Y * p, D d): px(p), pn(p, d) - { - boost::detail::sp_enable_shared_from_this( pn, p, p ); - } - - // As above, but with allocator. A's copy constructor shall not throw. - - template shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) - { - boost::detail::sp_enable_shared_from_this( pn, p, p ); - } - -// generated copy constructor, assignment, destructor are fine... - -// except that Borland C++ has a bug, and g++ with -Wsynth warns -#if defined(__BORLANDC__) || defined(__GNUC__) - - shared_ptr & operator=(shared_ptr const & r) // never throws - { - px = r.px; - pn = r.pn; // shared_count::op= doesn't throw - return *this; - } - -#endif - - template - explicit shared_ptr(weak_ptr const & r): pn(r.pn) // may throw - { - // it is now safe to copy r.px, as pn(r.pn) did not throw - px = r.px; - } - - template - shared_ptr( weak_ptr const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws - { - if( !pn.empty() ) - { - px = r.px; - } - } - - template -#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) - - shared_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) - -#else - - shared_ptr( shared_ptr const & r ) - -#endif - : px( r.px ), pn( r.pn ) // never throws - { - } - - // aliasing - template< class Y > - shared_ptr( shared_ptr const & r, T * p ): px( p ), pn( r.pn ) // never throws - { - } - - template - shared_ptr(shared_ptr const & r, boost::detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) - { - } - - template - shared_ptr(shared_ptr const & r, boost::detail::const_cast_tag): px(const_cast(r.px)), pn(r.pn) - { - } - - template - shared_ptr(shared_ptr const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) - { - if(px == 0) // need to allocate new counter -- the cast failed - { - pn = boost::detail::shared_count(); - } - } - - template - shared_ptr(shared_ptr const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) - { - if(px == 0) - { - boost::throw_exception(std::bad_cast()); - } - } - -#ifndef BOOST_NO_AUTO_PTR - - template - explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn() - { - Y * tmp = r.get(); - pn = boost::detail::shared_count(r); - boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); - } - -#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) - - template - shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() - { - typename Ap::element_type * tmp = r.get(); - pn = boost::detail::shared_count( r ); - boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); - } - - -#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -#endif // BOOST_NO_AUTO_PTR - -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) - - template - shared_ptr & operator=(shared_ptr const & r) // never throws - { - px = r.px; - pn = r.pn; // shared_count::op= doesn't throw - return *this; - } - -#endif - -#ifndef BOOST_NO_AUTO_PTR - - template - shared_ptr & operator=( std::auto_ptr & r ) - { - this_type(r).swap(*this); - return *this; - } - -#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) - - template - typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r ) - { - this_type( r ).swap( *this ); - return *this; - } - - -#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -#endif // BOOST_NO_AUTO_PTR - -// Move support - -#if defined( BOOST_HAS_RVALUE_REFS ) - - shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws - { - pn.swap( r.pn ); - r.px = 0; - } - - template -#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) - - shared_ptr( shared_ptr && r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) - -#else - - shared_ptr( shared_ptr && r ) - -#endif - : px( r.px ), pn() // never throws - { - pn.swap( r.pn ); - r.px = 0; - } - - shared_ptr & operator=( shared_ptr && r ) // never throws - { - this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); - return *this; - } - - template - shared_ptr & operator=( shared_ptr && r ) // never throws - { - this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); - return *this; - } - -#endif - - void reset() // never throws in 1.30+ - { - this_type().swap(*this); - } - - template void reset(Y * p) // Y must be complete - { - BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors - this_type(p).swap(*this); - } - - template void reset( Y * p, D d ) - { - this_type( p, d ).swap( *this ); - } - - template void reset( Y * p, D d, A a ) - { - this_type( p, d, a ).swap( *this ); - } - - template void reset( shared_ptr const & r, T * p ) - { - this_type( r, p ).swap( *this ); - } - - reference operator* () const // never throws - { - BOOST_ASSERT(px != 0); - return *px; - } - - T * operator-> () const // never throws - { - BOOST_ASSERT(px != 0); - return px; - } - - T * get() const // never throws - { - return px; - } - - // implicit conversion to "bool" - -#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) - - operator bool () const - { - return px != 0; - } - -#elif defined( _MANAGED ) - - static void unspecified_bool( this_type*** ) - { - } - - typedef void (*unspecified_bool_type)( this_type*** ); - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: unspecified_bool; - } - -#elif \ - ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ - ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \ - ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) ) - - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: &this_type::get; - } - -#else - - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: &this_type::px; - } - -#endif - - // operator! is redundant, but some compilers need it - - bool operator! () const // never throws - { - return px == 0; - } - - bool unique() const // never throws - { - return pn.unique(); - } - - long use_count() const // never throws - { - return pn.use_count(); - } - - void swap(shared_ptr & other) // never throws - { - std::swap(px, other.px); - pn.swap(other.pn); - } - - template bool _internal_less(shared_ptr const & rhs) const - { - return pn < rhs.pn; - } - - void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const - { - return pn.get_deleter( ti ); - } - - bool _internal_equiv( shared_ptr const & r ) const - { - return px == r.px && pn == r.pn; - } - -// Tasteless as this may seem, making all members public allows member templates -// to work in the absence of member template friends. (Matthew Langston) - -#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS - -private: - - template friend class shared_ptr; - template friend class weak_ptr; - - -#endif - - T * px; // contained pointer - boost::detail::shared_count pn; // reference counter - -}; // shared_ptr - -template inline bool operator==(shared_ptr const & a, shared_ptr const & b) -{ - return a.get() == b.get(); -} - -template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) -{ - return a.get() != b.get(); -} - -#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 - -// Resolve the ambiguity between our op!= and the one in rel_ops - -template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) -{ - return a.get() != b.get(); -} - -#endif - -template inline bool operator<(shared_ptr const & a, shared_ptr const & b) -{ - return a._internal_less(b); -} - -template inline void swap(shared_ptr & a, shared_ptr & b) -{ - a.swap(b); -} - -template shared_ptr static_pointer_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::static_cast_tag()); -} - -template shared_ptr const_pointer_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::const_cast_tag()); -} - -template shared_ptr dynamic_pointer_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::dynamic_cast_tag()); -} - -// shared_*_cast names are deprecated. Use *_pointer_cast instead. - -template shared_ptr shared_static_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::static_cast_tag()); -} - -template shared_ptr shared_dynamic_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::dynamic_cast_tag()); -} - -template shared_ptr shared_polymorphic_cast(shared_ptr const & r) -{ - return shared_ptr(r, boost::detail::polymorphic_cast_tag()); -} - -template shared_ptr shared_polymorphic_downcast(shared_ptr const & r) -{ - BOOST_ASSERT(dynamic_cast(r.get()) == r.get()); - return shared_static_cast(r); -} - -// get_pointer() enables boost::mem_fn to recognize shared_ptr - -template inline T * get_pointer(shared_ptr const & p) -{ - return p.get(); -} - -// operator<< - -#if !defined(BOOST_NO_IOSTREAM) - -#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) - -template std::ostream & operator<< (std::ostream & os, shared_ptr const & p) -{ - os << p.get(); - return os; -} - -#else - -// in STLport's no-iostreams mode no iostream symbols can be used -#ifndef _STLP_NO_IOSTREAMS - -# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) -// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL -using std::basic_ostream; -template basic_ostream & operator<< (basic_ostream & os, shared_ptr const & p) -# else -template std::basic_ostream & operator<< (std::basic_ostream & os, shared_ptr const & p) -# endif -{ - os << p.get(); - return os; -} - -#endif // _STLP_NO_IOSTREAMS - -#endif // __GNUC__ < 3 - -#endif // !defined(BOOST_NO_IOSTREAM) - -// get_deleter - -#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ - ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ - ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) ) - -// g++ 2.9x doesn't allow static_cast(void *) -// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it - -template D * get_deleter(shared_ptr const & p) -{ - void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D)); - return const_cast(static_cast(q)); -} - -#else - -template D * get_deleter(shared_ptr const & p) -{ - return static_cast(p._internal_get_deleter(BOOST_SP_TYPEID(D))); -} - -#endif - -// atomic access - -#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) - -template inline bool atomic_is_lock_free( shared_ptr const * /*p*/ ) -{ - return false; -} - -template shared_ptr atomic_load( shared_ptr const * p ) -{ - boost::detail::spinlock_pool<2>::scoped_lock lock( p ); - return *p; -} - -template inline shared_ptr atomic_load_explicit( shared_ptr const * p, memory_order /*mo*/ ) -{ - return atomic_load( p ); -} - -template void atomic_store( shared_ptr * p, shared_ptr r ) -{ - boost::detail::spinlock_pool<2>::scoped_lock lock( p ); - p->swap( r ); -} - -template inline void atomic_store_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) -{ - atomic_store( p, r ); // std::move( r ) -} - -template shared_ptr atomic_exchange( shared_ptr * p, shared_ptr r ) -{ - boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); - - sp.lock(); - p->swap( r ); - sp.unlock(); - - return r; // return std::move( r ) -} - -template shared_ptr atomic_exchange_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) -{ - return atomic_exchange( p, r ); // std::move( r ) -} - -template bool atomic_compare_exchange( shared_ptr * p, shared_ptr * v, shared_ptr w ) -{ - boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); - - sp.lock(); - - if( p->_internal_equiv( *v ) ) - { - p->swap( w ); - - sp.unlock(); - - return true; - } - else - { - shared_ptr tmp( *p ); - - sp.unlock(); - - tmp.swap( *v ); - return false; - } -} - -template inline bool atomic_compare_exchange_explicit( shared_ptr * p, shared_ptr * v, shared_ptr w, memory_order /*success*/, memory_order /*failure*/ ) -{ - return atomic_compare_exchange( p, v, w ); // std::move( w ) -} - -#endif - -} // namespace boost - -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif - -#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#include #endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED diff --git a/include/boost/detail/bad_weak_ptr.hpp b/include/boost/smart_ptr/bad_weak_ptr.hpp similarity index 86% rename from include/boost/detail/bad_weak_ptr.hpp rename to include/boost/smart_ptr/bad_weak_ptr.hpp index 93ecec9..3e0a1b7 100644 --- a/include/boost/detail/bad_weak_ptr.hpp +++ b/include/boost/smart_ptr/bad_weak_ptr.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_BAD_WEAK_PTR_HPP_INCLUDED -#define BOOST_BAD_WEAK_PTR_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED +#define BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -8,7 +8,7 @@ #endif // -// detail/bad_weak_ptr.hpp +// boost/smart_ptr/bad_weak_ptr.hpp // // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. // @@ -56,4 +56,4 @@ public: # pragma warn .8026 // Functions with excep. spec. are not expanded inline #endif -#endif // #ifndef BOOST_BAD_WEAK_PTR_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/atomic_count.hpp b/include/boost/smart_ptr/detail/atomic_count.hpp new file mode 100644 index 0000000..91236e4 --- /dev/null +++ b/include/boost/smart_ptr/detail/atomic_count.hpp @@ -0,0 +1,119 @@ +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/atomic_count.hpp - thread/SMP safe reference counter +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// typedef boost::detail::atomic_count; +// +// atomic_count a(n); +// +// (n is convertible to long) +// +// Effects: Constructs an atomic_count with an initial value of n +// +// a; +// +// Returns: (long) the current value of a +// +// ++a; +// +// Effects: Atomically increments the value of a +// Returns: nothing +// +// --a; +// +// Effects: Atomically decrements the value of a +// Returns: (long) zero if the new value of a is zero, +// unspecified non-zero value otherwise (usually the new value) +// +// Important note: when --a returns zero, it must act as a +// read memory barrier (RMB); i.e. the calling thread must +// have a synchronized view of the memory +// +// On Intel IA-32 (x86) memory is always synchronized, so this +// is not a problem. +// +// On many architectures the atomic instructions already act as +// a memory barrier. +// +// This property is necessary for proper reference counting, since +// a thread can update the contents of a shared object, then +// release its reference, and another thread may immediately +// release the last reference causing object destruction. +// +// The destructor needs to have a synchronized view of the +// object to perform proper cleanup. +// +// Original example by Alexander Terekhov: +// +// Given: +// +// - a mutable shared object OBJ; +// - two threads THREAD1 and THREAD2 each holding +// a private smart_ptr object pointing to that OBJ. +// +// t1: THREAD1 updates OBJ (thread-safe via some synchronization) +// and a few cycles later (after "unlock") destroys smart_ptr; +// +// t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization +// with respect to shared mutable object OBJ; OBJ destructors +// are called driven by smart_ptr interface... +// + +#include + +#ifndef BOOST_HAS_THREADS + +namespace boost +{ + +namespace detail +{ + +typedef long atomic_count; + +} + +} + +#elif defined(BOOST_AC_USE_PTHREADS) +# include + +#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) +# include + +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# include + +#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) +# include + +#elif defined(__GLIBCPP__) || defined(__GLIBCXX__) +# include + +#elif defined(BOOST_HAS_PTHREADS) + +# define BOOST_AC_USE_PTHREADS +# include + +#else + +// Use #define BOOST_DISABLE_THREADS to avoid the error +#error Unrecognized threading platform + +#endif + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_gcc.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp similarity index 85% rename from include/boost/detail/atomic_count_gcc.hpp rename to include/boost/smart_ptr/detail/atomic_count_gcc.hpp index 1160e44..6abfdf2 100644 --- a/include/boost/detail/atomic_count_gcc.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED -#define BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED // // boost/detail/atomic_count_gcc.hpp @@ -65,4 +65,4 @@ private: } // namespace boost -#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_gcc_x86.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp similarity index 87% rename from include/boost/detail/atomic_count_gcc_x86.hpp rename to include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp index 1312e8c..4fd1c57 100644 --- a/include/boost/detail/atomic_count_gcc_x86.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED -#define BOOST_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED // // boost/detail/atomic_count_gcc_x86.hpp @@ -81,4 +81,4 @@ private: } // namespace boost -#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_pthreads.hpp b/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp similarity index 88% rename from include/boost/detail/atomic_count_pthreads.hpp rename to include/boost/smart_ptr/detail/atomic_count_pthreads.hpp index 7ed055f..d8118f0 100644 --- a/include/boost/detail/atomic_count_pthreads.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED -#define BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED // // boost/detail/atomic_count_pthreads.hpp @@ -93,4 +93,4 @@ private: } // namespace boost -#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_solaris.hpp b/include/boost/smart_ptr/detail/atomic_count_solaris.hpp similarity index 82% rename from include/boost/detail/atomic_count_solaris.hpp rename to include/boost/smart_ptr/detail/atomic_count_solaris.hpp index 8e2907f..a13bcfb 100644 --- a/include/boost/detail/atomic_count_solaris.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_solaris.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED -#define BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED // // boost/detail/atomic_count_solaris.hpp @@ -56,4 +56,4 @@ private: } // namespace boost -#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_sync.hpp b/include/boost/smart_ptr/detail/atomic_count_sync.hpp similarity index 83% rename from include/boost/detail/atomic_count_sync.hpp rename to include/boost/smart_ptr/detail/atomic_count_sync.hpp index 676d3f9..f2d22fb 100644 --- a/include/boost/detail/atomic_count_sync.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_sync.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED -#define BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED // // boost/detail/atomic_count_sync.hpp @@ -58,4 +58,4 @@ private: } // namespace boost -#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/atomic_count_win32.hpp b/include/boost/smart_ptr/detail/atomic_count_win32.hpp similarity index 83% rename from include/boost/detail/atomic_count_win32.hpp rename to include/boost/smart_ptr/detail/atomic_count_win32.hpp index 0de2537..60a0569 100644 --- a/include/boost/detail/atomic_count_win32.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_win32.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED -#define BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -60,4 +60,4 @@ private: } // namespace boost -#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/lightweight_mutex.hpp b/include/boost/smart_ptr/detail/lightweight_mutex.hpp new file mode 100644 index 0000000..a2fc281 --- /dev/null +++ b/include/boost/smart_ptr/detail/lightweight_mutex.hpp @@ -0,0 +1,42 @@ +#ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/lightweight_mutex.hpp - lightweight mutex +// +// Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// typedef boost::detail::lightweight_mutex; +// +// boost::detail::lightweight_mutex is a header-only implementation of +// a subset of the Mutex concept requirements: +// +// http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex +// +// It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX. +// + +#include + +#if !defined(BOOST_HAS_THREADS) +# include +#elif defined(BOOST_HAS_PTHREADS) +# include +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# include +#else +// Use #define BOOST_DISABLE_THREADS to avoid the error +# error Unrecognized threading platform +#endif + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED diff --git a/include/boost/detail/lwm_nop.hpp b/include/boost/smart_ptr/detail/lwm_nop.hpp similarity index 76% rename from include/boost/detail/lwm_nop.hpp rename to include/boost/smart_ptr/detail/lwm_nop.hpp index c73ab68..521a88e 100644 --- a/include/boost/detail/lwm_nop.hpp +++ b/include/boost/smart_ptr/detail/lwm_nop.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED -#define BOOST_DETAIL_LWM_NOP_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -34,4 +34,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED diff --git a/include/boost/detail/lwm_pthreads.hpp b/include/boost/smart_ptr/detail/lwm_pthreads.hpp similarity index 88% rename from include/boost/detail/lwm_pthreads.hpp rename to include/boost/smart_ptr/detail/lwm_pthreads.hpp index a5bf75b..fc20dbb 100644 --- a/include/boost/detail/lwm_pthreads.hpp +++ b/include/boost/smart_ptr/detail/lwm_pthreads.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED -#define BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -83,4 +83,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED diff --git a/include/boost/detail/lwm_win32_cs.hpp b/include/boost/smart_ptr/detail/lwm_win32_cs.hpp similarity index 91% rename from include/boost/detail/lwm_win32_cs.hpp rename to include/boost/smart_ptr/detail/lwm_win32_cs.hpp index 8142069..00477e4 100644 --- a/include/boost/detail/lwm_win32_cs.hpp +++ b/include/boost/smart_ptr/detail/lwm_win32_cs.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED -#define BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -105,4 +105,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/quick_allocator.hpp b/include/boost/smart_ptr/detail/quick_allocator.hpp new file mode 100644 index 0000000..6d136f8 --- /dev/null +++ b/include/boost/smart_ptr/detail/quick_allocator.hpp @@ -0,0 +1,198 @@ +#ifndef BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/quick_allocator.hpp +// +// Copyright (c) 2003 David Abrahams +// Copyright (c) 2003 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +#include +#include +#include + +#include // ::operator new, ::operator delete +#include // std::size_t + +namespace boost +{ + +namespace detail +{ + +template union freeblock +{ + typedef typename boost::type_with_alignment::type aligner_type; + aligner_type aligner; + char bytes[size]; + freeblock * next; +}; + +template struct allocator_impl +{ + typedef freeblock block; + + // It may seem odd to use such small pages. + // + // However, on a typical Windows implementation that uses + // the OS allocator, "normal size" pages interact with the + // "ordinary" operator new, slowing it down dramatically. + // + // 512 byte pages are handled by the small object allocator, + // and don't interfere with ::new. + // + // The other alternative is to use much bigger pages (1M.) + // + // It is surprisingly easy to hit pathological behavior by + // varying the page size. g++ 2.96 on Red Hat Linux 7.2, + // for example, passionately dislikes 496. 512 seems OK. + +#if defined(BOOST_QA_PAGE_SIZE) + + enum { items_per_page = BOOST_QA_PAGE_SIZE / size }; + +#else + + enum { items_per_page = 512 / size }; // 1048560 / size + +#endif + +#ifdef BOOST_HAS_THREADS + + static lightweight_mutex & mutex() + { + static lightweight_mutex m; + return m; + } + + static lightweight_mutex * mutex_init; + +#endif + + static block * free; + static block * page; + static unsigned last; + + static inline void * alloc() + { +#ifdef BOOST_HAS_THREADS + lightweight_mutex::scoped_lock lock( mutex() ); +#endif + if(block * x = free) + { + free = x->next; + return x; + } + else + { + if(last == items_per_page) + { + // "Listen to me carefully: there is no memory leak" + // -- Scott Meyers, Eff C++ 2nd Ed Item 10 + page = ::new block[items_per_page]; + last = 0; + } + + return &page[last++]; + } + } + + static inline void * alloc(std::size_t n) + { + if(n != size) // class-specific new called for a derived object + { + return ::operator new(n); + } + else + { +#ifdef BOOST_HAS_THREADS + lightweight_mutex::scoped_lock lock( mutex() ); +#endif + if(block * x = free) + { + free = x->next; + return x; + } + else + { + if(last == items_per_page) + { + page = ::new block[items_per_page]; + last = 0; + } + + return &page[last++]; + } + } + } + + static inline void dealloc(void * pv) + { + if(pv != 0) // 18.4.1.1/13 + { +#ifdef BOOST_HAS_THREADS + lightweight_mutex::scoped_lock lock( mutex() ); +#endif + block * pb = static_cast(pv); + pb->next = free; + free = pb; + } + } + + static inline void dealloc(void * pv, std::size_t n) + { + if(n != size) // class-specific delete called for a derived object + { + ::operator delete(pv); + } + else if(pv != 0) // 18.4.1.1/13 + { +#ifdef BOOST_HAS_THREADS + lightweight_mutex::scoped_lock lock( mutex() ); +#endif + block * pb = static_cast(pv); + pb->next = free; + free = pb; + } + } +}; + +#ifdef BOOST_HAS_THREADS + +template + lightweight_mutex * allocator_impl::mutex_init = &allocator_impl::mutex(); + +#endif + +template + freeblock * allocator_impl::free = 0; + +template + freeblock * allocator_impl::page = 0; + +template + unsigned allocator_impl::last = allocator_impl::items_per_page; + +template +struct quick_allocator: public allocator_impl< sizeof(T), boost::alignment_of::value > +{ +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED diff --git a/include/boost/detail/shared_array_nmt.hpp b/include/boost/smart_ptr/detail/shared_array_nmt.hpp similarity index 92% rename from include/boost/detail/shared_array_nmt.hpp rename to include/boost/smart_ptr/detail/shared_array_nmt.hpp index 13ca6ac..450c9bc 100644 --- a/include/boost/detail/shared_array_nmt.hpp +++ b/include/boost/smart_ptr/detail/shared_array_nmt.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED -#define BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED // // detail/shared_array_nmt.hpp - shared_array.hpp without member templates @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include // for std::ptrdiff_t #include // for std::swap @@ -148,4 +148,4 @@ template void swap(shared_array & a, shared_array & b) } // namespace boost -#endif // #ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED diff --git a/include/boost/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp similarity index 96% rename from include/boost/detail/shared_count.hpp rename to include/boost/smart_ptr/detail/shared_count.hpp index 9e9b1ba..3384faa 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/smart_ptr/detail/shared_count.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED -#define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -25,9 +25,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include // In order to avoid circular dependencies with Boost.TR1 // we make sure that our include of doesn't try to @@ -427,4 +427,4 @@ inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( # pragma warn .8027 // Functions containing try are not expanded inline #endif -#endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED diff --git a/include/boost/detail/shared_ptr_nmt.hpp b/include/boost/smart_ptr/detail/shared_ptr_nmt.hpp similarity index 93% rename from include/boost/detail/shared_ptr_nmt.hpp rename to include/boost/smart_ptr/detail/shared_ptr_nmt.hpp index 0780e30..afc1ec0 100644 --- a/include/boost/detail/shared_ptr_nmt.hpp +++ b/include/boost/smart_ptr/detail/shared_ptr_nmt.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED -#define BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED // // detail/shared_ptr_nmt.hpp - shared_ptr.hpp without member templates @@ -17,7 +17,7 @@ #include #include #include -#include +#include #ifndef BOOST_NO_AUTO_PTR # include // for std::auto_ptr @@ -179,4 +179,4 @@ template inline T * get_pointer(shared_ptr const & p) } // namespace boost -#endif // #ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED diff --git a/include/boost/detail/sp_convertible.hpp b/include/boost/smart_ptr/detail/sp_convertible.hpp similarity index 89% rename from include/boost/detail/sp_convertible.hpp rename to include/boost/smart_ptr/detail/sp_convertible.hpp index 2c1539b..7d9502d 100644 --- a/include/boost/detail/sp_convertible.hpp +++ b/include/boost/smart_ptr/detail/sp_convertible.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED -#define BOOST_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -73,4 +73,4 @@ template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_i #endif // !defined( BOOST_SP_NO_SP_CONVERTIBLE ) -#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp similarity index 57% rename from include/boost/detail/sp_counted_base.hpp rename to include/boost/smart_ptr/detail/sp_counted_base.hpp index c25a57f..1352346 100644 --- a/include/boost/detail/sp_counted_base.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -20,47 +20,47 @@ #include #if defined( BOOST_SP_DISABLE_THREADS ) -# include +# include #elif defined( BOOST_SP_USE_SPINLOCK ) -# include +# include #elif defined( BOOST_SP_USE_PTHREADS ) -# include +# include #elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 ) -# include +# include #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) -# include +# include #elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER ) -# include +# include #elif defined(__HP_aCC) && defined(__ia64) -# include +# include #elif defined( __MWERKS__ ) && defined( __POWERPC__ ) -# include +# include #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) -# include +# include #elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) -# include +# include #elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) ) -# include +# include #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) -# include +# include #elif !defined( BOOST_HAS_THREADS ) -# include +# include #else -# include +# include #endif -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_acc_ia64.hpp b/include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp similarity index 92% rename from include/boost/detail/sp_counted_base_acc_ia64.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp index c956b8e..dffd995 100644 --- a/include/boost/detail/sp_counted_base_acc_ia64.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED // // detail/sp_counted_base_acc_ia64.hpp - aC++ on HP-UX IA64 @@ -147,4 +147,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_cw_ppc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp similarity index 92% rename from include/boost/detail/sp_counted_base_cw_ppc.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp index 3f43252..51ac56a 100644 --- a/include/boost/detail/sp_counted_base_cw_ppc.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -167,4 +167,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_cw_x86.hpp b/include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_cw_x86.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp index b2e3f9b..1234e78 100644 --- a/include/boost/detail/sp_counted_base_cw_x86.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -155,4 +155,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_gcc_ia64.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp index 7535295..d122a49 100644 --- a/include/boost/detail/sp_counted_base_gcc_ia64.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED // // detail/sp_counted_base_gcc_ia64.hpp - g++ on IA64 @@ -154,4 +154,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_gcc_ppc.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp index cea2740..7f5c414 100644 --- a/include/boost/detail/sp_counted_base_gcc_ppc.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -178,4 +178,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_gcc_sparc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_gcc_sparc.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp index 2afca16..8af6f0a 100644 --- a/include/boost/detail/sp_counted_base_gcc_sparc.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -163,4 +163,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_gcc_x86.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_gcc_x86.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp index 8bf3171..4d7fa8d 100644 --- a/include/boost/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -170,4 +170,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_nt.hpp b/include/boost/smart_ptr/detail/sp_counted_base_nt.hpp similarity index 90% rename from include/boost/detail/sp_counted_base_nt.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_nt.hpp index dc7a042..dfd70e7 100644 --- a/include/boost/detail/sp_counted_base_nt.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_nt.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -104,4 +104,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_pt.hpp b/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_pt.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_pt.hpp index cd30de9..3c56fec 100644 --- a/include/boost/detail/sp_counted_base_pt.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -132,4 +132,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_solaris.hpp b/include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp similarity index 91% rename from include/boost/detail/sp_counted_base_solaris.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp index a747b39..d1b6bec 100644 --- a/include/boost/detail/sp_counted_base_solaris.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED // // detail/sp_counted_base_solaris.hpp @@ -110,4 +110,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_spin.hpp b/include/boost/smart_ptr/detail/sp_counted_base_spin.hpp similarity index 90% rename from include/boost/detail/sp_counted_base_spin.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_spin.hpp index 610a468..bbd11e6 100644 --- a/include/boost/detail/sp_counted_base_spin.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_spin.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -19,7 +19,7 @@ // #include -#include +#include namespace boost { @@ -128,4 +128,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_sync.hpp b/include/boost/smart_ptr/detail/sp_counted_base_sync.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_sync.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_sync.hpp index d72dac2..41f654e 100644 --- a/include/boost/detail/sp_counted_base_sync.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_sync.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -152,4 +152,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_base_w32.hpp b/include/boost/smart_ptr/detail/sp_counted_base_w32.hpp similarity index 93% rename from include/boost/detail/sp_counted_base_w32.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_w32.hpp index f990393..06aa456 100644 --- a/include/boost/detail/sp_counted_base_w32.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_w32.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -127,4 +127,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED diff --git a/include/boost/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp similarity index 94% rename from include/boost/detail/sp_counted_impl.hpp rename to include/boost/smart_ptr/detail/sp_counted_impl.hpp index 81f92da..397421a 100644 --- a/include/boost/detail/sp_counted_impl.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED -#define BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -25,10 +25,10 @@ #endif #include -#include +#include #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) -#include +#include #endif #if defined(BOOST_SP_USE_STD_ALLOCATOR) @@ -228,4 +228,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED diff --git a/include/boost/detail/spinlock.hpp b/include/boost/smart_ptr/detail/spinlock.hpp similarity index 70% rename from include/boost/detail/spinlock.hpp rename to include/boost/smart_ptr/detail/spinlock.hpp index 346fb3c..9c6cb9f 100644 --- a/include/boost/detail/spinlock.hpp +++ b/include/boost/smart_ptr/detail/spinlock.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SPINLOCK_HPP_INCLUDED -#define BOOST_DETAIL_SPINLOCK_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -31,17 +31,17 @@ #include #if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ ) -# include +# include #elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) -# include +# include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# include +# include #elif defined(BOOST_HAS_PTHREADS) -# include +# include #elif !defined(BOOST_HAS_THREADS) -# include +# include #else # error Unrecognized threading platform #endif -#endif // #ifndef BOOST_DETAIL_SPINLOCK_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_gcc_arm.hpp b/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp similarity index 84% rename from include/boost/detail/spinlock_gcc_arm.hpp rename to include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp index c21163b..ba6c511 100644 --- a/include/boost/detail/spinlock_gcc_arm.hpp +++ b/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED -#define BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED // // Copyright (c) 2008 Peter Dimov @@ -9,7 +9,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#include namespace boost { @@ -82,4 +82,4 @@ public: #define BOOST_DETAIL_SPINLOCK_INIT {0} -#endif // #ifndef BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_nt.hpp b/include/boost/smart_ptr/detail/spinlock_nt.hpp similarity index 87% rename from include/boost/detail/spinlock_nt.hpp rename to include/boost/smart_ptr/detail/spinlock_nt.hpp index f03ba08..1f399d0 100644 --- a/include/boost/detail/spinlock_nt.hpp +++ b/include/boost/smart_ptr/detail/spinlock_nt.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED -#define BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -86,4 +86,4 @@ public: #define BOOST_DETAIL_SPINLOCK_INIT { false } -#endif // #ifndef BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_pool.hpp b/include/boost/smart_ptr/detail/spinlock_pool.hpp similarity index 91% rename from include/boost/detail/spinlock_pool.hpp rename to include/boost/smart_ptr/detail/spinlock_pool.hpp index a264b1a..0e2e08a 100644 --- a/include/boost/detail/spinlock_pool.hpp +++ b/include/boost/smart_ptr/detail/spinlock_pool.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED -#define BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -22,7 +22,7 @@ // #include -#include +#include #include namespace boost @@ -84,4 +84,4 @@ template< int I > spinlock spinlock_pool< I >::pool_[ 41 ] = } // namespace detail } // namespace boost -#endif // #ifndef BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_pt.hpp b/include/boost/smart_ptr/detail/spinlock_pt.hpp similarity index 86% rename from include/boost/detail/spinlock_pt.hpp rename to include/boost/smart_ptr/detail/spinlock_pt.hpp index dfb2d6f..f9cabfc 100644 --- a/include/boost/detail/spinlock_pt.hpp +++ b/include/boost/smart_ptr/detail/spinlock_pt.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED -#define BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -76,4 +76,4 @@ public: #define BOOST_DETAIL_SPINLOCK_INIT { PTHREAD_MUTEX_INITIALIZER } -#endif // #ifndef BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_sync.hpp b/include/boost/smart_ptr/detail/spinlock_sync.hpp similarity index 84% rename from include/boost/detail/spinlock_sync.hpp rename to include/boost/smart_ptr/detail/spinlock_sync.hpp index a752396..a7145c5 100644 --- a/include/boost/detail/spinlock_sync.hpp +++ b/include/boost/smart_ptr/detail/spinlock_sync.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED -#define BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -15,7 +15,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#include #if defined( __ia64__ ) && defined( __INTEL_COMPILER ) # include @@ -84,4 +84,4 @@ public: #define BOOST_DETAIL_SPINLOCK_INIT {0} -#endif // #ifndef BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED diff --git a/include/boost/detail/spinlock_w32.hpp b/include/boost/smart_ptr/detail/spinlock_w32.hpp similarity index 88% rename from include/boost/detail/spinlock_w32.hpp rename to include/boost/smart_ptr/detail/spinlock_w32.hpp index aa416c3..fb97629 100644 --- a/include/boost/detail/spinlock_w32.hpp +++ b/include/boost/smart_ptr/detail/spinlock_w32.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED -#define BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -16,7 +16,7 @@ // #include -#include +#include // BOOST_COMPILER_FENCE @@ -110,4 +110,4 @@ public: #define BOOST_DETAIL_SPINLOCK_INIT {0} -#endif // #ifndef BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED diff --git a/include/boost/detail/yield_k.hpp b/include/boost/smart_ptr/detail/yield_k.hpp similarity index 92% rename from include/boost/detail/yield_k.hpp rename to include/boost/smart_ptr/detail/yield_k.hpp index d97542d..a956cc0 100644 --- a/include/boost/detail/yield_k.hpp +++ b/include/boost/smart_ptr/detail/yield_k.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_DETAIL_YIELD_K_HPP_INCLUDED -#define BOOST_DETAIL_YIELD_K_HPP_INCLUDED +#ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -8,7 +8,7 @@ #endif // -// boost/detail/yield_k.hpp +// yield_k.hpp // // Copyright (c) 2008 Peter Dimov // @@ -146,4 +146,4 @@ inline void yield( unsigned ) #endif -#endif // #ifndef BOOST_DETAIL_YIELD_K_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED diff --git a/include/boost/smart_ptr/enable_shared_from_this.hpp b/include/boost/smart_ptr/enable_shared_from_this.hpp new file mode 100644 index 0000000..ed9aadd --- /dev/null +++ b/include/boost/smart_ptr/enable_shared_from_this.hpp @@ -0,0 +1,73 @@ +#ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED +#define BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED + +// +// enable_shared_from_this.hpp +// +// Copyright (c) 2002 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html +// + +#include +#include +#include +#include + +namespace boost +{ + +template class enable_shared_from_this +{ +protected: + + enable_shared_from_this() + { + } + + enable_shared_from_this(enable_shared_from_this const &) + { + } + + enable_shared_from_this & operator=(enable_shared_from_this const &) + { + return *this; + } + + ~enable_shared_from_this() + { + } + +public: + + shared_ptr shared_from_this() + { + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(p.get() == this); + return p; + } + + shared_ptr shared_from_this() const + { + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(p.get() == this); + return p; + } + +// Note: No, you don't need to initialize _internal_weak_this +// +// Please read the documentation, not the code +// +// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html + + typedef T _internal_element_type; // for bcc 5.5.1 + mutable weak_ptr<_internal_element_type> _internal_weak_this; +}; + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp new file mode 100644 index 0000000..f5acae3 --- /dev/null +++ b/include/boost/smart_ptr/intrusive_ptr.hpp @@ -0,0 +1,311 @@ +#ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED +#define BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED + +// +// intrusive_ptr.hpp +// +// Copyright (c) 2001, 2002 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation. +// + +#include + +#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash +# pragma warning(push) +# pragma warning(disable:4284) // odd return type for operator-> +#endif + +#include +#include +#include + +#include // for std::less + +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) +#include // for std::basic_ostream +#else +#include +#endif +#endif + + +namespace boost +{ + +// +// intrusive_ptr +// +// A smart pointer that uses intrusive reference counting. +// +// Relies on unqualified calls to +// +// void intrusive_ptr_add_ref(T * p); +// void intrusive_ptr_release(T * p); +// +// (p != 0) +// +// The object is responsible for destroying itself. +// + +template class intrusive_ptr +{ +private: + + typedef intrusive_ptr this_type; + +public: + + typedef T element_type; + + intrusive_ptr(): p_(0) + { + } + + intrusive_ptr(T * p, bool add_ref = true): p_(p) + { + if(p_ != 0 && add_ref) intrusive_ptr_add_ref(p_); + } + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + intrusive_ptr( intrusive_ptr const & rhs, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + intrusive_ptr( intrusive_ptr const & rhs ) + +#endif + : p_( rhs.get() ) + { + if( p_ != 0 ) intrusive_ptr_add_ref( p_ ); + } + +#endif + + intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_) + { + if(p_ != 0) intrusive_ptr_add_ref(p_); + } + + ~intrusive_ptr() + { + if(p_ != 0) intrusive_ptr_release(p_); + } + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) + + template intrusive_ptr & operator=(intrusive_ptr const & rhs) + { + this_type(rhs).swap(*this); + return *this; + } + +#endif + + intrusive_ptr & operator=(intrusive_ptr const & rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + intrusive_ptr & operator=(T * rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + void reset() + { + this_type().swap( *this ); + } + + void reset( T * rhs ) + { + this_type( rhs ).swap( *this ); + } + + T * get() const + { + return p_; + } + + T & operator*() const + { + BOOST_ASSERT( p_ != 0 ); + return *p_; + } + + T * operator->() const + { + BOOST_ASSERT( p_ != 0 ); + return p_; + } + +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return p_ != 0; + } + +#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return p_ == 0? 0: &this_type::get; + } + +#else + + typedef T * this_type::*unspecified_bool_type; + + operator unspecified_bool_type () const + { + return p_ == 0? 0: &this_type::p_; + } + +#endif + + // operator! is a Borland-specific workaround + bool operator! () const + { + return p_ == 0; + } + + void swap(intrusive_ptr & rhs) + { + T * tmp = p_; + p_ = rhs.p_; + rhs.p_ = tmp; + } + +private: + + T * p_; +}; + +template inline bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator==(intrusive_ptr const & a, U * b) +{ + return a.get() == b; +} + +template inline bool operator!=(intrusive_ptr const & a, U * b) +{ + return a.get() != b; +} + +template inline bool operator==(T * a, intrusive_ptr const & b) +{ + return a == b.get(); +} + +template inline bool operator!=(T * a, intrusive_ptr const & b) +{ + return a != b.get(); +} + +#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 + +// Resolve the ambiguity between our op!= and the one in rel_ops + +template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() != b.get(); +} + +#endif + +template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return std::less()(a.get(), b.get()); +} + +template void swap(intrusive_ptr & lhs, intrusive_ptr & rhs) +{ + lhs.swap(rhs); +} + +// mem_fn support + +template T * get_pointer(intrusive_ptr const & p) +{ + return p.get(); +} + +template intrusive_ptr static_pointer_cast(intrusive_ptr const & p) +{ + return static_cast(p.get()); +} + +template intrusive_ptr const_pointer_cast(intrusive_ptr const & p) +{ + return const_cast(p.get()); +} + +template intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & p) +{ + return dynamic_cast(p.get()); +} + +// operator<< + +#if !defined(BOOST_NO_IOSTREAM) + +#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) + +template std::ostream & operator<< (std::ostream & os, intrusive_ptr const & p) +{ + os << p.get(); + return os; +} + +#else + +// in STLport's no-iostreams mode no iostream symbols can be used +#ifndef _STLP_NO_IOSTREAMS + +# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) +// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL +using std::basic_ostream; +template basic_ostream & operator<< (basic_ostream & os, intrusive_ptr const & p) +# else +template std::basic_ostream & operator<< (std::basic_ostream & os, intrusive_ptr const & p) +# endif +{ + os << p.get(); + return os; +} + +#endif // _STLP_NO_IOSTREAMS + +#endif // __GNUC__ < 3 + +#endif // !defined(BOOST_NO_IOSTREAM) + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED diff --git a/include/boost/smart_ptr/make_shared.hpp b/include/boost/smart_ptr/make_shared.hpp new file mode 100644 index 0000000..58e38d2 --- /dev/null +++ b/include/boost/smart_ptr/make_shared.hpp @@ -0,0 +1,433 @@ +#ifndef BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED +#define BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED + +// make_shared.hpp +// +// Copyright (c) 2007, 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// See http://www.boost.org/libs/smart_ptr/make_shared.html +// for documentation. + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + +namespace detail +{ + +template< std::size_t N, std::size_t A > struct sp_aligned_storage +{ + union type + { + char data_[ N ]; + typename boost::type_with_alignment< A >::type align_; + }; +}; + +template< class T > class sp_ms_deleter +{ +private: + + typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type; + + bool initialized_; + storage_type storage_; + +private: + + void destroy() + { + if( initialized_ ) + { + reinterpret_cast< T* >( storage_.data_ )->~T(); + initialized_ = false; + } + } + +public: + + sp_ms_deleter(): initialized_( false ) + { + } + + ~sp_ms_deleter() + { + destroy(); + } + + void operator()( T * ) + { + destroy(); + } + + void * address() + { + return storage_.data_; + } + + void set_initialized() + { + initialized_ = true; + } +}; + +template< class T > T forward( T t ) +{ + return t; +} + +} // namespace detail + +// Zero-argument versions +// +// Used even when variadic templates are available because of the new T() vs new T issue + +template< class T > boost::shared_ptr< T > make_shared() +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T(); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T(); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) + +// Variadic templates, rvalue reference + +template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && ... args ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( detail::forward( args )... ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Args && ... args ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( detail::forward( args )... ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +#else + +// C++03 version + +template< class T, class A1 > +boost::shared_ptr< T > make_shared( A1 const & a1 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > +boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > +boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 ) +{ + boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a ); + + detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt ); + + void * pv = pd->address(); + + new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + pd->set_initialized(); + + return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); +} + +#endif + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED diff --git a/include/boost/smart_ptr/scoped_array.hpp b/include/boost/smart_ptr/scoped_array.hpp new file mode 100644 index 0000000..23c2f87 --- /dev/null +++ b/include/boost/smart_ptr/scoped_array.hpp @@ -0,0 +1,138 @@ +#ifndef BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED +#define BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// http://www.boost.org/libs/smart_ptr/scoped_array.htm +// + +#include +#include +#include // in case ptrdiff_t not in std + +#include + +#include // for std::ptrdiff_t + +namespace boost +{ + +// Debug hooks + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +void sp_array_constructor_hook(void * p); +void sp_array_destructor_hook(void * p); + +#endif + +// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to +// is guaranteed, either on destruction of the scoped_array or via an explicit +// reset(). Use shared_array or std::vector if your needs are more complex. + +template class scoped_array // noncopyable +{ +private: + + T * ptr; + + scoped_array(scoped_array const &); + scoped_array & operator=(scoped_array const &); + + typedef scoped_array this_type; + + void operator==( scoped_array const& ) const; + void operator!=( scoped_array const& ) const; + +public: + + typedef T element_type; + + explicit scoped_array(T * p = 0) : ptr(p) // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_array_constructor_hook(ptr); +#endif + } + + ~scoped_array() // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_array_destructor_hook(ptr); +#endif + boost::checked_array_delete(ptr); + } + + void reset(T * p = 0) // never throws + { + BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors + this_type(p).swap(*this); + } + + T & operator[](std::ptrdiff_t i) const // never throws + { + BOOST_ASSERT(ptr != 0); + BOOST_ASSERT(i >= 0); + return ptr[i]; + } + + T * get() const // never throws + { + return ptr; + } + + // implicit conversion to "bool" + +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return ptr != 0; + } + +#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return ptr == 0? 0: &this_type::get; + } + +#else + + typedef T * this_type::*unspecified_bool_type; + + operator unspecified_bool_type() const // never throws + { + return ptr == 0? 0: &this_type::ptr; + } + +#endif + + bool operator! () const // never throws + { + return ptr == 0; + } + + void swap(scoped_array & b) // never throws + { + T * tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } + +}; + +template inline void swap(scoped_array & a, scoped_array & b) // never throws +{ + a.swap(b); +} + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED diff --git a/include/boost/smart_ptr/scoped_ptr.hpp b/include/boost/smart_ptr/scoped_ptr.hpp new file mode 100644 index 0000000..518a254 --- /dev/null +++ b/include/boost/smart_ptr/scoped_ptr.hpp @@ -0,0 +1,160 @@ +#ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED +#define BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm +// + +#include +#include +#include + +#ifndef BOOST_NO_AUTO_PTR +# include // for std::auto_ptr +#endif + +namespace boost +{ + +// Debug hooks + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +void sp_scalar_constructor_hook(void * p); +void sp_scalar_destructor_hook(void * p); + +#endif + +// scoped_ptr mimics a built-in pointer except that it guarantees deletion +// of the object pointed to, either on destruction of the scoped_ptr or via +// an explicit reset(). scoped_ptr is a simple solution for simple needs; +// use shared_ptr or std::auto_ptr if your needs are more complex. + +template class scoped_ptr // noncopyable +{ +private: + + T * ptr; + + scoped_ptr(scoped_ptr const &); + scoped_ptr & operator=(scoped_ptr const &); + + typedef scoped_ptr this_type; + + void operator==( scoped_ptr const& ) const; + void operator!=( scoped_ptr const& ) const; + +public: + + typedef T element_type; + + explicit scoped_ptr(T * p = 0): ptr(p) // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_constructor_hook(ptr); +#endif + } + +#ifndef BOOST_NO_AUTO_PTR + + explicit scoped_ptr(std::auto_ptr p): ptr(p.release()) // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_constructor_hook(ptr); +#endif + } + +#endif + + ~scoped_ptr() // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_destructor_hook(ptr); +#endif + boost::checked_delete(ptr); + } + + void reset(T * p = 0) // never throws + { + BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors + this_type(p).swap(*this); + } + + T & operator*() const // never throws + { + BOOST_ASSERT(ptr != 0); + return *ptr; + } + + T * operator->() const // never throws + { + BOOST_ASSERT(ptr != 0); + return ptr; + } + + T * get() const // never throws + { + return ptr; + } + + // implicit conversion to "bool" + +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return ptr != 0; + } + +#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return ptr == 0? 0: &this_type::get; + } + +#else + typedef T * this_type::*unspecified_bool_type; + + operator unspecified_bool_type() const // never throws + { + return ptr == 0? 0: &this_type::ptr; + } + +#endif + + bool operator! () const // never throws + { + return ptr == 0; + } + + void swap(scoped_ptr & b) // never throws + { + T * tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } +}; + +template inline void swap(scoped_ptr & a, scoped_ptr & b) // never throws +{ + a.swap(b); +} + +// get_pointer(p) is a generic way to say p.get() + +template inline T * get_pointer(scoped_ptr const & p) +{ + return p.get(); +} + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp new file mode 100644 index 0000000..7d68aa2 --- /dev/null +++ b/include/boost/smart_ptr/shared_array.hpp @@ -0,0 +1,193 @@ +#ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED +#define BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED + +// +// shared_array.hpp +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation. +// + +#include // for broken compiler workarounds + +#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#include +#else + +#include // TR1 cyclic inclusion fix + +#include +#include + +#include +#include + +#include // for std::ptrdiff_t +#include // for std::swap +#include // for std::less + +namespace boost +{ + +// +// shared_array +// +// shared_array extends shared_ptr to arrays. +// The array pointed to is deleted when the last shared_array pointing to it +// is destroyed or reset. +// + +template class shared_array +{ +private: + + // Borland 5.5.1 specific workarounds + typedef checked_array_deleter deleter; + typedef shared_array this_type; + +public: + + typedef T element_type; + + explicit shared_array(T * p = 0): px(p), pn(p, deleter()) + { + } + + // + // Requirements: D's copy constructor must not throw + // + // shared_array will release p by calling d(p) + // + + template shared_array(T * p, D d): px(p), pn(p, d) + { + } + +// generated copy constructor, assignment, destructor are fine + + void reset(T * p = 0) + { + BOOST_ASSERT(p == 0 || p != px); + this_type(p).swap(*this); + } + + template void reset(T * p, D d) + { + this_type(p, d).swap(*this); + } + + T & operator[] (std::ptrdiff_t i) const // never throws + { + BOOST_ASSERT(px != 0); + BOOST_ASSERT(i >= 0); + return px[i]; + } + + T * get() const // never throws + { + return px; + } + + // implicit conversion to "bool" + +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return px != 0; + } + +#elif defined( _MANAGED ) + + static void unspecified_bool( this_type*** ) + { + } + + typedef void (*unspecified_bool_type)( this_type*** ); + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: unspecified_bool; + } + +#elif \ + ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ + ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) + + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::get; + } + +#else + + typedef T * this_type::*unspecified_bool_type; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::px; + } + +#endif + + bool operator! () const // never throws + { + return px == 0; + } + + bool unique() const // never throws + { + return pn.unique(); + } + + long use_count() const // never throws + { + return pn.use_count(); + } + + void swap(shared_array & other) // never throws + { + std::swap(px, other.px); + pn.swap(other.pn); + } + +private: + + T * px; // contained pointer + detail::shared_count pn; // reference counter + +}; // shared_array + +template inline bool operator==(shared_array const & a, shared_array const & b) // never throws +{ + return a.get() == b.get(); +} + +template inline bool operator!=(shared_array const & a, shared_array const & b) // never throws +{ + return a.get() != b.get(); +} + +template inline bool operator<(shared_array const & a, shared_array const & b) // never throws +{ + return std::less()(a.get(), b.get()); +} + +template void swap(shared_array & a, shared_array & b) // never throws +{ + a.swap(b); +} + +} // namespace boost + +#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) + +#endif // #ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp new file mode 100644 index 0000000..78711ed --- /dev/null +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -0,0 +1,751 @@ +#ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED +#define BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED + +// +// shared_ptr.hpp +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001-2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. +// + +#include // for broken compiler workarounds + +#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#include +#else + +// In order to avoid circular dependencies with Boost.TR1 +// we make sure that our include of doesn't try to +// pull in the TR1 headers: that's why we use this header +// rather than including directly: +#include // std::auto_ptr + +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) +#include +#include +#endif + +#include // for std::swap +#include // for std::less +#include // for std::bad_cast + +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) +#include // for std::basic_ostream +#else +#include +#endif +#endif + +#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash +# pragma warning(push) +# pragma warning(disable:4284) // odd return type for operator-> +#endif + +namespace boost +{ + +template class weak_ptr; +template class enable_shared_from_this; + +namespace detail +{ + +struct static_cast_tag {}; +struct const_cast_tag {}; +struct dynamic_cast_tag {}; +struct polymorphic_cast_tag {}; + +template struct shared_ptr_traits +{ + typedef T & reference; +}; + +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + +#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) + +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + +template<> struct shared_ptr_traits +{ + typedef void reference; +}; + +#endif + +// enable_shared_from_this support + +template void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this const * pe, Y const * px ) +{ + if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); +} + +#ifdef _MANAGED + +// Avoid C4793, ... causes native code generation + +struct sp_any_pointer +{ + template sp_any_pointer( T* ) {} +}; + +inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer ) +{ +} + +#else // _MANAGED + +#ifdef sgi +// Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed +# pragma set woff 3506 +#endif + +inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) +{ +} + +#ifdef sgi +# pragma reset woff 3506 +#endif + +#endif // _MANAGED + +#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) + +// rvalue auto_ptr support based on a technique by Dave Abrahams + +template< class T, class R > struct sp_enable_if_auto_ptr +{ +}; + +template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R > +{ + typedef R type; +}; + +#endif + +} // namespace detail + + +// +// shared_ptr +// +// An enhanced relative of scoped_ptr with reference counted copy semantics. +// The object pointed to is deleted when the last shared_ptr pointing to it +// is destroyed or reset. +// + +template class shared_ptr +{ +private: + + // Borland 5.5.1 specific workaround + typedef shared_ptr this_type; + +public: + + typedef T element_type; + typedef T value_type; + typedef T * pointer; + typedef typename boost::detail::shared_ptr_traits::reference reference; + + shared_ptr(): px(0), pn() // never throws in 1.30+ + { + } + + template + explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete + { + boost::detail::sp_enable_shared_from_this( pn, p, p ); + } + + // + // Requirements: D's copy constructor must not throw + // + // shared_ptr will release p by calling d(p) + // + + template shared_ptr(Y * p, D d): px(p), pn(p, d) + { + boost::detail::sp_enable_shared_from_this( pn, p, p ); + } + + // As above, but with allocator. A's copy constructor shall not throw. + + template shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) + { + boost::detail::sp_enable_shared_from_this( pn, p, p ); + } + +// generated copy constructor, assignment, destructor are fine... + +// except that Borland C++ has a bug, and g++ with -Wsynth warns +#if defined(__BORLANDC__) || defined(__GNUC__) + + shared_ptr & operator=(shared_ptr const & r) // never throws + { + px = r.px; + pn = r.pn; // shared_count::op= doesn't throw + return *this; + } + +#endif + + template + explicit shared_ptr(weak_ptr const & r): pn(r.pn) // may throw + { + // it is now safe to copy r.px, as pn(r.pn) did not throw + px = r.px; + } + + template + shared_ptr( weak_ptr const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws + { + if( !pn.empty() ) + { + px = r.px; + } + } + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + shared_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + shared_ptr( shared_ptr const & r ) + +#endif + : px( r.px ), pn( r.pn ) // never throws + { + } + + // aliasing + template< class Y > + shared_ptr( shared_ptr const & r, T * p ): px( p ), pn( r.pn ) // never throws + { + } + + template + shared_ptr(shared_ptr const & r, boost::detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) + { + } + + template + shared_ptr(shared_ptr const & r, boost::detail::const_cast_tag): px(const_cast(r.px)), pn(r.pn) + { + } + + template + shared_ptr(shared_ptr const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) + { + if(px == 0) // need to allocate new counter -- the cast failed + { + pn = boost::detail::shared_count(); + } + } + + template + shared_ptr(shared_ptr const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) + { + if(px == 0) + { + boost::throw_exception(std::bad_cast()); + } + } + +#ifndef BOOST_NO_AUTO_PTR + + template + explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn() + { + Y * tmp = r.get(); + pn = boost::detail::shared_count(r); + boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); + } + +#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + + template + shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() + { + typename Ap::element_type * tmp = r.get(); + pn = boost::detail::shared_count( r ); + boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); + } + + +#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_NO_AUTO_PTR + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + + template + shared_ptr & operator=(shared_ptr const & r) // never throws + { + px = r.px; + pn = r.pn; // shared_count::op= doesn't throw + return *this; + } + +#endif + +#ifndef BOOST_NO_AUTO_PTR + + template + shared_ptr & operator=( std::auto_ptr & r ) + { + this_type(r).swap(*this); + return *this; + } + +#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + + template + typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r ) + { + this_type( r ).swap( *this ); + return *this; + } + + +#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_NO_AUTO_PTR + +// Move support + +#if defined( BOOST_HAS_RVALUE_REFS ) + + shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws + { + pn.swap( r.pn ); + r.px = 0; + } + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + shared_ptr( shared_ptr && r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + shared_ptr( shared_ptr && r ) + +#endif + : px( r.px ), pn() // never throws + { + pn.swap( r.pn ); + r.px = 0; + } + + shared_ptr & operator=( shared_ptr && r ) // never throws + { + this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); + return *this; + } + + template + shared_ptr & operator=( shared_ptr && r ) // never throws + { + this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); + return *this; + } + +#endif + + void reset() // never throws in 1.30+ + { + this_type().swap(*this); + } + + template void reset(Y * p) // Y must be complete + { + BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors + this_type(p).swap(*this); + } + + template void reset( Y * p, D d ) + { + this_type( p, d ).swap( *this ); + } + + template void reset( Y * p, D d, A a ) + { + this_type( p, d, a ).swap( *this ); + } + + template void reset( shared_ptr const & r, T * p ) + { + this_type( r, p ).swap( *this ); + } + + reference operator* () const // never throws + { + BOOST_ASSERT(px != 0); + return *px; + } + + T * operator-> () const // never throws + { + BOOST_ASSERT(px != 0); + return px; + } + + T * get() const // never throws + { + return px; + } + + // implicit conversion to "bool" + +#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) + + operator bool () const + { + return px != 0; + } + +#elif defined( _MANAGED ) + + static void unspecified_bool( this_type*** ) + { + } + + typedef void (*unspecified_bool_type)( this_type*** ); + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: unspecified_bool; + } + +#elif \ + ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ + ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \ + ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) ) + + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::get; + } + +#else + + typedef T * this_type::*unspecified_bool_type; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::px; + } + +#endif + + // operator! is redundant, but some compilers need it + + bool operator! () const // never throws + { + return px == 0; + } + + bool unique() const // never throws + { + return pn.unique(); + } + + long use_count() const // never throws + { + return pn.use_count(); + } + + void swap(shared_ptr & other) // never throws + { + std::swap(px, other.px); + pn.swap(other.pn); + } + + template bool _internal_less(shared_ptr const & rhs) const + { + return pn < rhs.pn; + } + + void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const + { + return pn.get_deleter( ti ); + } + + bool _internal_equiv( shared_ptr const & r ) const + { + return px == r.px && pn == r.pn; + } + +// Tasteless as this may seem, making all members public allows member templates +// to work in the absence of member template friends. (Matthew Langston) + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + +private: + + template friend class shared_ptr; + template friend class weak_ptr; + + +#endif + + T * px; // contained pointer + boost::detail::shared_count pn; // reference counter + +}; // shared_ptr + +template inline bool operator==(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() != b.get(); +} + +#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 + +// Resolve the ambiguity between our op!= and the one in rel_ops + +template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() != b.get(); +} + +#endif + +template inline bool operator<(shared_ptr const & a, shared_ptr const & b) +{ + return a._internal_less(b); +} + +template inline void swap(shared_ptr & a, shared_ptr & b) +{ + a.swap(b); +} + +template shared_ptr static_pointer_cast(shared_ptr const & r) +{ + return shared_ptr(r, boost::detail::static_cast_tag()); +} + +template shared_ptr const_pointer_cast(shared_ptr const & r) +{ + return shared_ptr(r, boost::detail::const_cast_tag()); +} + +template shared_ptr dynamic_pointer_cast(shared_ptr const & r) +{ + return shared_ptr(r, boost::detail::dynamic_cast_tag()); +} + +// shared_*_cast names are deprecated. Use *_pointer_cast instead. + +template shared_ptr shared_static_cast(shared_ptr const & r) +{ + return shared_ptr(r, boost::detail::static_cast_tag()); +} + +template shared_ptr shared_dynamic_cast(shared_ptr const & r) +{ + return shared_ptr(r, boost::detail::dynamic_cast_tag()); +} + +template shared_ptr shared_polymorphic_cast(shared_ptr const & r) +{ + return shared_ptr(r, boost::detail::polymorphic_cast_tag()); +} + +template shared_ptr shared_polymorphic_downcast(shared_ptr const & r) +{ + BOOST_ASSERT(dynamic_cast(r.get()) == r.get()); + return shared_static_cast(r); +} + +// get_pointer() enables boost::mem_fn to recognize shared_ptr + +template inline T * get_pointer(shared_ptr const & p) +{ + return p.get(); +} + +// operator<< + +#if !defined(BOOST_NO_IOSTREAM) + +#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) + +template std::ostream & operator<< (std::ostream & os, shared_ptr const & p) +{ + os << p.get(); + return os; +} + +#else + +// in STLport's no-iostreams mode no iostream symbols can be used +#ifndef _STLP_NO_IOSTREAMS + +# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) +// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL +using std::basic_ostream; +template basic_ostream & operator<< (basic_ostream & os, shared_ptr const & p) +# else +template std::basic_ostream & operator<< (std::basic_ostream & os, shared_ptr const & p) +# endif +{ + os << p.get(); + return os; +} + +#endif // _STLP_NO_IOSTREAMS + +#endif // __GNUC__ < 3 + +#endif // !defined(BOOST_NO_IOSTREAM) + +// get_deleter + +#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ + ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ + ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) ) + +// g++ 2.9x doesn't allow static_cast(void *) +// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it + +template D * get_deleter(shared_ptr const & p) +{ + void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D)); + return const_cast(static_cast(q)); +} + +#else + +template D * get_deleter(shared_ptr const & p) +{ + return static_cast(p._internal_get_deleter(BOOST_SP_TYPEID(D))); +} + +#endif + +// atomic access + +#if !defined(BOOST_SP_NO_ATOMIC_ACCESS) + +template inline bool atomic_is_lock_free( shared_ptr const * /*p*/ ) +{ + return false; +} + +template shared_ptr atomic_load( shared_ptr const * p ) +{ + boost::detail::spinlock_pool<2>::scoped_lock lock( p ); + return *p; +} + +template inline shared_ptr atomic_load_explicit( shared_ptr const * p, memory_order /*mo*/ ) +{ + return atomic_load( p ); +} + +template void atomic_store( shared_ptr * p, shared_ptr r ) +{ + boost::detail::spinlock_pool<2>::scoped_lock lock( p ); + p->swap( r ); +} + +template inline void atomic_store_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) +{ + atomic_store( p, r ); // std::move( r ) +} + +template shared_ptr atomic_exchange( shared_ptr * p, shared_ptr r ) +{ + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); + + sp.lock(); + p->swap( r ); + sp.unlock(); + + return r; // return std::move( r ) +} + +template shared_ptr atomic_exchange_explicit( shared_ptr * p, shared_ptr r, memory_order /*mo*/ ) +{ + return atomic_exchange( p, r ); // std::move( r ) +} + +template bool atomic_compare_exchange( shared_ptr * p, shared_ptr * v, shared_ptr w ) +{ + boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); + + sp.lock(); + + if( p->_internal_equiv( *v ) ) + { + p->swap( w ); + + sp.unlock(); + + return true; + } + else + { + shared_ptr tmp( *p ); + + sp.unlock(); + + tmp.swap( *v ); + return false; + } +} + +template inline bool atomic_compare_exchange_explicit( shared_ptr * p, shared_ptr * v, shared_ptr w, memory_order /*success*/, memory_order /*failure*/ ) +{ + return atomic_compare_exchange( p, v, w ); // std::move( w ) +} + +#endif + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) + +#endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp new file mode 100644 index 0000000..bf5296a --- /dev/null +++ b/include/boost/smart_ptr/weak_ptr.hpp @@ -0,0 +1,182 @@ +#ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED +#define BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED + +// +// weak_ptr.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation. +// + +#include // boost.TR1 include order fix +#include +#include + +#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash +# pragma warning(push) +# pragma warning(disable:4284) // odd return type for operator-> +#endif + +namespace boost +{ + +template class weak_ptr +{ +private: + + // Borland 5.5.1 specific workarounds + typedef weak_ptr this_type; + +public: + + typedef T element_type; + + weak_ptr(): px(0), pn() // never throws in 1.30+ + { + } + +// generated copy constructor, assignment, destructor are fine + + +// +// The "obvious" converting constructor implementation: +// +// template +// weak_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // never throws +// { +// } +// +// has a serious problem. +// +// r.px may already have been invalidated. The px(r.px) +// conversion may require access to *r.px (virtual inheritance). +// +// It is not possible to avoid spurious access violations since +// in multithreaded programs r.px may be invalidated at any point. +// + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + weak_ptr( weak_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + weak_ptr( weak_ptr const & r ) + +#endif + : pn(r.pn) // never throws + { + px = r.lock().get(); + } + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + weak_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + weak_ptr( shared_ptr const & r ) + +#endif + : px( r.px ), pn( r.pn ) // never throws + { + } + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + + template + weak_ptr & operator=(weak_ptr const & r) // never throws + { + px = r.lock().get(); + pn = r.pn; + return *this; + } + + template + weak_ptr & operator=(shared_ptr const & r) // never throws + { + px = r.px; + pn = r.pn; + return *this; + } + +#endif + + shared_ptr lock() const // never throws + { + return shared_ptr( *this, boost::detail::sp_nothrow_tag() ); + } + + long use_count() const // never throws + { + return pn.use_count(); + } + + bool expired() const // never throws + { + return pn.use_count() == 0; + } + + void reset() // never throws in 1.30+ + { + this_type().swap(*this); + } + + void swap(this_type & other) // never throws + { + std::swap(px, other.px); + pn.swap(other.pn); + } + + void _internal_assign(T * px2, boost::detail::shared_count const & pn2) + { + px = px2; + pn = pn2; + } + + template bool _internal_less(weak_ptr const & rhs) const + { + return pn < rhs.pn; + } + +// Tasteless as this may seem, making all members public allows member templates +// to work in the absence of member template friends. (Matthew Langston) + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + +private: + + template friend class weak_ptr; + template friend class shared_ptr; + +#endif + + T * px; // contained pointer + boost::detail::weak_count pn; // reference counter + +}; // weak_ptr + +template inline bool operator<(weak_ptr const & a, weak_ptr const & b) +{ + return a._internal_less(b); +} + +template void swap(weak_ptr & a, weak_ptr & b) +{ + a.swap(b); +} + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index b300813..dd26869 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -6,177 +6,13 @@ // // Copyright (c) 2001, 2002, 2003 Peter Dimov // -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt // // See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation. // -#include // boost.TR1 include order fix -#include -#include - -#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash -# pragma warning(push) -# pragma warning(disable:4284) // odd return type for operator-> -#endif - -namespace boost -{ - -template class weak_ptr -{ -private: - - // Borland 5.5.1 specific workarounds - typedef weak_ptr this_type; - -public: - - typedef T element_type; - - weak_ptr(): px(0), pn() // never throws in 1.30+ - { - } - -// generated copy constructor, assignment, destructor are fine - - -// -// The "obvious" converting constructor implementation: -// -// template -// weak_ptr(weak_ptr const & r): px(r.px), pn(r.pn) // never throws -// { -// } -// -// has a serious problem. -// -// r.px may already have been invalidated. The px(r.px) -// conversion may require access to *r.px (virtual inheritance). -// -// It is not possible to avoid spurious access violations since -// in multithreaded programs r.px may be invalidated at any point. -// - - template -#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) - - weak_ptr( weak_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) - -#else - - weak_ptr( weak_ptr const & r ) - -#endif - : pn(r.pn) // never throws - { - px = r.lock().get(); - } - - template -#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) - - weak_ptr( shared_ptr const & r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) - -#else - - weak_ptr( shared_ptr const & r ) - -#endif - : px( r.px ), pn( r.pn ) // never throws - { - } - -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) - - template - weak_ptr & operator=(weak_ptr const & r) // never throws - { - px = r.lock().get(); - pn = r.pn; - return *this; - } - - template - weak_ptr & operator=(shared_ptr const & r) // never throws - { - px = r.px; - pn = r.pn; - return *this; - } - -#endif - - shared_ptr lock() const // never throws - { - return shared_ptr( *this, boost::detail::sp_nothrow_tag() ); - } - - long use_count() const // never throws - { - return pn.use_count(); - } - - bool expired() const // never throws - { - return pn.use_count() == 0; - } - - void reset() // never throws in 1.30+ - { - this_type().swap(*this); - } - - void swap(this_type & other) // never throws - { - std::swap(px, other.px); - pn.swap(other.pn); - } - - void _internal_assign(T * px2, boost::detail::shared_count const & pn2) - { - px = px2; - pn = pn2; - } - - template bool _internal_less(weak_ptr const & rhs) const - { - return pn < rhs.pn; - } - -// Tasteless as this may seem, making all members public allows member templates -// to work in the absence of member template friends. (Matthew Langston) - -#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS - -private: - - template friend class weak_ptr; - template friend class shared_ptr; - -#endif - - T * px; // contained pointer - boost::detail::weak_count pn; // reference counter - -}; // weak_ptr - -template inline bool operator<(weak_ptr const & a, weak_ptr const & b) -{ - return a._internal_less(b); -} - -template void swap(weak_ptr & a, weak_ptr & b) -{ - a.swap(b); -} - -} // namespace boost - -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif +#include #endif // #ifndef BOOST_WEAK_PTR_HPP_INCLUDED diff --git a/test/spinlock_pool_test.cpp b/test/spinlock_pool_test.cpp index c1ce2b3..53f61ca 100644 --- a/test/spinlock_pool_test.cpp +++ b/test/spinlock_pool_test.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include // Sanity check only From 6be1e3fceb0fb13efb9a4ee0c23575c95c79a4f3 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 2 Mar 2009 16:35:06 +0000 Subject: [PATCH 497/513] Merge [51514] to release. Closes #2394. [SVN r51535] --- include/boost/smart_ptr/detail/shared_count.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp index 3384faa..b968bba 100644 --- a/include/boost/smart_ptr/detail/shared_count.hpp +++ b/include/boost/smart_ptr/detail/shared_count.hpp @@ -319,7 +319,7 @@ public: weak_count(shared_count const & r): pi_(r.pi_) // nothrow #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - , id_(shared_count_id) + , id_(weak_count_id) #endif { if(pi_ != 0) pi_->weak_add_ref(); @@ -327,7 +327,7 @@ public: weak_count(weak_count const & r): pi_(r.pi_) // nothrow #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - , id_(shared_count_id) + , id_(weak_count_id) #endif { if(pi_ != 0) pi_->weak_add_ref(); From f93110620af5ccfcbbe879c5a04646a9a5b80a11 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 2 Mar 2009 16:37:31 +0000 Subject: [PATCH 498/513] Merge [51515] to release. Closes #2675. [SVN r51536] --- include/boost/smart_ptr/detail/lightweight_mutex.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/smart_ptr/detail/lightweight_mutex.hpp b/include/boost/smart_ptr/detail/lightweight_mutex.hpp index a2fc281..d46b193 100644 --- a/include/boost/smart_ptr/detail/lightweight_mutex.hpp +++ b/include/boost/smart_ptr/detail/lightweight_mutex.hpp @@ -32,7 +32,7 @@ # include #elif defined(BOOST_HAS_PTHREADS) # include -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +#elif defined(BOOST_HAS_WINTHREADS) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include #else // Use #define BOOST_DISABLE_THREADS to avoid the error From bad394b1e969eb4ae2a2bf262726d6bf359bbfdb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 2 Mar 2009 16:39:53 +0000 Subject: [PATCH 499/513] Merge [51516] to release. Closes #2662. [SVN r51537] --- include/boost/smart_ptr/make_shared.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/boost/smart_ptr/make_shared.hpp b/include/boost/smart_ptr/make_shared.hpp index 58e38d2..25b9cf0 100644 --- a/include/boost/smart_ptr/make_shared.hpp +++ b/include/boost/smart_ptr/make_shared.hpp @@ -60,6 +60,11 @@ public: { } + // optimization: do not copy storage_ + sp_ms_deleter( sp_ms_deleter const & ): initialized_( false ) + { + } + ~sp_ms_deleter() { destroy(); From dad59f3325a8f17fe4fb2020139d8c14688efb9c Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 2 Mar 2009 16:42:28 +0000 Subject: [PATCH 500/513] Merge [51517] to release. Closes #2525. [SVN r51538] --- .../boost/smart_ptr/detail/atomic_count.hpp | 5 +- .../smart_ptr/detail/atomic_count_gcc.hpp | 6 ++- .../smart_ptr/detail/sp_counted_base.hpp | 5 +- .../boost/smart_ptr/detail/sp_has_sync.hpp | 49 +++++++++++++++++++ include/boost/smart_ptr/detail/spinlock.hpp | 8 ++- 5 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 include/boost/smart_ptr/detail/sp_has_sync.hpp diff --git a/include/boost/smart_ptr/detail/atomic_count.hpp b/include/boost/smart_ptr/detail/atomic_count.hpp index 91236e4..a6ddea3 100644 --- a/include/boost/smart_ptr/detail/atomic_count.hpp +++ b/include/boost/smart_ptr/detail/atomic_count.hpp @@ -74,6 +74,7 @@ // #include +#include #ifndef BOOST_HAS_THREADS @@ -95,10 +96,10 @@ typedef long atomic_count; #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) # include -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include -#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) +#elif defined( BOOST_SP_HAS_SYNC ) # include #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) diff --git a/include/boost/smart_ptr/detail/atomic_count_gcc.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp index 6abfdf2..1305632 100644 --- a/include/boost/smart_ptr/detail/atomic_count_gcc.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp @@ -17,7 +17,11 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#if __GNUC__ * 100 + __GNUC_MINOR__ >= 402 +# include +#else +# include +#endif namespace boost { diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp index 1352346..df8be5b 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp @@ -18,6 +18,7 @@ // #include +#include #if defined( BOOST_SP_DISABLE_THREADS ) # include @@ -46,13 +47,13 @@ #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) +#elif defined( BOOST_SP_HAS_SYNC ) # include #elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) ) # include -#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) +#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined(__CYGWIN__) # include #elif !defined( BOOST_HAS_THREADS ) diff --git a/include/boost/smart_ptr/detail/sp_has_sync.hpp b/include/boost/smart_ptr/detail/sp_has_sync.hpp new file mode 100644 index 0000000..cb0282d --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_has_sync.hpp @@ -0,0 +1,49 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/smart_ptr/detail/sp_has_sync.hpp +// +// Copyright (c) 2008, 2009 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Defines the BOOST_SP_HAS_SYNC macro if the __sync_* intrinsics +// are available. +// + +#if defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + +#define BOOST_SP_HAS_SYNC + +#if defined( __arm__ ) || defined( __armel__ ) +#undef BOOST_SP_HAS_SYNC +#endif + +#if defined( __hppa ) || defined( __hppa__ ) +#undef BOOST_SP_HAS_SYNC +#endif + +#if defined( __m68k__ ) +#undef BOOST_SP_HAS_SYNC +#endif + +#if defined( __sparc__ ) +#undef BOOST_SP_HAS_SYNC +#endif + +#if defined( __INTEL_COMPILER ) && !defined( __ia64__ ) +#undef BOOST_SP_HAS_SYNC +#endif + +#endif // __GNUC__ * 100 + __GNUC_MINOR__ >= 401 + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/spinlock.hpp b/include/boost/smart_ptr/detail/spinlock.hpp index 9c6cb9f..1640a38 100644 --- a/include/boost/smart_ptr/detail/spinlock.hpp +++ b/include/boost/smart_ptr/detail/spinlock.hpp @@ -29,17 +29,23 @@ // #include +#include #if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ ) # include -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) && ( !defined( __INTEL_COMPILER ) || defined( __ia64__ ) ) + +#elif defined( BOOST_SP_HAS_SYNC ) # include + #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include + #elif defined(BOOST_HAS_PTHREADS) # include + #elif !defined(BOOST_HAS_THREADS) # include + #else # error Unrecognized threading platform #endif From 5a2771e58590a8f82b78a5258dddc247f8a2e003 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 2 Mar 2009 16:45:22 +0000 Subject: [PATCH 501/513] Merge [51518] to release. Closes #2814. [SVN r51539] --- .../boost/smart_ptr/detail/operator_bool.hpp | 56 ++++++++++++++++ include/boost/smart_ptr/intrusive_ptr.hpp | 67 ++++++------------- include/boost/smart_ptr/scoped_array.hpp | 61 +++++------------ include/boost/smart_ptr/scoped_ptr.hpp | 65 +++++------------- include/boost/smart_ptr/shared_array.hpp | 50 +------------- include/boost/smart_ptr/shared_ptr.hpp | 53 +-------------- 6 files changed, 112 insertions(+), 240 deletions(-) create mode 100644 include/boost/smart_ptr/detail/operator_bool.hpp diff --git a/include/boost/smart_ptr/detail/operator_bool.hpp b/include/boost/smart_ptr/detail/operator_bool.hpp new file mode 100644 index 0000000..842a05d --- /dev/null +++ b/include/boost/smart_ptr/detail/operator_bool.hpp @@ -0,0 +1,56 @@ +// This header intentionally has no include guards. +// +// Copyright (c) 2001-2009 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) + + operator bool () const + { + return px != 0; + } + +#elif defined( _MANAGED ) + + static void unspecified_bool( this_type*** ) + { + } + + typedef void (*unspecified_bool_type)( this_type*** ); + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: unspecified_bool; + } + +#elif \ + ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ + ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \ + ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) ) + + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::get; + } + +#else + + typedef T * this_type::*unspecified_bool_type; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::px; + } + +#endif + + // operator! is redundant, but some compilers need it + bool operator! () const // never throws + { + return px == 0; + } diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp index f5acae3..d3bd02b 100644 --- a/include/boost/smart_ptr/intrusive_ptr.hpp +++ b/include/boost/smart_ptr/intrusive_ptr.hpp @@ -63,13 +63,13 @@ public: typedef T element_type; - intrusive_ptr(): p_(0) + intrusive_ptr(): px( 0 ) { } - intrusive_ptr(T * p, bool add_ref = true): p_(p) + intrusive_ptr( T * p, bool add_ref = true ): px( p ) { - if(p_ != 0 && add_ref) intrusive_ptr_add_ref(p_); + if( px != 0 && add_ref ) intrusive_ptr_add_ref( px ); } #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) @@ -84,21 +84,21 @@ public: intrusive_ptr( intrusive_ptr const & rhs ) #endif - : p_( rhs.get() ) + : px( rhs.get() ) { - if( p_ != 0 ) intrusive_ptr_add_ref( p_ ); + if( px != 0 ) intrusive_ptr_add_ref( px ); } #endif - intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_) + intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px ) { - if(p_ != 0) intrusive_ptr_add_ref(p_); + if( px != 0 ) intrusive_ptr_add_ref( px ); } ~intrusive_ptr() { - if(p_ != 0) intrusive_ptr_release(p_); + if( px != 0 ) intrusive_ptr_release( px ); } #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) @@ -135,63 +135,34 @@ public: T * get() const { - return p_; + return px; } T & operator*() const { - BOOST_ASSERT( p_ != 0 ); - return *p_; + BOOST_ASSERT( px != 0 ); + return *px; } T * operator->() const { - BOOST_ASSERT( p_ != 0 ); - return p_; + BOOST_ASSERT( px != 0 ); + return px; } -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) - - operator bool () const - { - return p_ != 0; - } - -#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return p_ == 0? 0: &this_type::get; - } - -#else - - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type () const - { - return p_ == 0? 0: &this_type::p_; - } - -#endif - - // operator! is a Borland-specific workaround - bool operator! () const - { - return p_ == 0; - } +// implicit conversion to "bool" +#include void swap(intrusive_ptr & rhs) { - T * tmp = p_; - p_ = rhs.p_; - rhs.p_ = tmp; + T * tmp = px; + px = rhs.px; + rhs.px = tmp; } private: - T * p_; + T * px; }; template inline bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) diff --git a/include/boost/smart_ptr/scoped_array.hpp b/include/boost/smart_ptr/scoped_array.hpp index 23c2f87..483460f 100644 --- a/include/boost/smart_ptr/scoped_array.hpp +++ b/include/boost/smart_ptr/scoped_array.hpp @@ -39,7 +39,7 @@ template class scoped_array // noncopyable { private: - T * ptr; + T * px; scoped_array(scoped_array const &); scoped_array & operator=(scoped_array const &); @@ -53,79 +53,48 @@ public: typedef T element_type; - explicit scoped_array(T * p = 0) : ptr(p) // never throws + explicit scoped_array( T * p = 0 ) : px( p ) // never throws { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_array_constructor_hook(ptr); + boost::sp_array_constructor_hook( px ); #endif } ~scoped_array() // never throws { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_array_destructor_hook(ptr); + boost::sp_array_destructor_hook( px ); #endif - boost::checked_array_delete(ptr); + boost::checked_array_delete( px ); } void reset(T * p = 0) // never throws { - BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors + BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors this_type(p).swap(*this); } T & operator[](std::ptrdiff_t i) const // never throws { - BOOST_ASSERT(ptr != 0); - BOOST_ASSERT(i >= 0); - return ptr[i]; + BOOST_ASSERT( px != 0 ); + BOOST_ASSERT( i >= 0 ); + return px[i]; } T * get() const // never throws { - return ptr; + return px; } - // implicit conversion to "bool" - -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) - - operator bool () const - { - return ptr != 0; - } - -#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return ptr == 0? 0: &this_type::get; - } - -#else - - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type() const // never throws - { - return ptr == 0? 0: &this_type::ptr; - } - -#endif - - bool operator! () const // never throws - { - return ptr == 0; - } +// implicit conversion to "bool" +#include void swap(scoped_array & b) // never throws { - T * tmp = b.ptr; - b.ptr = ptr; - ptr = tmp; + T * tmp = b.px; + b.px = px; + px = tmp; } - }; template inline void swap(scoped_array & a, scoped_array & b) // never throws diff --git a/include/boost/smart_ptr/scoped_ptr.hpp b/include/boost/smart_ptr/scoped_ptr.hpp index 518a254..df479e5 100644 --- a/include/boost/smart_ptr/scoped_ptr.hpp +++ b/include/boost/smart_ptr/scoped_ptr.hpp @@ -40,7 +40,7 @@ template class scoped_ptr // noncopyable { private: - T * ptr; + T * px; scoped_ptr(scoped_ptr const &); scoped_ptr & operator=(scoped_ptr const &); @@ -54,19 +54,19 @@ public: typedef T element_type; - explicit scoped_ptr(T * p = 0): ptr(p) // never throws + explicit scoped_ptr( T * p = 0 ): px( p ) // never throws { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_scalar_constructor_hook(ptr); + boost::sp_scalar_constructor_hook( px ); #endif } #ifndef BOOST_NO_AUTO_PTR - explicit scoped_ptr(std::auto_ptr p): ptr(p.release()) // never throws + explicit scoped_ptr( std::auto_ptr p ): px( p.release() ) // never throws { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_scalar_constructor_hook(ptr); + boost::sp_scalar_constructor_hook( px ); #endif } @@ -75,71 +75,42 @@ public: ~scoped_ptr() // never throws { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - boost::sp_scalar_destructor_hook(ptr); + boost::sp_scalar_destructor_hook( px ); #endif - boost::checked_delete(ptr); + boost::checked_delete( px ); } void reset(T * p = 0) // never throws { - BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors + BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors this_type(p).swap(*this); } T & operator*() const // never throws { - BOOST_ASSERT(ptr != 0); - return *ptr; + BOOST_ASSERT( px != 0 ); + return *px; } T * operator->() const // never throws { - BOOST_ASSERT(ptr != 0); - return ptr; + BOOST_ASSERT( px != 0 ); + return px; } T * get() const // never throws { - return ptr; + return px; } - // implicit conversion to "bool" - -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) - - operator bool () const - { - return ptr != 0; - } - -#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return ptr == 0? 0: &this_type::get; - } - -#else - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type() const // never throws - { - return ptr == 0? 0: &this_type::ptr; - } - -#endif - - bool operator! () const // never throws - { - return ptr == 0; - } +// implicit conversion to "bool" +#include void swap(scoped_ptr & b) // never throws { - T * tmp = b.ptr; - b.ptr = ptr; - ptr = tmp; + T * tmp = b.px; + b.px = px; + px = tmp; } }; diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp index 7d68aa2..1f50403 100644 --- a/include/boost/smart_ptr/shared_array.hpp +++ b/include/boost/smart_ptr/shared_array.hpp @@ -94,54 +94,8 @@ public: return px; } - // implicit conversion to "bool" - -#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) - - operator bool () const - { - return px != 0; - } - -#elif defined( _MANAGED ) - - static void unspecified_bool( this_type*** ) - { - } - - typedef void (*unspecified_bool_type)( this_type*** ); - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: unspecified_bool; - } - -#elif \ - ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ - ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) - - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: &this_type::get; - } - -#else - - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: &this_type::px; - } - -#endif - - bool operator! () const // never throws - { - return px == 0; - } +// implicit conversion to "bool" +#include bool unique() const // never throws { diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 78711ed..c7cdaf7 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -425,57 +425,8 @@ public: return px; } - // implicit conversion to "bool" - -#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) - - operator bool () const - { - return px != 0; - } - -#elif defined( _MANAGED ) - - static void unspecified_bool( this_type*** ) - { - } - - typedef void (*unspecified_bool_type)( this_type*** ); - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: unspecified_bool; - } - -#elif \ - ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ - ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \ - ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) ) - - typedef T * (this_type::*unspecified_bool_type)() const; - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: &this_type::get; - } - -#else - - typedef T * this_type::*unspecified_bool_type; - - operator unspecified_bool_type() const // never throws - { - return px == 0? 0: &this_type::px; - } - -#endif - - // operator! is redundant, but some compilers need it - - bool operator! () const // never throws - { - return px == 0; - } +// implicit conversion to "bool" +#include bool unique() const // never throws { From 22f1b092c90efe89f19636c90b84c23b60a66fdd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 5 Mar 2009 23:06:17 +0000 Subject: [PATCH 502/513] Merge [51581] to release. Fixes #2126. Fixes #2584. [SVN r51632] --- .../smart_ptr/enable_shared_from_this.hpp | 36 ++- include/boost/smart_ptr/make_shared.hpp | 154 +++++++--- include/boost/smart_ptr/shared_ptr.hpp | 31 +- test/Jamfile.v2 | 4 + test/allocate_shared_esft_test.cpp | 264 ++++++++++++++++++ test/allocate_shared_test.cpp | 9 + test/esft_second_ptr_test.cpp | 51 ++++ test/esft_void_test.cpp | 41 +++ test/make_shared_esft_test.cpp | 263 +++++++++++++++++ test/make_shared_test.cpp | 9 + test/shared_from_this_test.cpp | 43 ++- test/shared_ptr_move_test.cpp | 11 + 12 files changed, 824 insertions(+), 92 deletions(-) create mode 100644 test/allocate_shared_esft_test.cpp create mode 100644 test/esft_second_ptr_test.cpp create mode 100644 test/esft_void_test.cpp create mode 100644 test/make_shared_esft_test.cpp diff --git a/include/boost/smart_ptr/enable_shared_from_this.hpp b/include/boost/smart_ptr/enable_shared_from_this.hpp index ed9aadd..f7b1445 100644 --- a/include/boost/smart_ptr/enable_shared_from_this.hpp +++ b/include/boost/smart_ptr/enable_shared_from_this.hpp @@ -4,11 +4,11 @@ // // enable_shared_from_this.hpp // -// Copyright (c) 2002 Peter Dimov +// Copyright 2002, 2009 Peter Dimov // -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt // // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html // @@ -46,26 +46,32 @@ public: shared_ptr shared_from_this() { - shared_ptr p(_internal_weak_this); - BOOST_ASSERT(p.get() == this); + shared_ptr p( weak_this_ ); + BOOST_ASSERT( p.get() == this ); return p; } shared_ptr shared_from_this() const { - shared_ptr p(_internal_weak_this); - BOOST_ASSERT(p.get() == this); + shared_ptr p( weak_this_ ); + BOOST_ASSERT( p.get() == this ); return p; } -// Note: No, you don't need to initialize _internal_weak_this -// -// Please read the documentation, not the code -// -// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html +public: // actually private, but avoids compiler template friendship issues - typedef T _internal_element_type; // for bcc 5.5.1 - mutable weak_ptr<_internal_element_type> _internal_weak_this; + // Note: invoked automatically by shared_ptr; do not call + template void _internal_accept_owner( shared_ptr const * ppx, Y * py ) const + { + if( weak_this_.expired() ) + { + weak_this_ = shared_ptr( *ppx, py ); + } + } + +private: + + mutable weak_ptr weak_this_; }; } // namespace boost diff --git a/include/boost/smart_ptr/make_shared.hpp b/include/boost/smart_ptr/make_shared.hpp index 25b9cf0..7e1e793 100644 --- a/include/boost/smart_ptr/make_shared.hpp +++ b/include/boost/smart_ptr/make_shared.hpp @@ -105,10 +105,13 @@ template< class T > boost::shared_ptr< T > make_shared() void * pv = pd->address(); - new( pv ) T(); + ::new( pv ) T(); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a ) @@ -119,10 +122,13 @@ template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a void * pv = pd->address(); - new( pv ) T(); + ::new( pv ) T(); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } #if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) @@ -137,10 +143,13 @@ template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && . void * pv = pd->address(); - new( pv ) T( detail::forward( args )... ); + ::new( pv ) T( detail::forward( args )... ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Args && ... args ) @@ -151,10 +160,13 @@ template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shar void * pv = pd->address(); - new( pv ) T( detail::forward( args )... ); + ::new( pv ) T( detail::forward( args )... ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } #else @@ -170,10 +182,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1 ) void * pv = pd->address(); - new( pv ) T( a1 ); + ::new( pv ) T( a1 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1 > @@ -185,10 +200,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 ) void * pv = pd->address(); - new( pv ) T( a1 ); + ::new( pv ) T( a1 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2 > @@ -200,10 +218,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 ) void * pv = pd->address(); - new( pv ) T( a1, a2 ); + ::new( pv ) T( a1, a2 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2 > @@ -215,10 +236,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2 ); + ::new( pv ) T( a1, a2 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2, class A3 > @@ -230,10 +254,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3 void * pv = pd->address(); - new( pv ) T( a1, a2, a3 ); + ::new( pv ) T( a1, a2, a3 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2, class A3 > @@ -245,10 +272,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2, a3 ); + ::new( pv ) T( a1, a2, a3 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2, class A3, class A4 > @@ -260,10 +290,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4 ); + ::new( pv ) T( a1, a2, a3, a4 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2, class A3, class A4 > @@ -275,10 +308,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4 ); + ::new( pv ) T( a1, a2, a3, a4 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2, class A3, class A4, class A5 > @@ -290,10 +326,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5 ); + ::new( pv ) T( a1, a2, a3, a4, a5 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2, class A3, class A4, class A5 > @@ -305,10 +344,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5 ); + ::new( pv ) T( a1, a2, a3, a4, a5 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2, class A3, class A4, class A5, class A6 > @@ -320,10 +362,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6 ); + ::new( pv ) T( a1, a2, a3, a4, a5, a6 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 > @@ -335,10 +380,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6 ); + ::new( pv ) T( a1, a2, a3, a4, a5, a6 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > @@ -350,10 +398,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); + ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 > @@ -365,10 +416,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); + ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > @@ -380,10 +434,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); + ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > @@ -395,10 +452,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); + ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > @@ -410,10 +470,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > @@ -425,10 +488,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a void * pv = pd->address(); - new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); + ::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); pd->set_initialized(); - return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) ); + T * pt2 = static_cast< T* >( pv ); + + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + return boost::shared_ptr< T >( pt, pt2 ); } #endif diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index c7cdaf7..0812c04 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -58,6 +58,7 @@ namespace boost { +template class shared_ptr; template class weak_ptr; template class enable_shared_from_this; @@ -100,9 +101,12 @@ template<> struct shared_ptr_traits // enable_shared_from_this support -template void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this const * pe, Y const * px ) +template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr const * ppx, Y const * py, boost::enable_shared_from_this< T > const * pe ) { - if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); + if( pe != 0 ) + { + pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) ); + } } #ifdef _MANAGED @@ -114,25 +118,16 @@ struct sp_any_pointer template sp_any_pointer( T* ) {} }; -inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer ) +inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer ) { } #else // _MANAGED -#ifdef sgi -// Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed -# pragma set woff 3506 -#endif - -inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) +inline void sp_enable_shared_from_this( ... ) { } -#ifdef sgi -# pragma reset woff 3506 -#endif - #endif // _MANAGED #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) @@ -182,7 +177,7 @@ public: template explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { - boost::detail::sp_enable_shared_from_this( pn, p, p ); + boost::detail::sp_enable_shared_from_this( this, p, p ); } // @@ -193,14 +188,14 @@ public: template shared_ptr(Y * p, D d): px(p), pn(p, d) { - boost::detail::sp_enable_shared_from_this( pn, p, p ); + boost::detail::sp_enable_shared_from_this( this, p, p ); } // As above, but with allocator. A's copy constructor shall not throw. template shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) { - boost::detail::sp_enable_shared_from_this( pn, p, p ); + boost::detail::sp_enable_shared_from_this( this, p, p ); } // generated copy constructor, assignment, destructor are fine... @@ -288,7 +283,7 @@ public: { Y * tmp = r.get(); pn = boost::detail::shared_count(r); - boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); + boost::detail::sp_enable_shared_from_this( this, tmp, tmp ); } #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) @@ -298,7 +293,7 @@ public: { typename Ap::element_type * tmp = r.get(); pn = boost::detail::shared_count( r ); - boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); + boost::detail::sp_enable_shared_from_this( this, tmp, tmp ); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5f68e20..34cd5f1 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -48,5 +48,9 @@ import testing ; [ run ip_convertible_test.cpp ] [ run allocate_shared_test.cpp ] [ run sp_atomic_test.cpp ] + [ run esft_void_test.cpp ] + [ run esft_second_ptr_test.cpp ] + [ run make_shared_esft_test.cpp ] + [ run allocate_shared_esft_test.cpp ] ; } diff --git a/test/allocate_shared_esft_test.cpp b/test/allocate_shared_esft_test.cpp new file mode 100644 index 0000000..2bb8ccc --- /dev/null +++ b/test/allocate_shared_esft_test.cpp @@ -0,0 +1,264 @@ +// allocate_shared_esft_test.cpp +// +// Copyright 2007-2009 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include + +class X: public boost::enable_shared_from_this +{ +private: + + X( X const & ); + X & operator=( X const & ); + +public: + + static int instances; + + explicit X( int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0 ) + { + ++instances; + } + + ~X() + { + --instances; + } +}; + +int X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator() ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2, 3 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7, 8 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator(), 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +} diff --git a/test/allocate_shared_test.cpp b/test/allocate_shared_test.cpp index 71ee948..97808c2 100644 --- a/test/allocate_shared_test.cpp +++ b/test/allocate_shared_test.cpp @@ -10,6 +10,7 @@ #include #include #include +#include class X { @@ -18,6 +19,14 @@ private: X( X const & ); X & operator=( X const & ); + void * operator new( std::size_t ); + + void operator delete( void * p ) + { + // lack of this definition causes link errors on MSVC + ::operator delete( p ); + } + public: static int instances; diff --git a/test/esft_second_ptr_test.cpp b/test/esft_second_ptr_test.cpp new file mode 100644 index 0000000..0600667 --- /dev/null +++ b/test/esft_second_ptr_test.cpp @@ -0,0 +1,51 @@ +// +// esft_second_ptr_test.cpp +// +// This test has been extracted from a real +// scenario that occurs in Boost.Python +// +// Copyright 2009 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + + +#include +#include +#include + +// + +class X: public boost::enable_shared_from_this +{ +}; + +void null_deleter( void const* ) +{ +} + +int main() +{ + boost::shared_ptr px( new X ); + + { + boost::shared_ptr px2( px.get(), null_deleter ); + BOOST_TEST( px == px2 ); + } + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + + return boost::report_errors(); +} diff --git a/test/esft_void_test.cpp b/test/esft_void_test.cpp new file mode 100644 index 0000000..b28c669 --- /dev/null +++ b/test/esft_void_test.cpp @@ -0,0 +1,41 @@ +// +// esft_void_test.cpp +// +// Copyright 2009 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + + +#include +#include +#include + +// + +class X: public boost::enable_shared_from_this +{ +}; + +int main() +{ + boost::shared_ptr< void const volatile > pv( new X ); + boost::shared_ptr< void > pv2 = boost::const_pointer_cast< void >( pv ); + boost::shared_ptr< X > px = boost::static_pointer_cast< X >( pv2 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + + return boost::report_errors(); +} diff --git a/test/make_shared_esft_test.cpp b/test/make_shared_esft_test.cpp new file mode 100644 index 0000000..1956cba --- /dev/null +++ b/test/make_shared_esft_test.cpp @@ -0,0 +1,263 @@ +// make_shared_esft_test.cpp +// +// Copyright 2007-2009 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +class X: public boost::enable_shared_from_this +{ +private: + + X( X const & ); + X & operator=( X const & ); + +public: + + static int instances; + + explicit X( int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0 ) + { + ++instances; + } + + ~X() + { + --instances; + } +}; + +int X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >(); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + BOOST_TEST( X::instances == 1 ); + + try + { + boost::shared_ptr< X > qx = px->shared_from_this(); + + BOOST_TEST( px == qx ); + BOOST_TEST( !( px < qx ) && !( qx < px ) ); + + px.reset(); + BOOST_TEST( X::instances == 1 ); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "px->shared_from_this() failed" ); + } + } + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +} diff --git a/test/make_shared_test.cpp b/test/make_shared_test.cpp index 9930e31..474d1c5 100644 --- a/test/make_shared_test.cpp +++ b/test/make_shared_test.cpp @@ -10,6 +10,7 @@ #include #include #include +#include class X { @@ -18,6 +19,14 @@ private: X( X const & ); X & operator=( X const & ); + void * operator new( std::size_t ); + + void operator delete( void * p ) + { + // lack of this definition causes link errors on MSVC + ::operator delete( p ); + } + public: static int instances; diff --git a/test/shared_from_this_test.cpp b/test/shared_from_this_test.cpp index 61515bd..68d6098 100644 --- a/test/shared_from_this_test.cpp +++ b/test/shared_from_this_test.cpp @@ -55,16 +55,23 @@ void test() BOOST_TEST(py.get() != 0); BOOST_TEST(py.use_count() == 1); - boost::shared_ptr px = py->getX(); - BOOST_TEST(px.get() != 0); - BOOST_TEST(py.use_count() == 2); + try + { + boost::shared_ptr px = py->getX(); + BOOST_TEST(px.get() != 0); + BOOST_TEST(py.use_count() == 2); - px->f(); + px->f(); - boost::shared_ptr py2 = boost::dynamic_pointer_cast(px); - BOOST_TEST(py.get() == py2.get()); - BOOST_TEST(!(py < py2 || py2 < py)); - BOOST_TEST(py.use_count() == 3); + boost::shared_ptr py2 = boost::dynamic_pointer_cast(px); + BOOST_TEST(py.get() == py2.get()); + BOOST_TEST(!(py < py2 || py2 < py)); + BOOST_TEST(py.use_count() == 3); + } + catch( boost::bad_weak_ptr const& ) + { + BOOST_ERROR( "py->getX() failed" ); + } } void test2(); @@ -124,19 +131,25 @@ void test3() { boost::shared_ptr p(new V); - boost::shared_ptr q = p->shared_from_this(); - BOOST_TEST(p == q); - BOOST_TEST(!(p < q) && !(q < p)); + try + { + boost::shared_ptr q = p->shared_from_this(); + BOOST_TEST(p == q); + BOOST_TEST(!(p < q) && !(q < p)); + } + catch( boost::bad_weak_ptr const & ) + { + BOOST_ERROR( "p->shared_from_this() failed" ); + } V v2(*p); try { boost::shared_ptr r = v2.shared_from_this(); - BOOST_TEST( p < r || r < p ); - BOOST_TEST( r.get() == &v2 ); + BOOST_ERROR("v2.shared_from_this() failed to throw"); } - catch(boost::bad_weak_ptr const &) + catch( boost::bad_weak_ptr const & ) { } @@ -147,7 +160,7 @@ void test3() BOOST_TEST(p == r); BOOST_TEST(!(p < r) && !(r < p)); } - catch(boost::bad_weak_ptr const &) + catch( boost::bad_weak_ptr const & ) { BOOST_ERROR("p->shared_from_this() threw bad_weak_ptr after *p = V()"); } diff --git a/test/shared_ptr_move_test.cpp b/test/shared_ptr_move_test.cpp index 8814d3d..bd785e4 100644 --- a/test/shared_ptr_move_test.cpp +++ b/test/shared_ptr_move_test.cpp @@ -8,6 +8,8 @@ // http://www.boost.org/LICENSE_1_0.txt // +#if defined( BOOST_HAS_RVALUE_REFS ) + #include #include @@ -93,3 +95,12 @@ int main() return boost::report_errors(); } + +#else // !defined( BOOST_HAS_RVALUE_REFS ) + +int main() +{ + return 0; +} + +#endif From 31e06b4a1d2bb84af98d6a9bd643016ac5831299 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 10 Mar 2009 18:26:57 +0000 Subject: [PATCH 503/513] Merge [51643] to release. Fixes #2813. [SVN r51688] --- include/boost/smart_ptr/shared_ptr.hpp | 27 +++--- test/Jamfile.v2 | 4 + test/sp_recursive_assign2_rv_test.cpp | 114 +++++++++++++++++++++++ test/sp_recursive_assign2_test.cpp | 122 +++++++++++++++++++++++++ test/sp_recursive_assign_rv_test.cpp | 114 +++++++++++++++++++++++ test/sp_recursive_assign_test.cpp | 122 +++++++++++++++++++++++++ 6 files changed, 487 insertions(+), 16 deletions(-) create mode 100644 test/sp_recursive_assign2_rv_test.cpp create mode 100644 test/sp_recursive_assign2_test.cpp create mode 100644 test/sp_recursive_assign_rv_test.cpp create mode 100644 test/sp_recursive_assign_test.cpp diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 0812c04..0ce3b97 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -198,19 +198,7 @@ public: boost::detail::sp_enable_shared_from_this( this, p, p ); } -// generated copy constructor, assignment, destructor are fine... - -// except that Borland C++ has a bug, and g++ with -Wsynth warns -#if defined(__BORLANDC__) || defined(__GNUC__) - - shared_ptr & operator=(shared_ptr const & r) // never throws - { - px = r.px; - pn = r.pn; // shared_count::op= doesn't throw - return *this; - } - -#endif +// generated copy constructor, destructor are fine template explicit shared_ptr(weak_ptr const & r): pn(r.pn) // may throw @@ -301,13 +289,20 @@ public: #endif // BOOST_NO_AUTO_PTR -#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) + // assignment + + shared_ptr & operator=( shared_ptr const & r ) // never throws + { + this_type(r).swap(*this); + return *this; + } + +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400) template shared_ptr & operator=(shared_ptr const & r) // never throws { - px = r.px; - pn = r.pn; // shared_count::op= doesn't throw + this_type(r).swap(*this); return *this; } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 34cd5f1..c862197 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -52,5 +52,9 @@ import testing ; [ run esft_second_ptr_test.cpp ] [ run make_shared_esft_test.cpp ] [ run allocate_shared_esft_test.cpp ] + [ run sp_recursive_assign_test.cpp ] + [ run sp_recursive_assign2_test.cpp ] + [ run sp_recursive_assign_rv_test.cpp ] + [ run sp_recursive_assign2_rv_test.cpp ] ; } diff --git a/test/sp_recursive_assign2_rv_test.cpp b/test/sp_recursive_assign2_rv_test.cpp new file mode 100644 index 0000000..e450c72 --- /dev/null +++ b/test/sp_recursive_assign2_rv_test.cpp @@ -0,0 +1,114 @@ +// +// sp_recursive_assign2_rv_test.cpp +// +// Copyright 2009 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + + +#include +#include + +// + +class X +{ +public: + + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const& ); +}; + +int X::instances = 0; + +class Y +{ +public: + + static int instances; + + Y() + { + ++instances; + } + + ~Y() + { + --instances; + } + +private: + + Y( Y const& ); +}; + +int Y::instances = 0; + +static boost::shared_ptr s_pv; + +class Z +{ +public: + + static int instances; + + Z() + { + ++instances; + } + + ~Z() + { + --instances; + s_pv = boost::shared_ptr( new Y ); + } + +private: + + Z( Z const& ); +}; + +int Z::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + s_pv = boost::shared_ptr( new Z ); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 1 ); + + s_pv = boost::shared_ptr( new X ); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 1 ); + BOOST_TEST( Z::instances == 0 ); + + s_pv = boost::shared_ptr(); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + return boost::report_errors(); +} diff --git a/test/sp_recursive_assign2_test.cpp b/test/sp_recursive_assign2_test.cpp new file mode 100644 index 0000000..ef6fa52 --- /dev/null +++ b/test/sp_recursive_assign2_test.cpp @@ -0,0 +1,122 @@ +// +// sp_recursive_assign2_test.cpp +// +// Copyright 2009 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + + +#include +#include + +// + +class X +{ +public: + + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const& ); +}; + +int X::instances = 0; + +class Y +{ +public: + + static int instances; + + Y() + { + ++instances; + } + + ~Y() + { + --instances; + } + +private: + + Y( Y const& ); +}; + +int Y::instances = 0; + +static boost::shared_ptr s_pv; + +class Z +{ +public: + + static int instances; + + Z() + { + ++instances; + } + + ~Z() + { + --instances; + + boost::shared_ptr pv( new Y ); + s_pv = pv; + } + +private: + + Z( Z const& ); +}; + +int Z::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + { + boost::shared_ptr pv( new Z ); + s_pv = pv; + } + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 1 ); + + { + boost::shared_ptr pv( new X ); + s_pv = pv; + } + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 1 ); + BOOST_TEST( Z::instances == 0 ); + + s_pv.reset(); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + return boost::report_errors(); +} diff --git a/test/sp_recursive_assign_rv_test.cpp b/test/sp_recursive_assign_rv_test.cpp new file mode 100644 index 0000000..8d80e72 --- /dev/null +++ b/test/sp_recursive_assign_rv_test.cpp @@ -0,0 +1,114 @@ +// +// sp_recursive_assign_rv_test.cpp +// +// Copyright 2009 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + + +#include +#include + +// + +class X +{ +public: + + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const& ); +}; + +int X::instances = 0; + +class Y +{ +public: + + static int instances; + + Y() + { + ++instances; + } + + ~Y() + { + --instances; + } + +private: + + Y( Y const& ); +}; + +int Y::instances = 0; + +static boost::shared_ptr s_pv; + +class Z +{ +public: + + static int instances; + + Z() + { + ++instances; + } + + ~Z() + { + --instances; + s_pv = boost::shared_ptr( new Y ); + } + +private: + + Z( Z const& ); +}; + +int Z::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + s_pv = boost::shared_ptr( new Z ); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 1 ); + + s_pv = boost::shared_ptr( new X ); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 1 ); + BOOST_TEST( Z::instances == 0 ); + + s_pv = boost::shared_ptr(); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + return boost::report_errors(); +} diff --git a/test/sp_recursive_assign_test.cpp b/test/sp_recursive_assign_test.cpp new file mode 100644 index 0000000..0f36891 --- /dev/null +++ b/test/sp_recursive_assign_test.cpp @@ -0,0 +1,122 @@ +// +// sp_recursive_assign_test.cpp +// +// Copyright 2009 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + + +#include +#include + +// + +class X +{ +public: + + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const& ); +}; + +int X::instances = 0; + +class Y +{ +public: + + static int instances; + + Y() + { + ++instances; + } + + ~Y() + { + --instances; + } + +private: + + Y( Y const& ); +}; + +int Y::instances = 0; + +static boost::shared_ptr s_pv; + +class Z +{ +public: + + static int instances; + + Z() + { + ++instances; + } + + ~Z() + { + --instances; + + boost::shared_ptr pv( new Y ); + s_pv = pv; + } + +private: + + Z( Z const& ); +}; + +int Z::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + { + boost::shared_ptr pv( new Z ); + s_pv = pv; + } + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 1 ); + + { + boost::shared_ptr pv( new X ); + s_pv = pv; + } + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 1 ); + BOOST_TEST( Z::instances == 0 ); + + s_pv.reset(); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( Y::instances == 0 ); + BOOST_TEST( Z::instances == 0 ); + + return boost::report_errors(); +} From 1742c37942455c617cf74dd48e41621ef3f2594e Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Wed, 11 Mar 2009 15:08:14 +0000 Subject: [PATCH 504/513] Merged [51699] and [51700] from trunk to release. Closes #1897 [SVN r51703] --- make_shared.html | 119 ++++++++++++++++++ shared_ptr.htm | 309 ++++++++++++++++++++++++----------------------- smart_ptr.htm | 159 ++++++++++++------------ 3 files changed, 361 insertions(+), 226 deletions(-) create mode 100644 make_shared.html diff --git a/make_shared.html b/make_shared.html new file mode 100644 index 0000000..e47fe2a --- /dev/null +++ b/make_shared.html @@ -0,0 +1,119 @@ + + + + make_shared and allocate_shared + + + +

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

    +

    Introduction
    + Synopsis
    + Free Functions
    + Example
    +

    Introduction

    +

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

    +

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

    +

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

    +

    Synopsis

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

    Free Functions

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

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

    +

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

    +

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

    +

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

    +

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

    +

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

    +

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

    +

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

    +
    +

    Example

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

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

    +

    Copyright 2008 Peter Dimov. Copyright 2008 Frank Mori Hess. + Distributed under the Boost Software License, + Version 1.0. See accompanying file LICENSE_1_0.txt + or copy at http://www.boost.org/LICENSE_1_0.txt.

    + + diff --git a/shared_ptr.htm b/shared_ptr.htm index 5b4444f..77e1fa8 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -19,54 +19,54 @@ Smart Pointer Timings
    Programming Techniques

    Introduction

    -

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

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

    -

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

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

    -

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

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

    -

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

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

    -

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

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

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

    -

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

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

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

    -

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

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

    Best Practices

    -

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

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

    shared_ptr<T> p(new Y);

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

    -

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

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

    -

    Avoid using unnamed shared_ptr temporaries to save typing; to +

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

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

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

    +

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

    Synopsis

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

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

    Throws: nothing.

    -

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

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

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

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

    Effects: Constructs a shared_ptr that owns the pointer p.

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

    -

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

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

    -

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

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

    -

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

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

    -

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

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

    -

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

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

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

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

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

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

    -

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

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

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

    -

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

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

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

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

    -

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

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

    -

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

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

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

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

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

    -

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

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

    Throws: nothing.

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

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

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

    -

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

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

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

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

    Postconditions: use_count() == 1.

    -

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

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

    -

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

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

    -

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

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

    destructor

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

    Effects:

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

    Throws: nothing.

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

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

    Returns: *this.

    -

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

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

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

    Returns: use_count() == 1.

    Throws: nothing.

    -

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

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

    use_count

    long use_count() const; // never throws
    -

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

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

    Throws: nothing.

    -

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

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

    conversions

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

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

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

    Throws: nothing.

    -

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

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

    -

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

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

    swap

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

    -

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

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

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

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

    swap

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

    Effects: Equivalent to a.swap(b).

    Throws: nothing.

    -

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

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

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

    get_pointer

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

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

    -

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

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

    Throws: nothing.

    Notes: the seemingly equivalent expression

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

    -

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

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

    const_pointer_cast

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

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

    -

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

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

    Throws: nothing.

    Notes: the seemingly equivalent expression

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

    -

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

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

    dynamic_pointer_cast

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

    Throws: nothing.

    Notes: the seemingly equivalent expression

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

    -

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

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

    operator<<

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

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

    Throws: nothing.

    Example

    -

    See shared_ptr_example.cpp for a +

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

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

    Handle/Body Idiom

    -

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

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

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

    Thread Safety

    -

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

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

    Any other simultaneous accesses result in undefined behavior.

    Examples:

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

     

    -

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

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

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

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

    If your program is single-threaded and does not link to any libraries that might have used shared_ptr in its default configuration, you can - #define the macro BOOST_SP_DISABLE_THREADS on a + #define the macro BOOST_SP_DISABLE_THREADS on a project-wide basis to switch to ordinary non-atomic reference count updates.

    -

    (Defining BOOST_SP_DISABLE_THREADS in some, but not all, - translation units is technically a violation of the One Definition Rule and - undefined behavior. Nevertheless, the implementation attempts to do its best to - accommodate the request to use non-atomic updates in those translation units. +

    (Defining BOOST_SP_DISABLE_THREADS in some, but not all, + translation units is technically a violation of the One Definition Rule and + undefined behavior. Nevertheless, the implementation attempts to do its best to + accommodate the request to use non-atomic updates in those translation units. No guarantees, though.)

    -

    You can define the macro BOOST_SP_USE_PTHREADS to turn off the - lock-free platform-specific implementation and fall back to the generic pthread_mutex_t-based +

    You can define the macro BOOST_SP_USE_PTHREADS to turn off the + lock-free platform-specific implementation and fall back to the generic pthread_mutex_t-based code.

    Frequently Asked Questions

    -

    Q. There are several variations of shared pointers, with different - tradeoffs; why does the smart pointer library supply only a single - implementation? It would be useful to be able to experiment with each type so +

    Q. There are several variations of shared pointers, with different + tradeoffs; why does the smart pointer library supply only a single + implementation? It would be useful to be able to experiment with each type so as to find the most suitable for the job at hand?

    - A. An important goal of shared_ptr is to provide a - standard shared-ownership pointer. Having a single pointer type is important - for stable library interfaces, since different shared pointers typically cannot - interoperate, i.e. a reference counted pointer (used by library A) cannot share + A. An important goal of shared_ptr is to provide a + standard shared-ownership pointer. Having a single pointer type is important + for stable library interfaces, since different shared pointers typically cannot + interoperate, i.e. a reference counted pointer (used by library A) cannot share ownership with a linked pointer (used by library B.)

    -

    Q. Why doesn't shared_ptr have template parameters supplying +

    Q. Why doesn't shared_ptr have template parameters supplying traits or policies to allow extensive user customization?

    - A. Parameterization discourages users. The shared_ptr template is - carefully crafted to meet common needs without extensive parameterization. Some - day a highly configurable smart pointer may be invented that is also very easy - to use and very hard to misuse. Until then, shared_ptr is the smart - pointer of choice for a wide range of applications. (Those interested in policy + A. Parameterization discourages users. The shared_ptr template is + carefully crafted to meet common needs without extensive parameterization. Some + day a highly configurable smart pointer may be invented that is also very easy + to use and very hard to misuse. Until then, shared_ptr is the smart + pointer of choice for a wide range of applications. (Those interested in policy based smart pointers should read Modern C++ Design by Andrei Alexandrescu.)

    -

    Q. I am not convinced. Default parameters can be used where appropriate +

    Q. I am not convinced. Default parameters can be used where appropriate to hide the complexity. Again, why not policies?

    - A. Template parameters affect the type. See the answer to the first + A. Template parameters affect the type. See the answer to the first question above.

    Q. Why doesn't shared_ptr use a linked list implementation?

    - A. A linked list implementation does not offer enough advantages to + A. A linked list implementation does not offer enough advantages to offset the added cost of an extra pointer. See timings - page. In addition, it is expensive to make a linked list implementation thread + page. In addition, it is expensive to make a linked list implementation thread safe.

    -

    Q. Why doesn't shared_ptr (or any of the other Boost smart +

    Q. Why doesn't shared_ptr (or any of the other Boost smart pointers) supply an automatic conversion to T*?

    A. Automatic conversion is believed to be too error prone.

    Q. Why does shared_ptr supply use_count()?

    - A. As an aid to writing test cases and debugging displays. One of the - progenitors had use_count(), and it was useful in tracking down bugs in a + A. As an aid to writing test cases and debugging displays. One of the + progenitors had use_count(), and it was useful in tracking down bugs in a complex project that turned out to have cyclic-dependencies.

    Q. Why doesn't shared_ptr specify complexity requirements?

    - A. Because complexity requirements limit implementors and complicate the - specification without apparent benefit to shared_ptr users. For example, - error-checking implementations might become non-conforming if they had to meet + A. Because complexity requirements limit implementors and complicate the + specification without apparent benefit to shared_ptr users. For example, + error-checking implementations might become non-conforming if they had to meet stringent complexity requirements.

    Q. Why doesn't shared_ptr provide a release() function?

    - A. shared_ptr cannot give away ownership unless it's unique() + A. shared_ptr cannot give away ownership unless it's unique() because the other copy will still destroy the object.

    Consider:

    shared_ptr<int> a(new int);
    @@ -692,25 +697,25 @@ int * p = a.release();
     
     // Who owns p now? b will still call delete on it in its destructor.
    -

    Furthermore, the pointer returned by release() would be difficult - to deallocate reliably, as the source shared_ptr could have been created +

    Furthermore, the pointer returned by release() would be difficult + to deallocate reliably, as the source shared_ptr could have been created with a custom deleter.

    -

    Q. Why is operator->() const, but its return value is a +

    Q. Why is operator->() const, but its return value is a non-const pointer to the element type?

    - A. Shallow copy pointers, including raw pointers, typically don't - propagate constness. It makes little sense for them to do so, as you can always - obtain a non-const pointer from a const one and then proceed to modify the - object through it.shared_ptr is "as close to raw pointers as possible + A. Shallow copy pointers, including raw pointers, typically don't + propagate constness. It makes little sense for them to do so, as you can always + obtain a non-const pointer from a const one and then proceed to modify the + object through it.shared_ptr is "as close to raw pointers as possible but no closer".


    $Date$

    -

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, +

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version 1.0. See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.

    diff --git a/smart_ptr.htm b/smart_ptr.htm index 497c63f..92ad2be 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -14,15 +14,15 @@ History and Acknowledgements
    References

    Introduction

    -

    Smart pointers are objects which store pointers to dynamically allocated (heap) - objects. They behave much like built-in C++ pointers except that they - automatically delete the object pointed to at the appropriate time. Smart - pointers are particularly useful in the face of exceptions as they ensure - proper destruction of dynamically allocated objects. They can also be used to +

    Smart pointers are objects which store pointers to dynamically allocated (heap) + objects. They behave much like built-in C++ pointers except that they + automatically delete the object pointed to at the appropriate time. Smart + pointers are particularly useful in the face of exceptions as they ensure + proper destruction of dynamically allocated objects. They can also be used to keep track of dynamically allocated objects shared by multiple owners.

    -

    Conceptually, smart pointers are seen as owning the object pointed to, and thus +

    Conceptually, smart pointers are seen as owning the object pointed to, and thus responsible for deletion of the object when it is no longer needed.

    -

    The smart pointer library provides five smart pointer class templates:

    +

    The smart pointer library provides six smart pointer class templates:

    - boost.png (6897 bytes) + boost.png (6897 bytes) +

    enable_shared_from_this.hpp

    @@ -38,7 +38,7 @@ - + @@ -58,126 +58,137 @@
    shared_ptr <boost/shared_ptr.hpp>Object ownership shared among multiple pointersObject ownership shared among multiple pointers.
    shared_array

    These templates are designed to complement the std::auto_ptr template.

    -

    They are examples of the "resource acquisition is initialization" idiom - described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition, +

    They are examples of the "resource acquisition is initialization" idiom + described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition, Section 14.4, Resource Management.

    -

    A test program, smart_ptr_test.cpp, is +

    Additionally, the smart pointer library provides efficient factory functions + for creating shared_ptr objects:

    +
    + + + + + + +
    make_shared and allocate_shared<boost/make_shared.hpp>Efficient creation of shared_ptr objects.
    +
    +

    A test program, smart_ptr_test.cpp, is provided to verify correct operation.

    -

    A page on compatibility with older versions of - the Boost smart pointer library describes some of the changes since earlier +

    A page on compatibility with older versions of + the Boost smart pointer library describes some of the changes since earlier versions of the smart pointer implementation.

    -

    A page on smart pointer timings will be of interest +

    A page on smart pointer timings will be of interest to those curious about performance issues.

    -

    A page on smart pointer programming techniques lists +

    A page on smart pointer programming techniques lists some advanced applications of shared_ptr and weak_ptr.

    Common Requirements

    -

    These smart pointer class templates have a template parameter, T, which - specifies the type of the object pointed to by the smart pointer. The behavior +

    These smart pointer class templates have a template parameter, T, which + specifies the type of the object pointed to by the smart pointer. The behavior of the smart pointer templates is undefined if the destructor or operator delete for objects of type T throw exceptions.

    -

    T may be an incomplete type at the point of smart pointer declaration. - Unless otherwise specified, it is required that T be a complete type at - points of smart pointer instantiation. Implementations are required to diagnose - (treat as an error) all violations of this requirement, including deletion of +

    T may be an incomplete type at the point of smart pointer declaration. + Unless otherwise specified, it is required that T be a complete type at + points of smart pointer instantiation. Implementations are required to diagnose + (treat as an error) all violations of this requirement, including deletion of an incomplete type. See the description of the checked_delete function template.

    -

    Note that shared_ptr does not have this restriction, as most of +

    Note that shared_ptr does not have this restriction, as most of its member functions do not require T to be a complete type.

    Rationale

    -

    The requirements on T are carefully crafted to maximize safety yet allow - handle-body (also called pimpl) and similar idioms. In these idioms a smart - pointer may appear in translation units where T is an incomplete type. - This separates interface from implementation and hides implementation from - translation units which merely use the interface. Examples described in the - documentation for specific smart pointers illustrate use of smart pointers in +

    The requirements on T are carefully crafted to maximize safety yet allow + handle-body (also called pimpl) and similar idioms. In these idioms a smart + pointer may appear in translation units where T is an incomplete type. + This separates interface from implementation and hides implementation from + translation units which merely use the interface. Examples described in the + documentation for specific smart pointers illustrate use of smart pointers in these idioms.

    -

    Note that scoped_ptr requires that T be a complete type at +

    Note that scoped_ptr requires that T be a complete type at destruction time, but shared_ptr does not.

    Exception Safety

    -

    Several functions in these smart pointer classes are specified as having "no - effect" or "no effect except such-and-such" if an exception is thrown. This - means that when an exception is thrown by an object of one of these classes, - the entire program state remains the same as it was prior to the function call - which resulted in the exception being thrown. This amounts to a guarantee that - there are no detectable side effects. Other functions never throw exceptions. - The only exception ever thrown by functions which do throw (assuming T meets - the common requirements) is std::bad_alloc, - and that is thrown only by functions which are explicitly documented as +

    Several functions in these smart pointer classes are specified as having "no + effect" or "no effect except such-and-such" if an exception is thrown. This + means that when an exception is thrown by an object of one of these classes, + the entire program state remains the same as it was prior to the function call + which resulted in the exception being thrown. This amounts to a guarantee that + there are no detectable side effects. Other functions never throw exceptions. + The only exception ever thrown by functions which do throw (assuming T meets + the common requirements) is std::bad_alloc, + and that is thrown only by functions which are explicitly documented as possibly throwing std::bad_alloc.

    Exception-specifications

    Exception-specifications are not used; see exception-specification rationale.

    -

    All the smart pointer templates contain member functions which can never throw - exceptions, because they neither throw exceptions themselves nor call other +

    All the smart pointer templates contain member functions which can never throw + exceptions, because they neither throw exceptions themselves nor call other functions which may throw exceptions. These members are indicated by a comment: // never throws.

    -

    Functions which destroy objects of the pointed to type are prohibited from +

    Functions which destroy objects of the pointed to type are prohibited from throwing exceptions by the common requirements.

    History and Acknowledgements

    -

    January 2002. Peter Dimov reworked all four classes, adding features, fixing - bugs, and splitting them into four separate headers, and added weak_ptr. - See the compatibility page for a summary of the +

    January 2002. Peter Dimov reworked all four classes, adding features, fixing + bugs, and splitting them into four separate headers, and added weak_ptr. + See the compatibility page for a summary of the changes.

    -

    May 2001. Vladimir Prus suggested requiring a complete type on destruction. - Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman - Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and +

    May 2001. Vladimir Prus suggested requiring a complete type on destruction. + Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman + Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and others.

    November 1999. Darin Adler provided operator ==, operator !=, and std::swap and std::less specializations for shared types.

    September 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap

    -

    May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a +

    May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a number of suggestions resulting in numerous improvements.

    -

    October 1998. Beman Dawes proposed reviving the original semantics under the - names safe_ptr and counted_ptr, meeting of Per Andersson, Matt - Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar Kühl, - Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new - class names were finalized, it was decided that there was no need to exactly - follow the std::auto_ptr interface, and various function signatures and +

    October 1998. Beman Dawes proposed reviving the original semantics under the + names safe_ptr and counted_ptr, meeting of Per Andersson, Matt + Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar Kühl, + Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new + class names were finalized, it was decided that there was no need to exactly + follow the std::auto_ptr interface, and various function signatures and semantics were finalized.

    -

    Over the next three months, several implementations were considered for shared_ptr, - and discussed on the boost.org mailing list. - The implementation questions revolved around the reference count which must be - kept, either attached to the pointed to object, or detached elsewhere. Each of +

    Over the next three months, several implementations were considered for shared_ptr, + and discussed on the boost.org mailing list. + The implementation questions revolved around the reference count which must be + kept, either attached to the pointed to object, or detached elsewhere. Each of those variants have themselves two major variants:

    • - Direct detached: the shared_ptr contains a pointer to the object, and a pointer + Direct detached: the shared_ptr contains a pointer to the object, and a pointer to the count.
    • - Indirect detached: the shared_ptr contains a pointer to a helper object, which + Indirect detached: the shared_ptr contains a pointer to a helper object, which in turn contains a pointer to the object and the count.
    • Embedded attached: the count is a member of the object pointed to.
    • Placement attached: the count is attached via operator new manipulations.
    -

    Each implementation technique has advantages and disadvantages. We went so far - as to run various timings of the direct and indirect approaches, and found that - at least on Intel Pentium chips there was very little measurable difference. - Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar - Kühl suggested an elegant partial template specialization technique to allow - users to choose which implementation they preferred, and that was also +

    Each implementation technique has advantages and disadvantages. We went so far + as to run various timings of the direct and indirect approaches, and found that + at least on Intel Pentium chips there was very little measurable difference. + Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar + Kühl suggested an elegant partial template specialization technique to allow + users to choose which implementation they preferred, and that was also experimented with.

    -

    But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage +

    But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage users", and in the end we choose to supply only the direct implementation.

    Summer, 1994. Greg Colvin proposed to the C++ Standards Committee classes named auto_ptr and counted_ptr which were very similar to what we now call scoped_ptr - and shared_ptr. [Col-94] In one of the very few - cases where the Library Working Group's recommendations were not followed by - the full committee, counted_ptr was rejected and surprising + and shared_ptr. [Col-94] In one of the very few + cases where the Library Working Group's recommendations were not followed by + the full committee, counted_ptr was rejected and surprising transfer-of-ownership semantics were added to auto_ptr.

    References

    [Col-94] Gregory Colvin, - Exception Safe Smart Pointers, C++ committee document 94-168/N0555, + Exception Safe Smart Pointers, C++ committee document 94-168/N0555, July, 1994.

    [E&D-94] John R. Ellis & David L. Detlefs, - Safe, Efficient Garbage Collection for C++, Usenix Proceedings, - February, 1994. This paper includes an extensive discussion of weak pointers + Safe, Efficient Garbage Collection for C++, Usenix Proceedings, + February, 1994. This paper includes an extensive discussion of weak pointers and an extensive bibliography.


    $Date$

    -

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. +

    Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Distributed under the Boost Software License, Version 1.0. See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.

    From 77971c6ff5f90fbe515f94ac0fa2c289477340de Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 18 Mar 2009 23:02:27 +0000 Subject: [PATCH 505/513] Merge [51686] to release. [SVN r51847] --- test/allocate_shared_test.cpp | 12 +++++++++--- test/make_shared_test.cpp | 12 +++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/test/allocate_shared_test.cpp b/test/allocate_shared_test.cpp index 97808c2..bdae793 100644 --- a/test/allocate_shared_test.cpp +++ b/test/allocate_shared_test.cpp @@ -1,6 +1,6 @@ -// allocate_shared_test.cpp +// allocate_shared_test.cpp // -// Copyright (c) 2007, 2008 Peter Dimov +// Copyright 2007-2009 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt or copy at @@ -19,11 +19,17 @@ private: X( X const & ); X & operator=( X const & ); - void * operator new( std::size_t ); + void * operator new( std::size_t n ) + { + // lack of this definition causes link errors on Comeau C++ + BOOST_ERROR( "private X::new called" ); + return ::operator new( n ); + } void operator delete( void * p ) { // lack of this definition causes link errors on MSVC + BOOST_ERROR( "private X::delete called" ); ::operator delete( p ); } diff --git a/test/make_shared_test.cpp b/test/make_shared_test.cpp index 474d1c5..9ebc3fa 100644 --- a/test/make_shared_test.cpp +++ b/test/make_shared_test.cpp @@ -1,6 +1,6 @@ -// make_shared_test.cpp +// make_shared_test.cpp // -// Copyright (c) 2007, 2008 Peter Dimov +// Copyright 2007-2009 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt or copy at @@ -19,11 +19,17 @@ private: X( X const & ); X & operator=( X const & ); - void * operator new( std::size_t ); + void * operator new( std::size_t n ) + { + // lack of this definition causes link errors on Comeau C++ + BOOST_ERROR( "private X::new called" ); + return ::operator new( n ); + } void operator delete( void * p ) { // lack of this definition causes link errors on MSVC + BOOST_ERROR( "private X::delete called" ); ::operator delete( p ); } From a1b4fc8d95eebb62a20eb3b2436fafd5190ef576 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 27 Mar 2009 13:10:46 +0000 Subject: [PATCH 506/513] Merge [51978], [51985] to release. Closes #2885. [SVN r52016] --- .../smart_ptr/detail/sp_counted_base.hpp | 3 + .../detail/sp_counted_base_gcc_mips.hpp | 172 ++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp index df8be5b..cab45cc 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp @@ -47,6 +47,9 @@ #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) # include +#elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) ) +# include + #elif defined( BOOST_SP_HAS_SYNC ) # include diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp new file mode 100644 index 0000000..0c69b0b --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp @@ -0,0 +1,172 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_gcc_mips.hpp - g++ on MIPS +// +// Copyright (c) 2009, Spirent Communications, Inc. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// +// Lock-free algorithm by Alexander Terekhov +// + +#include + +namespace boost +{ + +namespace detail +{ + +inline void atomic_increment( int * pw ) +{ + // ++*pw; + + int tmp; + + __asm__ __volatile__ + ( + "0:\n\t" + "ll %0, %1\n\t" + "addiu %0, 1\n\t" + "sc %0, %1\n\t" + "beqz %0, 0b": + "=&r"( tmp ), "=m"( *pw ): + "m"( *pw ) + ); +} + +inline int atomic_decrement( int * pw ) +{ + // return --*pw; + + int rv, tmp; + + __asm__ __volatile__ + ( + "0:\n\t" + "ll %1, %2\n\t" + "addiu %0, %1, -1\n\t" + "sc %0, %2\n\t" + "beqz %0, 0b\n\t" + "addiu %0, %1, -1": + "=&r"( rv ), "=&r"( tmp ), "=m"( *pw ): + "m"( *pw ): + "memory" + ); + + return rv; +} + +inline int atomic_conditional_increment( int * pw ) +{ + // if( *pw != 0 ) ++*pw; + // return *pw; + + int rv, tmp; + + __asm__ __volatile__ + ( + "0:\n\t" + "ll %0, %2\n\t" + "beqz %0, 1f\n\t" + "addiu %1, %0, 1\n\t" + "sc %1, %2\n\t" + "beqz %1, 0b\n\t" + "addiu %0, %0, 1\n\t" + "1:": + "=&r"( rv ), "=&r"( tmp ), "=m"( *pw ): + "m"( *pw ): + "memory" + ); + + return rv; +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED From 28de0cb1e3981756a8383b8352ec34c8ea1714ea Mon Sep 17 00:00:00 2001 From: David Deakins Date: Mon, 6 Apr 2009 21:25:18 +0000 Subject: [PATCH 507/513] Have config/select_stdlib_config.hpp and config/stdlib/stlport.hpp use instead of to determine which standard library is in use. For std lib implementations that rely on Boost components like TypeTraits, Bind, Function, or SmartPtr, this helps to avoid circular header dependency issues, since is much less likely to pull in Boost libraries than . In get_pointer.hpp, switched to using instead of using directly. As above, this helps avoid circular header dependency issues in Boost-supplemented std libs (specifically it avoids issues when pulls in pieces of Boost.SmartPtr). These two changes were made in response to testing done with STLport 5.2.1 using the _STLP_USE_BOOST_SUPPORT option. [SVN r52221] --- include/boost/get_pointer.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/boost/get_pointer.hpp b/include/boost/get_pointer.hpp index 17d11b8..a0cd5c0 100644 --- a/include/boost/get_pointer.hpp +++ b/include/boost/get_pointer.hpp @@ -5,7 +5,11 @@ #ifndef GET_POINTER_DWA20021219_HPP # define GET_POINTER_DWA20021219_HPP -# include +// In order to avoid circular dependencies with Boost.TR1 +// we make sure that our include of doesn't try to +// pull in the TR1 headers: that's why we use this header +// rather than including directly: +# include // std::auto_ptr namespace boost { From a4293f9dfaf78dabe08c5c6554a299c110bda240 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Apr 2009 21:32:43 +0000 Subject: [PATCH 508/513] Merge [52454] to release. Fixes #2951. [SVN r52472] --- include/boost/smart_ptr/shared_ptr.hpp | 2 +- test/Jamfile.v2 | 1 + test/auto_ptr_lv_fail.cpp | 32 ++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 test/auto_ptr_lv_fail.cpp diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 0ce3b97..7f46c35 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -277,7 +277,7 @@ public: #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) template - shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() + explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() { typename Ap::element_type * tmp = r.get(); pn = boost::detail::shared_count( r ); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c862197..0c760b2 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -56,5 +56,6 @@ import testing ; [ run sp_recursive_assign2_test.cpp ] [ run sp_recursive_assign_rv_test.cpp ] [ run sp_recursive_assign2_rv_test.cpp ] + [ compile-fail auto_ptr_lv_fail.cpp ] ; } diff --git a/test/auto_ptr_lv_fail.cpp b/test/auto_ptr_lv_fail.cpp new file mode 100644 index 0000000..b86832e --- /dev/null +++ b/test/auto_ptr_lv_fail.cpp @@ -0,0 +1,32 @@ +#include + +#if defined(BOOST_MSVC) +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#endif + +// +// auto_ptr_lv_fail.cpp - a negative test for converting an auto_ptr to shared_ptr +// +// Copyright 2009 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include +#include + +void f( boost::shared_ptr ) +{ +} + +int main() +{ + std::auto_ptr p; + f( p ); // must fail + return 0; +} From 9f30442d1e696ec26ed1c46faebb35ec6f19731f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20M=20L=C3=B3pez=20Mu=C3=B1oz?= Date: Sun, 19 Apr 2009 10:17:50 +0000 Subject: [PATCH 509/513] merged [52456], [52457] and [52464] from trunk [SVN r52486] --- .../boost/smart_ptr/detail/atomic_count.hpp | 5 +- .../smart_ptr/detail/atomic_count_gcc.hpp | 10 ++-- .../smart_ptr/detail/atomic_count_gcc_x86.hpp | 11 +--- .../detail/atomic_count_pthreads.hpp | 4 +- .../smart_ptr/detail/atomic_count_sync.hpp | 4 +- test/Jamfile.v2 | 1 + test/atomic_count_test2.cpp | 55 +++++++++++++++++++ 7 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 test/atomic_count_test2.cpp diff --git a/include/boost/smart_ptr/detail/atomic_count.hpp b/include/boost/smart_ptr/detail/atomic_count.hpp index a6ddea3..cc44ac2 100644 --- a/include/boost/smart_ptr/detail/atomic_count.hpp +++ b/include/boost/smart_ptr/detail/atomic_count.hpp @@ -31,13 +31,12 @@ // ++a; // // Effects: Atomically increments the value of a -// Returns: nothing +// Returns: (long) the new value of a // // --a; // // Effects: Atomically decrements the value of a -// Returns: (long) zero if the new value of a is zero, -// unspecified non-zero value otherwise (usually the new value) +// Returns: (long) the new value of a // // Important note: when --a returns zero, it must act as a // read memory barrier (RMB); i.e. the calling thread must diff --git a/include/boost/smart_ptr/detail/atomic_count_gcc.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp index 1305632..54807e9 100644 --- a/include/boost/smart_ptr/detail/atomic_count_gcc.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp @@ -40,21 +40,21 @@ class atomic_count { public: - explicit atomic_count(long v) : value_(v) {} + explicit atomic_count( long v ) : value_( v ) {} - void operator++() + long operator++() { - __atomic_add(&value_, 1); + return __exchange_and_add( &value_, +1 ) + 1; } long operator--() { - return __exchange_and_add(&value_, -1) - 1; + return __exchange_and_add( &value_, -1 ) - 1; } operator long() const { - return __exchange_and_add(&value_, 0); + return __exchange_and_add( &value_, 0 ); } private: diff --git a/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp index 4fd1c57..5c44d7c 100644 --- a/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp @@ -25,16 +25,9 @@ public: explicit atomic_count( long v ) : value_( static_cast< int >( v ) ) {} - void operator++() + long operator++() { - __asm__ - ( - "lock\n\t" - "incl %0": - "+m"( value_ ): // output (%0) - : // inputs - "cc" // clobbers - ); + return atomic_exchange_and_add( &value_, +1 ) + 1; } long operator--() diff --git a/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp b/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp index d8118f0..05f7867 100644 --- a/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp @@ -62,10 +62,10 @@ public: pthread_mutex_destroy(&mutex_); } - void operator++() + long operator++() { scoped_lock lock(mutex_); - ++value_; + return ++value_; } long operator--() diff --git a/include/boost/smart_ptr/detail/atomic_count_sync.hpp b/include/boost/smart_ptr/detail/atomic_count_sync.hpp index f2d22fb..b6359b5 100644 --- a/include/boost/smart_ptr/detail/atomic_count_sync.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_sync.hpp @@ -31,9 +31,9 @@ public: explicit atomic_count( long v ) : value_( v ) {} - void operator++() + long operator++() { - __sync_add_and_fetch( &value_, 1 ); + return __sync_add_and_fetch( &value_, 1 ); } long operator--() diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0c760b2..5c05f42 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -57,5 +57,6 @@ import testing ; [ run sp_recursive_assign_rv_test.cpp ] [ run sp_recursive_assign2_rv_test.cpp ] [ compile-fail auto_ptr_lv_fail.cpp ] + [ run atomic_count_test2.cpp ] ; } diff --git a/test/atomic_count_test2.cpp b/test/atomic_count_test2.cpp new file mode 100644 index 0000000..7e6dd97 --- /dev/null +++ b/test/atomic_count_test2.cpp @@ -0,0 +1,55 @@ +// +// atomic_count_test2.cpp +// +// Copyright 2009 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include +#include + +int main() +{ + boost::detail::atomic_count n( 4 ); + + BOOST_TEST( n == 4 ); + + BOOST_TEST( ++n == 5 ); + BOOST_TEST( ++n == 6 ); + + BOOST_TEST( n == 6 ); + + BOOST_TEST( --n == 5 ); + BOOST_TEST( --n == 4 ); + + BOOST_TEST( n == 4 ); + + boost::detail::atomic_count m( 0 ); + + BOOST_TEST( m == 0 ); + + BOOST_TEST( ++m == 1 ); + BOOST_TEST( ++m == 2 ); + + BOOST_TEST( m == 2 ); + + BOOST_TEST( --m == 1 ); + BOOST_TEST( --m == 0 ); + + BOOST_TEST( m == 0 ); + + BOOST_TEST( --m == -1 ); + BOOST_TEST( --m == -2 ); + + BOOST_TEST( m == -2 ); + + BOOST_TEST( ++m == -1 ); + BOOST_TEST( ++m == 0 ); + + BOOST_TEST( m == 0 ); + + return boost::report_errors(); +} From 5fa1cbf6e1da8b533cb2be37fb0a180b146057eb Mon Sep 17 00:00:00 2001 From: "Troy D. Straszheim" Date: Thu, 14 May 2009 20:20:34 +0000 Subject: [PATCH 510/513] shared_ptr and bind cmake tweaks [SVN r53001] --- test/CMakeLists.txt | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7ddae31..b3f1c3f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -12,7 +12,39 @@ boost_test_run(atomic_count_test) boost_test_run(lw_mutex_test) boost_test_compile_fail(shared_ptr_assign_fail) boost_test_compile_fail(shared_ptr_delete_fail) +boost_test_compile_fail(shared_ptr_compare_fail) boost_test_run(shared_ptr_alloc2_test) boost_test_run(pointer_cast_test) boost_test_compile(pointer_to_other_test) boost_test_run(auto_ptr_rv_test) +boost_test_run(shared_ptr_alias_test) +boost_test_run(shared_ptr_rv_test) +boost_test_run(shared_ptr_move_test) +boost_test_compile_fail(shared_ptr_pv_fail) +boost_test_run(sp_unary_addr_test) +boost_test_compile_fail(scoped_ptr_eq_fail) +boost_test_compile_fail(scoped_array_eq_fail) +boost_test_run(esft_regtest) +boost_test_run(yield_k_test) +message(STATUS "!!!> yield_k_test multhreaded") +boost_test_run(spinlock_test) +boost_test_run(spinlock_try_test) +message(STATUS "!!!> spinlock_try_test multithreaded") +boost_test_run(spinlock_pool_test) +boost_test_run(make_shared_test) +boost_test_run(sp_convertible_test) +boost_test_run(wp_convertible_test) +boost_test_run(ip_convertible_test) +boost_test_run(allocate_shared_test) +boost_test_run(sp_atomic_test) +boost_test_run(esft_void_test) +boost_test_run(esft_second_ptr_test) +boost_test_run(make_shared_esft_test) +boost_test_run(allocate_shared_esft_test) +boost_test_run(sp_recursive_assign_test) +boost_test_run(sp_recursive_assign2_test) +boost_test_run(sp_recursive_assign_rv_test) +boost_test_run(sp_recursive_assign2_rv_test) +boost_test_compile_fail(auto_ptr_lv_fail) +boost_test_run(atomic_count_test2) + From 8a421c2098ef23ef0304ea08663bfe15e8573a60 Mon Sep 17 00:00:00 2001 From: "Troy D. Straszheim" Date: Wed, 22 Jul 2009 21:51:01 +0000 Subject: [PATCH 511/513] Add basic copyright/license to keep cmake out of the inspection report [SVN r55095] --- CMakeLists.txt | 6 ++++++ test/CMakeLists.txt | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index abe2fc7..1c039fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,9 @@ +# +# Copyright Troy D. Straszheim +# +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt +# #---------------------------------------------------------------------------- # This file was automatically generated from the original CMakeLists.txt file # Add a variable to hold the headers for the library diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b3f1c3f..b89394e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,3 +1,9 @@ +# +# Copyright Troy D. Straszheim +# +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt +# boost_additional_test_dependencies(tokenizer BOOST_DEPENDS test intrusive) From 63b17c24eabb2f180ab0ea5ee03979ce2c9d930f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 8 Aug 2009 23:21:15 +0000 Subject: [PATCH 512/513] Merge [51909], [51912], [52937], [53672] to release. [SVN r55479] --- .../boost/smart_ptr/detail/shared_count.hpp | 14 ++ .../boost/smart_ptr/detail/sp_convertible.hpp | 2 +- .../smart_ptr/enable_shared_from_this2.hpp | 132 +++++++++++++ include/boost/smart_ptr/intrusive_ptr.hpp | 17 ++ include/boost/smart_ptr/shared_ptr.hpp | 13 +- include/boost/smart_ptr/weak_ptr.hpp | 52 ++++- test/Jamfile.v2 | 3 + test/esft_constructor_test.cpp | 169 ++++++++++++++++ test/intrusive_ptr_move_test.cpp | 184 ++++++++++++++++++ test/shared_ptr_move_test.cpp | 16 +- test/weak_ptr_move_test.cpp | 121 ++++++++++++ 11 files changed, 710 insertions(+), 13 deletions(-) create mode 100644 include/boost/smart_ptr/enable_shared_from_this2.hpp create mode 100644 test/esft_constructor_test.cpp create mode 100644 test/intrusive_ptr_move_test.cpp create mode 100644 test/weak_ptr_move_test.cpp diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp index b968bba..4943e37 100644 --- a/include/boost/smart_ptr/detail/shared_count.hpp +++ b/include/boost/smart_ptr/detail/shared_count.hpp @@ -333,6 +333,20 @@ public: if(pi_ != 0) pi_->weak_add_ref(); } +// Move support + +#if defined( BOOST_HAS_RVALUE_REFS ) + + weak_count(weak_count && r): pi_(r.pi_) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(weak_count_id) +#endif + { + r.pi_ = 0; + } + +#endif + ~weak_count() // nothrow { if(pi_ != 0) pi_->weak_release(); diff --git a/include/boost/smart_ptr/detail/sp_convertible.hpp b/include/boost/smart_ptr/detail/sp_convertible.hpp index 7d9502d..66e5ec7 100644 --- a/include/boost/smart_ptr/detail/sp_convertible.hpp +++ b/include/boost/smart_ptr/detail/sp_convertible.hpp @@ -45,7 +45,7 @@ template< class Y, class T > struct sp_convertible static yes f( T* ); static no f( ... ); - enum _vt { value = sizeof( f( (Y*)0 ) ) == sizeof(yes) }; + enum _vt { value = sizeof( f( static_cast(0) ) ) == sizeof(yes) }; }; struct sp_empty diff --git a/include/boost/smart_ptr/enable_shared_from_this2.hpp b/include/boost/smart_ptr/enable_shared_from_this2.hpp new file mode 100644 index 0000000..a5bfcff --- /dev/null +++ b/include/boost/smart_ptr/enable_shared_from_this2.hpp @@ -0,0 +1,132 @@ +#ifndef BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED +#define BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED + +// +// enable_shared_from_this2.hpp +// +// Copyright 2002, 2009 Peter Dimov +// Copyright 2008 Frank Mori Hess +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include +#include +#include +#include + +namespace boost +{ + +namespace detail +{ + +class esft2_deleter_wrapper +{ +private: + + shared_ptr deleter_; + +public: + + esft2_deleter_wrapper() + { + } + + template< class T > void set_deleter( shared_ptr const & deleter ) + { + deleter_ = deleter; + } + + template< class T> void operator()( T* ) + { + BOOST_ASSERT( deleter_.use_count() <= 1 ); + deleter_.reset(); + } +}; + +} // namespace detail + +template< class T > class enable_shared_from_this2 +{ +protected: + + enable_shared_from_this2() + { + } + + enable_shared_from_this2( enable_shared_from_this2 const & ) + { + } + + enable_shared_from_this2 & operator=( enable_shared_from_this2 const & ) + { + return *this; + } + + ~enable_shared_from_this2() + { + BOOST_ASSERT( shared_this_.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist + } + +private: + + mutable weak_ptr weak_this_; + mutable shared_ptr shared_this_; + +public: + + shared_ptr shared_from_this() + { + init_weak_once(); + return shared_ptr( weak_this_ ); + } + + shared_ptr shared_from_this() const + { + init_weak_once(); + return shared_ptr( weak_this_ ); + } + +private: + + void init_weak_once() const + { + if( weak_this_._empty() ) + { + shared_this_.reset( static_cast< T* >( 0 ), detail::esft2_deleter_wrapper() ); + weak_this_ = shared_this_; + } + } + +public: // actually private, but avoids compiler template friendship issues + + // Note: invoked automatically by shared_ptr; do not call + template void _internal_accept_owner( shared_ptr * ppx, Y * py ) const + { + BOOST_ASSERT( ppx != 0 ); + + if( weak_this_.use_count() == 0 ) + { + weak_this_ = shared_ptr( *ppx, py ); + } + else if( shared_this_.use_count() != 0 ) + { + BOOST_ASSERT( ppx->unique() ); // no weak_ptrs should exist either, but there's no way to check that + + detail::esft2_deleter_wrapper * pd = boost::get_deleter( shared_this_ ); + BOOST_ASSERT( pd != 0 ); + + pd->set_deleter( *ppx ); + + ppx->reset( shared_this_, ppx->get() ); + shared_this_.reset(); + } + } +}; + +} // namespace boost + +#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp index d3bd02b..6927a59 100644 --- a/include/boost/smart_ptr/intrusive_ptr.hpp +++ b/include/boost/smart_ptr/intrusive_ptr.hpp @@ -109,6 +109,23 @@ public: return *this; } +#endif + +// Move support + +#if defined( BOOST_HAS_RVALUE_REFS ) + + intrusive_ptr(intrusive_ptr && rhs): px( rhs.px ) + { + rhs.px = 0; + } + + intrusive_ptr & operator=(intrusive_ptr && rhs) + { + this_type(std::move(rhs)).swap(*this); + return *this; + } + #endif intrusive_ptr & operator=(intrusive_ptr const & rhs) diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 7f46c35..1b367f0 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -61,6 +61,7 @@ namespace boost template class shared_ptr; template class weak_ptr; template class enable_shared_from_this; +template class enable_shared_from_this2; namespace detail { @@ -109,6 +110,14 @@ template< class X, class Y, class T > inline void sp_enable_shared_from_this( bo } } +template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr * ppx, Y const * py, boost::enable_shared_from_this2< T > const * pe ) +{ + if( pe != 0 ) + { + pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) ); + } +} + #ifdef _MANAGED // Avoid C4793, ... causes native code generation @@ -359,14 +368,14 @@ public: shared_ptr & operator=( shared_ptr && r ) // never throws { - this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); + this_type( std::move( r ) ).swap( *this ); return *this; } template shared_ptr & operator=( shared_ptr && r ) // never throws { - this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); + this_type( std::move( r ) ).swap( *this ); return *this; } diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp index bf5296a..621c433 100644 --- a/include/boost/smart_ptr/weak_ptr.hpp +++ b/include/boost/smart_ptr/weak_ptr.hpp @@ -70,11 +70,43 @@ public: weak_ptr( weak_ptr const & r ) #endif - : pn(r.pn) // never throws + : px(r.lock().get()), pn(r.pn) // never throws { - px = r.lock().get(); } +#if defined( BOOST_HAS_RVALUE_REFS ) + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + weak_ptr( weak_ptr && r, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + weak_ptr( weak_ptr && r ) + +#endif + : px(r.lock().get()), pn(std::move(r.pn)) // never throws + { + r.px = 0; + } + + // for better efficiency in the T == Y case + weak_ptr( weak_ptr && r ): px( r.px ), pn(std::move(r.pn)) // never throws + { + r.px = 0; + } + + // for better efficiency in the T == Y case + weak_ptr & operator=( weak_ptr && r ) // never throws + { + this_type( std::move( r ) ).swap( *this ); + return *this; + } + + +#endif + template #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) @@ -99,6 +131,17 @@ public: return *this; } +#if defined( BOOST_HAS_RVALUE_REFS ) + + template + weak_ptr & operator=(weak_ptr && r) + { + this_type( std::move( r ) ).swap( *this ); + return *this; + } + +#endif + template weak_ptr & operator=(shared_ptr const & r) // never throws { @@ -124,6 +167,11 @@ public: return pn.use_count() == 0; } + bool _empty() const // extension, not in std::weak_ptr + { + return pn.empty(); + } + void reset() // never throws in 1.30+ { this_type().swap(*this); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5c05f42..db4bfb1 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -16,9 +16,11 @@ import testing ; [ run shared_ptr_basic_test.cpp : : : gcc:-Wno-non-virtual-dtor ] [ run shared_ptr_test.cpp : : : gcc:-Wno-non-virtual-dtor ] [ run weak_ptr_test.cpp ] + [ run weak_ptr_move_test.cpp ] [ run shared_from_this_test.cpp : : : gcc:-Wno-non-virtual-dtor ] [ run get_deleter_test.cpp ] [ run intrusive_ptr_test.cpp ] + [ run intrusive_ptr_move_test.cpp ] [ run atomic_count_test.cpp ] [ run lw_mutex_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] @@ -56,6 +58,7 @@ import testing ; [ run sp_recursive_assign2_test.cpp ] [ run sp_recursive_assign_rv_test.cpp ] [ run sp_recursive_assign2_rv_test.cpp ] + [ run esft_constructor_test.cpp ] [ compile-fail auto_ptr_lv_fail.cpp ] [ run atomic_count_test2.cpp ] ; diff --git a/test/esft_constructor_test.cpp b/test/esft_constructor_test.cpp new file mode 100644 index 0000000..ced24e2 --- /dev/null +++ b/test/esft_constructor_test.cpp @@ -0,0 +1,169 @@ +// +// esft_constructor_test.cpp +// +// A test for the new enable_shared_from_this support for calling +// shared_from_this from constructors (that is, prior to the +// object's ownership being passed to an external shared_ptr). +// +// Copyright (c) 2008 Frank Mori Hess +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include +#include +#include + +class X: public boost::enable_shared_from_this2< X > +{ +private: + + int destroyed_; + int deleted_; + int expected_; + +private: + + X( X const& ); + X& operator=( X const& ); + +public: + + static int instances; + +public: + + explicit X( int expected, boost::shared_ptr *early_px = 0 ): destroyed_( 0 ), deleted_( 0 ), expected_( expected ) + { + ++instances; + if( early_px ) *early_px = shared_from_this(); + } + + ~X() + { + BOOST_TEST( deleted_ == expected_ ); + BOOST_TEST( destroyed_ == 0 ); + ++destroyed_; + --instances; + } + + typedef void (*deleter_type)( X* ); + + static void deleter( X * px ) + { + ++px->deleted_; + } + + static void deleter2( X * px ) + { + ++px->deleted_; + delete px; + } +}; + +int X::instances = 0; + +template +bool are_shared_owners(const boost::shared_ptr &a, const boost::shared_ptr &b) +{ + return !(a < b) && !(b < a); +} + +struct Y: public boost::enable_shared_from_this2 +{}; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr early_px; + X* x = new X( 1, &early_px ); + BOOST_TEST( early_px.use_count() > 0 ); + BOOST_TEST( boost::get_deleter(early_px) == 0 ); + boost::shared_ptr px( x, &X::deleter2 ); + BOOST_TEST( early_px.use_count() == 2 && px.use_count() == 2 ); + BOOST_TEST(are_shared_owners(early_px, px)); + px.reset(); + BOOST_TEST( early_px.use_count() == 1 ); + BOOST_TEST( X::instances == 1 ); + // X::deleter_type *pd = boost::get_deleter(early_px); + // BOOST_TEST(pd && *pd == &X::deleter2 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr early_px; + X* x = new X( 1, &early_px ); + boost::weak_ptr early_weak_px = early_px; + early_px.reset(); + BOOST_TEST( !early_weak_px.expired() ); + boost::shared_ptr px( x, &X::deleter2 ); + BOOST_TEST( px.use_count() == 1 ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST(are_shared_owners(early_weak_px.lock(), px)); + px.reset(); + BOOST_TEST( early_weak_px.expired() ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr early_px; + X x( 1, &early_px ); + BOOST_TEST( early_px.use_count() > 0 ); + boost::shared_ptr px( &x, &X::deleter ); + BOOST_TEST( early_px.use_count() == 2 && px.use_count() == 2 ); + early_px.reset(); + BOOST_TEST( px.use_count() == 1 ); + BOOST_TEST( X::instances == 1 ); + px.reset(); + try + { + x.shared_from_this(); + BOOST_ERROR("x did not throw bad_weak_ptr"); + } + catch( const boost::bad_weak_ptr & ) + {} + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::weak_ptr early_weak_px; + { + boost::shared_ptr early_px; + X x( 0, &early_px ); + early_weak_px = early_px; + early_px.reset(); + BOOST_TEST( !early_weak_px.expired() ); + BOOST_TEST( X::instances == 1 ); + } + BOOST_TEST( early_weak_px.expired() ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr px(new Y()); + Y y(*px); + px.reset(); + try + { + y.shared_from_this(); + } + catch( const boost::bad_weak_ptr & ) + { + BOOST_ERROR("y threw bad_weak_ptr"); + } + } + + return boost::report_errors(); +} diff --git a/test/intrusive_ptr_move_test.cpp b/test/intrusive_ptr_move_test.cpp new file mode 100644 index 0000000..b5f0e65 --- /dev/null +++ b/test/intrusive_ptr_move_test.cpp @@ -0,0 +1,184 @@ +#include + +#if defined(BOOST_MSVC) + +#pragma warning(disable: 4786) // identifier truncated in debug info +#pragma warning(disable: 4710) // function not inlined +#pragma warning(disable: 4711) // function selected for automatic inline expansion +#pragma warning(disable: 4514) // unreferenced inline removed +#pragma warning(disable: 4355) // 'this' : used in base member initializer list +#pragma warning(disable: 4511) // copy constructor could not be generated +#pragma warning(disable: 4512) // assignment operator could not be generated + +#if (BOOST_MSVC >= 1310) +#pragma warning(disable: 4675) // resolved overload found with Koenig lookup +#endif + +#endif + +// +// intrusive_ptr_move_test.cpp +// +// Copyright (c) 2002-2005 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include +#include +#include +#include + +#if defined( BOOST_HAS_RVALUE_REFS ) + +namespace N +{ + +class base +{ +private: + + boost::detail::atomic_count use_count_; + + base(base const &); + base & operator=(base const &); + +protected: + + base(): use_count_(0) + { + ++instances; + } + + virtual ~base() + { + --instances; + } + +public: + + static long instances; + + long use_count() const + { + return use_count_; + } + +#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + + inline friend void intrusive_ptr_add_ref(base * p) + { + ++p->use_count_; + } + + inline friend void intrusive_ptr_release(base * p) + { + if(--p->use_count_ == 0) delete p; + } + +#else + + void add_ref() + { + ++use_count_; + } + + void release() + { + if(--use_count_ == 0) delete this; + } + +#endif +}; + +long base::instances = 0; + +} // namespace N + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + +namespace boost +{ + +inline void intrusive_ptr_add_ref(N::base * p) +{ + p->add_ref(); +} + +inline void intrusive_ptr_release(N::base * p) +{ + p->release(); +} + +} // namespace boost + +#endif + +// + +struct X: public virtual N::base +{ +}; + +struct Y: public X +{ +}; + +int main() +{ + BOOST_TEST( N::base::instances == 0 ); + + { + boost::intrusive_ptr p( new X ); + BOOST_TEST( N::base::instances == 1 ); + + boost::intrusive_ptr p2( std::move( p ) ); + BOOST_TEST( N::base::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + p2.reset(); + BOOST_TEST( N::base::instances == 0 ); + } + + { + boost::intrusive_ptr p( new X ); + BOOST_TEST( N::base::instances == 1 ); + + boost::intrusive_ptr p2; + p2 = std::move( p ); + BOOST_TEST( N::base::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + p2.reset(); + BOOST_TEST( N::base::instances == 0 ); + } + + { + boost::intrusive_ptr p( new X ); + BOOST_TEST( N::base::instances == 1 ); + + boost::intrusive_ptr p2( new X ); + BOOST_TEST( N::base::instances == 2 ); + p2 = std::move( p ); + BOOST_TEST( N::base::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + + p2.reset(); + BOOST_TEST( N::base::instances == 0 ); + } + + return boost::report_errors(); +} + +#else // !defined( BOOST_HAS_RVALUE_REFS ) + +int main() +{ + return 0; +} + +#endif diff --git a/test/shared_ptr_move_test.cpp b/test/shared_ptr_move_test.cpp index bd785e4..c02ffa9 100644 --- a/test/shared_ptr_move_test.cpp +++ b/test/shared_ptr_move_test.cpp @@ -8,11 +8,11 @@ // http://www.boost.org/LICENSE_1_0.txt // -#if defined( BOOST_HAS_RVALUE_REFS ) - #include #include +#if defined( BOOST_HAS_RVALUE_REFS ) + struct X { static long instances; @@ -43,11 +43,11 @@ int main() boost::shared_ptr p( new X ); BOOST_TEST( X::instances == 1 ); - boost::shared_ptr p2( static_cast< boost::shared_ptr && >( p ) ); + boost::shared_ptr p2( std::move( p ) ); BOOST_TEST( X::instances == 1 ); BOOST_TEST( p.get() == 0 ); - boost::shared_ptr p3( static_cast< boost::shared_ptr && >( p2 ) ); + boost::shared_ptr p3( std::move( p2 ) ); BOOST_TEST( X::instances == 1 ); BOOST_TEST( p2.get() == 0 ); @@ -60,12 +60,12 @@ int main() BOOST_TEST( X::instances == 1 ); boost::shared_ptr p2; - p2 = static_cast< boost::shared_ptr && >( p ); + p2 = std::move( p ); BOOST_TEST( X::instances == 1 ); BOOST_TEST( p.get() == 0 ); boost::shared_ptr p3; - p3 = static_cast< boost::shared_ptr && >( p2 ); + p3 = std::move( p2 ); BOOST_TEST( X::instances == 1 ); BOOST_TEST( p2.get() == 0 ); @@ -79,13 +79,13 @@ int main() boost::shared_ptr p2( new X ); BOOST_TEST( X::instances == 2 ); - p2 = static_cast< boost::shared_ptr && >( p ); + p2 = std::move( p ); BOOST_TEST( X::instances == 1 ); BOOST_TEST( p.get() == 0 ); boost::shared_ptr p3( new X ); BOOST_TEST( X::instances == 2 ); - p3 = static_cast< boost::shared_ptr && >( p2 ); + p3 = std::move( p2 ); BOOST_TEST( X::instances == 1 ); BOOST_TEST( p2.get() == 0 ); diff --git a/test/weak_ptr_move_test.cpp b/test/weak_ptr_move_test.cpp new file mode 100644 index 0000000..572b13d --- /dev/null +++ b/test/weak_ptr_move_test.cpp @@ -0,0 +1,121 @@ +// +// weak_ptr_move_test.cpp +// +// Copyright (c) 2007 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include +#include + +#if defined( BOOST_HAS_RVALUE_REFS ) + +struct X +{ + static long instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const & ); + X & operator=( X const & ); +}; + +long X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr p_( new X ); + boost::weak_ptr p( p_ ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.use_count() == 1 ); + + boost::weak_ptr p2( std::move( p ) ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p2.use_count() == 1 ); + BOOST_TEST( p.expired() ); + + boost::weak_ptr p3( std::move( p2 ) ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p3.use_count() == 1 ); + BOOST_TEST( p2.expired() ); + + p_.reset(); + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( p3.expired() ); + } + + { + boost::shared_ptr p_( new X ); + boost::weak_ptr p( p_ ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.use_count() == 1 ); + + boost::weak_ptr p2; + p2 = static_cast< boost::weak_ptr && >( p ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p2.use_count() == 1 ); + BOOST_TEST( p.expired() ); + + boost::weak_ptr p3; + p3 = std::move( p2 ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p3.use_count() == 1 ); + BOOST_TEST( p2.expired() ); + + p_.reset(); + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( p3.expired() ); + } + + { + boost::shared_ptr p_( new X ); + boost::weak_ptr p( p_ ); + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( p.use_count() == 1 ); + + boost::shared_ptr p_2( new X ); + boost::weak_ptr p2( p_2 ); + BOOST_TEST( X::instances == 2 ); + p2 = std::move( p ); + BOOST_TEST( X::instances == 2 ); + BOOST_TEST( p2.use_count() == 1 ); + BOOST_TEST( p.expired() ); + BOOST_TEST( p2.lock() != p_2 ); + + boost::shared_ptr p_3( new X ); + boost::weak_ptr p3( p_3 ); + BOOST_TEST( X::instances == 3 ); + p3 = std::move( p2 ); + BOOST_TEST( X::instances == 3 ); + BOOST_TEST( p3.use_count() == 1 ); + BOOST_TEST( p2.expired() ); + BOOST_TEST( p3.lock() != p_3 ); + } + + return boost::report_errors(); +} + +#else // !defined( BOOST_HAS_RVALUE_REFS ) + +int main() +{ + return 0; +} + +#endif From e94f64039d6f540d1bada3bd422f592bd8733b8c Mon Sep 17 00:00:00 2001 From: "Troy D. Straszheim" Date: Sat, 17 Oct 2009 01:10:45 +0000 Subject: [PATCH 513/513] rm cmake from the release branch before it goes out broken. Policy dictates that you never commit to release, you commit to trunk and merge to release. [SVN r56941] --- CMakeLists.txt | 36 ----------------------------- module.cmake | 1 - test/CMakeLists.txt | 56 --------------------------------------------- 3 files changed, 93 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 module.cmake delete mode 100644 test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 1c039fc..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright Troy D. Straszheim -# -# Distributed under the Boost Software License, Version 1.0. -# See http://www.boost.org/LICENSE_1_0.txt -# -#---------------------------------------------------------------------------- -# This file was automatically generated from the original CMakeLists.txt file -# Add a variable to hold the headers for the library -set (lib_headers - enable_shared_from_this.hpp - pointer_cast.hpp - scoped_array.hpp - scoped_ptr.hpp - shared_array.hpp - shared_ptr.hpp - weak_ptr.hpp -) - -# Add a library target to the build system -boost_library_project( - smart_ptr - # SRCDIRS - TESTDIRS test - HEADERS ${lib_headers} - # DOCDIRS - DESCRIPTION "Five smart pointer class templates." - MODULARIZED - AUTHORS "Greg Colvin" - "Beman Dawes " - "Peter Dimov " - "Darin Adler" - # MAINTAINERS -) - - diff --git a/module.cmake b/module.cmake deleted file mode 100644 index d83266c..0000000 --- a/module.cmake +++ /dev/null @@ -1 +0,0 @@ -boost_module(smart_ptr DEPENDS utility) \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt deleted file mode 100644 index b89394e..0000000 --- a/test/CMakeLists.txt +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright Troy D. Straszheim -# -# Distributed under the Boost Software License, Version 1.0. -# See http://www.boost.org/LICENSE_1_0.txt -# -boost_additional_test_dependencies(tokenizer BOOST_DEPENDS test intrusive) - - -boost_test_run(smart_ptr_test) -boost_test_run(shared_ptr_basic_test) -boost_test_run(shared_ptr_test) -boost_test_run(weak_ptr_test) -boost_test_run(shared_from_this_test) -boost_test_run(get_deleter_test) -boost_test_run(intrusive_ptr_test) -boost_test_run(atomic_count_test) -boost_test_run(lw_mutex_test) -boost_test_compile_fail(shared_ptr_assign_fail) -boost_test_compile_fail(shared_ptr_delete_fail) -boost_test_compile_fail(shared_ptr_compare_fail) -boost_test_run(shared_ptr_alloc2_test) -boost_test_run(pointer_cast_test) -boost_test_compile(pointer_to_other_test) -boost_test_run(auto_ptr_rv_test) -boost_test_run(shared_ptr_alias_test) -boost_test_run(shared_ptr_rv_test) -boost_test_run(shared_ptr_move_test) -boost_test_compile_fail(shared_ptr_pv_fail) -boost_test_run(sp_unary_addr_test) -boost_test_compile_fail(scoped_ptr_eq_fail) -boost_test_compile_fail(scoped_array_eq_fail) -boost_test_run(esft_regtest) -boost_test_run(yield_k_test) -message(STATUS "!!!> yield_k_test multhreaded") -boost_test_run(spinlock_test) -boost_test_run(spinlock_try_test) -message(STATUS "!!!> spinlock_try_test multithreaded") -boost_test_run(spinlock_pool_test) -boost_test_run(make_shared_test) -boost_test_run(sp_convertible_test) -boost_test_run(wp_convertible_test) -boost_test_run(ip_convertible_test) -boost_test_run(allocate_shared_test) -boost_test_run(sp_atomic_test) -boost_test_run(esft_void_test) -boost_test_run(esft_second_ptr_test) -boost_test_run(make_shared_esft_test) -boost_test_run(allocate_shared_esft_test) -boost_test_run(sp_recursive_assign_test) -boost_test_run(sp_recursive_assign2_test) -boost_test_run(sp_recursive_assign_rv_test) -boost_test_run(sp_recursive_assign2_rv_test) -boost_test_compile_fail(auto_ptr_lv_fail) -boost_test_run(atomic_count_test2) -