Compare commits

..

2 Commits

Author SHA1 Message Date
nobody
e982a20e93 This commit was manufactured by cvs2svn to create tag
'Version_1_27_0'.

[SVN r12749]
2002-02-07 13:33:59 +00:00
nobody
d1f2ed19d3 This commit was manufactured by cvs2svn to create branch 'RC_1_27_0'.
[SVN r12739]
2002-02-06 03:32:50 +00:00
63 changed files with 2034 additions and 12042 deletions

View File

@@ -1,93 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Boost: enable_shared_from_this.hpp documentation</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
<table border="0" width="100%">
<tr>
<td width="277">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277" height="86">
</td>
<td align="middle">
<h1>enable_shared_from_this.hpp</h1>
</td>
</tr>
<tr>
<td colspan="2" height="64">&nbsp;</td>
</tr>
</table>
<h3><a name="Purpose">Purpose</a></h3>
<p>
The header <STRONG>&lt;boost/enable_shared_from_this.hpp&gt;</STRONG> defines
the class template <STRONG>enable_shared_from_this</STRONG>. It is used as a
base class that allows a <A href="shared_ptr.htm">shared_ptr</A> to the current
object to be obtained from within a member function.
</p>
<P><STRONG>enable_shared_from_this&lt;T&gt;</STRONG> defines two member functions
called <STRONG>shared_from_this</STRONG> that return a <STRONG>shared_ptr&lt;T&gt;</STRONG>
and <STRONG>shared_ptr&lt;T const&gt;</STRONG>, depending on constness, to <STRONG>this</STRONG>.</P>
<h3><a name="Example">Example</a></h3>
<pre>
class Y: public enable_shared_from_this&lt;Y&gt;
{
public:
shared_ptr&lt;Y&gt; f()
{
return shared_from_this();
}
}
int main()
{
shared_ptr&lt;Y&gt; p(new Y);
shared_ptr&lt;Y&gt; q = p-&gt;f();
assert(p == q);
assert(!(p &lt; q || q &lt; p)); // p and q must share ownership
}
</pre>
<h3><a name="Synopsis">Synopsis</a></h3>
<pre>
namespace boost
{
template&lt;class T&gt; class enable_shared_from_this
{
public:
shared_ptr&lt;T&gt; shared_from_this();
shared_ptr&lt;T const&gt; shared_from_this() const;
}
}
</pre>
<h4>template&lt;class T&gt; shared_ptr&lt;T&gt;
enable_shared_from_this&lt;T&gt;::shared_from_this();</h4>
<h4>template&lt;class T&gt; shared_ptr&lt;T const&gt;
enable_shared_from_this&lt;T&gt;::shared_from_this() const;</h4>
<blockquote>
<p>
<b>Requires:</b> <STRONG>enable_shared_from_this&lt;T&gt;</STRONG> must be an
accessible base class of <b>T</b>. <STRONG>*this</STRONG> must be a subobject
of an instance <STRONG>t</STRONG> of type <STRONG>T</STRONG> . There must exist
at least one <STRONG>shared_ptr</STRONG> instance <STRONG>p</STRONG> that <EM>owns</EM>
<STRONG>t</STRONG>.
</p>
<p>
<b>Returns:</b> A <b>shared_ptr&lt;T&gt;</b> instance <b>r</b> that shares
ownership with <b>p</b>.
</p>
<p>
<b>Postconditions:</b> <tt>r.get() == this</tt>.
</p>
</blockquote>
<p>
<br>
<small>Copyright <20> 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.</small></p>
</body>
</html>

View File

@@ -1,10 +1,8 @@
#ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
#define BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED #define BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
// MS compatible compilers support #pragma once #if _MSC_VER >= 1020
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif #endif
// //
@@ -74,8 +72,6 @@
// are called driven by smart_ptr interface... // 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 <boost/config.hpp> #include <boost/config.hpp>
@@ -93,21 +89,33 @@ typedef long atomic_count;
} }
#elif defined(BOOST_USE_ASM_ATOMIC_H)
# include <boost/detail/atomic_count_linux.hpp>
#elif defined(BOOST_AC_USE_PTHREADS)
# include <boost/detail/atomic_count_pthreads.hpp>
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
# include <boost/detail/atomic_count_win32.hpp>
#elif defined(__GLIBCPP__) #include <boost/detail/atomic_count_win32.hpp>
# include <boost/detail/atomic_count_gcc.hpp>
#elif defined(linux) || defined(__linux) || defined(__linux__)
#include <boost/detail/atomic_count_linux.hpp>
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
# define BOOST_AC_USE_PTHREADS
# include <boost/detail/atomic_count_pthreads.hpp> #include <boost/detail/atomic_count_pthreads.hpp>
#else #else
// Use #define BOOST_DISABLE_THREADS to avoid the error // #warning Unrecognized platform, detail::atomic_count will not be thread safe
#error Unrecognized threading platform
namespace boost
{
namespace detail
{
typedef long atomic_count;
}
}
#endif #endif

View File

@@ -1,61 +0,0 @@
#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<42>nnes <larsbj@lyx.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.
//
#include <bits/atomicity.h>
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

View File

@@ -13,13 +13,7 @@
// //
// //
// This implementation uses <asm/atomic.h>. This is a kernel header; // On Linux, atomic.h is usually located in /usr/include/asm
// 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 <asm/atomic.h> #include <asm/atomic.h>

View File

@@ -19,9 +19,11 @@
// inefficiencies. Example: a class with two atomic_count members // inefficiencies. Example: a class with two atomic_count members
// can get away with a single mutex. // can get away with a single mutex.
// //
// Users can detect this situation by checking BOOST_AC_USE_PTHREADS. // Define a macro so that users can detect the situation and optimize.
// //
#define BOOST_ATOMIC_COUNT_USES_PTHREADS
namespace boost namespace boost
{ {

View File

@@ -1,16 +1,14 @@
#ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED #ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
#define BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED #define BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
// MS compatible compilers support #pragma once #if _MSC_VER >= 1020
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif #endif
// //
// boost/detail/atomic_count_win32.hpp // boost/detail/atomic_count_win32.hpp
// //
// Copyright (c) 2001, 2002, 2003 Peter Dimov // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
@@ -18,46 +16,19 @@
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
#ifdef BOOST_USE_WINDOWS_H
# include <windows.h>
#endif
namespace boost namespace boost
{ {
namespace detail namespace detail
{ {
#ifndef BOOST_USE_WINDOWS_H // Avoid #including <windows.h>
#ifdef _WIN64 namespace win32
// 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 InterlockedIncrement(long volatile *);
extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement(long volatile *); extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement(long volatile *);
}
#endif // _WIN64
#endif // #ifndef BOOST_USE_WINDOWS_H
class atomic_count class atomic_count
{ {
@@ -69,13 +40,12 @@ public:
long operator++() long operator++()
{ {
// Some older <windows.h> versions do not accept volatile return win32::InterlockedIncrement(&value_);
return InterlockedIncrement(const_cast<long*>(&value_));
} }
long operator--() long operator--()
{ {
return InterlockedDecrement(const_cast<long*>(&value_)); return win32::InterlockedDecrement(&value_);
} }
operator long() const operator long() const

View File

@@ -1,99 +0,0 @@
#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
//
// boost/detail/lightweight_mutex.hpp - lightweight mutex
//
// 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.
//
// typedef <unspecified> 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
//
// * 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.
//
// 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.
#include <boost/config.hpp>
// 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 <boost/detail/lwm_win32_nt.hpp>
# else
# include <boost/detail/lwm_nop.hpp>
# endif
#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(BOOST_USE_ASM_ATOMIC_H)
# include <boost/detail/lwm_linux.hpp>
#elif defined(BOOST_LWM_USE_CRITICAL_SECTION)
# include <boost/detail/lwm_win32_cs.hpp>
#elif defined(BOOST_LWM_USE_PTHREADS)
# include <boost/detail/lwm_pthreads.hpp>
#elif defined(BOOST_LWM_WIN32)
# include <boost/detail/lwm_win32.hpp>
#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(__sgi)
# include <boost/detail/lwm_irix.hpp>
#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(__GLIBCPP__)
# include <boost/detail/lwm_gcc.hpp>
#elif defined(BOOST_HAS_PTHREADS)
# define BOOST_LWM_USE_PTHREADS
# include <boost/detail/lwm_pthreads.hpp>
#else
// Use #define BOOST_DISABLE_THREADS to avoid the error
# error Unrecognized threading platform
#endif
#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED

View File

@@ -1,78 +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<42>nnes <larsbj@lyx.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.
//
#include <bits/atomicity.h>
#include <sched.h>
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

View File

@@ -1,74 +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
//
// 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 <sgidefs.h>
#include <mutex.h>
#include <sched.h>
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

View File

@@ -1,85 +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.
//
// 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.
//
//
// This implementation uses <asm/atomic.h>. 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 <asm/atomic.h>
#include <sched.h>
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

View File

@@ -1,38 +0,0 @@
#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
//
// boost/detail/lwm_nop.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.
//
namespace boost
{
namespace detail
{
class lightweight_mutex
{
public:
typedef lightweight_mutex scoped_lock;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED

View File

@@ -1,87 +0,0 @@
#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
//
// boost/detail/lwm_pthreads.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 <pthread.h>
namespace boost
{
namespace detail
{
class lightweight_mutex
{
private:
pthread_mutex_t m_;
lightweight_mutex(lightweight_mutex const &);
lightweight_mutex & operator=(lightweight_mutex const &);
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()
{
pthread_mutex_destroy(&m_);
}
class scoped_lock;
friend class scoped_lock;
class scoped_lock
{
private:
pthread_mutex_t & m_;
scoped_lock(scoped_lock const &);
scoped_lock & operator=(scoped_lock const &);
public:
scoped_lock(lightweight_mutex & m): m_(m.m_)
{
pthread_mutex_lock(&m_);
}
~scoped_lock()
{
pthread_mutex_unlock(&m_);
}
};
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED

View File

@@ -1,123 +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
//
// 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.
//
#ifdef BOOST_USE_WINDOWS_H
# include <windows.h>
#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

View File

@@ -1,105 +0,0 @@
#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
//
// boost/detail/lwm_win32_cs.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.
//
#ifdef BOOST_USE_WINDOWS_H
# include <windows.h>
#endif
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:
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_);
}
};
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED

View File

@@ -1,64 +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
//
// 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

View File

@@ -17,13 +17,11 @@
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/checked_delete.hpp> #include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/detail/atomic_count.hpp> #include <boost/detail/atomic_count.hpp>
#include <cstddef> // for std::ptrdiff_t #include <cstddef> // for std::ptrdiff_t
#include <algorithm> // for std::swap #include <algorithm> // for std::swap
#include <functional> // for std::less #include <functional> // for std::less
#include <new> // for std::bad_alloc
namespace boost namespace boost
{ {
@@ -40,36 +38,22 @@ public:
explicit shared_array(T * p = 0): px(p) explicit shared_array(T * p = 0): px(p)
{ {
#ifndef BOOST_NO_EXCEPTIONS
try // prevent leak if new throws try // prevent leak if new throws
{ {
pn = new count_type(1); pn = new count_type(1);
} }
catch(...) catch(...)
{ {
boost::checked_array_delete(p); checked_array_delete(p);
throw; throw;
} }
#else
pn = new count_type(1);
if(pn == 0)
{
boost::checked_array_delete(p);
boost::throw_exception(std::bad_alloc());
}
#endif
} }
~shared_array() ~shared_array()
{ {
if(--*pn == 0) if(--*pn == 0)
{ {
boost::checked_array_delete(px); checked_array_delete(px);
delete pn; delete pn;
} }
} }

View File

@@ -1,16 +1,14 @@
#ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
#define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED #define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
// MS compatible compilers support #pragma once #if _MSC_VER >= 1020
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif #endif
// //
// detail/shared_count.hpp // detail/shared_count.hpp
// //
// Copyright (c) 2001, 2002, 2003 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 // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
@@ -20,354 +18,161 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR) #ifndef BOOST_NO_AUTO_PTR
# error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible. # include <memory>
#endif #endif
#include <boost/checked_delete.hpp> #include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp> #include <boost/detail/atomic_count.hpp>
#include <boost/detail/lightweight_mutex.hpp>
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
#include <boost/detail/quick_allocator.hpp>
#endif
#include <memory> // std::auto_ptr, std::allocator
#include <functional> // std::less
#include <exception> // std::exception
#include <new> // std::bad_alloc
#include <typeinfo> // std::type_info in get_deleter
#include <cstddef> // 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
namespace boost 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
// 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
// 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 bad_weak_ptr: public std::exception
{
public:
virtual char const * what() const throw()
{
return "boost::bad_weak_ptr";
}
};
#if defined(__BORLANDC__) && __BORLANDC__ == 0x551
# pragma option pop
#endif
namespace detail namespace detail
{ {
class sp_counted_base class counted_base
{ {
private:
typedef detail::lightweight_mutex mutex_type;
public: public:
sp_counted_base(): use_count_(1), weak_count_(1) 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 ~sp_counted_base() // nothrow virtual ~counted_base() // nothrow
{ {
} }
// dispose() is called when use_count_ drops to zero, to release // dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this. // 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() = 0; // nothrow virtual void dispose() // 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() // nothrow
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_; ++use_count_;
++weak_count_;
} }
void release() // nothrow void release() // nothrow
{ {
if(--use_count_ == 0)
{ {
#if defined(BOOST_HAS_THREADS) dispose();
mutex_type::scoped_lock lock(mtx_);
#endif
long new_use_count = --use_count_;
if(new_use_count != 0) return;
} }
dispose(); if(--weak_count_ == 0)
weak_release(); {
// not a direct 'delete this', because the inlined
// release() may use a different heap manager
self_deleter_(this);
}
} }
void weak_add_ref() // nothrow void weak_add_ref() // nothrow
{ {
#if defined(BOOST_HAS_THREADS)
mutex_type::scoped_lock lock(mtx_);
#endif
++weak_count_; ++weak_count_;
} }
void weak_release() // nothrow void weak_release() // nothrow
{ {
long new_weak_count; if(--weak_count_ == 0)
{ {
#if defined(BOOST_HAS_THREADS) self_deleter_(this);
mutex_type::scoped_lock lock(mtx_);
#endif
new_weak_count = --weak_count_;
}
if(new_weak_count == 0)
{
destruct();
} }
} }
long use_count() const // nothrow long use_count() const // nothrow
{ {
#if defined(BOOST_HAS_THREADS)
mutex_type::scoped_lock lock(mtx_);
#endif
return use_count_; return use_count_;
} }
private: private:
sp_counted_base(sp_counted_base const &); counted_base(counted_base const &);
sp_counted_base & operator= (sp_counted_base const &); counted_base & operator= (counted_base const &);
long use_count_; // #shared static void self_delete(counted_base * p)
long weak_count_; // #weak + (#shared != 0) {
delete p;
}
#if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32) // inv: use_count_ <= weak_count_
mutable mutex_type mtx_;
#endif count_type use_count_;
count_type weak_count_;
void (*self_deleter_) (counted_base *);
}; };
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) template<class P, class D> class counted_base_impl: public counted_base
template<class T> void cbi_call_constructor_hook(sp_counted_base * pn, T * px, checked_deleter<T> const &, int)
{
boost::sp_scalar_constructor_hook(px, sizeof(T), pn);
}
template<class T> void cbi_call_constructor_hook(sp_counted_base *, T * px, checked_array_deleter<T> const &, int)
{
boost::sp_array_constructor_hook(px);
}
template<class P, class D> void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long)
{
}
template<class T> void cbi_call_destructor_hook(sp_counted_base * pn, T * px, checked_deleter<T> const &, int)
{
boost::sp_scalar_destructor_hook(px, sizeof(T), pn);
}
template<class T> void cbi_call_destructor_hook(sp_counted_base *, T * px, checked_array_deleter<T> const &, int)
{
boost::sp_array_destructor_hook(px);
}
template<class P, class D> 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 P, class D> class sp_counted_base_impl: public sp_counted_base
{ {
private: private:
P ptr; // copy constructor must not throw P ptr; // copy constructor must not throw
D del; // copy constructor must not throw D del; // copy constructor must not throw
sp_counted_base_impl(sp_counted_base_impl const &); counted_base_impl(counted_base_impl const &);
sp_counted_base_impl & operator= (sp_counted_base_impl const &); counted_base_impl & operator= (counted_base_impl const &);
typedef sp_counted_base_impl<P, D> this_type;
public: public:
// pre: initial_use_count <= initial_weak_count, d(p) must not throw // pre: initial_use_count <= initial_weak_count, d(p) must not throw
sp_counted_base_impl(P p, D d): ptr(p), del(d) 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)
{ {
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
detail::cbi_call_constructor_hook(this, p, d, 0);
#endif
} }
virtual void dispose() // nothrow 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)
{
return ti == typeid(D)? &del: 0;
}
#if defined(BOOST_SP_USE_STD_ALLOCATOR)
void * operator new(std::size_t)
{
return std::allocator<this_type>().allocate(1, static_cast<this_type *>(0));
}
void operator delete(void * p)
{
std::allocator<this_type>().deallocate(static_cast<this_type *>(p), 1);
}
#endif
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
void * operator new(std::size_t)
{
return quick_allocator<this_type>::alloc();
}
void operator delete(void * p)
{
quick_allocator<this_type>::dealloc(p);
}
#endif
}; };
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
int const shared_count_id = 0x2C35F101;
int const weak_count_id = 0x298C38A4;
#endif
class weak_count;
class shared_count class shared_count
{ {
private: private:
sp_counted_base * pi_; counted_base * pi_;
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
int id_;
#endif
friend class weak_count; friend class weak_count;
public: public:
shared_count(): pi_(0) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{
}
template<class P, class D> shared_count(P p, D d): pi_(0) template<class P, class D> shared_count(P p, D d): pi_(0)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{ {
#ifndef BOOST_NO_EXCEPTIONS
try try
{ {
pi_ = new sp_counted_base_impl<P, D>(p, d); pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
} }
catch(...) catch(...)
{ {
d(p); // delete p d(p); // delete p
throw; throw;
} }
#else
pi_ = new sp_counted_base_impl<P, D>(p, d);
if(pi_ == 0)
{
d(p); // delete p
boost::throw_exception(std::bad_alloc());
}
#endif
} }
#ifndef BOOST_NO_AUTO_PTR #ifndef BOOST_NO_AUTO_PTR
// auto_ptr<Y> is special cased to provide the strong guarantee // auto_ptr<Y> is special cased to provide the strong guarantee
template<class Y> template<typename Y>
explicit shared_count(std::auto_ptr<Y> & r): pi_(new sp_counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>())) explicit shared_count(std::auto_ptr<Y> & r): pi_(new counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>(), 1, 1))
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{ {
r.release(); r.release();
} }
@@ -376,27 +181,19 @@ public:
~shared_count() // nothrow ~shared_count() // nothrow
{ {
if(pi_ != 0) pi_->release(); pi_->release();
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
id_ = 0;
#endif
} }
shared_count(shared_count const & r): pi_(r.pi_) // nothrow shared_count(shared_count const & r): pi_(r.pi_) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{ {
if(pi_ != 0) pi_->add_ref_copy(); pi_->add_ref();
} }
explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
shared_count & operator= (shared_count const & r) // nothrow shared_count & operator= (shared_count const & r) // nothrow
{ {
sp_counted_base * tmp = r.pi_; counted_base * tmp = r.pi_;
if(tmp != 0) tmp->add_ref_copy(); tmp->add_ref();
if(pi_ != 0) pi_->release(); pi_->release();
pi_ = tmp; pi_ = tmp;
return *this; return *this;
@@ -404,92 +201,54 @@ public:
void swap(shared_count & r) // nothrow void swap(shared_count & r) // nothrow
{ {
sp_counted_base * tmp = r.pi_; counted_base * tmp = r.pi_;
r.pi_ = pi_; r.pi_ = pi_;
pi_ = tmp; pi_ = tmp;
} }
long use_count() const // nothrow long use_count() const // nothrow
{ {
return pi_ != 0? pi_->use_count(): 0; return pi_->use_count();
} }
bool unique() const // nothrow bool unique() const // nothrow
{ {
return use_count() == 1; return pi_->use_count() == 1;
}
friend inline bool operator==(shared_count const & a, shared_count const & b)
{
return a.pi_ == b.pi_;
}
friend inline bool operator<(shared_count const & a, shared_count const & b)
{
return std::less<sp_counted_base *>()(a.pi_, b.pi_);
}
void * get_deleter(std::type_info const & ti) const
{
return pi_? pi_->get_deleter(ti): 0;
} }
}; };
#ifdef __CODEGUARD__
# pragma option pop
#endif
class weak_count class weak_count
{ {
private: private:
sp_counted_base * pi_; counted_base * pi_;
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
int id_;
#endif
friend class shared_count;
public: public:
weak_count(): pi_(0) // nothrow weak_count(): pi_(new counted_base(0, 1)) // can throw
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
{ {
} }
weak_count(shared_count const & r): pi_(r.pi_) // nothrow weak_count(shared_count const & r): pi_(r.pi_) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{ {
if(pi_ != 0) pi_->weak_add_ref(); pi_->weak_add_ref();
} }
weak_count(weak_count const & r): pi_(r.pi_) // nothrow weak_count(weak_count const & r): pi_(r.pi_) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{ {
if(pi_ != 0) pi_->weak_add_ref(); pi_->weak_add_ref();
} }
~weak_count() // nothrow ~weak_count() // nothrow
{ {
if(pi_ != 0) pi_->weak_release(); pi_->weak_release();
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
id_ = 0;
#endif
} }
weak_count & operator= (shared_count const & r) // nothrow weak_count & operator= (shared_count const & r) // nothrow
{ {
sp_counted_base * tmp = r.pi_; counted_base * tmp = r.pi_;
if(tmp != 0) tmp->weak_add_ref(); tmp->weak_add_ref();
if(pi_ != 0) pi_->weak_release(); pi_->weak_release();
pi_ = tmp; pi_ = tmp;
return *this; return *this;
@@ -497,9 +256,9 @@ public:
weak_count & operator= (weak_count const & r) // nothrow weak_count & operator= (weak_count const & r) // nothrow
{ {
sp_counted_base * tmp = r.pi_; counted_base * tmp = r.pi_;
if(tmp != 0) tmp->weak_add_ref(); tmp->weak_add_ref();
if(pi_ != 0) pi_->weak_release(); pi_->weak_release();
pi_ = tmp; pi_ = tmp;
return *this; return *this;
@@ -507,49 +266,19 @@ public:
void swap(weak_count & r) // nothrow void swap(weak_count & r) // nothrow
{ {
sp_counted_base * tmp = r.pi_; counted_base * tmp = r.pi_;
r.pi_ = pi_; r.pi_ = pi_;
pi_ = tmp; pi_ = tmp;
} }
long use_count() const // nothrow long use_count() const // nothrow
{ {
return pi_ != 0? pi_->use_count(): 0; return pi_->use_count();
}
friend inline bool operator==(weak_count const & a, weak_count const & b)
{
return a.pi_ == b.pi_;
}
friend inline bool operator<(weak_count const & a, weak_count const & b)
{
return std::less<sp_counted_base *>()(a.pi_, b.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
{
if(pi_ != 0)
{
pi_->add_ref_lock();
}
else
{
boost::throw_exception(boost::bad_weak_ptr());
}
}
} // namespace detail } // namespace detail
} // namespace boost } // 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 #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED

View File

@@ -17,16 +17,14 @@
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/checked_delete.hpp> #include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/detail/atomic_count.hpp> #include <boost/detail/atomic_count.hpp>
#ifndef BOOST_NO_AUTO_PTR #ifndef BOOST_NO_AUTO_PTR
# include <memory> // for std::auto_ptr #include <memory> // for std::auto_ptr
#endif #endif
#include <algorithm> // for std::swap #include <algorithm> // for std::swap
#include <functional> // for std::less #include <functional> // for std::less
#include <new> // for std::bad_alloc
namespace boost namespace boost
{ {
@@ -40,40 +38,25 @@ private:
public: public:
typedef T element_type; typedef T element_type;
typedef T value_type;
explicit shared_ptr(T * p = 0): px(p) explicit shared_ptr(T * p = 0): px(p)
{ {
#ifndef BOOST_NO_EXCEPTIONS
try // prevent leak if new throws try // prevent leak if new throws
{ {
pn = new count_type(1); pn = new count_type(1);
} }
catch(...) catch(...)
{ {
boost::checked_delete(p); checked_delete(p);
throw; throw;
} }
#else
pn = new count_type(1);
if(pn == 0)
{
boost::checked_delete(p);
boost::throw_exception(std::bad_alloc());
}
#endif
} }
~shared_ptr() ~shared_ptr()
{ {
if(--*pn == 0) if(--*pn == 0)
{ {
boost::checked_delete(px); checked_delete(px);
delete pn; delete pn;
} }
} }

View File

@@ -1,68 +0,0 @@
#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 <boost/weak_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>
namespace boost
{
template<class T> 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<T> shared_from_this()
{
shared_ptr<T> p(_internal_weak_this);
BOOST_ASSERT(p.get() == this);
return p;
}
shared_ptr<T const> shared_from_this() const
{
shared_ptr<T const> p(_internal_weak_this);
BOOST_ASSERT(p.get() == this);
return p;
}
typedef T _internal_element_type; // for bcc 5.5.1
weak_ptr<_internal_element_type> _internal_weak_this;
};
} // namespace boost
#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED

View File

@@ -1,30 +0,0 @@
// 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 <memory>
namespace boost {
// get_pointer(p) extracts a ->* capable pointer from p
template<class T> T * get_pointer(T * p)
{
return p;
}
// get_pointer(shared_ptr<T> const & p) has been moved to shared_ptr.hpp
template<class T> T * get_pointer(std::auto_ptr<T> const& p)
{
return p.get();
}
} // namespace boost
#endif // GET_POINTER_DWA20021219_HPP

View File

@@ -1,273 +0,0 @@
#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.
//
#include <boost/config.hpp>
#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 <boost/assert.hpp>
#include <boost/detail/workaround.hpp>
#include <functional> // for std::less
#include <iosfwd> // for std::basic_ostream
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 T> 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<class U> intrusive_ptr(intrusive_ptr<U> const & rhs): 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<class U> intrusive_ptr & operator=(intrusive_ptr<U> 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;
}
T * get() const
{
return p_;
}
T & operator*() const
{
return *p_;
}
T * operator->() const
{
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<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
{
return a.get() == b.get();
}
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
{
return a.get() != b.get();
}
template<class T> inline bool operator==(intrusive_ptr<T> const & a, T * b)
{
return a.get() == b;
}
template<class T> inline bool operator!=(intrusive_ptr<T> const & a, T * b)
{
return a.get() != b;
}
template<class T> inline bool operator==(T * a, intrusive_ptr<T> const & b)
{
return a == b.get();
}
template<class T> inline bool operator!=(T * a, intrusive_ptr<T> 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<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
{
return a.get() != b.get();
}
#endif
template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
{
return std::less<T *>()(a.get(), b.get());
}
template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)
{
lhs.swap(rhs);
}
// mem_fn support
template<class T> T * get_pointer(intrusive_ptr<T> const & p)
{
return p.get();
}
template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
{
return static_cast<T *>(p.get());
}
template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
{
return const_cast<T *>(p.get());
}
template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
{
return dynamic_cast<T *>(p.get());
}
// operator<<
#if defined(__GNUC__) && (__GNUC__ < 3)
template<class Y> std::ostream & operator<< (std::ostream & os, intrusive_ptr<Y> const & p)
{
os << p.get();
return os;
}
#else
# 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<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
# else
template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
# endif
{
os << p.get();
return os;
}
#endif
} // namespace boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif // #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED

View File

@@ -9,34 +9,21 @@
// This software is provided "as is" without express or implied // This software 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.
// //
// http://www.boost.org/libs/smart_ptr/scoped_array.htm // See http://www.boost.org/libs/smart_ptr/scoped_array.htm for documentation.
// //
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/config.hpp> // in case ptrdiff_t not in std #include <boost/config.hpp> // in case ptrdiff_t not in std
#include <boost/detail/workaround.hpp>
#include <cstddef> // for std::ptrdiff_t #include <cstddef> // for std::ptrdiff_t
namespace boost 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 // 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 // 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. // reset(). Use shared_array or std::vector if your needs are more complex.
template<class T> class scoped_array // noncopyable template<typename T> class scoped_array // noncopyable
{ {
private: private:
@@ -45,31 +32,29 @@ private:
scoped_array(scoped_array const &); scoped_array(scoped_array const &);
scoped_array & operator=(scoped_array const &); scoped_array & operator=(scoped_array const &);
typedef scoped_array<T> this_type;
public: public:
typedef T element_type; typedef T element_type;
explicit scoped_array(T * p = 0) : ptr(p) // never throws 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 ~scoped_array() // never throws
{ {
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) typedef char type_must_be_complete[sizeof(T)];
boost::sp_array_destructor_hook(ptr); delete [] ptr;
#endif
boost::checked_array_delete(ptr);
} }
void reset(T * p = 0) // never throws void reset(T * p = 0) // never throws
{ {
BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors typedef char type_must_be_complete[sizeof(T)];
this_type(p).swap(*this);
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
@@ -84,39 +69,6 @@ public:
return ptr; 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 void swap(scoped_array & b) // never throws
{ {
T * tmp = b.ptr; T * tmp = b.ptr;

View File

@@ -9,79 +9,51 @@
// This software is provided "as is" without express or implied // This software 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.
// //
// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm // See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation.
// //
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/detail/workaround.hpp>
#ifndef BOOST_NO_AUTO_PTR
# include <memory> // for std::auto_ptr
#endif
namespace boost 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 // 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 // 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. // use shared_ptr or std::auto_ptr if your needs are more complex.
template<class T> class scoped_ptr // noncopyable template<typename T> class scoped_ptr // noncopyable
{ {
private: private:
T * ptr; T* ptr;
scoped_ptr(scoped_ptr const &); scoped_ptr(scoped_ptr const &);
scoped_ptr & operator=(scoped_ptr const &); scoped_ptr & operator=(scoped_ptr const &);
typedef scoped_ptr<T> this_type;
public: public:
typedef T element_type; typedef T element_type;
explicit scoped_ptr(T * p = 0): ptr(p) // never throws 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<T> 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 ~scoped_ptr() // never throws
{ {
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) typedef char type_must_be_complete[sizeof(T)];
boost::sp_scalar_destructor_hook(ptr); delete ptr;
#endif
boost::checked_delete(ptr);
} }
void reset(T * p = 0) // never throws void reset(T * p = 0) // never throws
{ {
BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors typedef char type_must_be_complete[sizeof(T)];
this_type(p).swap(*this);
if (ptr != p)
{
delete ptr;
ptr = p;
}
} }
T & operator*() const // never throws T & operator*() const // never throws
@@ -101,38 +73,6 @@ public:
return ptr; 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 void swap(scoped_ptr & b) // never throws
{ {
T * tmp = b.ptr; T * tmp = b.ptr;
@@ -141,18 +81,11 @@ public:
} }
}; };
template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) // never throws template<typename T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) // never throws
{ {
a.swap(b); a.swap(b);
} }
// get_pointer(p) is a generic way to say p.get()
template<class T> inline T * get_pointer(scoped_ptr<T> const & p)
{
return p.get();
}
} // namespace boost } // namespace boost
#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED #endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED

View File

@@ -17,7 +17,7 @@
#include <boost/config.hpp> // for broken compiler workarounds #include <boost/config.hpp> // for broken compiler workarounds
#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) #ifndef BOOST_MSVC6_MEMBER_TEMPLATES
#include <boost/detail/shared_array_nmt.hpp> #include <boost/detail/shared_array_nmt.hpp>
#else #else
@@ -25,7 +25,6 @@
#include <boost/checked_delete.hpp> #include <boost/checked_delete.hpp>
#include <boost/detail/shared_count.hpp> #include <boost/detail/shared_count.hpp>
#include <boost/detail/workaround.hpp>
#include <cstddef> // for std::ptrdiff_t #include <cstddef> // for std::ptrdiff_t
#include <algorithm> // for std::swap #include <algorithm> // for std::swap
@@ -42,7 +41,7 @@ namespace boost
// is destroyed or reset. // is destroyed or reset.
// //
template<class T> class shared_array template<typename T> class shared_array
{ {
private: private:
@@ -64,7 +63,7 @@ public:
// shared_array will release p by calling d(p) // shared_array will release p by calling d(p)
// //
template<class D> shared_array(T * p, D d): px(p), pn(p, d) template<typename D> shared_array(T * p, D d): px(p), pn(p, d)
{ {
} }
@@ -76,7 +75,7 @@ public:
this_type(p).swap(*this); this_type(p).swap(*this);
} }
template <class D> void reset(T * p, D d) template <typename D> void reset(T * p, D d)
{ {
this_type(p, d).swap(*this); this_type(p, d).swap(*this);
} }
@@ -93,39 +92,6 @@ public:
return px; return px;
} }
// implicit conversion to "bool"
#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
operator bool () const
{
return px != 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 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 bool unique() const // never throws
{ {
return pn.unique(); return pn.unique();
@@ -149,28 +115,28 @@ private:
}; // shared_array }; // shared_array
template<class T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) // never throws template<typename T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) // never throws
{ {
return a.get() == b.get(); return a.get() == b.get();
} }
template<class T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) // never throws template<typename T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) // never throws
{ {
return a.get() != b.get(); return a.get() != b.get();
} }
template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) // never throws template<typename T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) // never throws
{ {
return std::less<T*>()(a.get(), b.get()); return std::less<T*>()(a.get(), b.get());
} }
template<class T> void swap(shared_array<T> & a, shared_array<T> & b) // never throws template<typename T> void swap(shared_array<T> & a, shared_array<T> & b) // never throws
{ {
a.swap(b); a.swap(b);
} }
} // namespace boost } // namespace boost
#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) #endif // #ifndef BOOST_MSVC6_MEMBER_TEMPLATES
#endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED #endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED

View File

@@ -5,7 +5,7 @@
// shared_ptr.hpp // shared_ptr.hpp
// //
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002, 2003 Peter Dimov // Copyright (c) 2001, 2002 Peter Dimov
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
@@ -17,21 +17,18 @@
#include <boost/config.hpp> // for broken compiler workarounds #include <boost/config.hpp> // for broken compiler workarounds
#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) #ifndef BOOST_MSVC6_MEMBER_TEMPLATES
#include <boost/detail/shared_ptr_nmt.hpp> #include <boost/detail/shared_ptr_nmt.hpp>
#else #else
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/checked_delete.hpp> #include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/detail/shared_count.hpp> #include <boost/detail/shared_count.hpp>
#include <boost/detail/workaround.hpp>
#include <memory> // for std::auto_ptr #include <memory> // for std::auto_ptr
#include <algorithm> // for std::swap #include <algorithm> // for std::swap
#include <functional> // for std::less #include <functional> // for std::less
#include <typeinfo> // for std::bad_cast
#include <iosfwd> // for std::basic_ostream
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
# pragma warning(push) # pragma warning(push)
@@ -41,18 +38,13 @@
namespace boost namespace boost
{ {
template<class T> class weak_ptr;
template<class T> class enable_shared_from_this;
namespace detail namespace detail
{ {
struct static_cast_tag {}; struct static_cast_tag {};
struct const_cast_tag {};
struct dynamic_cast_tag {}; struct dynamic_cast_tag {};
struct polymorphic_cast_tag {};
template<class T> struct shared_ptr_traits template<typename T> struct shared_ptr_traits
{ {
typedef T & reference; typedef T & reference;
}; };
@@ -62,36 +54,6 @@ template<> struct shared_ptr_traits<void>
typedef void reference; typedef void reference;
}; };
#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
template<> struct shared_ptr_traits<void const>
{
typedef void reference;
};
template<> struct shared_ptr_traits<void volatile>
{
typedef void reference;
};
template<> struct shared_ptr_traits<void const volatile>
{
typedef void reference;
};
#endif
// enable_shared_from_this support
template<class T, class Y> void sp_enable_shared_from_this(boost::enable_shared_from_this<T> * pe, Y * px, shared_count const & pn)
{
if(pe != 0) pe->_internal_weak_this._internal_assign(px, pn);
}
inline void sp_enable_shared_from_this(void const volatile *, void const volatile *, shared_count const &)
{
}
} // namespace detail } // namespace detail
@@ -103,110 +65,65 @@ inline void sp_enable_shared_from_this(void const volatile *, void const volatil
// is destroyed or reset. // is destroyed or reset.
// //
template<class T> class shared_ptr template<typename T> class weak_ptr;
template<typename T> class shared_ptr
{ {
private: private:
// Borland 5.5.1 specific workaround // Borland 5.5.1 specific workarounds
typedef checked_deleter<T> deleter;
typedef shared_ptr<T> this_type; typedef shared_ptr<T> this_type;
public: public:
typedef T element_type; typedef T element_type;
typedef T value_type;
typedef T * pointer;
typedef typename detail::shared_ptr_traits<T>::reference reference;
shared_ptr(): px(0), pn() // never throws in 1.30+ explicit shared_ptr(T * p = 0): px(p), pn(p, deleter())
{ {
} }
template<class Y>
explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter<Y>()) // Y must be complete
{
detail::sp_enable_shared_from_this(p, p, pn);
}
// //
// Requirements: D's copy constructor must not throw // Requirements: D's copy constructor must not throw
// //
// shared_ptr will release p by calling d(p) // shared_ptr will release p by calling d(p)
// //
template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d) template<typename D> shared_ptr(T * p, D d): px(p), pn(p, d)
{ {
detail::sp_enable_shared_from_this(p, p, pn);
} }
// generated copy constructor, assignment, destructor are fine... // generated copy constructor, assignment, destructor are fine
// except that Borland C++ has a bug, and g++ with -Wsynth warns template<typename Y>
#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<class Y>
explicit shared_ptr(weak_ptr<Y> 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<class Y>
shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
{ {
} }
template<class Y> template<typename Y>
shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn) shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
{ {
} }
template<class Y> template<typename Y>
shared_ptr(shared_ptr<Y> const & r, detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
{
}
template<class Y>
shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn) shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(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(); pn = detail::shared_count(static_cast<element_type *>(0), deleter());
}
}
template<class Y>
shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
{
if(px == 0)
{
boost::throw_exception(std::bad_cast());
} }
} }
#ifndef BOOST_NO_AUTO_PTR #ifndef BOOST_NO_AUTO_PTR
template<class Y> template<typename Y>
explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn() explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn(r)
{ {
Y * tmp = r.get();
pn = detail::shared_count(r);
detail::sp_enable_shared_from_this(tmp, tmp, pn);
} }
#endif #endif
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) template<typename Y>
template<class Y>
shared_ptr & operator=(shared_ptr<Y> const & r) // never throws shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
{ {
px = r.px; px = r.px;
@@ -214,11 +131,9 @@ public:
return *this; return *this;
} }
#endif
#ifndef BOOST_NO_AUTO_PTR #ifndef BOOST_NO_AUTO_PTR
template<class Y> template<typename Y>
shared_ptr & operator=(std::auto_ptr<Y> & r) shared_ptr & operator=(std::auto_ptr<Y> & r)
{ {
this_type(r).swap(*this); this_type(r).swap(*this);
@@ -227,23 +142,18 @@ public:
#endif #endif
void reset() // never throws in 1.30+ void reset(T * p = 0)
{ {
this_type().swap(*this); BOOST_ASSERT(p == 0 || p != px);
}
template<class Y> void reset(Y * p) // Y must be complete
{
BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
this_type(p).swap(*this); this_type(p).swap(*this);
} }
template<class Y, class D> void reset(Y * p, D d) template<typename D> void reset(T * p, D d)
{ {
this_type(p, d).swap(*this); this_type(p, d).swap(*this);
} }
reference operator* () const // never throws typename detail::shared_ptr_traits<T>::reference operator* () const // never throws
{ {
BOOST_ASSERT(px != 0); BOOST_ASSERT(px != 0);
return *px; return *px;
@@ -260,41 +170,6 @@ public:
return px; return px;
} }
// implicit conversion to "bool"
#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
operator bool () const
{
return px != 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 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 bool unique() const // never throws
{ {
return pn.unique(); return pn.unique();
@@ -311,16 +186,6 @@ public:
pn.swap(other.pn); pn.swap(other.pn);
} }
template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
{
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 // Tasteless as this may seem, making all members public allows member templates
// to work in the absence of member template friends. (Matthew Langston) // to work in the absence of member template friends. (Matthew Langston)
@@ -328,8 +193,8 @@ public:
private: private:
template<class Y> friend class shared_ptr; template<typename Y> friend class shared_ptr;
template<class Y> friend class weak_ptr; template<typename Y> friend class weak_ptr;
#endif #endif
@@ -339,136 +204,49 @@ private:
}; // shared_ptr }; // shared_ptr
template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) template<typename T, typename U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
{ {
return a.get() == b.get(); return a.get() == b.get();
} }
template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) template<typename T, typename U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
{ {
return a.get() != b.get(); return a.get() != b.get();
} }
#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 template<typename T> inline bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b)
// Resolve the ambiguity between our op!= and the one in rel_ops
template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
{ {
return a.get() != b.get(); return std::less<T*>()(a.get(), b.get());
} }
#endif template<typename T> void swap(shared_ptr<T> & a, shared_ptr<T> & b)
template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
{
return a._internal_less(b);
}
template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
{ {
a.swap(b); a.swap(b);
} }
template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) template<typename T, typename U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
{ {
return shared_ptr<T>(r, detail::static_cast_tag()); return shared_ptr<T>(r, detail::static_cast_tag());
} }
template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) template<typename T, typename U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
{
return shared_ptr<T>(r, detail::const_cast_tag());
}
template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
{ {
return shared_ptr<T>(r, detail::dynamic_cast_tag()); return shared_ptr<T>(r, detail::dynamic_cast_tag());
} }
// shared_*_cast names are deprecated. Use *_pointer_cast instead.
template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
{
return shared_ptr<T>(r, detail::static_cast_tag());
}
template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
{
return shared_ptr<T>(r, detail::dynamic_cast_tag());
}
template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
{
return shared_ptr<T>(r, detail::polymorphic_cast_tag());
}
template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
{
BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
return shared_static_cast<T>(r);
}
// get_pointer() enables boost::mem_fn to recognize shared_ptr // get_pointer() enables boost::mem_fn to recognize shared_ptr
template<class T> inline T * get_pointer(shared_ptr<T> const & p) template<typename T> inline T * get_pointer(shared_ptr<T> const & p)
{ {
return p.get(); return p.get();
} }
// operator<<
#if defined(__GNUC__) && (__GNUC__ < 3)
template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
{
os << p.get();
return os;
}
#else
# 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<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
# else
template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
# endif
{
os << p.get();
return os;
}
#endif
// get_deleter (experimental)
#if (defined(__GNUC__) && (__GNUC__ < 3)) || (defined(__EDG_VERSION__) && (__EDG_VERSION__ <= 238))
// g++ 2.9x doesn't allow static_cast<X const *>(void *)
// apparently EDG 2.38 also doesn't accept it
template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
{
void const * q = p._internal_get_deleter(typeid(D));
return const_cast<D *>(static_cast<D const *>(q));
}
#else
template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
{
return static_cast<D *>(p._internal_get_deleter(typeid(D)));
}
#endif
} // namespace boost } // namespace boost
#ifdef BOOST_MSVC #ifdef BOOST_MSVC
# pragma warning(pop) # pragma warning(pop)
#endif #endif
#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) #endif // #ifndef BOOST_MSVC6_MEMBER_TEMPLATES
#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED #endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED

View File

@@ -1,29 +1,9 @@
// // Boost smart_ptr.hpp header file -----------------------------------------//
// smart_ptr.hpp
//
// 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.
//
// http://www.boost.org/libs/smart_ptr/smart_ptr.htm
//
#include <boost/config.hpp> // For compatibility, this header includes the header for the four "classic"
// smart pointer class templates.
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp> #include <boost/scoped_array.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp> #include <boost/shared_array.hpp>
#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
# include <boost/weak_ptr.hpp>
# include <boost/intrusive_ptr.hpp>
# include <boost/enable_shared_from_this.hpp>
#endif

View File

@@ -4,7 +4,7 @@
// //
// weak_ptr.hpp // weak_ptr.hpp
// //
// Copyright (c) 2001, 2002, 2003 Peter Dimov // Copyright (c) 2001, 2002 Peter Dimov
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
@@ -16,6 +16,14 @@
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/config.hpp> // for broken compiler workarounds
#include <boost/assert.hpp>
#include <boost/detail/shared_count.hpp>
#include <algorithm> // for std::swap
#include <functional> // for std::less
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
# pragma warning(push) # pragma warning(push)
# pragma warning(disable:4284) // odd return type for operator-> # pragma warning(disable:4284) // odd return type for operator->
@@ -24,7 +32,7 @@
namespace boost namespace boost
{ {
template<class T> class weak_ptr template<typename T> class weak_ptr
{ {
private: private:
@@ -35,52 +43,45 @@ public:
typedef T element_type; typedef T element_type;
weak_ptr(): px(0), pn() // never throws in 1.30+ weak_ptr(): px(0), pn()
{ {
} }
// generated copy constructor, assignment, destructor are fine // generated copy constructor, assignment, destructor are fine
template<typename Y>
// weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
// The "obvious" converting constructor implementation:
//
// template<class Y>
// weak_ptr(weak_ptr<Y> 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<class Y>
weak_ptr(weak_ptr<Y> const & r): pn(r.pn) // never throws
{ {
px = r.lock().get();
} }
template<class Y> template<typename Y>
weak_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws weak_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
{ {
} }
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) template<typename Y>
weak_ptr(weak_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
{
}
template<class Y> template<typename Y>
weak_ptr(weak_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
{
if (px == 0) // need to allocate new counter -- the cast failed
{
pn = detail::weak_count();
}
}
template<typename Y>
weak_ptr & operator=(weak_ptr<Y> const & r) // never throws weak_ptr & operator=(weak_ptr<Y> const & r) // never throws
{ {
px = r.lock().get(); px = r.px;
pn = r.pn; pn = r.pn;
return *this; return *this;
} }
template<class Y> template<typename Y>
weak_ptr & operator=(shared_ptr<Y> const & r) // never throws weak_ptr & operator=(shared_ptr<Y> const & r) // never throws
{ {
px = r.px; px = r.px;
@@ -88,35 +89,28 @@ public:
return *this; return *this;
} }
#endif void reset()
shared_ptr<T> lock() const // never throws
{ {
#if defined(BOOST_HAS_THREADS) this_type().swap(*this);
// optimization: avoid throw overhead
if(expired())
{
return shared_ptr<element_type>();
} }
try T * get() const // never throws
{ {
return shared_ptr<element_type>(*this); return use_count() == 0? 0: px;
}
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<element_type>();
} }
#else typename detail::shared_ptr_traits<T>::reference operator* () const // never throws
{
T * p = get();
BOOST_ASSERT(p != 0);
return *p;
}
// optimization: avoid try/catch overhead when single threaded T * operator-> () const // never throws
return expired()? shared_ptr<element_type>(): shared_ptr<element_type>(*this); {
T * p = get();
#endif BOOST_ASSERT(p != 0);
return p;
} }
long use_count() const // never throws long use_count() const // never throws
@@ -124,33 +118,12 @@ public:
return pn.use_count(); return pn.use_count();
} }
bool expired() const // never throws void swap(weak_ptr<T> & other) // 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); std::swap(px, other.px);
pn.swap(other.pn); pn.swap(other.pn);
} }
void _internal_assign(T * px2, detail::shared_count const & pn2)
{
px = px2;
pn = pn2;
}
template<class Y> bool _internal_less(weak_ptr<Y> const & rhs) const
{
return pn < rhs.pn;
}
// Tasteless as this may seem, making all members public allows member templates // Tasteless as this may seem, making all members public allows member templates
// to work in the absence of member template friends. (Matthew Langston) // to work in the absence of member template friends. (Matthew Langston)
@@ -158,8 +131,7 @@ public:
private: private:
template<class Y> friend class weak_ptr; template<typename Y> friend class weak_ptr;
template<class Y> friend class shared_ptr;
#endif #endif
@@ -168,9 +140,19 @@ private:
}; // weak_ptr }; // weak_ptr
template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) template<class T, class U> inline bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b)
{ {
return a._internal_less(b); return a.get() == b.get();
}
template<class T, class U> inline bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b)
{
return a.get() != b.get();
}
template<class T> inline bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b)
{
return std::less<T*>()(a.get(), b.get());
} }
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
@@ -178,10 +160,21 @@ template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
a.swap(b); a.swap(b);
} }
// deprecated, provided for backward compatibility template<class T, class U> weak_ptr<T> shared_static_cast(weak_ptr<U> const & r)
template<class T> shared_ptr<T> make_shared(weak_ptr<T> const & r)
{ {
return r.lock(); return weak_ptr<T>(r, detail::static_cast_tag());
}
template<class T, class U> weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r)
{
return weak_ptr<T>(r, detail::dynamic_cast_tag());
}
// get_pointer() enables boost::mem_fn to recognize weak_ptr
template<class T> inline T * get_pointer(weak_ptr<T> const & p)
{
return p.get();
} }
} // namespace boost } // namespace boost

47
index.htm Normal file
View File

@@ -0,0 +1,47 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Boost Smart Pointer Library</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<table border="1" bgcolor="#007F7F" cellpadding="2">
<tr>
<td bgcolor="#FFFFFF"><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277" height="86"></td>
<td><a href="../../index.htm"><font face="Arial" color="#FFFFFF"><big>Home</big></font></a></td>
<td><a href="../libraries.htm"><font face="Arial" color="#FFFFFF"><big>Libraries</big></font></a></td>
<td><a href="../../people/people.htm"><font face="Arial" color="#FFFFFF"><big>People</big></font></a></td>
<td><a href="../../more/faq.htm"><font face="Arial" color="#FFFFFF"><big>FAQ</big></font></a></td>
<td><a href="../../more/index.htm"><font face="Arial" color="#FFFFFF"><big>More</big></font></a></td>
</tr>
</table>
<h1>Smart Pointer Library</h1>
<p>The smart pointer library includes five smart pointer class templates. Smart
pointers ease the management of memory dynamically allocated with C++ <b>new</b>
expressions. In addition, <b>scoped_ptr</b> can ease the management of memory
dynamically allocated in other ways.</p>
<ul>
<li><a href="smart_ptr.htm">Documentation</a> (HTML).</li>
<li>Header <a href="../../boost/scoped_ptr.hpp">scoped_ptr.hpp</a>.</li>
<li>Header <a href="../../boost/scoped_array.hpp">scoped_array.hpp</a>.</li>
<li>Header <a href="../../boost/shared_ptr.hpp">shared_ptr.hpp</a>.</li>
<li>Header <a href="../../boost/shared_array.hpp">shared_array.hpp</a>.</li>
<li>Header <a href="../../boost/weak_ptr.hpp">weak_ptr.hpp</a>.</li>
<li>Test program <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.</li>
<li>Originally submitted by
<a href="../../people/greg_colvin.htm">Greg Colvin</a> and
<a href="../../people/beman_dawes.html">Beman Dawes</a>,
currently maintained by
<a href="../../people/peter_dimov.htm">Peter Dimov</a> and
<a href="../../people/darin_adler.htm">Darin Adler</a>.</li>
</ul>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->1 February 2002<!--webbot bot="Timestamp" endspan i-checksum="14885" -->.</p>
</body>
</html>

View File

@@ -1,9 +0,0 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=smart_ptr.htm">
</head>
<body>
Automatic redirection failed, please go to
<a href="smart_ptr.htm">smart_ptr.htm</a>.
</body>
</html>

View File

@@ -1,286 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>intrusive_ptr</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body text="#000000" bgColor="#ffffff">
<h1><IMG height="86" alt="c++boost.gif (8819 bytes)" src="../../c++boost.gif" width="277" align="middle">intrusive_ptr
class template</h1>
<p>
<A href="#Introduction">Introduction</A><br>
<A href="#Synopsis">Synopsis</A><br>
<A href="#Members">Members</A><br>
<A href="#functions">Free Functions</A><br>
</p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <b>intrusive_ptr</b> class template stores a pointer to an object with an
embedded reference count. Every new <b>intrusive_ptr</b> instance increments
the reference count by using an unqualified call to the function <STRONG>intrusive_ptr_add_ref</STRONG>,
passing it the pointer as an argument. Similarly, when an <STRONG>intrusive_ptr</STRONG>
is destroyed, it calls <STRONG>intrusive_ptr_release</STRONG>; 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, <STRONG>intrusive_ptr_add_ref</STRONG>
and <STRONG>intrusive_ptr_release</STRONG> should be defined in the namespace
that corresponds to their parameter; otherwise, the definitions need to go in
namespace <STRONG>boost</STRONG>.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <STRONG>intrusive_ptr&lt;T&gt;</STRONG> can be implicitly converted to <STRONG>intrusive_ptr&lt;U&gt;</STRONG>
whenever <STRONG>T*</STRONG> can be implicitly converted to <STRONG>U*</STRONG>.</p>
<P>The main reasons to use <STRONG>intrusive_ptr</STRONG> are:</P>
<UL>
<LI>
Some existing frameworks or OSes provide objects with embedded reference
counts;</LI>
<LI>
The memory footprint of <STRONG>intrusive_ptr</STRONG> is the same as the
corresponding raw pointer;</LI>
<LI>
<STRONG>intrusive_ptr&lt;T&gt;</STRONG> can be constructed from an arbitrary
raw pointer of type <STRONG>T *</STRONG>.</LI></UL>
<P>As a general rule, if it isn't obvious whether <STRONG>intrusive_ptr</STRONG> better
fits your needs than <STRONG>shared_ptr</STRONG>, try a <STRONG>shared_ptr</STRONG>-based
design first.</P>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost {
template&lt;class T&gt; class intrusive_ptr {
public:
typedef T <A href="#element_type" >element_type</A>;
<A href="#constructors" >intrusive_ptr</A>(); // never throws
<A href="#constructors" >intrusive_ptr</A>(T * p, bool add_ref = true);
<A href="#constructors" >intrusive_ptr</A>(intrusive_ptr const &amp; r);
template&lt;class Y&gt; <A href="#constructors" >intrusive_ptr</A>(intrusive_ptr&lt;Y&gt; const &amp; r);
<A href="#destructor" >~intrusive_ptr</A>();
intrusive_ptr &amp; <A href="#assignment" >operator=</A>(intrusive_ptr const &amp; r);
template&lt;class Y&gt; intrusive_ptr &amp; <A href="#assignment" >operator=</A>(intrusive_ptr&lt;Y&gt; const &amp; r);
template&lt;class Y&gt; intrusive_ptr &amp; <A href="#assignment" >operator=</A>(T * r);
T &amp; <A href="#indirection" >operator*</A>() const; // never throws
T * <A href="#indirection" >operator-&gt;</A>() const; // never throws
T * <A href="#get" >get</A>() const; // never throws
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
void <A href="#swap" >swap</A>(intrusive_ptr &amp; b); // never throws
};
template&lt;class T, class U&gt;
bool <A href="#comparison" >operator==</A>(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class T, class U&gt;
bool <A href="#comparison" >operator!=</A>(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class T&gt;
bool <A href="#comparison" >operator==</A>(intrusive_ptr&lt;T&gt; const &amp; a, T * b); // never throws
template&lt;class T&gt;
bool <A href="#comparison" >operator!=</A>(intrusive_ptr&lt;T&gt; const &amp; a, T * b); // never throws
template&lt;class T&gt;
bool <A href="#comparison" >operator==</A>(T * a, intrusive_ptr&lt;T&gt; const &amp; b); // never throws
template&lt;class T&gt;
bool <A href="#comparison" >operator!=</A>(T * a, intrusive_ptr&lt;T&gt; const &amp; b); // never throws
template&lt;class T, class U&gt;
bool <A href="#comparison" >operator&lt;</A>(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class T&gt; void <A href="#free-swap" >swap</A>(intrusive_ptr&lt;T&gt; &amp; a, intrusive_ptr&lt;T&gt; &amp; b); // never throws
template&lt;class T&gt; T * <A href="#get_pointer" >get_pointer</A>(intrusive_ptr&lt;T&gt; const &amp; p); // never throws
template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; <A href="#static_pointer_cast" >static_pointer_cast</A>(intrusive_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; <A href="#const_pointer_cast" >const_pointer_cast</A>(intrusive_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; <A href="#dynamic_pointer_cast" >dynamic_pointer_cast</A>(intrusive_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class E, class T, class Y&gt;
std::basic_ostream&lt;E, T&gt; &amp; <A href="#insertion-operator" >operator&lt;&lt;</A> (std::basic_ostream&lt;E, T&gt; &amp; os, intrusive_ptr&lt;Y&gt; const &amp; p);
}</pre>
<h2><a name="Members">Members</a></h2>
<h3><a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre>
<blockquote>
<p>Provides the type of the template parameter T.</p>
</blockquote>
<h3><a name="constructors">constructors</a></h3>
<pre>intrusive_ptr(); // never throws</pre>
<blockquote>
<p><b>Postconditions:</b> <code>get() == 0</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>intrusive_ptr(T * p, bool add_ref = true);</pre>
<blockquote>
<p><b>Effects:</b> <code>if(p != 0 &amp;&amp; add_ref) intrusive_ptr_add_ref(p);</code>.</p>
<p><b>Postconditions:</b> <code>get() == p</code>.</p>
</blockquote>
<pre>intrusive_ptr(intrusive_ptr const &amp; r); // never throws
template&lt;class Y&gt; intrusive_ptr(intrusive_ptr&lt;Y&gt; const &amp; r); // never throws</pre>
<blockquote>
<p><b>Effects:</b> <code>if(r.get() != 0) intrusive_ptr_add_ref(r.get());</code>.</p>
<p><b>Postconditions:</b> <code>get() == r.get()</code>.</p>
</blockquote>
<h3><a name="destructor">destructor</a></h3>
<pre>~intrusive_ptr();</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> <code>if(get() != 0) intrusive_ptr_release(get());</code>.</P>
</BLOCKQUOTE>
<H3><a name="assignment">assignment</a></H3>
<pre>intrusive_ptr &amp; operator=(intrusive_ptr const &amp; r); // never throws
template&lt;class Y&gt; intrusive_ptr &amp; operator=(intrusive_ptr&lt;Y&gt; const &amp; r); // never throws
intrusive_ptr &amp; operator=(T * r);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>intrusive_ptr(r).swap(*this)</code>.</P>
<P><B>Returns:</B> <code>*this</code>.</P>
</BLOCKQUOTE>
<h3><a name="indirection">indirection</a></h3>
<pre>T &amp; operator*() const; // never throws</pre>
<blockquote>
<p><b>Requirements:</b> <code>get() != 0</code>.</p>
<p><b>Returns:</b> <code>*get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>T * operator-&gt;() const; // never throws</pre>
<blockquote>
<p><b>Requirements:</b> <code>get() != 0</code>.</p>
<p><b>Returns:</b> <code>get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> the stored pointer.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h3><a name="conversions">conversions</a></h3>
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> an unspecified value that, when used in boolean contexts, is
equivalent to <code>get() != 0</code>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> This conversion operator allows <b>intrusive_ptr</b> objects to be
used in boolean contexts, like <code>if (p &amp;&amp; p-&gt;valid()) {}</code>.
The actual target type is typically a pointer to a member function, avoiding
many of the implicit conversion pitfalls.</P>
</blockquote>
<h3><a name="swap">swap</a></h3>
<pre>void swap(intrusive_ptr &amp; b); // never throws</pre>
<blockquote>
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h2><a name="functions">Free Functions</a></h2>
<h3><a name="comparison">comparison</a></h3>
<pre>template&lt;class T, class U&gt;
bool operator==(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class T, class U&gt;
bool operator!=(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a.get() != b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class T&gt;
bool operator==(intrusive_ptr&lt;T&gt; const &amp; a, T * b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a.get() == b</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class T&gt;
bool operator!=(intrusive_ptr&lt;T&gt; const &amp; a, T * b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a.get() != b</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class T&gt;
bool operator==(T * a, intrusive_ptr&lt;T&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a == b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class T&gt;
bool operator!=(T * a, intrusive_ptr&lt;T&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a != b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class T, class U&gt;
bool operator&lt;(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>std::less&lt;T *&gt;()(a.get(), b.get())</code>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> Allows <STRONG>intrusive_ptr</STRONG> objects to be used as keys
in associative containers.</P>
</blockquote>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;class T&gt;
void swap(intrusive_ptr&lt;T&gt; &amp; a, intrusive_ptr&lt;T&gt; &amp; b); // never throws</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
generic programming.</P>
</BLOCKQUOTE>
<h3><a name="get_pointer">get_pointer</a></h3>
<pre>template&lt;class T&gt;
T * get_pointer(intrusive_ptr&lt;T&gt; const &amp; p); // never throws</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> <code>p.get()</code>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> Provided as an aid to generic programming. Used by <A href="../bind/mem_fn.html">
mem_fn</A>.</P>
</BLOCKQUOTE>
<h3><a name="static_pointer_cast">static_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; static_pointer_cast(intrusive_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> <code>intrusive_ptr&lt;T&gt;(static_cast&lt;T*&gt;(r.get()))</code>.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<h3><a name="const_pointer_cast">const_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; const_pointer_cast(intrusive_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> <code>intrusive_ptr&lt;T&gt;(const_cast&lt;T*&gt;(r.get()))</code>.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<h3><a name="dynamic_pointer_cast">dynamic_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; dynamic_pointer_cast(intrusive_ptr&lt;U&gt; const &amp; r);</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> <code>intrusive_ptr&lt;T&gt;(dynamic_cast&lt;T*&gt;(r.get()))</code>.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<h3><a name="insertion-operator">operator&lt;&lt;</a></h3>
<pre>template&lt;class E, class T, class Y&gt;
std::basic_ostream&lt;E, T&gt; &amp; operator&lt;&lt; (std::basic_ostream&lt;E, T&gt; &amp; os, intrusive_ptr&lt;Y&gt; const &amp; p);</pre>
<BLOCKQUOTE>
<p><STRONG>Effects:</STRONG> <code>os &lt;&lt; p.get();</code>.</p>
<P><B>Returns:</B> <code>os</code>.</P>
</BLOCKQUOTE>
<hr>
<p>
$Date$</p>
<p>
<small>Copyright <20> 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.</small></p>
</body>
</html>

View File

@@ -1,111 +1,145 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>scoped_array</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#ffffff" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86"><a name="scoped_array">scoped_array</a>
class template</h1>
<p>The <b>scoped_array</b> class template stores a pointer to a dynamically
allocated array. (Dynamically allocated arrays are allocated with the C++ <b>new[]</b>
expression.) The array pointed to is guaranteed to be deleted, either on
destruction of the <b>scoped_array</b>, or via an explicit <b>reset</b>.</p>
<p>The <b>scoped_array</b> 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
<a href="../utility/utility.htm#Class_noncopyable">noncopyable</a>) signal its intent to retain ownership solely within the
current scope. Because it is
<a href="../utility/utility.htm#Class_noncopyable">noncopyable</a>,
it is safer than <b>shared_array</b> for pointers which should not be copied.</p>
<p>Because <b>scoped_array</b> 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.</p>
<p>It cannot be used in C++ standard library containers. See <a href="shared_array.htm">
<b>shared_array</b></a> if <b>scoped_array</b> does not meet your needs.</p>
<p>It cannot correctly hold a pointer to a single object. See <a href="scoped_ptr.htm"><b>scoped_ptr</b></a>
for that usage.</p>
<p>A <b>std::vector</b> is an alternative to a <b>scoped_array</b> that is a bit
heavier duty but far more flexible. A <b>boost::array</b> is an alternative
that does not use dynamic allocation.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p>
<h2>Synopsis</h2>
<pre>namespace boost {
template&lt;class T&gt; class scoped_array : <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a> { <html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>scoped_array</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86"><a name="scoped_array">scoped_array</a> class template</h1>
<p>The <b>scoped_array</b> class template stores a pointer to a dynamically allocated
array. (Dynamically allocated arrays are allocated with the C++ <b>new[]</b>
expression.) The array pointed to is guaranteed to be deleted,
either on destruction of the <b>scoped_array</b>, or via an explicit <b>reset</b>.</p>
<p>The <b>scoped_array</b> template is a simple solution for simple
needs. It supplies a basic &quot;resource acquisition is
initialization&quot; facility, without shared-ownership or transfer-of-ownership
semantics. Both its name and enforcement of semantics (by being
<a href="../utility/utility.htm#class noncopyable">noncopyable</a>)
signal its intent to retain ownership solely within the current scope.
Because it is <a href="../utility/utility.htm#class noncopyable">noncopyable</a>, it is
safer than <b>shared_array</b> for pointers which should not be copied.</p>
<p>Because <b>scoped_array</b> 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.</p>
<p>It cannot be used in C++ standard library containers.
See <a href="shared_array.htm"><b>shared_array</b></a>
if <b>scoped_array</b> does not meet your needs.</p>
<p>It cannot correctly hold a pointer to a single object.
See <a href="scoped_ptr.htm"><b>scoped_ptr</b></a>
for that usage.</p>
<p>A <b>std::vector</b> is an alternative to a <b>scoped_array</b> that is
a bit heavier duty but far more flexible.
A <b>boost::array</b> is an alternative that does not use dynamic allocation.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object
pointed to. <b>T</b> must meet the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h2>Synopsis</h2>
<pre>namespace boost {
template&lt;typename T&gt; class scoped_array : <a href="../utility/utility.htm#noncopyable">noncopyable</a> {
public: public:
typedef T <a href="#element_type">element_type</a>; typedef T <a href="#element_type">element_type</a>;
explicit <a href="#ctor">scoped_array</a>(T * p = 0); // never throws explicit <a href="#ctor">scoped_array</a>(T * p = 0); // never throws
<a href="#destructor">~scoped_array</a>(); // never throws <a href="#~scoped_array">~scoped_array</a>(); // never throws
void <a href="#reset">reset</a>(T * p = 0); // never throws void <a href="#reset">reset</a>(T * p = 0); // never throws
T &amp; <a href="#operator[]">operator[]</a>(std::ptrdiff_t i) const; // never throws T &amp; <a href="#operator[]">operator[]</a>(std::size_t i) const; // never throws
T * <a href="#get">get</a>() const; // never throws T * <a href="#get">get</a>() const; // never throws
void <a href="#swap">swap</a>(scoped_array &amp; b); // never throws void <a href="#swap">swap</a>(scoped_array &amp; b); // never throws
}; };
template&lt;class T&gt; void <a href="#free-swap">swap</a>(scoped_array&lt;T&gt; &amp; a, scoped_array&lt;T&gt; &amp; b); // never throws template&lt;typename T&gt; void <a href="#free-swap">swap</a>(scoped_array&lt;T&gt; &amp; a, scoped_array&lt;T&gt; &amp; b); // never throws
}</pre> }</pre>
<h2>Members</h2>
<h3> <h2>Members</h2>
<a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre> <h3>
<p>Provides the type of the stored pointer.</p> <a name="element_type">element_type</a></h3>
<h3><a name="ctor">constructors</a></h3> <pre>typedef T element_type;</pre>
<pre>explicit scoped_array(T * p = 0); // never throws</pre> <p>Provides the type of the stored pointer.</p>
<p>Constructs a <b>scoped_array</b>, storing a copy of <b>p</b>, which must have
been allocated via a C++ <b>new</b>[] expression or be 0. <b>T</b> is not <h3><a name="ctor">constructors</a></h3>
required be a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements"> <pre>explicit scoped_array(T * p = 0); // never throws</pre>
common requirements</a>.</p> <p>Constructs a <b>scoped_array</b>, storing a copy of <b>p</b>, which must
<h3><a name="destructor">destructor</a></h3> have been allocated via a C++ <b>new</b>[] expression or be 0.
<pre>~scoped_array(); // never throws</pre> <b>T</b> is not required be a complete type.
<p>Deletes the array pointed to by the stored pointer. Note that <b>delete[]</b> on See the smart pointer
a pointer with a value of 0 is harmless. The guarantee that this does not throw <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
exceptions depends on the requirement that the deleted array's objects'
destructors do not throw exceptions. See the smart pointer <a href="smart_ptr.htm#common_requirements"> <h3><a name="~scoped_array">destructor</a></h3>
common requirements</a>.</p> <pre>~scoped_array(); // never throws</pre>
<h3><a name="reset">reset</a></h3> <p>Deletes the array pointed to by the stored pointer.
<pre>void reset(T * p = 0); // never throws</pre> Note that <b>delete[]</b> on a pointer with a value of 0 is harmless.
<p> The guarantee that this does not throw exceptions depends on the requirement that the
Deletes the array pointed to by the stored pointer and then stores a copy of p, deleted array's objects' destructors do not throw exceptions.
which must have been allocated via a C++ <b>new[]</b> expression or be 0. The See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
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 <h3><a name="reset">reset</a></h3>
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p> <pre>void reset(T * p = 0); // never throws</pre>
<h3><a name="operator[]">subscripting</a></h3> <p>If p is not equal to the stored pointer, deletes the array pointed to by the
<pre>T &amp; operator[](std::ptrdiff_t i) const; // never throws</pre> stored pointer and then stores a copy of p, which must have been allocated via a
<p>Returns a reference to element <b>i</b> of the array pointed to by the stored C++ <b>new[]</b> expression or be 0.
pointer. Behavior is undefined and almost certainly undesirable if the stored The guarantee that this does not throw exceptions depends on the requirement that the
pointer is 0, or if <b>i</b> is less than 0 or is greater than or equal to the deleted array's objects' destructors do not throw exceptions.
number of elements in the array.</p> See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre> <h3><a name="operator[]">subscripting</a></h3>
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart <pre>T &amp; operator[](std::size_t i) const; // never throws</pre>
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p> <p>Returns a reference to element <b>i</b> of the array pointed to by the
<h3><a name="swap">swap</a></h3> stored pointer.
<pre>void swap(scoped_array &amp; b); // never throws</pre> Behavior is undefined and almost certainly undesirable if the stored pointer is 0,
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a or if <b>i</b> is less than 0 or is greater than or equal to the number of elements
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common in the array.</p>
requirements</a>.</p>
<h2><a name="functions">Free Functions</a></h2> <h3><a name="get">get</a></h3>
<h3><a name="free-swap">swap</a></h3> <pre>T * get() const; // never throws</pre>
<pre>template&lt;class T&gt; void swap(scoped_array&lt;T&gt; &amp; a, scoped_array&lt;T&gt; &amp; b); // never throws</pre> <p>Returns the stored pointer.
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>. <b>T</b> need not be a complete type.
Provided as an aid to generic programming.</p> See the smart pointer
<hr> <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan-->09 January 2003<!--webbot bot="Timestamp" endspan i-checksum="32310"--></p>
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. <h3><a name="swap">swap</a></h3>
Permission to copy, use, modify, sell and distribute this document is granted <pre>void swap(scoped_array &amp; b); // never throws</pre>
provided this copyright notice appears in all copies. This document is provided <p>Exchanges the contents of the two smart pointers.
"as is" without express or implied warranty, and with no claim as to its <b>T</b> need not be a complete type.
suitability for any purpose.</p> See the smart pointer
</body> <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h2><a name="functions">Free Functions</a></h2>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;typename T&gt; void swap(scoped_array&lt;T&gt; &amp; a, scoped_array&lt;T&gt; &amp; b); // never throws</pre>
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
Provided as an aid to generic programming.</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan-->1 February 2002<!--webbot bot="Timestamp" endspan i-checksum="13964"--></p>
<p>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 &quot;as is&quot; without express or implied warranty,
and with no claim as to its suitability for any purpose.</p>
</body>
</html> </html>

View File

@@ -1,46 +1,59 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>scoped_ptr</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#ffffff" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86"><a name="scoped_ptr">scoped_ptr</a>
class template</h1>
<p>The <b>scoped_ptr</b> class template stores a pointer to a dynamically allocated
object. (Dynamically allocated objects are allocated with the C++ <b>new</b> expression.)
The object pointed to is guaranteed to be deleted, either on destruction of the <b>scoped_ptr</b>,
or via an explicit <b>reset</b>. See the <a href="#example">example</a>.</p>
<p>The <b>scoped_ptr</b> 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 <a href="../utility/utility.htm#Class_noncopyable">
noncopyable</a>) signal its intent to retain ownership solely within the
current scope. Because it is <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a>,
it is safer than <b>shared_ptr</b> or <b>std::auto_ptr</b> for pointers which
should not be copied.</p>
<p>Because <b>scoped_ptr</b> 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.</p>
<p><STRONG>scoped_ptr</STRONG> cannot be used in C++ Standard Library containers.
Use <a href="shared_ptr.htm"><b>shared_ptr</b></a> if you need a smart pointer
that can.</p>
<p><STRONG>scoped_ptr</STRONG> cannot correctly hold a pointer to a dynamically
allocated array. See <a href="scoped_array.htm"><b>scoped_array</b></a> for
that usage.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p>
<h2>Synopsis</h2>
<pre>namespace boost {
template&lt;class T&gt; class scoped_ptr : <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a> { <html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>scoped_ptr</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86"><a name="scoped_ptr">scoped_ptr</a> class template</h1>
<p>The <b>scoped_ptr</b> class template stores a pointer to a dynamically allocated
object. (Dynamically allocated objects are allocated with the C++ <b>new</b>
expression.) The object pointed to is guaranteed to be deleted,
either on destruction of the <b>scoped_ptr</b>, or via an explicit <b>reset</b>.
See the <a href="#example">example</a>.</p>
<p>The <b>scoped_ptr</b> template is a simple solution for simple
needs. It supplies a basic &quot;resource acquisition is
initialization&quot; facility, without shared-ownership or transfer-of-ownership
semantics. Both its name and enforcement of semantics (by being
<a href="../utility/utility.htm#class noncopyable">noncopyable</a>)
signal its intent to retain ownership solely within the current scope.
Because it is <a href="../utility/utility.htm#class noncopyable">noncopyable</a>, it is
safer than <b>shared_ptr</b> or <b>std::auto_ptr</b> for pointers which should not be
copied.</p>
<p>Because <b>scoped_ptr</b> 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.</p>
<p>It cannot be used in C++ Standard Library containers.
See <a href="shared_ptr.htm"><b>shared_ptr</b></a>
or <b>std::auto_ptr</b> if <b>scoped_ptr</b> does not meet your needs.</p>
<p>It cannot correctly hold a pointer to a
dynamically allocated array. See <a href="scoped_array.htm"><b>scoped_array</b></a>
for that usage.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object
pointed to. <b>T</b> must meet the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h2>Synopsis</h2>
<pre>namespace boost {
template&lt;typename T&gt; class scoped_ptr : <a href="../utility/utility.htm#class noncopyable">noncopyable</a> {
public: public:
typedef T <a href="#element_type">element_type</a>; typedef T <a href="#element_type">element_type</a>;
explicit <a href="#constructors">scoped_ptr</a>(T * p = 0); // never throws explicit <a href="#constructors">scoped_ptr</a>(T * p = 0); // never throws
<a href="#destructor">~scoped_ptr</a>(); // never throws <a href="#~scoped_ptr">~scoped_ptr</a>(); // never throws
void <a href="#reset">reset</a>(T * p = 0); // never throws void <a href="#reset">reset</a>(T * p = 0); // never throws
@@ -51,62 +64,78 @@
void <a href="#swap">swap</a>(scoped_ptr &amp; b); // never throws void <a href="#swap">swap</a>(scoped_ptr &amp; b); // never throws
}; };
template&lt;class T&gt; void <a href="#free-swap">swap</a>(scoped_ptr&lt;T&gt; &amp; a, scoped_ptr&lt;T&gt; &amp; b); // never throws template&lt;typename T&gt; void <a href="#free-swap">swap</a>(scoped_ptr&lt;T&gt; &amp; a, scoped_ptr&lt;T&gt; &amp; b); // never throws
}</pre> }</pre>
<h2>Members</h2>
<h3><a name="element_type">element_type</a></h3> <h2>Members</h2>
<pre>typedef T element_type;</pre>
<p>Provides the type of the stored pointer.</p> <h3><a name="element_type">element_type</a></h3>
<h3><a name="constructors">constructors</a></h3> <pre>typedef T element_type;</pre>
<pre>explicit scoped_ptr(T * p = 0); // never throws</pre> <p>Provides the type of the stored pointer.</p>
<p>Constructs a <b>scoped_ptr</b>, storing a copy of <b>p</b>, which must have been
allocated via a C++ <b>new</b> expression or be 0. <b>T</b> is not required be <h3><a name="constructors">constructors</a></h3>
a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common <pre>explicit scoped_ptr(T * p = 0); // never throws</pre>
requirements</a>.</p> <p>Constructs a <b>scoped_ptr</b>, storing a copy of <b>p</b>, which must
<h3><a name="destructor">destructor</a></h3> have been allocated via a C++ <b>new</b> expression or be 0.
<pre>~scoped_ptr(); // never throws</pre> <b>T</b> is not required be a complete type.
<p>Destroys the object pointed to by the stored pointer, if any, as if by using <tt>delete See the smart pointer
this-&gt;get()</tt>.</p> <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<P>
The guarantee that this does not throw exceptions depends on the requirement <h3><a name="~scoped_ptr">destructor</a></h3>
that the deleted object's destructor does not throw exceptions. See the smart <pre>~scoped_ptr(); // never throws</pre>
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</P> <p>Deletes the object pointed to by the stored pointer.
<h3><a name="reset">reset</a></h3> Note that <b>delete</b> on a pointer with a value of 0 is harmless.
<pre>void reset(T * p = 0); // never throws</pre> The guarantee that this does not throw exceptions depends on the requirement that the
<p> deleted object's destructor does not throw exceptions.
Deletes the object pointed to by the stored pointer and then stores a copy of See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
p, which must have been allocated via a C++ <b>new</b> expression or be 0. The
guarantee that this does not throw exceptions depends on the requirement that <h3><a name="reset">reset</a></h3>
the deleted object's destructor does not throw exceptions. See the smart <pre>void reset(T * p = 0); // never throws</pre>
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p> <p>If p is not equal to the stored pointer, deletes the object pointed to by the
<h3><a name="indirection">indirection</a></h3> stored pointer and then stores a copy of p, which must have been allocated via a
<pre>T &amp; operator*() const; // never throws</pre> C++ <b>new</b> expression or be 0.
<p>Returns a reference to the object pointed to by the stored pointer. Behavior is The guarantee that this does not throw exceptions depends on the requirement that the
undefined if the stored pointer is 0.</p> deleted object's destructor does not throw exceptions.
<pre>T * operator-&gt;() const; // never throws</pre> See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
<h3><a name="get">get</a></h3> <h3><a name="indirection">indirection</a></h3>
<pre>T * get() const; // never throws</pre> <pre>T &amp; operator*() const; // never throws</pre>
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart <p>Returns a reference to the object pointed to by the stored pointer.
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p> Behavior is undefined if the stored pointer is 0.</p>
<h3><a name="swap">swap</a></h3> <pre>T * operator-&gt;() const; // never throws</pre>
<pre>void swap(scoped_ptr &amp; b); // never throws</pre> <p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common <h3><a name="get">get</a></h3>
requirements</a>.</p> <pre>T * get() const; // never throws</pre>
<h2><a name="functions">Free Functions</a></h2> <p>Returns the stored pointer.
<h3><a name="free-swap">swap</a></h3> <b>T</b> need not be a complete type.
<pre>template&lt;class T&gt; void swap(scoped_ptr&lt;T&gt; &amp; a, scoped_ptr&lt;T&gt; &amp; b); // never throws</pre> See the smart pointer
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>. <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
Provided as an aid to generic programming.</p>
<h2><a name="example">Example</a></h2> <h3><a name="swap">swap</a></h3>
<p>Here's an example that uses <b>scoped_ptr</b>.</p> <pre>void swap(scoped_ptr &amp; b); // never throws</pre>
<blockquote> <p>Exchanges the contents of the two smart pointers.
<pre>#include &lt;boost/scoped_ptr.hpp&gt; <b>T</b> need not be a complete type.
See the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h2><a name="functions">Free Functions</a></h2>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;typename T&gt; void swap(scoped_ptr&lt;T&gt; &amp; a, scoped_ptr&lt;T&gt; &amp; b); // never throws</pre>
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
Provided as an aid to generic programming.</p>
<h2><a name="example">Example</a></h2>
<p>Here's an example that uses <b>scoped_ptr</b>.</p>
<blockquote>
<pre>#include &lt;boost/scoped_ptr.hpp&gt;
#include &lt;iostream&gt; #include &lt;iostream&gt;
struct Shoe { ~Shoe() { std::cout &lt;&lt; "Buckle my shoe\n"; } }; struct Shoe { ~Shoe() { std::cout &lt;&lt; &quot;Buckle my shoe\n&quot;; } };
class MyClass { class MyClass {
boost::scoped_ptr&lt;int&gt; ptr; boost::scoped_ptr&lt;int&gt; ptr;
@@ -122,55 +151,67 @@ void main()
std::cout &lt;&lt; my_instance.add_one() &lt;&lt; '\n'; std::cout &lt;&lt; my_instance.add_one() &lt;&lt; '\n';
std::cout &lt;&lt; my_instance.add_one() &lt;&lt; '\n'; std::cout &lt;&lt; my_instance.add_one() &lt;&lt; '\n';
}</pre> }</pre>
</blockquote> </blockquote>
<p>The example program produces the beginning of a child's nursery rhyme:</p>
<blockquote> <p>The example program produces the beginning of a child's nursery rhyme:</p>
<blockquote>
<pre>1 <pre>1
2 2
Buckle my shoe</pre> Buckle my shoe</pre>
</blockquote> </blockquote>
<h2>Rationale</h2>
<p>The primary reason to use <b>scoped_ptr</b> rather than <b>auto_ptr</b> is to <h2>Rationale</h2>
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 <p>The primary reason to use <b>scoped_ptr</b> rather than <b>auto_ptr</b> is to let readers
transfer ownership.</p> of your code know that you intend "resource acquisition is initialization" to be applied only
<p>A secondary reason to use <b>scoped_ptr</b> is to prevent a later maintenance for the current scope, and have no intent to transfer ownership.</p>
programmer from adding a function that transfers ownership by returning the <b>auto_ptr</b>,
because the maintenance programmer saw <b>auto_ptr</b>, and assumed ownership <p>A secondary reason to use <b>scoped_ptr</b> is to prevent a later maintenance programmer
could safely be transferred.</p> from adding a function that transfers ownership by returning the <b>auto_ptr</b>,
<p>Think of <b>bool</b> vs <b>int</b>. We all know that under the covers <b>bool</b> because the maintenance programmer saw <b>auto_ptr</b>, and assumed ownership could safely
is usually just an <b>int</b>. Indeed, some argued against including <b>bool</b> be transferred.</p>
in the C++ standard because of that. But by coding <b>bool</b> rather than <b>int</b>,
you tell your readers what your intent is. Same with <b>scoped_ptr</b>; by <p>Think of <b>bool</b> vs <b>int</b>. We all know that under the covers <b>bool</b> is usually
using it you are signaling intent.</p> just an <b>int</b>. Indeed, some argued against including <b>bool</b> in the
<p>It has been suggested that <b>scoped_ptr&lt;T&gt;</b> is equivalent to <b>std::auto_ptr&lt;T&gt; C++ standard because of that. But by coding <b>bool</b> rather than <b>int</b>, you tell your readers
const</b>. Ed Brey pointed out, however, that <b>reset</b> will not work on what your intent is. Same with <b>scoped_ptr</b>; by using it you are signaling intent.</p>
a <b>std::auto_ptr&lt;T&gt; const.</b></p>
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2> <p>It has been suggested that <b>scoped_ptr&lt;T&gt;</b> is equivalent to
<p>One common usage of <b>scoped_ptr</b> is to implement a handle/body (also called <b>std::auto_ptr&lt;T> const</b>. Ed Brey pointed out, however, that
pimpl) idiom which avoids exposing the body (implementation) in the header <b>reset</b> will not work on a <b>std::auto_ptr&lt;T> const.</b></p>
file.</p>
<p>The <a href="example/scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a> sample <h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
program includes a header file, <a href="example/scoped_ptr_example.hpp">scoped_ptr_example.hpp</a>,
which uses a <b>scoped_ptr&lt;&gt;</b> to an incomplete type to hide the <p>One common usage of <b>scoped_ptr</b> is to implement a handle/body (also
implementation. The instantiation of member functions which require a complete called pimpl) idiom which avoids exposing the body (implementation) in the header
type occurs in the <a href="example/scoped_ptr_example.cpp">scoped_ptr_example.cpp</a> file.</p>
implementation file.</p>
<h2>Frequently Asked Questions</h2> <p>The <a href="scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a>
<p><b>Q</b>. Why doesn't <b>scoped_ptr</b> have a release() member?<br> sample program includes a header file, <a href="scoped_ptr_example.hpp">scoped_ptr_example.hpp</a>,
<b>A</b>. When reading source code, it is valuable to be able to draw which uses a <b>scoped_ptr&lt;&gt;</b> to an incomplete type to hide the
conclusions about program behavior based on the types being used. If <STRONG>scoped_ptr</STRONG> implementation. The
had a release() member, it would become possible to transfer ownership of the instantiation of member functions which require a complete type occurs in
held pointer, weakening its role as a way of limiting resource lifetime to a the <a href="scoped_ptr_example.cpp">scoped_ptr_example.cpp</a>
given context. Use <STRONG>std::auto_ptr</STRONG> where transfer of ownership implementation file.</p>
is required. (supplied by Dave Abrahams)</p>
<hr> <h2>Frequently Asked Questions</h2>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->
09 January 2003<!--webbot bot="Timestamp" endspan i-checksum="32310" --></p> <p><b>Q</b>. Why doesn't <b>scoped_ptr</b> have a release() member?<br>
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. <b>A</b>. Because the point of <b>scoped_ptr</b> is to signal intent, not
Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and to transfer ownership. Use <b>std::auto_ptr</b> if ownership transfer is
distribute this document is granted provided this copyright notice appears in required.</p>
all copies. This document is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.</p> <hr>
</body>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->1 February 2002<!--webbot bot="Timestamp" endspan i-checksum="15110" --></p>
<p>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 &quot;as is&quot; without express or implied warranty,
and with no claim as to its suitability for any purpose.</p>
</body>
</html> </html>

View File

@@ -1,10 +1,5 @@
// Boost scoped_ptr_example implementation file -----------------------------// // Boost scoped_ptr_example implementation file -----------------------------//
// Copyright Beman Dawes 2001.
// See accompanying license for terms and conditions of use.
// See http://www.boost.org/libs/smart_ptr for documentation.
#include "scoped_ptr_example.hpp" #include "scoped_ptr_example.hpp"
#include <iostream> #include <iostream>

View File

@@ -1,10 +1,5 @@
// Boost scoped_ptr_example header file ------------------------------------// // Boost scoped_ptr_example header file ------------------------------------//
// Copyright Beman Dawes 2001.
// See accompanying license for terms and conditions of use.
// See http://www.boost.org/libs/smart_ptr for documentation.
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
@@ -14,7 +9,7 @@
// is complete where it counts - in the inplementation translation unit where // is complete where it counts - in the inplementation translation unit where
// destruction is actually instantiated. // destruction is actually instantiated.
class example : private boost::noncopyable class example : boost::noncopyable
{ {
public: public:
example(); example();

View File

@@ -1,10 +1,5 @@
// Boost scoped_ptr_example_test main program -------------------------------// // Boost scoped_ptr_example_test main program -------------------------------//
// Copyright Beman Dawes 2001.
// See accompanying license for terms and conditions of use.
// See http://www.boost.org/libs/smart_ptr for documentation.
#include "scoped_ptr_example.hpp" #include "scoped_ptr_example.hpp"
int main() int main()

View File

@@ -1,51 +1,63 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>shared_array</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#ffffff" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">shared_array
class template</h1>
<p>The <b>shared_array</b> class template stores a pointer to a dynamically
allocated array. (Dynamically allocated array are allocated with the C++ <b>new[]</b>
expression.) The object pointed to is guaranteed to be deleted when the last <b>shared_array</b>
pointing to it is destroyed or reset.</p>
<p>Every <b>shared_array</b> meets the <b>CopyConstructible</b> and <b>Assignable</b>
requirements of the C++ Standard Library, and so can be used in standard
library containers. Comparison operators are supplied so that <b>shared_array</b>
works with the standard library's associative containers.</p>
<p>Normally, a <b>shared_array</b> cannot correctly hold a pointer to an object
that has been allocated with the non-array form of <STRONG>new</STRONG>. See <a href="shared_ptr.htm">
<b>shared_ptr</b></a> for that usage.</p>
<p>Because the implementation uses reference counting, cycles of <b>shared_array</b>
instances will not be reclaimed. For example, if <b>main()</b> holds a <b>shared_array</b>
to <b>A</b>, which directly or indirectly holds a <b>shared_array</b> back to <b>A</b>,
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_array</b>
will leave <b>A</b> dangling with a use count of 1.</p>
<p>A <b>shared_ptr</b> to a <b>std::vector</b> is an alternative to a <b>shared_array</b>
that is a bit heavier duty but far more flexible.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p>
<h2>Synopsis</h2>
<pre>namespace boost {
template&lt;class T&gt; class shared_array { <html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>shared_array</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">shared_array class template</h1>
<p>The <b>shared_array</b> class template stores a pointer to a dynamically allocated
array. (Dynamically allocated array are allocated with the C++ <b>new[]</b>
expression.) The object pointed to is guaranteed to be deleted when
the last <b>shared_array</b> pointing to it is destroyed or reset.</p>
<p>Every <b>shared_array</b> meets the <b>CopyConstructible</b>
and <b>Assignable</b> requirements of the C++ Standard Library, and so
can be used in standard library containers. Comparison operators
are supplied so that <b>shared_array</b> works with
the standard library's associative containers.</p>
<p>Normally, a <b>shared_array</b> cannot correctly hold a pointer to a
dynamically allocated array. See <a href="shared_ptr.htm"><b>shared_ptr</b></a>
for that usage.</p>
<p>Because the implementation uses reference counting, <b>shared_array</b> will not work
correctly with cyclic data structures. For example, if <b>main()</b> holds a <b>shared_array</b>
to <b>A</b>, which directly or indirectly holds a <b>shared_array</b> back to <b>A</b>,
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_array</b>
will leave <b>A</b> dangling with a use count of 1.</p>
<p>A <b>shared_ptr</b> to a <b>std::vector</b> is an alternative to a <b>shared_array</b> that is
a bit heavier duty but far more flexible.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object
pointed to. <b>T</b> must meet the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h2>Synopsis</h2>
<pre>namespace boost {
template&lt;typename T&gt; class shared_array {
public: public:
typedef T <a href="#element_type">element_type</a>; typedef T <a href="#element_type">element_type</a>;
explicit <a href="#constructors">shared_array</a>(T * p = 0); explicit <a href="#constructors">shared_array</a>(T * p = 0);
template&lt;class D&gt; <a href="#constructors">shared_array</a>(T * p, D d); template&lt;typename D&gt; <a href="#constructors">shared_array</a>(T * p, D d);
<a href="#destructor">~shared_array</a>(); // never throws <a href="#destructor">~shared_array</a>(); // never throws
<a href="#constructors">shared_array</a>(shared_array const &amp; r); // never throws <a href="#constructors">shared_array</a>(shared_array const &amp; r); // never throws
shared_array &amp; <a href="#assignment">operator=</a>(shared_array const &amp; r); // never throws shared_array &amp; <a href="#assignment">operator=</a>(shared_array const &amp; r); // never throws
void <a href="#reset">reset</a>(T * p = 0); void <a href="#reset">reset</a>(T * p = 0); // never throws
template&lt;class D&gt; void <a href="#reset">reset</a>(T * p, D d); template&lt;typename D&gt; void <a href="#reset">reset</a>(T * p, D d); // never throws
T &amp; <a href="#indexing">operator[]</a>(std::ptrdiff_t i) const() const; // never throws T &amp; <a href="#indexing">operator[]</a>(std::ptrdiff_t i) const() const; // never throws
T * <a href="#get">get</a>() const; // never throws T * <a href="#get">get</a>() const; // never throws
@@ -56,125 +68,157 @@
void <a href="#swap">swap</a>(shared_array&lt;T&gt; &amp; b); // never throws void <a href="#swap">swap</a>(shared_array&lt;T&gt; &amp; b); // never throws
}; };
template&lt;class T&gt; template&lt;typename T&gt;
bool <a href="#comparison">operator==</a>(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws bool <a href="#operator==">operator==</a>(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws
template&lt;class T&gt; template&lt;typename T&gt;
bool <a href="#comparison">operator!=</a>(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws bool <a href="#operator!=">operator!=</a>(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws
template&lt;class T&gt; template&lt;typename T&gt;
bool <a href="#comparison">operator&lt;</a>(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws bool <a href="#operator&lt;">operator&lt;</a>(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws
template&lt;class T&gt; void <a href="#free-swap">swap</a>(shared_array&lt;T&gt; &amp; a, shared_array&lt;T&gt; &amp; b); // never throws template&lt;typename T&gt; void <a href="#free-swap">swap</a>(shared_array&lt;T&gt; &amp; a, shared_array&lt;T&gt; &amp; b); // never throws
}</pre> }</pre>
<h2>Members</h2>
<h3><a name="element_type">element_type</a></h3> <h2>Members</h2>
<pre>typedef T element_type;</pre>
<p>Provides the type of the stored pointer.</p> <h3><a name="element_type">element_type</a></h3>
<h3><a name="constructors">constructors</a></h3> <pre>typedef T element_type;</pre>
<pre>explicit shared_array(T * p = 0);</pre> <p>Provides the type of the stored pointer.</p>
<p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b>, which must be a
pointer to an array that was allocated via a C++ <b>new[]</b> expression or be <h3><a name="constructors">constructors</a></h3>
0. Afterwards, the <a href="#use_count">use count</a> is 1 (even if p == 0; see <a href="#destructor">
~shared_array</a>). The only exception which may be thrown by this <pre>explicit shared_array(T * p = 0);</pre>
constructor is <b>std::bad_alloc</b>. If an exception is thrown, <b>delete[] p</b> <p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b>, which
is called.</p> must be a pointer to an array that was allocated via a C++ <b>new[]</b> expression or be 0.
<pre>template&lt;class D&gt; shared_array(T * p, D d);</pre> Afterwards, the <a href="#use_count">use count</a> is 1 (even if p == 0; see <a href="#destructor">~shared_array</a>).
<p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b> and of <b>d</b>. The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
Afterwards, the <a href="#use_count">use count</a> is 1. <b>D</b>'s copy If an exception is thrown, <b>delete[] p</b> is called.</p>
constructor and destructor must not throw. When the the time comes to delete
the array pointed to by <b>p</b>, the object <b>d</b> is used in the statement <b>d(p)</b>. <pre>template&lt;typename D&gt; shared_array(T * p, D d);</pre>
Invoking the object <b>d</b> with parameter <b>p</b> in this way must not <p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b> and of <b>d</b>.
throw. The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>. Afterwards, the <a href="#use_count">use count</a> is 1.
If an exception is thrown, <b>d(p)</b> is called.</p> <b>D</b>'s copy constructor and destructor must not throw.
<pre>shared_array(shared_array const &amp; r); // never throws</pre> When the the time comes to delete the array pointed to by <b>p</b>, the object
<p>Constructs a <b>shared_array</b>, as if by storing a copy of the pointer stored <b>d</b> is used in the statement <b>d(p)</b>. Invoking the object <b>d</b> with
in <b>r</b>. Afterwards, the <a href="#use_count">use count</a> for all copies parameter <b>p</b> in this way must not throw.
is 1 more than the initial use count.</p> The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
<h3><a name="destructor">destructor</a></h3> If an exception is thrown, <b>d(p)</b> is called.</p>
<pre>~shared_array(); // never throws</pre>
<p>Decrements the <a href="#use_count">use count</a>. Then, if the use count is 0, <pre>shared_array(shared_array const &amp; r); // never throws</pre>
deletes the array pointed to by the stored pointer. Note that <b>delete[]</b> on <p>Constructs a <b>shared_array</b>, as if by storing a copy of the
a pointer with a value of 0 is harmless. <b>T</b> need not be a complete type. pointer stored in <b>r</b>. Afterwards, the <a href="#use_count">use count</a>
The guarantee that this does not throw exceptions depends on the requirement for all copies is 1 more than the initial use count.</p>
that the deleted object's destructor does not throw exceptions. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p> <h3><a name="destructor">destructor</a></h3>
<h3><a name="assignment">assignment</a></h3>
<pre>shared_array &amp; operator=(shared_array const &amp; r); // never throws</pre> <pre>~shared_array(); // never throws</pre>
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>, <p>Decrements the <a href="#use_count">use count</a>. Then, if the use count is 0,
then replaces this <b>shared_array</b> with the new one, destroying the deletes the array pointed to by the stored pointer.
replaced object.</p> Note that <b>delete[]</b> on a pointer with a value of 0 is harmless.
<h3><a name="reset">reset</a></h3> <b>T</b> need not be a complete type.
<pre>void reset(T * p = 0);</pre> The guarantee that this does not throw exceptions depends on the requirement that the
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>, deleted object's destructor does not throw exceptions.
then replaces this <b>shared_array</b> with the new one, destroying the See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
replaced object. The only exception which may be thrown is <b>std::bad_alloc</b>.
If an exception is thrown, <b>delete[] p</b> is called.</p> <h3><a name="operator=">assignment</a></h3>
<pre>template&lt;class D&gt; void reset(T * p, D d);</pre>
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>, <pre>shared_array &amp; <a href="#assignment">operator=</a>(shared_array const &amp; r); // never throws</pre>
then replaces this <b>shared_array</b> with the new one, destroying the <p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
replaced object. <b>D</b>'s copy constructor must not throw. The only exception then replaces this <b>shared_array</b> with the new one, destroying the replaced object.</p>
which may be thrown is <b>std::bad_alloc</b>. If an exception is thrown, <b>d(p)</b>
is called.</p> <h3><a name="reset">reset</a></h3>
<h3><a name="indexing">indexing</a></h3>
<pre>T &amp; operator[](std::ptrdiff_t i) const; // never throws</pre> <pre>void reset(T * p = 0);</pre>
<p>Returns a reference to element <b>i</b> of the array pointed to by the stored <p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
pointer. Behavior is undefined and almost certainly undesirable if the stored then replaces this <b>shared_array</b> with the new one, destroying the replaced object.
pointer is 0, or if <b>i</b> is less than 0 or is greater than or equal to the The only exception which may be thrown is <b>std::bad_alloc</b>. If
number of elements in the array.</p> an exception is thrown, <b>delete[] p</b> is called.</p>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre> <pre>template&lt;typename D&gt; void reset(T * p, D d);</pre>
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart <p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p> then replaces this <b>shared_array</b> with the new one, destroying the replaced object.
<h3><a name="unique">unique</a></h3> <b>D</b>'s copy constructor must not throw.
<pre>bool unique() const; // never throws</pre> The only exception which may be thrown is <b>std::bad_alloc</b>. If
<p>Returns true if no other <b>shared_array</b> is sharing ownership of the stored an exception is thrown, <b>d(p)</b> is called.</p>
pointer, false otherwise. <b>T</b> need not be a complete type. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p> <h3><a name="indirection">indexing</a></h3>
<h3><a name="use_count">use_count</a></h3> <pre>T &amp; operator[](std::size_t i) const; // never throws</pre>
<pre>long use_count() const; // never throws</pre> <p>Returns a reference to element <b>i</b> of the array pointed to by the stored pointer.
<p>Returns the number of <b>shared_array</b> objects sharing ownership of the Behavior is undefined and almost certainly undesirable if the stored pointer is 0,
stored pointer. <b>T</b> need not be a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements"> or if <b>i</b> is less than 0 or is greater than or equal to the number of elements
common requirements</a>.</p> in the array.</p>
<p>Because <b>use_count</b> is not necessarily efficient to implement for
implementations of <b>shared_array</b> that do not use an explicit reference <h3><a name="get">get</a></h3>
count, it might be removed from some future version. Thus it should be used for <pre>T * get() const; // never throws</pre>
debugging purposes only, and not production code.</p> <p>Returns the stored pointer.
<h3><a name="swap">swap</a></h3> <b>T</b> need not be a complete type.
<pre>void swap(shared_ptr &amp; b); // never throws</pre> See the smart pointer
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
requirements</a>.</p> <h3><a name="unique">unique</a></h3>
<h2><a name="functions">Free Functions</a></h2> <pre>bool unique() const; // never throws</pre>
<h3><a name="comparison">comparison</a></h3> <p>Returns true if no other <b>shared_array</b> is sharing ownership of
<pre>template&lt;class T&gt; the stored pointer, false otherwise.
bool operator==(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws <b>T</b> need not be a complete type.
template&lt;class T&gt; See the smart pointer
bool operator!=(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
template&lt;class T&gt;
bool operator&lt;(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws</pre> <h3><a name="use_count">use_count</a></h3>
<p>Compares the stored pointers of the two smart pointers. <b>T</b> need not be a <pre>long use_count() const; // never throws</pre>
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common <p>Returns the number of <b>shared_array</b> objects sharing ownership of the
requirements</a>.</p> stored pointer.
<p>The <b>operator&lt;</b> overload is provided to define an ordering so that <b>shared_array</b> <b>T</b> need not be a complete type.
objects can be used in associative containers such as <b>std::map</b>. The See the smart pointer
implementation uses <b>std::less&lt;T *&gt;</b> to perform the comparison. This <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
ensures that the comparison is handled correctly, since the standard mandates <p>Because <b>use_count</b> is not necessarily efficient to implement for
that relational operations on pointers are unspecified (5.9 [expr.rel] implementations of <b>shared_array</b> that do not use an explicit reference
paragraph 2) but <b>std::less&lt;&gt;</b> on pointers is well-defined (20.3.3 count, it might be removed from some future version. Thus it should
[lib.comparisons] paragraph 8).</p> be used for debugging purposes only, and not production code.</p>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;class T&gt; <h3><a name="swap">swap</a></h3>
<pre>void swap(shared_ptr &amp; b); // never throws</pre>
<p>Exchanges the contents of the two smart pointers.
<b>T</b> need not be a complete type.
See the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h2><a name="functions">Free Functions</a></h2>
<h3><a name="comparison">comparison</a></h3>
<pre>template&lt;typename T&gt;
bool <a href="#operator==">operator==</a>(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws
template&lt;typename T&gt;
bool <a href="#operator!=">operator!=</a>(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws
template&lt;typename T&gt;
bool <a href="#operator&lt;">operator&lt;</a>(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws</pre>
<p>Compares the stored pointers of the two smart pointers.
<b>T</b> need not be a complete type.
See the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<p>The <b>operator&lt;</b> overload is provided to define an ordering so that <b>shared_array</b>
objects can be used in associative containers such as <b>std::map</b>.
The implementation uses <b>std::less&lt;T *&gt;</b> 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 <b>std::less&lt;&gt;</b> on pointers is well-defined (20.3.3 [lib.comparisons]
paragraph 8).</p>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;typename T&gt;
void swap(shared_array&lt;T&gt; &amp; a, shared_array&lt;T&gt; &amp; b) // never throws</pre> void swap(shared_array&lt;T&gt; &amp; a, shared_array&lt;T&gt; &amp; b) // never throws</pre>
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>. <p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
Provided as an aid to generic programming.</p> Provided as an aid to generic programming.</p>
<hr>
<p>Revised <hr>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->
09 January 2003<!--webbot bot="Timestamp" endspan i-checksum="32310" --></p> <p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->1 February 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
Permission to copy, use, modify, sell and distribute this document is granted <p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
provided this copyright notice appears in all copies. This document is provided Permission to copy, use, modify, sell and distribute this document is granted
"as is" without express or implied warranty, and with no claim as to its provided this copyright notice appears in all copies.
suitability for any purpose.</p> This document is provided &quot;as is&quot; without express or implied warranty,
</body> and with no claim as to its suitability for any purpose.</p>
</body>
</html> </html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,12 @@
// Boost shared_ptr_example.cpp --------------------------------------------// // Boost shared_ptr_example.cpp --------------------------------------------//
// Copyright Beman Dawes 2001. // (C) Copyright Beman Dawes 2001. Permission to copy,
// See accompanying license for terms and conditions of use. // 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 for documentation. // See http://www.boost.org for most recent version including documentation.
// Revision History // Revision History
// 21 May 01 Initial complete version (Beman Dawes) // 21 May 01 Initial complete version (Beman Dawes)

View File

@@ -1,10 +1,5 @@
// Boost shared_ptr_example2 implementation file -----------------------------// // Boost shared_ptr_example2 implementation file -----------------------------//
// Copyright Beman Dawes 2001.
// See accompanying license for terms and conditions of use.
// See http://www.boost.org/libs/smart_ptr for documentation.
#include "shared_ptr_example2.hpp" #include "shared_ptr_example2.hpp"
#include <iostream> #include <iostream>
@@ -15,6 +10,10 @@ class example::implementation
}; };
example::example() : _imp( new 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() void example::do_something()
{ std::cout << "use_count() is " << _imp.use_count() << "\n"; } { std::cout << "use_count() is " << _imp.use_count() << "\n"; }

View File

@@ -1,10 +1,5 @@
// Boost shared_ptr_example2 header file -----------------------------------// // Boost shared_ptr_example2 header file -----------------------------------//
// Copyright Beman Dawes 2001.
// See accompanying license for terms and conditions of use.
// See http://www.boost.org/libs/smart_ptr for documentation.
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
// This example demonstrates the handle/body idiom (also called pimpl and // This example demonstrates the handle/body idiom (also called pimpl and
@@ -19,10 +14,12 @@
class example class example
{ {
public: public:
example(); example();
example( const example & );
example & operator=( const example & );
void do_something(); void do_something();
private: private:
class implementation; class implementation;
boost::shared_ptr< implementation > _imp; // hide implementation details boost::shared_ptr< implementation > _imp; // hide implementation details
}; };

View File

@@ -1,10 +1,5 @@
// Boost shared_ptr_example2_test main program ------------------------------// // Boost shared_ptr_example2_test main program ------------------------------//
// Copyright Beman Dawes 2001.
// See accompanying license for terms and conditions of use.
// See http://www.boost.org/libs/smart_ptr for documentation.
#include "shared_ptr_example2.hpp" #include "shared_ptr_example2.hpp"
int main() int main()

162
shared_ptr_test.cpp Normal file
View File

@@ -0,0 +1,162 @@
#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 <boost/test/test_tools.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
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<X> p(new Y);
shared_ptr<X> p2(new X);
shared_ptr<Y> p3 = shared_dynamic_cast<Y>(p);
shared_ptr<Y> p4 = shared_dynamic_cast<Y>(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<void> p5(p);
std::cout << "--\n";
p.reset();
p2.reset();
p3.reset();
p4.reset();
std::cout << "--\n";
BOOST_TEST(p5.use_count() == 1);
weak_ptr<X> wp1;
BOOST_TEST(wp1.use_count() == 0);
BOOST_TEST(wp1.get() == 0);
weak_ptr<X> wp2 = shared_static_cast<X>(p5);
BOOST_TEST(wp2.use_count() == 1);
BOOST_TEST(wp2.get() != 0);
weak_ptr<Y> wp3 = shared_dynamic_cast<Y>(wp2);
BOOST_TEST(wp3.use_count() == 1);
BOOST_TEST(wp3.get() != 0);
BOOST_TEST(wp2 == wp3);
weak_ptr<X> wp4(wp3);
wp1 = p2;
wp1 = p4;
wp1 = 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<int> p6(get_object(), release_object);
}
BOOST_TEST(cnt == 0);
return 0;
}

View File

@@ -1,30 +1,32 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head>
<title>Smart Pointers</title> <head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> <title>Smart Pointers</title>
<body bgcolor="#ffffff" text="#000000"> </head>
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">Smart
Pointers</h1> <body bgcolor="#FFFFFF" text="#000000">
<p><a href="#Introduction">Introduction</a><br>
<a href="#common_requirements">Common Requirements</a><br> <h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">Smart
<a href="#Exception_Safety">Exception Safety</a><br> Pointers</h1>
<a href="#Exception-specifications">Exception-specifications</a><br>
<a href="#History">History and Acknowledgements</a><br> <p>Smart pointers are objects which store pointers to dynamically allocated
<a href="#References">References</a></p> (heap) objects. They behave much like built-in C++ pointers except that
<h2><a name="Introduction">Introduction</a></h2> they automatically delete the object pointed to at the appropriate
<p>Smart pointers are objects which store pointers to dynamically allocated (heap) time. Smart pointers are particularly useful in the face of exceptions as
objects. They behave much like built-in C++ pointers except that they they ensure proper destruction of dynamically allocated objects. They can also
automatically delete the object pointed to at the appropriate time. Smart be used to keep track of dynamically allocated objects shared by multiple
pointers are particularly useful in the face of exceptions as they ensure owners.</p>
proper destruction of dynamically allocated objects. They can also be used to
keep track of dynamically allocated objects shared by multiple owners.</p> <p>Conceptually, smart pointers are seen as owning the object pointed to, and
<p>Conceptually, smart pointers are seen as owning the object pointed to, and thus thus responsible for deletion of the object when it is no longer needed.</p>
responsible for deletion of the object when it is no longer needed.</p>
<p>The smart pointer library provides five smart pointer class templates:</p> <p>The smart pointer library provides five smart pointer class templates:</p>
<div align="left">
<table border="1" cellpadding="4" cellspacing="0"> <div align="left">
<table border="1" cellpadding="4" cellspacing="4">
<tr> <tr>
<td><a href="scoped_ptr.htm"><b>scoped_ptr</b></a></td> <td><a href="scoped_ptr.htm"><b>scoped_ptr</b></a></td>
<td><a href="../../boost/scoped_ptr.hpp">&lt;boost/scoped_ptr.hpp&gt;</a></td> <td><a href="../../boost/scoped_ptr.hpp">&lt;boost/scoped_ptr.hpp&gt;</a></td>
@@ -50,137 +52,160 @@
<td><a href="../../boost/weak_ptr.hpp">&lt;boost/weak_ptr.hpp&gt;</a></td> <td><a href="../../boost/weak_ptr.hpp">&lt;boost/weak_ptr.hpp&gt;</a></td>
<td>Non-owning observers of an object owned by <b>shared_ptr</b>.</td> <td>Non-owning observers of an object owned by <b>shared_ptr</b>.</td>
</tr> </tr>
<tr>
<td><a href="intrusive_ptr.html"><b>intrusive_ptr</b></a></td>
<td><a href="../../boost/intrusive_ptr.hpp">&lt;boost/intrusive_ptr.hpp&gt;</a></td>
<td>Shared ownership of objects with an embedded reference count.</td>
</tr>
</table> </table>
</div> </div>
<p>These templates are designed to complement the <b>std::auto_ptr</b> template.</p>
<p>They are examples of the "resource acquisition is initialization" idiom <p>These templates are designed to complement the <b>std::auto_ptr</b> template.</p>
described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition,
Section 14.4, Resource Management.</p> <p>They are examples of the &quot;resource acquisition is initialization&quot;
<p>A test program, <a href="test/smart_ptr_test.cpp">smart_ptr_test.cpp</a>, is idiom described in Bjarne Stroustrup's &quot;The C++ Programming Language&quot;,
provided to verify correct operation.</p> 3rd edition, Section 14.4, Resource Management.</p>
<p>A page on <a href="compatibility.htm">compatibility</a> with older versions of
the Boost smart pointer library describes some of the changes since earlier <p>A test program, <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>, is
versions of the smart pointer implementation.</p> provided to verify correct operation.</p>
<p>A page on <a href="smarttests.htm">smart pointer timings</a> will be of interest
to those curious about performance issues.</p> <p>A page on <a href="compatibility.htm">compatibility</a> with older versions of
<P>A page on <A href="sp_techniques.html">smart pointer programming techniques</A> lists the Boost smart pointer library describes some of the changes since earlier versions
some advanced applications of <code>shared_ptr</code> and <code>weak_ptr</code>.</P> of the smart pointer implementation.</p>
<h2><a name="common_requirements">Common Requirements</a></h2>
<p>These smart pointer class templates have a template parameter, <b>T</b>, which <p>A page on <a href="smarttests.htm">smart pointer timings</a> will be of
specifies the type of the object pointed to by the smart pointer. The behavior interest to those curious about performance issues.</p>
of the smart pointer templates is undefined if the destructor or <b>operator delete</b>
for objects of type <b>T</b> throw exceptions.</p> <h2><a name="Common requirements">Common Requirements</a></h2>
<p><b>T</b> may be an incomplete type at the point of smart pointer declaration.
Unless otherwise specified, it is required that <b>T</b> be a complete type at <p>These smart pointer class templates have a template parameter, <b>T</b>, which
points of smart pointer instantiation. Implementations are required to diagnose specifies the type of the object pointed to by the smart pointer. The
(treat as an error) all violations of this requirement, including deletion of behavior of the smart pointer templates is undefined if the destructor or <b>operator delete</b>
an incomplete type. See the description of the <a href="../utility/utility.htm#checked_delete"> for objects of type <b>T</b> throw exceptions.</p>
<b>checked_delete</b></a> function template.</p>
<P>Note that <STRONG>shared_ptr</STRONG> does not have this restriction, as most of <p><b>T</b> may be an incomplete type at the point of smart pointer
its member functions do not require <STRONG>T</STRONG> to be a complete type.</P> declaration. Unless otherwise specified, it is required that <b>T</b>
<h3>Rationale</h3> be a complete type at points of smart pointer instantiation. Implementations are
<p>The requirements on <b>T</b> are carefully crafted to maximize safety yet allow required to diagnose (treat as an error) all violations of this requirement,
handle-body (also called pimpl) and similar idioms. In these idioms a smart including deletion of an incomplete type.
pointer may appear in translation units where <b>T</b> is an incomplete type. See the description of the <a href="../utility/utility.htm#checked_delete"><b>checked_delete</b></a>
This separates interface from implementation and hides implementation from function template.</p>
translation units which merely use the interface. Examples described in the
documentation for specific smart pointers illustrate use of smart pointers in <h3>Rationale</h3>
these idioms.</p>
<p>Note that <b>scoped_ptr</b> requires that <b>T</b> be a complete type at <p>The requirements on <b>T</b> are carefully crafted to maximize safety
destruction time, but <b>shared_ptr</b> does not.</p> yet allow handle-body (also called pimpl) and similar idioms. In these idioms a
<h2><a name="Exception_Safety">Exception Safety</a></h2> smart pointer may appear in translation units where <b>T</b> is an
<p>Several functions in these smart pointer classes are specified as having "no incomplete type. This separates interface from implementation and hides
effect" or "no effect except such-and-such" if an exception is thrown. This implementation from translation units which merely use the interface.
means that when an exception is thrown by an object of one of these classes, Examples described in the documentation for specific smart pointers illustrate
the entire program state remains the same as it was prior to the function call use of smart pointers in these idioms.</p>
which resulted in the exception being thrown. This amounts to a guarantee that
there are no detectable side effects. Other functions never throw exceptions. <p>Note that <b>scoped_ptr</b> requires that <b>T</b> be a complete type
The only exception ever thrown by functions which do throw (assuming <b>T</b> meets at destruction time, but <b>shared_ptr</b> does not.</p>
the <a href="#common_requirements">common requirements</a>) is <b>std::bad_alloc</b>,
and that is thrown only by functions which are explicitly documented as <h2>Exception Safety</h2>
possibly throwing <b>std::bad_alloc</b>.</p>
<h2><a name="Exception-specifications">Exception-specifications</a></h2> <p>Several functions in these smart pointer classes are specified as having
<p>Exception-specifications are not used; see <a href="../../more/lib_guide.htm#Exception-specification"> &quot;no effect&quot; or &quot;no effect except such-and-such&quot; if an
exception-specification rationale</a>.</p> exception is thrown. This means that when an exception is thrown by
<p>All the smart pointer templates contain member functions which can never throw an object of one of these classes, the entire program state remains the same as
exceptions, because they neither throw exceptions themselves nor call other it was prior to the function call which resulted in the exception being
functions which may throw exceptions. These members are indicated by a comment: <code> thrown. This amounts to a guarantee that there are no detectable side
// never throws</code>. effects. Other functions never throw exceptions. The only exception
</p> ever thrown by functions which do throw (assuming <b>T</b> meets the
<p>Functions which destroy objects of the pointed to type are prohibited from <a href="#Common requirements">common requirements</a>) is <b>std::bad_alloc</b>,
throwing exceptions by the <a href="#common_requirements">common requirements</a>.</p> and that is thrown only by functions which are explicitly documented as possibly
<h2><a name="History">History</a> and Acknowledgements</h2> throwing <b>std::bad_alloc</b>.</p>
<p>January 2002. Peter Dimov reworked all four classes, adding features, fixing
bugs, and splitting them into four separate headers, and added <b>weak_ptr</b>. <h2>Exception-specifications</h2>
See the <a href="compatibility.htm">compatibility</a> page for a summary of the
changes.</p> <p>Exception-specifications are not used; see
<p>May 2001. Vladimir Prus suggested requiring a complete type on destruction. <a href="../../more/lib_guide.htm#Exception-specification">exception-specification
Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman rationale</a>.</p>
Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and
others.</p> <p>All the smart pointer templates contain member functions which can never throw exceptions,
<p>November 1999. Darin Adler provided <b>operator ==</b>, <b>operator !=</b>, and <b>std::swap</b> because they neither throw exceptions themselves nor call other functions which
and <b>std::less</b> specializations for shared types.</p> may throw exceptions. These members are indicated by a comment:
<p>September 1999. Luis Coelho provided <b>shared_ptr::swap</b> and <b>shared_array::swap</b></p> <code>// never throws</code>. </p>
<p>May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a
number of suggestions resulting in numerous improvements.</p> <p>Functions which destroy objects of the pointed to type are prohibited from
<p>October 1998. Beman Dawes proposed reviving the original semantics under the throwing exceptions by the <a href="#Common requirements">common requirements</a>.</p>
names <b>safe_ptr</b> and <b>counted_ptr</b>, meeting of Per Andersson, Matt
Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar K<>hl, <h2>History and Acknowledgements</h2>
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 <p>January 2002. Peter Dimov reworked all four classes, adding features, fixing bugs,
follow the <b>std::auto_ptr</b> interface, and various function signatures and and splitting them into four separate headers, and added <b>weak_ptr</b>. See the
semantics were finalized.</p> <a href="compatibility.htm">compatibility</a> page for a summary of the changes.</p>
<p>Over the next three months, several implementations were considered for <b>shared_ptr</b>,
and discussed on the <a href="http://www.boost.org">boost.org</a> mailing list. <p>May 2001. Vladimir Prus suggested requiring a complete type on
The implementation questions revolved around the reference count which must be destruction. Refinement evolved in discussions including Dave Abrahams,
kept, either attached to the pointed to object, or detached elsewhere. Each of Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus,
those variants have themselves two major variants: Shankar Sai, and others.</p>
<ul>
<li> <p>November 1999. Darin Adler provided operator ==, operator !=, and std::swap
Direct detached: the shared_ptr contains a pointer to the object, and a pointer and std::less specializations for shared types.</p>
to the count.
<li> <p>September 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap</p>
Indirect detached: the shared_ptr contains a pointer to a helper object, which
in turn contains a pointer to the object and the count. <p>May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams
<li> made a number of suggestions resulting in numerous improvements. See the
Embedded attached: the count is a member of the object pointed to. revision history in <a href="../../boost/smart_ptr.hpp"><b>smart_ptr.hpp</b></a>
<li> for the specific changes made as a result of their constructive criticism.</p>
Placement attached: the count is attached via operator new manipulations.</li>
</ul> <p>October 1998. In 1994 Greg Colvin proposed to the C++ Standards Committee
<p>Each implementation technique has advantages and disadvantages. We went so far classes named <b>auto_ptr</b> and <b>counted_ptr</b> which
as to run various timings of the direct and indirect approaches, and found that were very similar to what we now call <b>scoped_ptr</b> and <b>shared_ptr</b>.
at least on Intel Pentium chips there was very little measurable difference. The committee document was 94-168/N0555, Exception Safe Smart Pointers. In
Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar one of the very few cases where the Library Working Group's recommendations were
K<>hl suggested an elegant partial template specialization technique to allow not followed by the full committee, <b>counted_ptr</b> was rejected
users to choose which implementation they preferred, and that was also and surprising transfer-of-ownership semantics were added to <b>auto_ptr</b>.</p>
experimented with.</p>
<p>But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage <p>Beman Dawes proposed reviving the original semantics under the names <b>safe_ptr</b>
users", and in the end we choose to supply only the direct implementation.</p> and <b>counted_ptr</b> at an October, 1998, meeting of Per Andersson,
<p>Summer, 1994. Greg Colvin proposed to the C++ Standards Committee classes named <b>auto_ptr</b> Matt Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar
and <b>counted_ptr</b> which were very similar to what we now call <b>scoped_ptr</b> K<EFBFBD>hl, Nathan Myers, Chichiang Wan and Judy Ward. During the discussion,
and <b>shared_ptr</b>. <a href="#Col-94">[Col-94]</a> In one of the very few the four class names were finalized, it was decided that there was no need to
cases where the Library Working Group's recommendations were not followed by exactly follow the <b>std::auto_ptr</b> interface, and various
the full committee, <b>counted_ptr</b> was rejected and surprising function signatures and semantics were finalized.</p>
transfer-of-ownership semantics were added to <b>auto_ptr</b>.</p>
<h2><a name="References">References</a></h2> <p>Over the next three months, several implementations were considered for <b>shared_ptr</b>,
<p>[<a name="Col-94">Col-94</a>] Gregory Colvin, <a href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/1994/N0555.pdf"> and discussed on the <a href="http://www.boost.org">boost.org</a> mailing
Exception Safe Smart Pointers</a>, C++ committee document 94-168/N0555, list. The implementation questions revolved around the reference count
July, 1994.</p> which must be kept, either attached to the pointed to object, or detached
<p>[<a name="E&amp;D-94">E&amp;D-94</a>] John R. Ellis &amp; David L. Detlefs, <a href="http://www.usenix.org/publications/library/proceedings/c++94/full_papers/ellis.a"> elsewhere. Each of those variants have themselves two major variants:
Safe, Efficient Garbage Collection for C++</a>, Usenix Proceedings,
February, 1994. This paper includes an extensive discussion of weak pointers <ul>
and an extensive bibliography.</p> <li>Direct detached: the shared_ptr contains a pointer to the object, and a
<hr> pointer to the count.</li>
<p>$Date$</p> <li>Indirect detached: the shared_ptr contains a pointer to a helper object,
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. which in turn contains a pointer to the object and the count.</li>
Permission to copy, use, modify, sell and distribute this document is granted <li>Embedded attached: the count is a member of the object pointed to.</li>
provided this copyright notice appears in all copies. This document is provided <li>Placement attached: the count is attached via operator new manipulations.</li>
"as is" without express or implied warranty, and with no claim as to its </ul>
suitability for any purpose.</p>
</body> <p>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 &quot;Counted Body
Techniques.&quot; 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.</p>
<p>But Greg Colvin and Jerry Schwarz argued that &quot;parameterization will
discourage users&quot;, and in the end we choose to supply only the direct
implementation.</p>
<p>See the Revision History section of the header for further contributors.</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan
-->4 February 2002<!--webbot bot="Timestamp" endspan i-checksum="40737"
--></p>
<p>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 &quot;as is&quot;
without express or implied warranty, and with no claim as to its suitability for
any purpose.</p>
</body>
</html> </html>

295
smart_ptr_test.cpp Normal file
View File

@@ -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 <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <cstring>
#include <iostream>
#include <set>
bool boost_error(char const *, char const *, char const *, long)
{
return true; // fail with assert()
}
class Incomplete;
Incomplete * get_ptr( boost::shared_ptr<Incomplete>& incomplete )
{
return incomplete.get();
}
using namespace std;
using boost::scoped_ptr;
using boost::scoped_array;
using boost::shared_ptr;
using boost::shared_array;
template<typename T>
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\n";
}
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>& incomplete )
{
return incomplete.get();
}
Incomplete * check_incomplete( shared_ptr<Incomplete>& incomplete,
shared_ptr<Incomplete>& i2 )
{
incomplete.swap(i2);
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 ** ) {
BOOST_TEST( UDT_use_count == 0 ); // reality check
// test scoped_ptr with a built-in type
long * lp = new long;
scoped_ptr<long> 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<long*>(sp.get()), 1234568901L );
ck( lp, *sp );
sp.reset();
BOOST_TEST( sp.get() == 0 );
// test scoped_ptr with a user defined type
scoped_ptr<UDT> 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<char> 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<int> 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<int*>(cp.get()), 54321 );
ck( static_cast<int*>(ip), *cp );
shared_ptr<int> 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<int*>(cp2.get()), 54321 );
ck( static_cast<int*>(ip), *cp2 );
shared_ptr<int> 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<int> cp4;
swap( cp2, cp4 );
BOOST_TEST( cp4.use_count() == 3 );
BOOST_TEST( *cp4 == 87654 );
BOOST_TEST( cp2.get() == 0 );
set< shared_ptr<int> > scp;
scp.insert(cp4);
BOOST_TEST( scp.find(cp4) != scp.end() );
BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) );
// test shared_array with a built-in type
char * cap = new char [ 100 ];
shared_array<char> 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<char> ca2 ( ca );
shared_array<char> 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<char> 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<char> > sca;
sca.insert(ca4);
BOOST_TEST( sca.find(ca4) != sca.end() );
BOOST_TEST( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) );
// test shared_array with user defined type
shared_array<UDT> udta ( new UDT[3] );
udta[0].value( 111 );
udta[1].value( 222 );
udta[2].value( 333 );
shared_array<UDT> 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<UDT> 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<UDT> 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
return 0;
} // main

View File

@@ -22,7 +22,7 @@
a guide for current and future investigations into smart pointer implementation a guide for current and future investigations into smart pointer implementation
strategies.</p> strategies.</p>
<p>Thanks are due to <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>, <p>Thanks are due to <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>,
Gavin Collings, <a href="../../people/gavin_collings.htm">Gavin Collings</a>,
<a href="../../people/greg_colvin.htm">Greg Colvin</a> and <a href="../../people/greg_colvin.htm">Greg Colvin</a> and
<a href="../../people/beman_dawes.html">Beman Dawes</a> <a href="../../people/beman_dawes.html">Beman Dawes</a>
for test code and trial implementations, the final version of which can be found for test code and trial implementations, the final version of which can be found

View File

@@ -1,760 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Smart Pointer Programming Techniques</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body text="#000000" bgColor="#ffffff">
<h1><IMG height="86" alt="c++boost.gif (8819 bytes)" src="../../c++boost.gif" width="277" align="middle">Smart
Pointer Programming Techniques</h1>
<p><A href="#incomplete">Using incomplete classes for implementation hiding</A><br>
<A href="#pimpl">The "Pimpl" idiom</A><br>
<A href="#abstract">Using abstract classes for implementation hiding</A><br>
<A href="#preventing_delete">Preventing <code>delete px.get()</code></A><br>
<A href="#array">Using a <code>shared_ptr</code> to hold a pointer to an array</A><br>
<A href="#encapsulation">Encapsulating allocation details, wrapping factory
functions</A><br>
<A href="#static">Using a <code>shared_ptr</code> to hold a pointer to a statically
allocated object</A><br>
<A href="#com">Using a <code>shared_ptr</code> to hold a pointer to a COM object</A><br>
<A href="#intrusive">Using a <code>shared_ptr</code> to hold a pointer to an object
with an embedded reference count</A><br>
<A href="#another_sp">Using a <code>shared_ptr</code> to hold another shared
ownership smart pointer</A><br>
<A href="#from_raw">Obtaining a <code>shared_ptr</code> from a raw pointer</A><br>
<A href="#in_constructor">Obtaining a <code>shared_ptr</code> (<code>weak_ptr</code>)
to <code>this</code> in a constructor</A><br>
<A href="#from_this">Obtaining a <code>shared_ptr</code> to <code>this</code></A><br>
<A href="#handle">Using <code>shared_ptr</code> as a smart counted handle</A><br>
<A href="#on_block_exit">Using <code>shared_ptr</code> to execute code on block
exit</A><br>
<A href="#pvoid">Using <code>shared_ptr&lt;void&gt;</code> to hold an arbitrary
object</A><br>
<A href="#extra_data">Associating arbitrary data with heterogeneous <code>shared_ptr</code>
instances</A><br>
<A href="#as_lock">Using <code>shared_ptr</code> as a CopyConstructible mutex lock</A><br>
<A href="#wrapper">Using <code>shared_ptr</code> to wrap member function calls</A><br>
<A href="#delayed">Delayed deallocation</A><br>
<A href="#weak_without_shared">Weak pointers to objects not managed by a <code>shared_ptr</code></A><br>
</p>
<h2><A name="incomplete">Using incomplete classes for implementation hiding</A></h2>
<p>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:</p>
<pre>class FILE;
FILE * fopen(char const * name, char const * mode);
void fread(FILE * f, void * data, size_t size);
void fclose(FILE * f);
</pre>
<p>It is possible to express the above interface using <code>shared_ptr</code>,
eliminating the need to manually call <code>fclose</code>:</p>
<pre>class FILE;
shared_ptr&lt;FILE&gt; fopen(char const * name, char const * mode);
void fread(shared_ptr&lt;FILE&gt; f, void * data, size_t size);
</pre>
<p>This technique relies on <code>shared_ptr</code>'s ability to execute a custom
deleter, eliminating the explicit call to <code>fclose</code>, and on the fact
that <code>shared_ptr&lt;X&gt;</code> can be copied and destroyed when <code>X</code>
is incomplete.</p>
<h2><A name="pimpl">The "Pimpl" idiom</A></h2>
<p>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. <code>shared_ptr</code> can be used to implement a "Pimpl":</p>
<pre>// file.hpp:
class file
{
private:
class impl;
shared_ptr&lt;impl&gt; pimpl_;
public:
file(char const * name, char const * mode);
// compiler generated members are fine and useful
void read(void * data, size_t size);
};
</pre>
<pre>// file.cpp:
#include "file.hpp"
class file::impl
{
private:
impl(impl const &amp;);
impl &amp; operator=(impl const &amp;);
// 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_-&gt;read(data, size);
}
</pre>
<p>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, <code>
file</code> is <code>CopyConstructible</code> and <code>Assignable</code>,
allowing its use in standard containers.</p>
<h2><A name="abstract">Using abstract classes for implementation hiding</A></h2>
<p>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, <code>shared_ptr</code> can be used as the return type of
the factory functions:</p>
<pre>// X.hpp:
class X
{
public:
virtual void f() = 0;
virtual void g() = 0;
protected:
~X() {}
};
shared_ptr&lt;X&gt; createX();
</pre>
<pre>-- X.cpp:
class X_impl: public X
{
private:
X_impl(X_impl const &amp;);
X_impl &amp; operator=(X_impl const &amp;);
public:
virtual void f()
{
// ...
}
virtual void g()
{
// ...
}
};
shared_ptr&lt;X&gt; createX()
{
shared_ptr&lt;X&gt; px(new X_impl);
return px;
}
</pre>
<p>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 <code>X</code>;
the <code>shared_ptr&lt;X&gt;</code> instance returned from <code>createX</code>
will correctly call <code>~X_impl</code>.</p>
<h2><A name="preventing_delete">Preventing <code>delete px.get()</code></A></h2>
<p>It is often desirable to prevent client code from deleting a pointer that is
being managed by <code>shared_ptr</code>. The previous technique showed one
possible approach, using a protected destructor. Another alternative is to use
a private deleter:</p>
<pre>class X
{
private:
~X();
class deleter;
friend class deleter;
class deleter
{
public:
void operator()(X * p) { delete p; }
};
public:
static shared_ptr&lt;X&gt; create()
{
shared_ptr&lt;X&gt; px(new X, X::deleter());
return px;
}
};
</pre>
<h2><A name="array">Using a <code>shared_ptr</code> to hold a pointer to an array</A></h2>
<p>A <code>shared_ptr</code> can be used to hold a pointer to an array allocated
with <code>new[]</code>:</p>
<pre>shared_ptr&lt;X&gt; px(new X[1], <A href="../utility/checked_delete.html" >checked_array_deleter</A>&lt;X&gt;());
</pre>
<p>Note, however, that <code><A href="shared_array.htm">shared_array</A></code> is
often preferable, if this is an option. It has an array-specific interface,
without <code>operator*</code> and <code>operator-&gt;</code>, and does not
allow pointer conversions.</p>
<h2><A name="encapsulation">Encapsulating allocation details, wrapping factory
functions</A></h2>
<p><code>shared_ptr</code> 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 <code>CreateX</code> might allocate <code>X</code> from its own private
heap, <code>~X</code> may be inaccessible, or <code>X</code> may be incomplete:</p>
<pre>X * CreateX();
void DestroyX(X *);
</pre>
<p>The only way to reliably destroy a pointer returned by <code>CreateX</code> is
to call <code>DestroyX</code>.</p>
<P>Here is how a <code>shared_ptr</code>-based wrapper may look like:</P>
<pre>shared_ptr&lt;X&gt; createX()
{
shared_ptr&lt;X&gt; px(CreateX(), DestroyX);
return px;
}
</pre>
<p>Client code that calls <code>createX</code> still does not need to know how the
object has been allocated, but now the destruction is automatic.</p>
<h2><A name="static">Using a <code>shared_ptr</code> to hold a pointer to a statically
allocated object</A></h2>
<p>Sometimes it is desirable to create a <code>shared_ptr</code> to an already
existing object, so that the <code>shared_ptr</code> does not attempt to
destroy the object when there are no more references left. As an example, the
factory function:</p>
<pre>shared_ptr&lt;X&gt; createX();
</pre>
<p>in certain situations may need to return a pointer to a statically allocated <code>X</code>
instance.</p>
<P>The solution is to use a custom deleter that does nothing:</P>
<pre>struct null_deleter
{
void operator()(void const *) const
{
}
};
static X x;
shared_ptr&lt;X&gt; createX()
{
shared_ptr&lt;X&gt; px(&amp;x, null_deleter());
return px;
}
</pre>
<p>The same technique works for any object known to outlive the pointer.</p>
<h2><A name="com">Using a <code>shared_ptr</code> to hold a pointer to a COM Object</A></h2>
<p>Background: COM objects have an embedded reference count and two member
functions that manipulate it. <code>AddRef()</code> increments the count. <code>Release()</code>
decrements the count and destroys itself when the count drops to zero.</p>
<P>It is possible to hold a pointer to a COM object in a <code>shared_ptr</code>:</P>
<pre>shared_ptr&lt;IWhatever&gt; make_shared_from_COM(IWhatever * p)
{
p-&gt;AddRef();
shared_ptr&lt;IWhatever&gt; pw(p, <A href="../bind/mem_fn.html" >mem_fn</A>(&amp;IWhatever::Release));
return pw;
}
</pre>
<p>Note, however, that <code>shared_ptr</code> copies created from <code>pw</code> will
not "register" in the embedded count of the COM object; they will share the
single reference created in <code>make_shared_from_COM</code>. Weak pointers
created from <code>pw</code> will be invalidated when the last <code>shared_ptr</code>
is destroyed, regardless of whether the COM object itself is still alive.</p>
<h2><A name="intrusive">Using a <code>shared_ptr</code> to hold a pointer to an object
with an embedded reference count</A></h2>
<p>This is a generalization of the above technique. The example assumes that the
object implements the two functions required by <code><A href="intrusive_ptr.html">intrusive_ptr</A></code>,
<code>intrusive_ptr_add_ref</code> and <code>intrusive_ptr_release</code>:</p>
<pre>template&lt;class T&gt; struct intrusive_deleter
{
void operator()(T * p)
{
if(p) intrusive_ptr_release(p);
}
};
shared_ptr&lt;X&gt; make_shared_from_intrusive(X * p)
{
if(p) intrusive_ptr_add_ref(p);
shared_ptr&lt;X&gt; px(p, intrusive_deleter&lt;X&gt;());
return px;
}
</pre>
<h2><A name="another_sp">Using a <code>shared_ptr</code> to hold another shared
ownership smart pointer</A></h2>
<p>One of the design goals of <code>shared_ptr</code> is to be used in library
interfaces. It is possible to encounter a situation where a library takes a <code>shared_ptr</code>
argument, but the object at hand is being managed by a different reference
counted or linked smart pointer.</p>
<P>It is possible to exploit <code>shared_ptr</code>'s custom deleter feature to
wrap this existing smart pointer behind a <code>shared_ptr</code> facade:</P>
<pre>template&lt;class P&gt; struct smart_pointer_deleter
{
private:
P p_;
public:
smart_pointer_deleter(P const &amp; p): p_(p)
{
}
void operator()(void const *)
{
p_.reset();
}
P const &amp; get() const
{
return p_;
}
};
shared_ptr&lt;X&gt; make_shared_from_another(another_ptr&lt;X&gt; qx)
{
shared_ptr&lt;X&gt; px(qx.get(), smart_pointer_deleter&lt; another_ptr&lt;X&gt; &gt;(qx));
return px;
}
</pre>
<p>One subtle point is that deleters are not allowed to throw exceptions, and the
above example as written assumes that <code>p_.reset()</code> doesn't throw. If
this is not the case, <code>p_.reset()</code> should be wrapped in a <code>try {}
catch(...) {}</code> block that ignores exceptions. In the (usually
unlikely) event when an exception is thrown and ignored, <code>p_</code> will
be released when the lifetime of the deleter ends. This happens when all
references, including weak pointers, are destroyed or reset.</p>
<P>Another twist is that it is possible, given the above <code>shared_ptr</code> instance,
to recover the original smart pointer, using <code><A href="shared_ptr.htm#get_deleter">
get_deleter</A></code>:</P>
<pre>void extract_another_from_shared(shared_ptr&lt;X&gt; px)
{
typedef smart_pointer_deleter&lt; another_ptr&lt;X&gt; &gt; deleter;
if(deleter const * pd = get_deleter&lt;deleter&gt;(px))
{
another_ptr&lt;X&gt; qx = pd-&gt;get();
}
else
{
// not one of ours
}
}
</pre>
<h2><A name="from_raw">Obtaining a <code>shared_ptr</code> from a raw pointer</A></h2>
<p>Sometimes it is necessary to obtain a <code>shared_ptr</code> given a raw
pointer to an object that is already managed by another <code>shared_ptr</code>
instance. Example:</p>
<pre>void f(X * p)
{
shared_ptr&lt;X&gt; px(<i>???</i>);
}
</pre>
<p>Inside <code>f</code>, we'd like to create a <code>shared_ptr</code> to <code>*p</code>.</p>
<P>In the general case, this problem has no solution. One approach is to modify <code>f</code>
to take a <code>shared_ptr</code>, if possible:</P>
<pre>void f(shared_ptr&lt;X&gt; px);
</pre>
<p>The same transformation can be used for nonvirtual member functions, to convert
the implicit <code>this</code>:</p>
<pre>void X::f(int m);
</pre>
<p>would become a free function with a <code>shared_ptr</code> first argument:</p>
<pre>void f(shared_ptr&lt;X&gt; this_, int m);
</pre>
<p>If <code>f</code> cannot be changed, but <code>X</code> uses intrusive counting,
use <code><A href="#intrusive">make_shared_from_intrusive</A></code> described
above. Or, if it's known that the <code>shared_ptr</code> created in <code>f</code>
will never outlive the object, use <A href="#static">a null deleter</A>.</p>
<h2><A name="in_constructor">Obtaining a <code>shared_ptr</code> (<code>weak_ptr</code>)
to <code>this</code> in a constructor</A></h2>
<p>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:</p>
<pre>class X
{
public:
X()
{
shared_ptr&lt;X&gt; this_(<i>???</i>);
}
};
</pre>
<p>In the general case, the problem cannot be solved. The <code>X</code> instance
being constructed can be an automatic variable or a static variable; it can be
created on the heap:</p>
<pre>shared_ptr&lt;X&gt; px(new X);</pre>
<P>but at construction time, <code>px</code> does not exist yet, and it is
impossible to create another <code>shared_ptr</code> instance that shares
ownership with it.</P>
<P>Depending on context, if the inner <code>shared_ptr</code> <code>this_</code> doesn't
need to keep the object alive, use a <code>null_deleter</code> as explained <A href="#static">
here</A> and <A href="#weak_without_shared">here</A>. If <code>X</code> is
supposed to always live on the heap, and be managed by a <code>shared_ptr</code>,
use a static factory function:</P>
<pre>class X
{
private:
X() { ... }
public:
static shared_ptr&lt;X&gt; create()
{
shared_ptr&lt;X&gt; px(new X);
// use px as 'this_'
return px;
}
};
</pre>
<h2><A name="from_this">Obtaining a <code>shared_ptr</code> to <code>this</code></A></h2>
<p>Sometimes it is needed to obtain a <code>shared_ptr</code> from <code>this</code>
in a virtual member function under the assumption that <code>this</code> is
already managed by a <code>shared_ptr</code>. The transformations <A href="#from_raw">
described in the previous technique</A> cannot be applied.</p>
<P>A typical example:</P>
<pre>class X
{
public:
virtual void f() = 0;
protected:
~X() {}
};
class Y
{
public:
virtual shared_ptr&lt;X&gt; getX() = 0;
protected:
~Y() {}
};
// --
class impl: public X, public Y
{
public:
impl() { ... }
virtual void f() { ... }
virtual shared_ptr&lt;X&gt; getX()
{
shared_ptr&lt;X&gt; px(<i>???</i>);
return px;
}
};
</pre>
<p>The solution is to keep a weak pointer to <code>this</code> as a member in <code>impl</code>:</p>
<pre>class impl: public X, public Y
{
private:
weak_ptr&lt;impl&gt; weak_this;
impl(impl const &amp;);
impl &amp; operator=(impl const &amp;);
impl() { ... }
public:
static shared_ptr&lt;impl&gt; create()
{
shared_ptr&lt;impl&gt; pi(new impl);
pi-&gt;weak_this = pi;
return pi;
}
virtual void f() { ... }
virtual shared_ptr&lt;X&gt; getX()
{
shared_ptr&lt;X&gt; px(weak_this);
return px;
}
};
</pre>
<p>The library now includes a helper class template <code><A href="enable_shared_from_this.html">
enable_shared_from_this</A></code> that can be used to encapsulate the
solution:</p>
<pre>class impl: public X, public Y, public enable_shared_from_this&lt;impl&gt;
{
public:
impl(impl const &amp;);
impl &amp; operator=(impl const &amp;);
public:
virtual void f() { ... }
virtual shared_ptr&lt;X&gt; getX()
{
return shared_from_this();
}
}
</pre>
<h2><A name="handle">Using <code>shared_ptr</code> as a smart counted handle</A></h2>
<p>Some library interfaces use opaque handles, a variation of the <A href="#incomplete">
incomplete class technique</A> described above. An example:</p>
<pre>typedef void * HANDLE;
HANDLE CreateProcess();
void CloseHandle(HANDLE);
</pre>
<p>Instead of a raw pointer, it is possible to use <code>shared_ptr</code> as the
handle and get reference counting and automatic resource management for free:</p>
<pre>typedef shared_ptr&lt;void&gt; handle;
handle createProcess()
{
shared_ptr&lt;void&gt; pv(CreateProcess(), CloseHandle);
return pv;
}
</pre>
<h2><A name="on_block_exit">Using <code>shared_ptr</code> to execute code on block exit</A></h2>
<p><code>shared_ptr&lt;void&gt;</code> can automatically execute cleanup code when
control leaves a scope.</p>
<UL>
<LI>
Executing <code>f(p)</code>, where <code>p</code> is a pointer:</LI></UL>
<pre> shared_ptr&lt;void&gt; guard(p, f);
</pre>
<UL>
<LI>
Executing arbitrary code: <code>f(x, y)</code>:</LI></UL>
<pre> shared_ptr&lt;void&gt; guard(static_cast&lt;void*&gt;(0), <A href="../bind/bind.html" >bind</A>(f, x, y));
</pre>
<P>For a more thorough treatment, see the article "Simplify Your Exception-Safe
Code" by Andrei Alexandrescu and Petru Marginean, available online at <A href="http://www.cuj.com/experts/1812/alexandr.htm?topic=experts">
http://www.cuj.com/experts/1812/alexandr.htm?topic=experts</A>.</P>
<h2><A name="pvoid">Using <code>shared_ptr&lt;void&gt;</code> to hold an arbitrary
object</A></h2>
<p><code>shared_ptr&lt;void&gt;</code> can act as a generic object pointer similar
to <code>void*</code>. When a <code>shared_ptr&lt;void&gt;</code> instance
constructed as:</p>
<pre> shared_ptr&lt;void&gt; pv(new X);
</pre>
<p>is destroyed, it will correctly dispose of the <code>X</code> object by
executing <code>~X</code>.</p>
<p>This propery can be used in much the same manner as a raw <code>void*</code> is
used to temporarily strip type information from an object pointer. A <code>shared_ptr&lt;void&gt;</code>
can later be cast back to the correct type by using <code><A href="shared_ptr.htm#static_pointer_cast">
static_pointer_cast</A></code>.</p>
<h2><A name="extra_data">Associating arbitrary data with heterogeneous <code>shared_ptr</code>
instances</A></h2>
<p><code>shared_ptr</code> and <code>weak_ptr</code> support <code>operator&lt;</code>
comparisons required by standard associative containers such as <code>std::map</code>.
This can be used to non-intrusively associate arbitrary data with objects
managed by <code>shared_ptr</code>:</p>
<pre>typedef int Data;
std::map&lt; shared_ptr&lt;void&gt;, Data &gt; userData;
// or std::map&lt; weak_ptr&lt;void&gt;, Data &gt; userData; to not affect the lifetime
shared_ptr&lt;X&gt; px(new X);
shared_ptr&lt;int&gt; pi(new int(3));
userData[px] = 42;
userData[pi] = 91;
</pre>
<h2><A name="as_lock">Using <code>shared_ptr</code> as a CopyConstructible mutex lock</A></h2>
<p>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 <code>shared_ptr</code>
as a mutex lock:</p>
<pre>class mutex
{
public:
void lock();
void unlock();
};
shared_ptr&lt;mutex&gt; lock(mutex &amp; m)
{
m.lock();
return shared_ptr&lt;mutex&gt;(&amp;m, mem_fn(&amp;mutex::unlock));
}
</pre>
<p>Better yet, the <code>shared_ptr</code> instance acting as a lock can be
encapsulated in a dedicated <code>shared_lock</code> class:</p>
<pre>class shared_lock
{
private:
shared_ptr&lt;void&gt; pv;
public:
template&lt;class Mutex&gt; explicit shared_lock(Mutex &amp; m): pv((m.lock(), &amp;m), mem_fn(&amp;Mutex::unlock)) {}
};
</pre>
<p><code>shared_lock</code> can now be used as:</p>
<pre> shared_lock lock(m);
</pre>
<p>Note that <code>shared_lock</code> is not templated on the mutex type, thanks to <code>
shared_ptr&lt;void&gt;</code>'s ability to hide type information.</p>
<h2><A name="wrapper">Using <code>shared_ptr</code> to wrap member function calls</A></h2>
<p><code>shared_ptr</code> implements the ownership semantics required from the <code>Wrap</code>/<code>CallProxy</code>
scheme described in Bjarne Stroustrup's article "Wrapping C++ Member Function
Calls" (available online at <A href="http://www.research.att.com/~bs/wrapper.pdf">http://www.research.att.com/~bs/wrapper.pdf</A>).
An implementation is given below:</p>
<pre>template&lt;class T&gt; class pointer
{
private:
T * p_;
public:
explicit pointer(T * p): p_(p)
{
}
shared_ptr&lt;T&gt; operator-&gt;() const
{
p_-&gt;prefix();
return shared_ptr&lt;T&gt;(p_, <A href="../bind/mem_fn.html" >mem_fn</A>(&amp;T::suffix));
}
};
class X
{
private:
void prefix();
void suffix();
friend class pointer&lt;X&gt;;
public:
void f();
void g();
};
int main()
{
X x;
pointer&lt;X&gt; px(&amp;x);
px-&gt;f();
px-&gt;g();
}
</pre>
<h2><A name="delayed">Delayed deallocation</A></h2>
<p>In some situations, a single <code>px.reset()</code> can trigger an expensive
deallocation in a performance-critical region:</p>
<pre>class X; // ~X is expensive
class Y
{
shared_ptr&lt;X&gt; px;
public:
void f()
{
px.reset();
}
};
</pre>
<p>The solution is to postpone the potential deallocation by moving <code>px</code>
to a dedicated free list that can be periodically emptied when performance and
response times are not an issue:</p>
<pre>vector&lt; shared_ptr&lt;void&gt; &gt; free_list;
class Y
{
shared_ptr&lt;X&gt; px;
public:
void f()
{
free_list.push_back(px);
px.reset();
}
};
// periodically invoke free_list.clear() when convenient
</pre>
<p>Another variation is to move the free list logic to the construction point by
using a delayed deleter:</p>
<pre>struct delayed_deleter
{
template&lt;class T&gt; void operator()(T * p)
{
try
{
shared_ptr&lt;void&gt; pv(p);
free_list.push_back(pv);
}
catch(...)
{
}
}
};
</pre>
<h2><A name="weak_without_shared">Weak pointers to objects not managed by a <code>shared_ptr</code></A></h2>
<p>Make the object hold a <code>shared_ptr</code> to itself, using a <code>null_deleter</code>:</p>
<pre>class X
{
private:
shared_ptr&lt;X&gt; 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 &amp; rhs): this_(this, null_deleter()), i_(rhs.i_)
{
}
// do not forget to not assign this_ in the copy assignment
X &amp; operator=(X const &amp; rhs)
{
i_ = rhs.i_;
}
weak_ptr&lt;X&gt; get_weak_ptr() const { return this_; }
};
</pre>
<p>When the object's lifetime ends, <code>X::this_</code> will be destroyed, and
all weak pointers will automatically expire.</p>
<hr>
<p>$Date$</p>
<p><small>Copyright <20> 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.</small></p>
</body>
</html>

View File

@@ -1,269 +0,0 @@
//
// 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_SP_ENABLE_DEBUG_HOOKS)
#include <boost/assert.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/detail/lightweight_mutex.hpp>
#include <cstdlib>
#include <map>
#include <deque>
#include <iostream>
typedef std::map< void const *, std::pair<void *, size_t> > 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<void const *, long> 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<unsigned char const *>(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<shared_ptr_layout const *>(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<void const *> 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<unsigned char const *>(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<shared_ptr_layout const *>(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<boost::detail::sp_counted_base const *>(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<boost::detail::sp_counted_base const *>(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<X> > 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<unsigned char *>(area);
for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)
{
shared_ptr_layout * q = reinterpret_cast<shared_ptr_layout *>(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<X> * ppx = reinterpret_cast< boost::shared_ptr<X> * >(p);
free.push_back(*ppx);
ppx->reset();
}
}
}
void free_unreachable_objects()
{
free_list_type free;
{
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);
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_SP_ENABLE_DEBUG_HOOKS)

View File

@@ -1,244 +0,0 @@
//
// sp_debug_hooks.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_SP_ENABLE_DEBUG_HOOKS)
#include <boost/assert.hpp>
#include <new>
#include <cstdlib>
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;
int const adopted_array = 0x0567890A;
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);
set_new_handler(p);
return p;
}
static void * allocate(size_t n, int mark)
{
int * pm;
for(;;)
{
pm = static_cast<int*>(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
// debug hooks
namespace boost
{
void sp_scalar_constructor_hook(void * p)
{
if(p == 0) return;
int * pm = static_cast<int*>(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_constructor_hook(void * px, std::size_t, void *)
{
sp_scalar_constructor_hook(px);
}
void sp_scalar_destructor_hook(void * p)
{
if(p == 0) return;
int * pm = static_cast<int*>(p);
pm -= m;
BOOST_ASSERT(*pm == adopted_scalar); // attempt to destroy nonmanaged block
*pm = allocated_scalar;
}
void sp_scalar_destructor_hook(void * px, std::size_t, void *)
{
sp_scalar_destructor_hook(px);
}
// 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<int*>(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<int*>(p);
pm -= m;
BOOST_ASSERT(*pm == adopted_array); // attempt to destroy nonmanaged block
*pm = allocated_array;
*/
}
} // namespace boost
// operator delete
void operator delete(void * p) throw()
{
if(p == 0) return;
int * pm = static_cast<int*>(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<int*>(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_SP_ENABLE_DEBUG_HOOKS)

View File

@@ -1,41 +0,0 @@
# 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 ;
# 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 : : : <gcc><*><cxxflags>-Wno-non-virtual-dtor ]
[ run shared_ptr_test.cpp : : : <gcc><*><cxxflags>-Wno-non-virtual-dtor ]
[ run weak_ptr_test.cpp ]
[ run shared_from_this_test.cpp : : : <gcc><*><cxxflags>-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 [ in-invocation-subdir ]
{
run shared_ptr_alloc_test.cpp ;
}
}

View File

@@ -1,36 +0,0 @@
# 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 : : : <toolset><gcc>:<cxxflags>-Wno-non-virtual-dtor ]
[ run shared_ptr_test.cpp : : : <toolset>gcc:<cxxflags>-Wno-non-virtual-dtor ]
[ run weak_ptr_test.cpp ]
[ run shared_from_this_test.cpp : : : <toolset>gcc:<cxxflags>-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 ;
#}
}

View File

@@ -1,100 +0,0 @@
//
// 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 <boost/shared_ptr.hpp>
#include <vector>
#include <iostream>
#include <cstdlib>
#include <ctime>
// 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<X> 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<double>(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<double>(t) / CLOCKS_PER_SEC << " seconds.\n";
}
int main()
{
std::vector< boost::shared_ptr<X> > 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<X>(new X));
v2.push_back(boost::shared_ptr<X>(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();
}

View File

@@ -1,96 +0,0 @@
//
// 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 <boost/shared_ptr.hpp>
#include <boost/detail/lightweight_test.hpp>
struct deleter
{
int data;
deleter(): data(0)
{
}
void operator()(void *)
{
BOOST_TEST(data == 17041);
}
};
struct deleter2
{
};
struct X
{
};
int main()
{
{
boost::shared_ptr<X> p;
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
}
{
boost::shared_ptr<X> p(new X);
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
}
{
X x;
boost::shared_ptr<X> p(&x, deleter());
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
deleter * q = boost::get_deleter<deleter>(p);
BOOST_TEST(q != 0);
BOOST_TEST(q->data == 0);
q->data = 17041;
deleter const * r = boost::get_deleter<deleter const>(p);
BOOST_TEST(r == q);
BOOST_TEST(r->data == 17041);
}
return boost::report_errors();
}

View File

@@ -1,561 +0,0 @@
#include <boost/config.hpp>
#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_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 <boost/detail/lightweight_test.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/config.hpp>
#include <algorithm>
#include <functional>
//
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<X>::element_type T;
T t;
f(t);
}
} // namespace n_element_type
namespace n_constructors
{
void default_constructor()
{
boost::intrusive_ptr<X> px;
BOOST_TEST(px.get() == 0);
}
void pointer_constructor()
{
{
boost::intrusive_ptr<X> px(0);
BOOST_TEST(px.get() == 0);
}
{
boost::intrusive_ptr<X> px(0, false);
BOOST_TEST(px.get() == 0);
}
{
X * p = new X;
BOOST_TEST(p->use_count() == 0);
boost::intrusive_ptr<X> 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<X> px(p, false);
BOOST_TEST(px.get() == p);
BOOST_TEST(px->use_count() == 1);
}
}
void copy_constructor()
{
{
boost::intrusive_ptr<X> px;
boost::intrusive_ptr<X> px2(px);
BOOST_TEST(px2.get() == px.get());
}
{
boost::intrusive_ptr<Y> py;
boost::intrusive_ptr<X> px(py);
BOOST_TEST(px.get() == py.get());
}
{
boost::intrusive_ptr<X> px(0);
boost::intrusive_ptr<X> px2(px);
BOOST_TEST(px2.get() == px.get());
}
{
boost::intrusive_ptr<Y> py(0);
boost::intrusive_ptr<X> px(py);
BOOST_TEST(px.get() == py.get());
}
{
boost::intrusive_ptr<X> px(0, false);
boost::intrusive_ptr<X> px2(px);
BOOST_TEST(px2.get() == px.get());
}
{
boost::intrusive_ptr<Y> py(0, false);
boost::intrusive_ptr<X> px(py);
BOOST_TEST(px.get() == py.get());
}
{
boost::intrusive_ptr<X> px(new X);
boost::intrusive_ptr<X> px2(px);
BOOST_TEST(px2.get() == px.get());
}
{
boost::intrusive_ptr<Y> py(new Y);
boost::intrusive_ptr<X> 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<X> px(new X);
BOOST_TEST(px->use_count() == 1);
{
boost::intrusive_ptr<X> 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<X> 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<X> 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<X> 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<X> px;
boost::intrusive_ptr<X> 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<X> px;
boost::intrusive_ptr<X> px2(p);
boost::intrusive_ptr<X> 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<X> px(p1);
boost::intrusive_ptr<X> px2(p2);
boost::intrusive_ptr<X> 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<class T, class U> void test2(boost::intrusive_ptr<T> const & p, boost::intrusive_ptr<U> const & q)
{
BOOST_TEST((p == q) == (p.get() == q.get()));
BOOST_TEST((p != q) == (p.get() != q.get()));
}
template<class T> void test3(boost::intrusive_ptr<T> const & p, boost::intrusive_ptr<T> 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<T*> less;
BOOST_TEST((p < q) == less(p.get(), q.get()));
}
void test()
{
{
boost::intrusive_ptr<X> px;
test3(px, px);
boost::intrusive_ptr<X> px2;
test3(px, px2);
boost::intrusive_ptr<X> px3(px);
test3(px3, px3);
test3(px, px3);
}
{
boost::intrusive_ptr<X> px;
boost::intrusive_ptr<X> px2(new X);
test3(px, px2);
test3(px2, px2);
boost::intrusive_ptr<X> px3(new X);
test3(px2, px3);
boost::intrusive_ptr<X> px4(px2);
test3(px2, px4);
test3(px4, px4);
}
{
boost::intrusive_ptr<X> px(new X);
boost::intrusive_ptr<Y> py(new Y);
test2(px, py);
boost::intrusive_ptr<X> 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<X> next;
};
void test()
{
boost::intrusive_ptr<X> p(new X);
p->next = boost::intrusive_ptr<X>(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<foo> 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();
}

View File

@@ -1,154 +0,0 @@
#include <boost/config.hpp>
#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_from_this_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 <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/detail/lightweight_test.hpp>
//
class X
{
public:
virtual void f() = 0;
protected:
~X() {}
};
class Y
{
public:
virtual boost::shared_ptr<X> getX() = 0;
protected:
~Y() {}
};
boost::shared_ptr<Y> createY();
void test()
{
boost::shared_ptr<Y> py = createY();
BOOST_TEST(py.get() != 0);
BOOST_TEST(py.use_count() == 1);
boost::shared_ptr<X> px = py->getX();
BOOST_TEST(px.get() != 0);
BOOST_TEST(py.use_count() == 2);
px->f();
boost::shared_ptr<Y> py2 = boost::dynamic_pointer_cast<Y>(px);
BOOST_TEST(py.get() == py2.get());
BOOST_TEST(!(py < py2 || py2 < py));
BOOST_TEST(py.use_count() == 3);
}
void test2();
void test3();
int main()
{
test();
test2();
test3();
return boost::report_errors();
}
// virtual inheritance to stress the implementation
// (prevents Y* -> impl*, enable_shared_from_this<impl>* -> impl* casts)
class impl: public X, public virtual Y, public virtual boost::enable_shared_from_this<impl>
{
public:
virtual void f()
{
}
virtual boost::shared_ptr<X> getX()
{
boost::shared_ptr<impl> pi = shared_from_this();
BOOST_TEST(pi.get() == this);
return pi;
}
};
// intermediate impl2 to stress the implementation
class impl2: public impl
{
};
boost::shared_ptr<Y> createY()
{
boost::shared_ptr<Y> pi(new impl2);
return pi;
}
void test2()
{
boost::shared_ptr<Y> pi(static_cast<impl2*>(0));
}
//
struct V: public boost::enable_shared_from_this<V>
{
};
void test3()
{
boost::shared_ptr<V> p(new V);
boost::shared_ptr<V> q = p->shared_from_this();
BOOST_TEST(p == q);
BOOST_TEST(!(p < q) && !(q < p));
V v2(*p);
try
{
boost::shared_ptr<V> 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<V> 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()");
}
}

View File

@@ -1,167 +0,0 @@
//
// shared_ptr_alloc_test.cpp - use to evaluate the impact of count allocations
//
// 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 <boost/shared_ptr.hpp>
#include <boost/config.hpp>
#include <boost/detail/quick_allocator.hpp>
#include <iostream>
#include <vector>
#include <ctime>
#include <cstddef>
#include <memory>
int const n = 1024 * 1024;
template<class T> void test(T * = 0)
{
std::clock_t t = std::clock();
std::clock_t t2;
{
std::vector< boost::shared_ptr<T> > v;
for(int i = 0; i < n; ++i)
{
boost::shared_ptr<T> pi(new T(i));
v.push_back(pi);
}
t2 = std::clock();
}
std::clock_t t3 = std::clock();
std::cout << " " << static_cast<double>(t3 - t) / CLOCKS_PER_SEC << " seconds, " << static_cast<double>(t2 - t) / CLOCKS_PER_SEC << " + " << static_cast<double>(t3 - t2) / CLOCKS_PER_SEC << ".\n";
}
class X
{
public:
explicit X(int n): n_(n)
{
}
void * operator new(std::size_t)
{
return std::allocator<X>().allocate(1, static_cast<X*>(0));
}
void operator delete(void * p)
{
std::allocator<X>().deallocate(static_cast<X*>(p), 1);
}
private:
X(X const &);
X & operator=(X const &);
int n_;
};
class Y
{
public:
explicit Y(int n): n_(n)
{
}
void * operator new(std::size_t n)
{
return boost::detail::quick_allocator<Y>::alloc(n);
}
void operator delete(void * p, std::size_t n)
{
boost::detail::quick_allocator<Y>::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";
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
#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
#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<int> allocations + deallocations:\n";
test<int>();
test<int>();
test<int>();
std::cout << n << " shared_ptr<X> allocations + deallocations:\n";
test<X>();
test<X>();
test<X>();
std::cout << n << " shared_ptr<Y> allocations + deallocations:\n";
test<Y>();
test<Y>();
test<Y>();
std::cout << n << " shared_ptr<Z> allocations + deallocations:\n";
test<Z>();
test<Z>();
test<Z>();
}

View File

@@ -1,33 +0,0 @@
#include <boost/config.hpp>
#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_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 <boost/shared_ptr.hpp>
bool boost_error(char const *, char const *, char const *, long)
{
return true;
}
int main()
{
boost::shared_ptr<int> p;
p = new int(42); // assignment must fail
return 0;
}

View File

@@ -1,300 +0,0 @@
#include <boost/config.hpp>
#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
//
// 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 <boost/detail/lightweight_test.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
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<class T> void test_is_X(boost::shared_ptr<T> const & p)
{
BOOST_TEST(p->id() == 1);
BOOST_TEST((*p).id() == 1);
}
template<class T> void test_is_X(boost::weak_ptr<T> const & p)
{
BOOST_TEST(p.get() != 0);
BOOST_TEST(p.get()->id() == 1);
}
template<class T> void test_is_Y(boost::shared_ptr<T> const & p)
{
BOOST_TEST(p->id() == 2);
BOOST_TEST((*p).id() == 2);
}
template<class T> void test_is_Y(boost::weak_ptr<T> const & p)
{
boost::shared_ptr<T> q = p.lock();
BOOST_TEST(q.get() != 0);
BOOST_TEST(q->id() == 2);
}
template<class T> 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<class T> 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<class T, class U> void test_shared(boost::weak_ptr<T> const & a, boost::weak_ptr<U> const & b)
{
BOOST_TEST(!(a < b));
BOOST_TEST(!(b < a));
}
template<class T, class U> void test_nonshared(boost::weak_ptr<T> const & a, boost::weak_ptr<U> const & b)
{
BOOST_TEST(a < b || b < a);
BOOST_TEST(!(a < b && b < a));
}
template<class T, class U> void test_eq2(T const & a, U const & b)
{
BOOST_TEST(a == b);
BOOST_TEST(!(a != b));
}
template<class T, class U> void test_ne2(T const & a, U const & b)
{
BOOST_TEST(!(a == b));
BOOST_TEST(a != b);
}
template<class T> void test_is_zero(boost::shared_ptr<T> const & p)
{
BOOST_TEST(!p);
BOOST_TEST(p.get() == 0);
}
template<class T> void test_is_nonzero(boost::shared_ptr<T> 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<X> p(new Y);
shared_ptr<X> 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<X> q(p);
test_eq(p, q);
}
shared_ptr<Y> p3 = dynamic_pointer_cast<Y>(p);
shared_ptr<Y> p4 = dynamic_pointer_cast<Y>(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<void> p5(p);
test_is_nonzero(p5);
test_eq2(p, p5);
weak_ptr<X> 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<X> sp1(wp1);
BOOST_ERROR("shared_ptr<X> sp1(wp1) failed to throw");
}
catch(boost::bad_weak_ptr const &)
{
}
test_is_zero(wp1.lock());
weak_ptr<X> wp2 = static_pointer_cast<X>(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<X> sp2(wp2);
test_is_nonzero(wp2.lock());
}
weak_ptr<Y> wp3 = dynamic_pointer_cast<Y>(wp2.lock());
BOOST_TEST(wp3.use_count() == 1);
test_shared(wp2, wp3);
weak_ptr<X> wp4(wp3);
BOOST_TEST(wp4.use_count() == 1);
test_shared(wp2, wp4);
wp1 = p2;
test_is_zero(wp1.lock());
wp1 = p4;
wp1 = wp3;
wp1 = wp2;
BOOST_TEST(wp1.use_count() == 1);
test_shared(wp1, wp2);
weak_ptr<X> 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<void> p6(get_object(), release_object);
}
}
BOOST_TEST(cnt == 0);
return boost::report_errors();
}

View File

@@ -1,182 +0,0 @@
#include <boost/config.hpp>
#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_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 <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <vector>
#include <memory>
#include <stdexcept>
#include <cstdio>
#include <ctime>
// '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 <windows.h>
#include <process.h>
typedef HANDLE pthread_t;
unsigned __stdcall common_thread_routine(void * pv)
{
abstract_thread * pt = static_cast<abstract_thread *>(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 <pthread.h>
extern "C" void * common_thread_routine(void * pv)
{
abstract_thread * pt = static_cast<abstract_thread *>(pv);
pt->run();
delete pt;
return 0;
}
#endif
//
template<class F> class thread: public abstract_thread
{
public:
explicit thread(F f): f_(f)
{
}
void run()
{
f_();
}
private:
F f_;
};
template<class F> pthread_t createThread(F f)
{
std::auto_ptr<abstract_thread> p(new thread<F>(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<int> const & pi)
{
std::vector< boost::shared_ptr<int> > v;
for(int i = 0; i < n; ++i)
{
v.push_back(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);
boost::shared_ptr<int> pi(new int(42));
clock_t t = clock();
pthread_t a[m];
for(int i = 0; i < m; ++i)
{
a[i] = createThread( boost::bind(test, pi) );
}
for(int j = 0; j < m; ++j)
{
pthread_join(a[j], 0);
}
t = clock() - t;
printf("\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,47 +0,0 @@
#include <boost/config.hpp>
#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_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 <boost/shared_ptr.hpp>
#include <iostream>
#include <vector>
#include <ctime>
int const n = 8 * 1024 * 1024;
int main()
{
using namespace std;
std::vector< boost::shared_ptr<int> > v;
boost::shared_ptr<int> pi(new int);
clock_t t = clock();
for(int i = 0; i < n; ++i)
{
v.push_back(pi);
}
t = clock() - t;
std::cout << static_cast<double>(t) / CLOCKS_PER_SEC << '\n';
return 0;
}

View File

@@ -1,309 +0,0 @@
// 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.
#include <boost/config.hpp>
#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__
# pragma warn -8092 // template argument passed to 'find' is not an iterator
#endif
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <cstring>
#include <iostream>
#include <set>
class Incomplete;
Incomplete * get_ptr( boost::shared_ptr<Incomplete>& incomplete )
{
return incomplete.get();
}
using namespace std;
using boost::scoped_ptr;
using boost::scoped_array;
using boost::shared_ptr;
using boost::shared_array;
template<class T>
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\n";
}
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>& incomplete )
{
return incomplete.get();
}
Incomplete * check_incomplete( shared_ptr<Incomplete>& incomplete,
shared_ptr<Incomplete>& i2 )
{
incomplete.swap(i2);
cout << incomplete.use_count() << ' ' << incomplete.unique() << '\n';
return incomplete.get();
}
// This isn't a very systematic test; it just hits some of the basics.
void test()
{
BOOST_TEST( UDT_use_count == 0 ); // reality check
// test scoped_ptr with a built-in type
long * lp = new long;
scoped_ptr<long> 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<long*>(sp.get()), 1234568901L );
ck( lp, *sp );
sp.reset();
BOOST_TEST( sp.get() == 0 );
// test scoped_ptr with a user defined type
scoped_ptr<UDT> 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<char> 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<int> 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<int*>(cp.get()), 54321 );
ck( static_cast<int*>(ip), *cp );
shared_ptr<int> 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<int*>(cp2.get()), 54321 );
ck( static_cast<int*>(ip), *cp2 );
shared_ptr<int> 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 );
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<int> cp4;
swap( cp2, cp4 );
BOOST_TEST( cp4.use_count() == 3 );
BOOST_TEST( *cp4 == 87654 );
BOOST_TEST( cp2.get() == 0 );
set< shared_ptr<int> > scp;
scp.insert(cp4);
BOOST_TEST( scp.find(cp4) != scp.end() );
BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) );
// test shared_array with a built-in type
char * cap = new char [ 100 ];
shared_array<char> 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<char> ca2 ( ca );
shared_array<char> 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<char> 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<char> > sca;
sca.insert(ca4);
BOOST_TEST( sca.find(ca4) != sca.end() );
BOOST_TEST( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) );
// test shared_array with user defined type
shared_array<UDT> udta ( new UDT[3] );
udta[0].value( 111 );
udta[1].value( 222 );
udta[2].value( 333 );
shared_array<UDT> 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<UDT> 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<UDT> 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();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,245 +1,220 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head>
<title>weak_ptr</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body text="#000000" bgColor="#ffffff">
<h1><IMG height="86" alt="c++boost.gif (8819 bytes)" src="../../c++boost.gif" width="277" align="middle">weak_ptr
class template</h1>
<p><A href="#Introduction">Introduction</A><br>
<A href="#Synopsis">Synopsis</A><br>
<A href="#Members">Members</A><br>
<A href="#functions">Free Functions</A><br>
<A href="#FAQ">Frequently Asked Questions</A>
</p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <b>weak_ptr</b> class template stores a "weak reference" to an object that's
already managed by a <b>shared_ptr</b>. To access the object, a <STRONG>weak_ptr</STRONG>
can be converted to a <STRONG>shared_ptr</STRONG> using <A href="shared_ptr.htm#constructors">
the <STRONG>shared_ptr</STRONG> constructor</A> or the member function <STRONG><A href="#lock">
lock</A></STRONG>. When the last <b>shared_ptr</b> to the object goes
away and the object is deleted, the attempt to obtain a <STRONG>shared_ptr</STRONG>
from the <b>weak_ptr</b> instances that refer to the deleted object will fail:
the constructor will throw an exception of type <STRONG>boost::bad_weak_ptr</STRONG>,
and <STRONG>weak_ptr::lock</STRONG> will return an <EM>empty</EM> <STRONG>shared_ptr</STRONG>.</p>
<p>Every <b>weak_ptr</b> meets the <b>CopyConstructible</b> and <b>Assignable</b> requirements
of the C++ Standard Library, and so can be used in standard library containers.
Comparison operators are supplied so that <b>weak_ptr</b> works with the
standard library's associative containers.</p>
<P><STRONG>weak_ptr</STRONG> operations never throw&nbsp;exceptions.</P>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
to.</p>
<P>Compared to <STRONG>shared_ptr</STRONG>, <STRONG>weak_ptr</STRONG> 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.) Pretend for a moment that <b>weak_ptr</b>
has a <b>get</b> member function that returns a raw pointer, and consider this
innocent piece of code:</P>
<pre>shared_ptr&lt;int&gt; p(new int(5));
weak_ptr&lt;int&gt; q(p);
// some time later <head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>weak_ptr</title>
</head>
if(int * r = q.get()) <body bgcolor="#FFFFFF" text="#000000">
{
// use *r
}
</pre>
<P>Imagine that after the <STRONG>if</STRONG>, but immediately before <STRONG>r</STRONG>
is used, another thread executes the statement <code>p.reset()</code>. Now <STRONG>r</STRONG>
is a dangling pointer.</P>
<P>The solution to this problem is to create a temporary <STRONG>shared_ptr</STRONG>
from <STRONG>q</STRONG>:</P>
<pre>shared_ptr&lt;int&gt; p(new int(5));
weak_ptr&lt;int&gt; q(p);
// some time later <h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">weak_ptr class template</h1>
if(shared_ptr&lt;int&gt; r = q.<A href="#lock" >lock</A>()) <p>The <b>weak_ptr</b> class template stores a pointer to an
{ object that's already managed by a <b>shared_ptr</b>. When the
// use *r object last <b>shared_ptr</b> to the object goes away and the object
} is deleted, all <b>weak_ptr</b> objects have their stored pointers
</pre> set to 0.</p>
<p>Now <STRONG>r</STRONG> holds a reference to the object that was pointed by <STRONG>q</STRONG>.
Even if <code>p.reset()</code> is executed in another thread, the object will
stay alive until <STRONG>r</STRONG> goes out of scope or is reset. By obtaining
a <STRONG>shared_ptr</STRONG> to the object, we have effectively locked it
against destruction.</p>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost {
template&lt;class T&gt; class weak_ptr { <p>Every <b>weak_ptr</b> meets the <b>CopyConstructible</b>
and <b>Assignable</b> requirements of the C++ Standard Library, and so
can be used in standard library containers. Comparison operators
are supplied so that <b>weak_ptr</b> works with
the standard library's associative containers.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object
pointed to. <b>T</b> must meet the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost {
template&lt;typename T&gt; class weak_ptr {
public: public:
typedef T <A href="#element_type" >element_type</A>; typedef T <a href="#element_type">element_type</a>;
<A href="#default-constructor" >weak_ptr</A>(); explicit <a href="#constructors">weak_ptr</a>();
template&lt;typename Y&gt; <a href="#constructors">weak_ptr</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
<a href="#destructor">~weak_ptr</a>(); // never throws
template&lt;class Y&gt; <A href="#constructors" >weak_ptr</A>(shared_ptr&lt;Y&gt; const &amp; r); <a href="#constructors">weak_ptr</a>(weak_ptr const &amp; r); // never throws
<A href="#constructors" >weak_ptr</A>(weak_ptr const &amp; r); template&lt;typename Y&gt; <a href="#constructors">weak_ptr</a>(weak_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;class Y&gt; <A href="#constructors" >weak_ptr</A>(weak_ptr&lt;Y&gt; const &amp; r);
<A href="#destructor" >~weak_ptr</A>(); weak_ptr &amp; <a href="#assignment">operator=</a>(weak_ptr const &amp; r); // never throws
template&lt;typename Y&gt; weak_ptr &amp; <a href="#assignment">operator=</a>(weak_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;typename Y&gt; weak_ptr &amp; <a href="#assignment">operator=</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
weak_ptr &amp; <A href="#assignment" >operator=</A>(weak_ptr const &amp; r); void <a href="#reset">reset</a>(); // never throws
template&lt;class Y&gt; weak_ptr &amp; <A href="#assignment" >operator=</A>(weak_ptr&lt;Y&gt; const &amp; r);
template&lt;class Y&gt; weak_ptr &amp; <A href="#assignment" >operator=</A>(shared_ptr&lt;Y&gt; const &amp; r);
long <A href="#use_count" >use_count</A>() const; T &amp; <a href="#indirection">operator*</a>() const; // never throws
bool <A href="#expired" >expired</A>() const; T * <a href="#indirection">operator-&gt;</a>() const; // never throws
shared_ptr&lt;T&gt; <A href="#lock" >lock</A>() const; T * <a href="#get">get</a>() const; // never throws
void <A href="#reset" >reset</A>(); long <a href="#use_count">use_count</a>() const; // never throws
void <A href="#swap" >swap</A>(weak_ptr&lt;T&gt; &amp; b);
void <a href="#swap">swap</a>(weak_ptr&lt;T&gt; &amp; b); // never throws
}; };
template&lt;class T, class U&gt; template&lt;typename T, typename U&gt;
bool <A href="#comparison" >operator&lt;</A>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); bool <a href="#operator==">operator==</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;typename T, typename U&gt;
bool <a href="#operator!=">operator!=</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;typename T, typename U&gt;
bool <a href="#operator&lt;">operator&lt;</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class T&gt; template&lt;typename T&gt; void <a href="#free-swap">swap</a>(weak_ptr&lt;T&gt; &amp; a, weak_ptr&lt;T&gt; &amp; b); // never throws
void <A href="#free-swap" >swap</A>(weak_ptr&lt;T&gt; &amp; a, weak_ptr&lt;T&gt; &amp; b);
}
</pre>
<h2><a name="Members">Members</a></h2>
<h3><a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre>
<blockquote>
<p>Provides the type of the template parameter T.</p>
</blockquote>
<h3><a name="default-constructor">constructors</a></h3>
<pre>weak_ptr();</pre>
<blockquote>
<p><b>Effects:</b> Constructs an <EM>empty</EM> <b>weak_ptr</b>.</p>
<p><b>Postconditions:</b> <code>use_count() == 0</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote><a name="constructors"></a>
<pre>template&lt;class Y&gt; weak_ptr</A>(shared_ptr&lt;Y&gt; const &amp; r);
weak_ptr(weak_ptr const &amp; r);
template&lt;class Y&gt; weak_ptr(weak_ptr&lt;Y&gt; const &amp; r);</pre>
<blockquote>
<p><b>Effects:</b> If <STRONG>r</STRONG> is <EM>empty</EM>, constructs an <EM>empty</EM>
<STRONG>weak_ptr</STRONG>; otherwise, constructs a <b>weak_ptr</b> that <EM>shares
ownership</EM> with <STRONG>r</STRONG> as if by storing a copy of the
pointer stored in <b>r</b>.</p>
<p><b>Postconditions:</b> <code>use_count() == r.use_count()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h3><a name="destructor">destructor</a></h3>
<pre>~weak_ptr();</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Destroys this <b>weak_ptr</b> but has no effect on the object
its stored pointer points to.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<h3><a name="assignment">assignment</a></h3>
<pre>weak_ptr &amp; operator=(weak_ptr const &amp; r);
template&lt;class Y&gt; weak_ptr &amp; operator=(weak_ptr&lt;Y&gt; const &amp; r);
template&lt;class Y&gt; weak_ptr &amp; operator=(shared_ptr&lt;Y&gt; const &amp; r);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>weak_ptr(r).swap(*this)</code>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> The implementation is free to meet the effects (and the implied
guarantees) via different means, without creating a temporary.</P>
</BLOCKQUOTE>
<h3><a name="use_count">use_count</a></h3>
<pre>long use_count() const;</pre>
<blockquote>
<p><b>Returns:</b> if <STRONG>*this</STRONG> is <EM>empty</EM>, an unspecified
nonnegative value; otherwise, the number of <b>shared_ptr</b> objects that <EM>share
ownership</EM> with <STRONG>*this</STRONG>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <code>use_count()</code> is not necessarily efficient. Use only
for debugging and testing purposes, not for production code.</P>
</blockquote>
<h3><a name="expired">expired</a></h3>
<pre>bool expired() const;</pre>
<blockquote>
<p><b>Returns:</b> <code>use_count() == 0</code>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <code>expired()</code> may be faster than <code>use_count()</code>.</P>
</blockquote>
<h3><a name="lock">lock</a></h3>
<pre>shared_ptr&lt;T&gt; lock() const;</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> <code>expired()? shared_ptr&lt;T&gt;(): shared_ptr&lt;T&gt;(*this)</code>.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<h3><a name="reset">reset</a></h3>
<pre>void reset();</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>weak_ptr().swap(*this)</code>.</P>
</BLOCKQUOTE>
<h3><a name="swap">swap</a></h3>
<pre>void swap(weak_ptr &amp; b);</pre>
<blockquote>
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h2><a name="functions">Free Functions</a></h2>
<h3><a name="comparison">comparison</a></h3>
<pre>template&lt;class T, class U&gt;
bool operator&lt;(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b);</pre>
<blockquote>
<p><b>Returns:</b> an unspecified value such that</p>
<UL>
<LI>
<b>operator&lt;</b> is a strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
of the C++ standard;
<LI>
under the equivalence relation defined by <STRONG>operator&lt;</STRONG>, <code>!(a
&lt; b) &amp;&amp; !(b &lt; a)</code>, two <STRONG>weak_ptr</STRONG> instances
are equivalent if and only if they <EM>share ownership</EM>.</LI></UL>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> Allows <STRONG>weak_ptr</STRONG> objects to be used as keys in
associative containers.</P>
</blockquote>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;class T&gt;
void swap(weak_ptr&lt;T&gt; &amp; a, weak_ptr&lt;T&gt; &amp; b)</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
generic programming.</P>
</BLOCKQUOTE>
<h2><a name="FAQ">Frequently Asked Questions</a></h2>
<P><B>Q.</B> Can an object create a <STRONG>weak_ptr</STRONG> to itself in its
constructor?</P>
<P><b>A.</b> No. A <STRONG>weak_ptr</STRONG> can only be created from a <STRONG>shared_ptr</STRONG>,
and at object construction time no <STRONG>shared_ptr</STRONG> to the object
exists yet. Even if you could create a temporary <STRONG>shared_ptr</STRONG> to <STRONG>
this</STRONG>, it would go out of scope at the end of the constructor, and
all <STRONG>weak_ptr</STRONG> instances would instantly expire.</P>
<P>The solution is to make the constructor private, and supply a factory function
that returns a <STRONG>shared_ptr</STRONG>:<BR>
</P>
<pre>
class X
{
private:
X(); template&lt;typename T, typename U&gt;
weak_ptr&lt;T&gt <a href="#shared_static_cast">shared_static_cast</a>(weak_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;typename T, typename U&gt;
weak_ptr&lt;T&gt <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(weak_ptr&lt;U&gt; const &amp; r);
public: }</pre>
<h2><a name="Members">Members</a></h2>
<h3><a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre>
<p>Provides the type of the stored pointer.</p>
<h3><a name="constructors">constructors</a></h3>
<pre>explicit weak_ptr();</pre>
<p>Constructs a <b>weak_ptr</b>, with 0 as its stored pointer.
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
If an exception is thrown, the constructor has no effect.</p>
<pre>template&lt;typename Y&gt; weak_ptr</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws</pre>
<p>Constructs a <b>weak_ptr</b>, as if by storing a copy of the pointer stored in <b>r</b>.
Afterwards, the <a href="#use_count">use count</a> for all copies is unchanged.
When the last <b>shared_ptr</b> is destroyed, the use count and stored pointer become 0.</p>
<pre>weak_ptr(weak_ptr const &amp; r); // never throws
template&lt;typename Y&gt; weak_ptr(weak_ptr&lt;Y&gt; const &amp; r); // never throws</pre>
<p>Constructs a <b>weak_ptr</b>, as if by storing a copy of the
pointer stored in <b>r</b>.</p>
<h3><a name="destructor">destructor</a></h3>
<pre>~weak_ptr(); // never throws</pre>
<p>Destroys this <b>weak_ptr</b> but has no effect on the object its stored pointer points to.
<b>T</b> need not be a complete type.
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h3><a name="operator=">assignment</a></h3>
<pre>weak_ptr &amp; <a href="#assignment">operator=</a>(weak_ptr const &amp; r); // never throws
template&lt;typename Y&gt; weak_ptr &amp; <a href="#assignment">operator=</a>(weak_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;typename Y&gt; weak_ptr &amp; <a href="#assignment">operator=</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws</pre>
<p>Constructs a new <b>weak_ptr</b> as described <a href="#constructors">above</a>,
then replaces this <b>weak_ptr</b> with the new one, destroying the replaced object.</p>
<h3><a name="reset">reset</a></h3>
<pre>void reset();</pre>
<p>Constructs a new <b>weak_ptr</b> as described <a href="#constructors">above</a>,
then replaces this <b>weak_ptr</b> with the new one, destroying the replaced object.
The only exception which may be thrown is <b>std::bad_alloc</b>. If
an exception is thrown, the <b>reset</b> has no effect.</p>
<h3><a name="indirection">indirection</a></h3>
<pre>T &amp; operator*() const; // never throws</pre>
<p>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 <b>shared_ptr</b> objects for that
pointer are destroyed.</p>
<pre>T * operator-&gt;() const; // never throws</pre>
<p>Returns the stored pointer.
Behavior is undefined if the stored pointer is 0.
Note that the stored pointer becomes 0 if all <b>shared_ptr</b> objects for that
pointer are destroyed.</p>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<p>Returns the stored pointer.
Note that the stored pointer becomes 0 if all <b>shared_ptr</b> objects for that
pointer are destroyed.
<b>T</b> need not be a complete type.
See the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h3><a name="use_count">use_count</a></h3>
<pre>long use_count() const; // never throws</pre>
<p>Returns the number of <b>shared_ptr</b> objects sharing ownership of the
stored pointer.
<b>T</b> need not be a complete type.
See the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<p>Because <b>use_count</b> is not necessarily efficient to implement for
implementations of <b>weak_ptr</b> 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 <b>get</b> should be used for
production code.</p>
<h3><a name="swap">swap</a></h3>
<pre>void swap(weak_ptr &amp; b); // never throws</pre>
<p>Exchanges the contents of the two smart pointers.
<b>T</b> need not be a complete type.
See the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h2><a name="functions">Free Functions</a></h2>
<h3><a name="comparison">comparison</a></h3>
<pre>template&lt;typename T, typename U&gt;
bool <a href="#operator==">operator==</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;typename T, typename U&gt;
bool <a href="#operator!=">operator!=</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;typename T, typename U&gt;
bool <a href="#operator&lt;">operator&lt;</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<p>Compares the stored pointers of the two smart pointers.
<b>T</b> need not be a complete type.
See the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<p>The <b>operator&lt;</b> overload is provided to define an ordering so that <b>weak_ptr</b>
objects can be used in associative containers such as <b>std::map</b>.
The implementation uses <b>std::less&lt;T *&gt;</b> 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 <b>std::less&lt;&gt;</b> on pointers is well-defined (20.3.3 [lib.comparisons]
paragraph 8).</p>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;typename T&gt;
void swap(weak_ptr&lt;T&gt; &amp; a, weak_ptr&lt;T&gt; &amp; b) // never throws</pre>
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
Provided as an aid to generic programming.</p>
<h3><a name="shared_static_cast">shared_static_cast</a></h3>
<pre>template&lt;typename T, typename U&gt;
weak_ptr&lt;T&gt <a href="#shared_static_cast">shared_static_cast</a>(weak_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<p>Perform a <b>static_cast</b> on the stored pointer, returning another <b>weak_ptr</b>.
The resulting smart pointer will share its use count with the original pointer.</p>
<h3><a name="shared_dynamic_cast">shared_dynamic_cast</a></h3>
<pre>template&lt;typename T, typename U&gt;
weak_ptr&lt;T&gt <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(weak_ptr&lt;U&gt; const &amp; r);</pre>
<p>Perform a <b>dynamic_cast</b> on the stored pointer, returning another <b>weak_ptr</b>.
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 <b>std::bad_alloc</b>, which may be thrown during the
construction of the new <b>weak_ptr</b> if the result of the cast is 0. If an exception is thrown, the
cast has no effect.</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->1 February 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
<p>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 &quot;as is&quot; without express or implied warranty,
and with no claim as to its suitability for any purpose.</p>
</body>
static shared_ptr&lt;X&gt; create()
{
shared_ptr&lt;X&gt; px(new X);
// create weak pointers from px here
return px;
}
};
</pre>
<p><br>
</p>
<hr>
<p>$Date$</p>
<p><small>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.</small></p>
</A>
</body>
</html> </html>