Compare commits

..

2 Commits

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

[SVN r13949]
2002-05-16 13:26:18 +00:00
nobody
da5e9a964c This commit was manufactured by cvs2svn to create branch 'RC_1_28_0'.
[SVN r13795]
2002-05-10 04:34:27 +00:00
79 changed files with 2501 additions and 12149 deletions

View File

@@ -9,7 +9,7 @@
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86">Smart
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">Smart
Pointer Changes</h1>
<p>The February 2002 change to the Boost smart pointers introduced a number

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="../../boost.png" alt="boost.png (6897 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,17 +0,0 @@
// Boost scoped_ptr_example_test main program -------------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/smart_ptr for documentation.
#include "scoped_ptr_example.hpp"
int main()
{
example my_example;
my_example.do_something();
return 0;
}

View File

@@ -1,10 +1,8 @@
#ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
#define BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#if _MSC_VER >= 1020
#pragma once
#endif
//
@@ -12,9 +10,10 @@
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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 <implementation-defined> boost::detail::atomic_count;
//
@@ -73,6 +72,9 @@
// 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>
#ifndef BOOST_HAS_THREADS
@@ -89,19 +91,30 @@ 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__)
# include <boost/detail/atomic_count_win32.hpp>
#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
# include <boost/detail/atomic_count_gcc.hpp>
#elif defined(BOOST_HAS_PTHREADS)
# define BOOST_AC_USE_PTHREADS
# include <boost/detail/atomic_count_pthreads.hpp>
#else
// Use #define BOOST_DISABLE_THREADS to avoid the error
#error Unrecognized threading platform
// #warning Unrecognized platform, detail::atomic_count will not be thread safe
namespace boost
{
namespace detail
{
typedef long atomic_count;
}
}
#endif

View File

@@ -1,68 +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>
// Copyright 2003-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <bits/atomicity.h>
namespace boost
{
namespace detail
{
#if defined(__GLIBCXX__) // g++ 3.4+
using __gnu_cxx::__atomic_add;
using __gnu_cxx::__exchange_and_add;
#endif
class atomic_count
{
public:
explicit atomic_count(long v) : value_(v) {}
void operator++()
{
__atomic_add(&value_, 1);
}
long operator--()
{
return __exchange_and_add(&value_, -1) - 1;
}
operator long() const
{
return __exchange_and_add(&value_, 0);
}
private:
atomic_count(atomic_count const &);
atomic_count & operator=(atomic_count const &);
mutable _Atomic_word value_;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED

View File

@@ -0,0 +1,70 @@
#ifndef BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED
#define BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED
//
// boost/detail/atomic_count_linux.hpp
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//
// 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 significantly higher than the pthreads version. Use at your own risk
// (by defining BOOST_USE_ASM_ATOMIC_H.)
//
#include <asm/atomic.h>
namespace boost
{
namespace detail
{
class atomic_count
{
public:
explicit atomic_count(long v)
{
atomic_t init = ATOMIC_INIT(v);
value_ = init;
}
void operator++()
{
atomic_inc(&value_);
}
long operator--()
{
return !atomic_dec_and_test(&value_);
}
operator long() const
{
return atomic_read(&value_);
}
private:
atomic_count(atomic_count const &);
atomic_count & operator=(atomic_count const &);
atomic_t value_;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED

View File

@@ -6,9 +6,10 @@
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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>

View File

@@ -1,23 +1,22 @@
#ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
#define BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/detail/atomic_count_win32.hpp
//
// Copyright (c) 2001-2005 Peter Dimov
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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/interlocked.hpp>
#include <boost/detail/winapi.hpp>
namespace boost
{
@@ -29,31 +28,31 @@ class atomic_count
{
public:
explicit atomic_count( long v ): value_( v )
explicit atomic_count(long v): value_(v)
{
}
long operator++()
{
return BOOST_INTERLOCKED_INCREMENT( &value_ );
return winapi::InterlockedIncrement(&value_);
}
long operator--()
{
return BOOST_INTERLOCKED_DECREMENT( &value_ );
return winapi::InterlockedDecrement(&value_);
}
operator long() const
{
return static_cast<long const volatile &>( value_ );
return value_;
}
private:
atomic_count( atomic_count const & );
atomic_count & operator=( atomic_count const & );
atomic_count(atomic_count const &);
atomic_count & operator=(atomic_count const &);
long value_;
volatile long value_;
};
} // namespace detail

View File

@@ -1,59 +0,0 @@
#ifndef BOOST_BAD_WEAK_PTR_HPP_INCLUDED
#define BOOST_BAD_WEAK_PTR_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/bad_weak_ptr.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <exception>
#ifdef __BORLANDC__
# pragma warn -8026 // Functions with excep. spec. are not expanded inline
#endif
namespace boost
{
// The standard library that comes with Borland C++ 5.5.1, 5.6.4
// defines std::exception and its members as having C calling
// convention (-pc). When the definition of bad_weak_ptr
// is compiled with -ps, the compiler issues an error.
// Hence, the temporary #pragma option -pc below.
#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564
# pragma option push -pc
#endif
class bad_weak_ptr: public std::exception
{
public:
virtual char const * what() const throw()
{
return "boost::bad_weak_ptr";
}
};
#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564
# pragma option pop
#endif
} // namespace boost
#ifdef __BORLANDC__
# pragma warn .8026 // Functions with excep. spec. are not expanded inline
#endif
#endif // #ifndef BOOST_BAD_WEAK_PTR_HPP_INCLUDED

View File

@@ -1,42 +1,67 @@
#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
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/detail/lightweight_mutex.hpp - lightweight mutex
//
// Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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;
// typedef <implementation-defined> boost::detail::lightweight_mutex;
//
// boost::detail::lightweight_mutex is a header-only implementation of
// a subset of the Mutex concept requirements:
// boost::detail::lightweight_mutex meets the Mutex concept requirements
// See http://www.boost.org/libs/thread/doc/mutex_concept.html#Mutex
//
// http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex
//
// It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX.
// * 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.
//
// Note: lwm_linux.hpp has been disabled by default; see the comments
// inside for more info.
#include <boost/config.hpp>
#if !defined(BOOST_HAS_THREADS)
# include <boost/detail/lwm_nop.hpp>
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
//
// Note to implementors: if you write a platform-specific lightweight_mutex
// for a platform that supports pthreads, be sure to test its performance
// against the pthreads-based version using smart_ptr_timing_test.cpp and
// smart_ptr_mt_test.cpp. Custom versions are usually not worth the trouble
// _unless_ the performance gains are substantial.
//
#ifndef BOOST_HAS_THREADS
# include <boost/detail/lwm_nop.hpp>
#elif 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(WIN32) || defined(_WIN32) || defined(__WIN32__)
# include <boost/detail/lwm_win32.hpp>
#elif defined(__sgi)
# include <boost/detail/lwm_irix.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
# include <boost/detail/lwm_nop.hpp>
#endif
#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED

View File

@@ -0,0 +1,78 @@
#ifndef BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED
#define BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/detail/lwm_irix.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2002 Dan Gohman
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <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

@@ -0,0 +1,89 @@
#ifndef BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED
#define BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/detail/lwm_linux.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//
// 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_WIN32_HPP_INCLUDED

View File

@@ -1,10 +1,8 @@
#ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED
#define BOOST_DETAIL_LWM_NOP_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#if _MSC_VER >= 1020
#pragma once
#endif
//
@@ -12,9 +10,10 @@
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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

View File

@@ -1,10 +1,8 @@
#ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED
#define BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#if _MSC_VER >= 1020
#pragma once
#endif
//
@@ -12,9 +10,10 @@
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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>
@@ -38,14 +37,7 @@ 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()

View File

@@ -0,0 +1,81 @@
#ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED
#define BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/detail/lwm_win32.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 <boost/detail/winapi.hpp>
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:
lightweight_mutex & m_;
scoped_lock(scoped_lock const &);
scoped_lock & operator=(scoped_lock const &);
public:
explicit scoped_lock(lightweight_mutex & m): m_(m)
{
while( winapi::InterlockedExchange(&m_.l_, 1) )
{
winapi::Sleep(0);
}
}
~scoped_lock()
{
winapi::InterlockedExchange(&m_.l_, 0);
// Note: adding a Sleep(0) here will make
// the mutex 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
#endif // #ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED

View File

@@ -1,25 +1,22 @@
#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
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/detail/lwm_win32_cs.hpp
//
// Copyright (c) 2002, 2003 Peter Dimov
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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
#include <boost/detail/winapi.hpp>
namespace boost
{
@@ -27,34 +24,11 @@ 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_;
winapi::critical_section cs_;
lightweight_mutex(lightweight_mutex const &);
lightweight_mutex & operator=(lightweight_mutex const &);
@@ -63,12 +37,12 @@ public:
lightweight_mutex()
{
InitializeCriticalSection(&cs_);
winapi::InitializeCriticalSection(&cs_);
}
~lightweight_mutex()
{
DeleteCriticalSection(&cs_);
winapi::DeleteCriticalSection(&cs_);
}
class scoped_lock;
@@ -87,12 +61,12 @@ public:
explicit scoped_lock(lightweight_mutex & m): m_(m)
{
EnterCriticalSection(&m_.cs_);
winapi::EnterCriticalSection(&m_.cs_);
}
~scoped_lock()
{
LeaveCriticalSection(&m_.cs_);
winapi::LeaveCriticalSection(&m_.cs_);
}
};
};

View File

@@ -7,22 +7,21 @@
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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/shared_array.htm for documentation.
//
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/detail/atomic_count.hpp>
#include <cstddef> // for std::ptrdiff_t
#include <algorithm> // for std::swap
#include <functional> // for std::less
#include <new> // for std::bad_alloc
#include <cstddef> // for std::ptrdiff_t
#include <algorithm> // for std::swap
#include <functional> // for std::less
namespace boost
{
@@ -39,36 +38,22 @@ public:
explicit shared_array(T * p = 0): px(p)
{
#ifndef BOOST_NO_EXCEPTIONS
try // prevent leak if new throws
{
pn = new count_type(1);
}
catch(...)
{
boost::checked_array_delete(p);
checked_array_delete(p);
throw;
}
#else
pn = new count_type(1);
if(pn == 0)
{
boost::checked_array_delete(p);
boost::throw_exception(std::bad_alloc());
}
#endif
}
}
~shared_array()
{
if(--*pn == 0)
{
boost::checked_array_delete(px);
checked_array_delete(px);
delete pn;
}
}
@@ -78,19 +63,19 @@ public:
pn = r.pn;
++*pn;
}
shared_array & operator=(shared_array const & r)
{
shared_array(r).swap(*this);
return *this;
}
void reset(T * p = 0)
{
BOOST_ASSERT(p == 0 || p != px);
shared_array(p).swap(*this);
}
T * get() const // never throws
{
return px;
@@ -102,7 +87,7 @@ public:
BOOST_ASSERT(i >= 0);
return px[i];
}
long use_count() const // never throws
{
return *pn;
@@ -112,15 +97,15 @@ public:
{
return *pn == 1;
}
void swap(shared_array<T> & other) // never throws
{
std::swap(px, other.px);
std::swap(pn, other.pn);
}
private:
T * px; // contained pointer
count_type * pn; // ptr to reference counter

View File

@@ -1,51 +1,209 @@
#ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
#define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#if _MSC_VER >= 1020
#pragma once
#endif
//
// detail/shared_count.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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 __BORLANDC__
# pragma warn -8027 // Functions containing try are not expanded inline
#endif
#include <boost/config.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/detail/bad_weak_ptr.hpp>
#include <boost/detail/sp_counted_base.hpp>
#include <boost/detail/sp_counted_impl.hpp>
#include <memory> // std::auto_ptr, std::allocator
#include <functional> // std::less
#include <new> // std::bad_alloc
#include <typeinfo> // std::type_info in get_deleter
#ifndef BOOST_NO_AUTO_PTR
# include <memory>
#endif
#include <boost/checked_delete.hpp>
#include <boost/detail/lightweight_mutex.hpp>
#include <functional> // for std::less
#include <exception> // for std::exception
namespace boost
{
class use_count_is_zero: public std::exception
{
public:
virtual char const * what() const throw()
{
return "use_count_is_zero";
}
};
class counted_base
{
private:
typedef detail::lightweight_mutex mutex_type;
public:
counted_base():
use_count_(0), weak_count_(0), self_deleter_(&self_delete)
{
}
// pre: initial_use_count <= initial_weak_count
explicit counted_base(long initial_use_count, long initial_weak_count):
use_count_(initial_use_count), weak_count_(initial_weak_count), self_deleter_(&self_delete)
{
}
virtual ~counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
//
// counted_base doesn't manage any resources except itself, and
// the default implementation is a no-op.
//
// dispose() is not pure virtual since weak_ptr instantiates a
// counted_base in its default constructor.
virtual void dispose() // nothrow
{
}
void add_ref()
{
#ifdef BOOST_HAS_THREADS
mutex_type::scoped_lock lock(mtx_);
#endif
if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero();
++use_count_;
++weak_count_;
}
void release() // nothrow
{
long new_use_count;
long new_weak_count;
{
#ifdef BOOST_HAS_THREADS
mutex_type::scoped_lock lock(mtx_);
#endif
new_use_count = --use_count_;
new_weak_count = --weak_count_;
}
if(new_use_count == 0)
{
dispose();
}
if(new_weak_count == 0)
{
// not a direct 'delete this', because the inlined
// release() may use a different heap manager
self_deleter_(this);
}
}
void weak_add_ref() // nothrow
{
#ifdef BOOST_HAS_THREADS
mutex_type::scoped_lock lock(mtx_);
#endif
++weak_count_;
}
void weak_release() // nothrow
{
long new_weak_count;
{
#ifdef BOOST_HAS_THREADS
mutex_type::scoped_lock lock(mtx_);
#endif
new_weak_count = --weak_count_;
}
if(new_weak_count == 0)
{
self_deleter_(this);
}
}
long use_count() const // nothrow
{
#ifdef BOOST_HAS_THREADS
mutex_type::scoped_lock lock(mtx_);
#endif
return use_count_;
}
private:
counted_base(counted_base const &);
counted_base & operator= (counted_base const &);
static void self_delete(counted_base * p)
{
delete p;
}
// inv: use_count_ <= weak_count_
long use_count_;
long weak_count_;
#ifdef BOOST_HAS_THREADS
mutable mutex_type mtx_;
#endif
void (*self_deleter_) (counted_base *);
};
inline void intrusive_ptr_add_ref(counted_base * p)
{
p->add_ref();
}
inline void intrusive_ptr_release(counted_base * p)
{
p->release();
}
namespace detail
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
template<class P, class D> class counted_base_impl: public counted_base
{
private:
int const shared_count_id = 0x2C35F101;
int const weak_count_id = 0x298C38A4;
P ptr; // copy constructor must not throw
D del; // copy constructor must not throw
#endif
counted_base_impl(counted_base_impl const &);
counted_base_impl & operator= (counted_base_impl const &);
public:
// pre: initial_use_count <= initial_weak_count, d(p) must not throw
counted_base_impl(P p, D d, long initial_use_count, long initial_weak_count):
counted_base(initial_use_count, initial_weak_count), ptr(p), del(d)
{
}
virtual void dispose() // nothrow
{
del(ptr);
}
};
class weak_count;
@@ -53,102 +211,48 @@ class shared_count
{
private:
sp_counted_base * pi_;
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
int id_;
#endif
counted_base * pi_;
friend class weak_count;
template<class P, class D> shared_count(P, D, counted_base const *);
public:
shared_count(): pi_(0) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
shared_count(): pi_(new counted_base(1, 1))
{
}
template<class Y> explicit shared_count( Y * p ): pi_( 0 )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
explicit shared_count(counted_base * pi): pi_(pi) // never throws
{
#ifndef BOOST_NO_EXCEPTIONS
try
{
pi_ = new sp_counted_impl_p<Y>( p );
}
catch(...)
{
boost::checked_delete( p );
throw;
}
#else
pi_ = new sp_counted_impl_p<Y>( p );
if( pi_ == 0 )
{
boost::checked_delete( p );
boost::throw_exception( std::bad_alloc() );
}
#endif
pi_->add_ref();
}
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
template<class P, class D> shared_count(P p, D d, void const * = 0): pi_(0)
{
#ifndef BOOST_NO_EXCEPTIONS
try
{
pi_ = new sp_counted_impl_pd<P, D>(p, d);
pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
}
catch(...)
{
d(p); // delete p
throw;
}
}
#else
pi_ = new sp_counted_impl_pd<P, D>(p, d);
if(pi_ == 0)
{
d(p); // delete p
boost::throw_exception(std::bad_alloc());
}
#endif
template<class P, class D> shared_count(P, D, counted_base * pi): pi_(pi)
{
pi_->add_ref();
}
#ifndef BOOST_NO_AUTO_PTR
// auto_ptr<Y> is special cased to provide the strong guarantee
template<class Y>
explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
template<typename 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))
{
#ifdef BOOST_NO_EXCEPTIONS
if( pi_ == 0 )
{
boost::throw_exception(std::bad_alloc());
}
#endif
r.release();
}
@@ -156,51 +260,41 @@ public:
~shared_count() // nothrow
{
if( pi_ != 0 ) pi_->release();
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
id_ = 0;
#endif
pi_->release();
}
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
explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0
shared_count & operator= (shared_count const & r) // nothrow
{
sp_counted_base * tmp = r.pi_;
if( tmp != pi_ )
{
if( tmp != 0 ) tmp->add_ref_copy();
if( pi_ != 0 ) pi_->release();
pi_ = tmp;
}
counted_base * tmp = r.pi_;
tmp->add_ref();
pi_->release();
pi_ = tmp;
return *this;
}
void swap(shared_count & r) // nothrow
{
sp_counted_base * tmp = r.pi_;
counted_base * tmp = r.pi_;
r.pi_ = pi_;
pi_ = tmp;
}
long use_count() const // nothrow
{
return pi_ != 0? pi_->use_count(): 0;
return pi_->use_count();
}
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)
@@ -210,66 +304,44 @@ public:
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;
return std::less<counted_base *>()(a.pi_, b.pi_);
}
};
class weak_count
{
private:
sp_counted_base * pi_;
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
int id_;
#endif
counted_base * pi_;
friend class shared_count;
public:
weak_count(): pi_(0) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
weak_count(): pi_(new counted_base(0, 1)) // can throw
{
}
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
#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
{
if(pi_ != 0) pi_->weak_release();
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
id_ = 0;
#endif
pi_->weak_release();
}
weak_count & operator= (shared_count const & r) // nothrow
{
sp_counted_base * tmp = r.pi_;
if(tmp != 0) tmp->weak_add_ref();
if(pi_ != 0) pi_->weak_release();
counted_base * tmp = r.pi_;
tmp->weak_add_ref();
pi_->weak_release();
pi_ = tmp;
return *this;
@@ -277,9 +349,9 @@ public:
weak_count & operator= (weak_count const & r) // nothrow
{
sp_counted_base * tmp = r.pi_;
if(tmp != 0) tmp->weak_add_ref();
if(pi_ != 0) pi_->weak_release();
counted_base * tmp = r.pi_;
tmp->weak_add_ref();
pi_->weak_release();
pi_ = tmp;
return *this;
@@ -287,14 +359,14 @@ public:
void swap(weak_count & r) // nothrow
{
sp_counted_base * tmp = r.pi_;
counted_base * tmp = r.pi_;
r.pi_ = pi_;
pi_ = tmp;
}
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)
@@ -304,27 +376,17 @@ public:
friend inline bool operator<(weak_count const & a, weak_count const & b)
{
return std::less<sp_counted_base *>()(a.pi_, b.pi_);
return std::less<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
inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
{
if( pi_ == 0 || !pi_->add_ref_lock() )
{
boost::throw_exception( boost::bad_weak_ptr() );
}
pi_->add_ref();
}
} // namespace detail
} // namespace boost
#ifdef __BORLANDC__
# pragma warn .8027 // Functions containing try are not expanded inline
#endif
#endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED

View File

@@ -7,25 +7,24 @@
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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/shared_ptr.htm for documentation.
//
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/detail/atomic_count.hpp>
#ifndef BOOST_NO_AUTO_PTR
# include <memory> // for std::auto_ptr
#include <memory> // for std::auto_ptr
#endif
#include <algorithm> // for std::swap
#include <functional> // for std::less
#include <new> // for std::bad_alloc
#include <algorithm> // for std::swap
#include <functional> // for std::less
namespace boost
{
@@ -39,40 +38,25 @@ private:
public:
typedef T element_type;
typedef T value_type;
explicit shared_ptr(T * p = 0): px(p)
{
#ifndef BOOST_NO_EXCEPTIONS
try // prevent leak if new throws
{
pn = new count_type(1);
}
catch(...)
{
boost::checked_delete(p);
checked_delete(p);
throw;
}
#else
pn = new count_type(1);
if(pn == 0)
{
boost::checked_delete(p);
boost::throw_exception(std::bad_alloc());
}
#endif
}
}
~shared_ptr()
{
if(--*pn == 0)
{
boost::checked_delete(px);
checked_delete(px);
delete pn;
}
}

View File

@@ -1,69 +0,0 @@
#ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
#define BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base.hpp
//
// Copyright 2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/config.hpp>
#if defined( BOOST_SP_DISABLE_THREADS )
# include <boost/detail/sp_counted_base_nt.hpp>
#elif defined( BOOST_SP_USE_PTHREADS )
# include <boost/detail/sp_counted_base_pt.hpp>
#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
# include <boost/detail/sp_counted_base_gcc_x86.hpp>
//~ #elif defined( __MWERKS__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
//~ # include <boost/detail/sp_counted_base_cw_x86.hpp>
#elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER )
# include <boost/detail/sp_counted_base_gcc_ia64.hpp>
#elif defined( __MWERKS__ ) && defined( __POWERPC__ )
# include <boost/detail/sp_counted_base_cw_ppc.hpp>
#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) )
# include <boost/detail/sp_counted_base_gcc_ppc.hpp>
#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
# include <boost/detail/sp_counted_base_w32.hpp>
#elif !defined( BOOST_HAS_THREADS )
# include <boost/detail/sp_counted_base_nt.hpp>
#elif defined( BOOST_HAS_PTHREADS )
# include <boost/detail/sp_counted_base_pt.hpp>
#else
// Use #define BOOST_DISABLE_THREADS to avoid the error
# error Unrecognized threading platform
#endif
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED

View File

@@ -1,170 +0,0 @@
#ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED
#define BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_cw_ppc.hpp - CodeWarrior on PowerPC
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
// formulation
//
#include <typeinfo>
namespace boost
{
namespace detail
{
inline void atomic_increment( register long * pw )
{
register int a;
asm
{
loop:
lwarx a, 0, pw
addi a, a, 1
stwcx. a, 0, pw
bne- loop
}
}
inline long atomic_decrement( register long * pw )
{
register int a;
asm
{
sync
loop:
lwarx a, 0, pw
addi a, a, -1
stwcx. a, 0, pw
bne- loop
isync
}
return a;
}
inline long atomic_conditional_increment( register long * pw )
{
register int a;
asm
{
loop:
lwarx a, 0, pw
cmpwi a, 0
beq store
addi a, a, 1
store:
stwcx. a, 0, pw
bne- loop
}
return a;
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared
long weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( std::type_info const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_decrement( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_decrement( &weak_count_ ) == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<long const volatile &>( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED

View File

@@ -1,158 +0,0 @@
#ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
#define BOOST_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_cw_x86.hpp - CodeWarrion on 486+
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
// Copyright 2005 Rene Rivera
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
// formulation
//
#include <typeinfo>
namespace boost
{
namespace detail
{
inline int atomic_exchange_and_add( int * pw, int dv )
{
// int r = *pw;
// *pw += dv;
// return r;
asm
{
mov esi, [pw]
mov eax, dv
lock xadd dword ptr [esi], eax
}
}
inline void atomic_increment( int * pw )
{
//atomic_exchange_and_add( pw, 1 );
asm
{
mov esi, [pw]
lock inc dword ptr [esi]
}
}
inline int atomic_conditional_increment( int * pw )
{
// int rv = *pw;
// if( rv != 0 ) ++*pw;
// return rv;
asm
{
mov esi, [pw]
mov eax, dword ptr [esi]
L0:
test eax, eax
je L1
mov ebx, eax
inc ebx
lock cmpxchg dword ptr [esi], ebx
jne L0
L1:
}
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
int use_count_; // #shared
int weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( std::type_info const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<int const volatile &>( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED

View File

@@ -1,157 +0,0 @@
#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED
#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED
//
// detail/sp_counted_base_gcc_ia64.hpp - g++ on IA64
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
// Copyright 2005 Ben Hutchings
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
#include <typeinfo>
namespace boost
{
namespace detail
{
inline void atomic_increment( long * pw )
{
// ++*pw;
long tmp;
// No barrier is required here but fetchadd always has an acquire or
// release barrier associated with it. We choose release as it should be
// cheaper.
__asm__ ("fetchadd8.rel %0=[%2],1" :
"=r"(tmp), "=m"(*pw) :
"r"(pw));
}
inline long atomic_decrement( long * pw )
{
// return --*pw;
long rv;
__asm__ (" fetchadd8.rel %0=[%2],-1 ;; \n"
" cmp.eq p7,p0=1,%0 ;; \n"
"(p7) ld8.acq %0=[%2] " :
"=&r"(rv), "=m"(*pw) :
"r"(pw) :
"p7");
return rv;
}
inline long atomic_conditional_increment( long * pw )
{
// if( *pw != 0 ) ++*pw;
// return *pw;
long rv, tmp, tmp2;
__asm__ ("0: ld8 %0=[%4] ;; \n"
" cmp.eq p7,p0=0,%0 ;; \n"
"(p7) br.cond.spnt 1f \n"
" mov ar.ccv=%0 \n"
" add %1=1,%0 ;; \n"
" cmpxchg8.acq %2=[%4],%1,ar.ccv ;; \n"
" cmp.ne p7,p0=%0,%2 ;; \n"
"(p7) br.cond.spnt 0b \n"
" mov %0=%1 ;; \n"
"1:" :
"=&r"(rv), "=&r"(tmp), "=&r"(tmp2), "=m"(*pw) :
"r"(pw) :
"ar.ccv", "p7");
return rv;
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared
long weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( std::type_info const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_decrement( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_decrement( &weak_count_ ) == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<long const volatile &>( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED

View File

@@ -1,181 +0,0 @@
#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED
#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_gcc_ppc.hpp - g++ on PowerPC
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
// formulation
//
#include <typeinfo>
namespace boost
{
namespace detail
{
inline void atomic_increment( int * pw )
{
// ++*pw;
int tmp;
__asm__
(
"0:\n\t"
"lwarx %1, 0, %2\n\t"
"addi %1, %1, 1\n\t"
"stwcx. %1, 0, %2\n\t"
"bne- 0b":
"=m"( *pw ), "=&b"( tmp ):
"r"( pw ):
"cc"
);
}
inline int atomic_decrement( int * pw )
{
// return --*pw;
int rv;
__asm__ __volatile__
(
"sync\n\t"
"0:\n\t"
"lwarx %1, 0, %2\n\t"
"addi %1, %1, -1\n\t"
"stwcx. %1, 0, %2\n\t"
"bne- 0b\n\t"
"isync":
"=m"( *pw ), "=&b"( rv ):
"r"( pw ):
"memory", "cc"
);
return rv;
}
inline int atomic_conditional_increment( int * pw )
{
// if( *pw != 0 ) ++*pw;
// return *pw;
int rv;
__asm__
(
"0:\n\t"
"lwarx %1, 0, %2\n\t"
"cmpwi %1, 0\n\t"
"beq 1f\n\t"
"addi %1, %1, 1\n\t"
"1:\n\t"
"stwcx. %1, 0, %2\n\t"
"bne- 0b":
"=m"( *pw ), "=&b"( rv ):
"r"( pw ):
"cc"
);
return rv;
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
int use_count_; // #shared
int weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( std::type_info const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_decrement( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_decrement( &weak_count_ ) == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<int const volatile &>( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED

View File

@@ -1,173 +0,0 @@
#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_gcc_x86.hpp - g++ on 486+ or AMD64
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
// formulation
//
#include <typeinfo>
namespace boost
{
namespace detail
{
inline int atomic_exchange_and_add( int * pw, int dv )
{
// int r = *pw;
// *pw += dv;
// return r;
int r;
__asm__ __volatile__
(
"lock\n\t"
"xadd %1, %0":
"=m"( *pw ), "=r"( r ): // outputs (%0, %1)
"m"( *pw ), "1"( dv ): // inputs (%2, %3 == %1)
"memory", "cc" // clobbers
);
return r;
}
inline void atomic_increment( int * pw )
{
//atomic_exchange_and_add( pw, 1 );
__asm__
(
"lock\n\t"
"incl %0":
"=m"( *pw ): // output (%0)
"m"( *pw ): // input (%1)
"cc" // clobbers
);
}
inline int atomic_conditional_increment( int * pw )
{
// int rv = *pw;
// if( rv != 0 ) ++*pw;
// return rv;
int rv, tmp;
__asm__
(
"movl %0, %%eax\n\t"
"0:\n\t"
"test %%eax, %%eax\n\t"
"je 1f\n\t"
"movl %%eax, %2\n\t"
"incl %2\n\t"
"lock\n\t"
"cmpxchgl %2, %0\n\t"
"jne 0b\n\t"
"1:":
"=m"( *pw ), "=&a"( rv ), "=&r"( tmp ): // outputs (%0, %1, %2)
"m"( *pw ): // input (%3)
"cc" // clobbers
);
return rv;
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
int use_count_; // #shared
int weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( std::type_info const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<int const volatile &>( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED

View File

@@ -1,107 +0,0 @@
#ifndef BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED
#define BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_nt.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <typeinfo>
namespace boost
{
namespace detail
{
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared
long weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( std::type_info const & ti ) = 0;
void add_ref_copy()
{
++use_count_;
}
bool add_ref_lock() // true on success
{
if( use_count_ == 0 ) return false;
++use_count_;
return true;
}
void release() // nothrow
{
if( --use_count_ == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
++weak_count_;
}
void weak_release() // nothrow
{
if( --weak_count_ == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
return use_count_;
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED

View File

@@ -1,135 +0,0 @@
#ifndef BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
#define BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_pt.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <typeinfo>
#include <pthread.h>
namespace boost
{
namespace detail
{
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared
long weak_count_; // #weak + (#shared != 0)
mutable pthread_mutex_t m_;
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
#if defined(__hpux) && defined(_DECTHREADS_)
pthread_mutex_init( &m_, pthread_mutexattr_default );
#else
pthread_mutex_init( &m_, 0 );
#endif
}
virtual ~sp_counted_base() // nothrow
{
pthread_mutex_destroy( &m_ );
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( std::type_info const & ti ) = 0;
void add_ref_copy()
{
pthread_mutex_lock( &m_ );
++use_count_;
pthread_mutex_unlock( &m_ );
}
bool add_ref_lock() // true on success
{
pthread_mutex_lock( &m_ );
bool r = use_count_ == 0? false: ( ++use_count_, true );
pthread_mutex_unlock( &m_ );
return r;
}
void release() // nothrow
{
pthread_mutex_lock( &m_ );
long new_use_count = --use_count_;
pthread_mutex_unlock( &m_ );
if( new_use_count == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
pthread_mutex_lock( &m_ );
++weak_count_;
pthread_mutex_unlock( &m_ );
}
void weak_release() // nothrow
{
pthread_mutex_lock( &m_ );
long new_weak_count = --weak_count_;
pthread_mutex_unlock( &m_ );
if( new_weak_count == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
pthread_mutex_lock( &m_ );
long r = use_count_;
pthread_mutex_unlock( &m_ );
return r;
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED

View File

@@ -1,117 +0,0 @@
#ifndef BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
#define BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_w32.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
// formulation
//
#include <boost/detail/interlocked.hpp>
#include <typeinfo>
namespace boost
{
namespace detail
{
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared
long weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( std::type_info const & ti ) = 0;
void add_ref_copy()
{
BOOST_INTERLOCKED_INCREMENT( &use_count_ );
}
bool add_ref_lock() // true on success
{
for( ;; )
{
long tmp = static_cast< long const volatile& >( use_count_ );
if( tmp == 0 ) return false;
if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true;
}
}
void release() // nothrow
{
if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
BOOST_INTERLOCKED_INCREMENT( &weak_count_ );
}
void weak_release() // nothrow
{
if( BOOST_INTERLOCKED_DECREMENT( &weak_count_ ) == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<long const volatile &>( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED

View File

@@ -1,187 +0,0 @@
#ifndef BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
#define BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_impl.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/config.hpp>
#if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR)
# error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible.
#endif
#include <boost/checked_delete.hpp>
#include <boost/detail/sp_counted_base.hpp>
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
#include <boost/detail/quick_allocator.hpp>
#endif
#include <memory> // std::allocator
#include <typeinfo> // std::type_info in get_deleter
#include <cstddef> // std::size_t
namespace boost
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
void sp_scalar_constructor_hook( void * px, std::size_t size, void * pn );
void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn );
#endif
namespace detail
{
template<class X> class sp_counted_impl_p: public sp_counted_base
{
private:
X * px_;
sp_counted_impl_p( sp_counted_impl_p const & );
sp_counted_impl_p & operator= ( sp_counted_impl_p const & );
typedef sp_counted_impl_p<X> this_type;
public:
explicit sp_counted_impl_p( X * px ): px_( px )
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_constructor_hook( px, sizeof(X), this );
#endif
}
virtual void dispose() // nothrow
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_destructor_hook( px_, sizeof(X), this );
#endif
boost::checked_delete( px_ );
}
virtual void * get_deleter( std::type_info const & )
{
return 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
};
//
// 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_impl_pd: public sp_counted_base
{
private:
P ptr; // copy constructor must not throw
D del; // copy constructor must not throw
sp_counted_impl_pd( sp_counted_impl_pd const & );
sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );
typedef sp_counted_impl_pd<P, D> this_type;
public:
// pre: d(p) must not throw
sp_counted_impl_pd( P p, D d ): ptr(p), del(d)
{
}
virtual void dispose() // nothrow
{
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
};
#ifdef __CODEGUARD__
# pragma option pop
#endif
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED

View File

@@ -0,0 +1,75 @@
#ifndef BOOST_DETAIL_WINAPI_HPP_INCLUDED
#define BOOST_DETAIL_WINAPI_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/detail/winapi.hpp - a lightweight version of <windows.h>
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
namespace boost
{
namespace detail
{
namespace winapi
{
typedef long long_type;
typedef unsigned long dword_type;
typedef void * handle_type;
#if defined(_WIN64)
typedef __int64 int_ptr_type;
typedef unsigned __int64 uint_ptr_type;
typedef __int64 long_ptr_type;
typedef unsigned __int64 ulong_ptr_type;
#else
typedef int int_ptr_type;
typedef unsigned int uint_ptr_type;
typedef long long_ptr_type;
typedef unsigned long ulong_ptr_type;
#endif
struct critical_section
{
struct critical_section_debug * DebugInfo;
long_type LockCount;
long_type RecursionCount;
handle_type OwningThread;
handle_type LockSemaphore;
ulong_ptr_type SpinCount;
};
extern "C" __declspec(dllimport) long_type __stdcall InterlockedIncrement(long_type volatile *);
extern "C" __declspec(dllimport) long_type __stdcall InterlockedDecrement(long_type volatile *);
extern "C" __declspec(dllimport) long_type __stdcall InterlockedExchange(long_type volatile *, long_type);
extern "C" __declspec(dllimport) void __stdcall Sleep(dword_type);
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *);
extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(critical_section *);
extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(critical_section *);
extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(critical_section *);
} // namespace winapi
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_WINAPI_HPP_INCLUDED

View File

@@ -1,67 +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
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
//
#include <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
mutable weak_ptr<_internal_element_type> _internal_weak_this;
};
} // namespace boost
#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED

View File

@@ -1,29 +0,0 @@
// Copyright Peter Dimov and David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef GET_POINTER_DWA20021219_HPP
# define GET_POINTER_DWA20021219_HPP
# 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

@@ -6,26 +6,20 @@
//
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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
#include <functional> // std::less
namespace boost
{
@@ -53,18 +47,21 @@ private:
public:
typedef T element_type;
intrusive_ptr(): p_(0)
{
}
intrusive_ptr(T * p, bool add_ref = true): p_(p)
intrusive_ptr(T * p): p_(p)
{
if(p_ != 0 && add_ref) intrusive_ptr_add_ref(p_);
if(p_ != 0) intrusive_ptr_add_ref(p_);
}
#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
~intrusive_ptr()
{
if(p_ != 0) intrusive_ptr_release(p_);
}
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
template<class U> intrusive_ptr(intrusive_ptr<U> const & rhs): p_(rhs.get())
{
@@ -78,12 +75,7 @@ public:
if(p_ != 0) intrusive_ptr_add_ref(p_);
}
~intrusive_ptr()
{
if(p_ != 0) intrusive_ptr_release(p_);
}
#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
template<class U> intrusive_ptr & operator=(intrusive_ptr<U> const & rhs)
{
@@ -105,6 +97,13 @@ public:
return *this;
}
void swap(intrusive_ptr & rhs)
{
T * tmp = p_;
p_ = rhs.p_;
rhs.p_ = tmp;
}
T * get() const
{
return p_;
@@ -120,43 +119,16 @@ public:
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
bool empty() const
{
return p_ == 0;
}
void swap(intrusive_ptr & rhs)
typedef bool (intrusive_ptr::*bool_type) () const;
operator bool_type () const
{
T * tmp = p_;
p_ = rhs.p_;
rhs.p_ = tmp;
return p_ == 0? 0: &intrusive_ptr::empty;
}
private:
@@ -164,6 +136,21 @@ private:
T * p_;
};
template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)
{
lhs.swap(rhs);
}
template<class T, class U> intrusive_ptr<T> shared_dynamic_cast(intrusive_ptr<U> const & p)
{
return dynamic_cast<T *>(p.get());
}
template<class T, class U> intrusive_ptr<T> shared_static_cast(intrusive_ptr<U> const & p)
{
return static_cast<T *>(p.get());
}
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
{
return a.get() == b.get();
@@ -174,6 +161,11 @@ template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, in
return a.get() != b.get();
}
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> inline bool operator==(intrusive_ptr<T> const & a, T * b)
{
return a.get() == b;
@@ -194,27 +186,6 @@ 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)
@@ -222,47 +193,6 @@ 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

View File

@@ -4,38 +4,27 @@
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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/scoped_array.htm
// See http://www.boost.org/libs/smart_ptr/scoped_array.htm for documentation.
//
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/config.hpp> // in case ptrdiff_t not in std
#include <boost/detail/workaround.hpp>
#include <cstddef> // for std::ptrdiff_t
namespace boost
{
// Debug hooks
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
void sp_array_constructor_hook(void * p);
void sp_array_destructor_hook(void * p);
#endif
// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
// is guaranteed, either on destruction of the scoped_array or via an explicit
// reset(). Use shared_array or std::vector if your needs are more complex.
template<class T> class scoped_array // noncopyable
template<typename T> class scoped_array // noncopyable
{
private:
@@ -44,31 +33,26 @@ private:
scoped_array(scoped_array const &);
scoped_array & operator=(scoped_array const &);
typedef scoped_array<T> this_type;
public:
typedef T element_type;
explicit scoped_array(T * p = 0) : ptr(p) // never throws
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_array_constructor_hook(ptr);
#endif
}
~scoped_array() // never throws
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_array_destructor_hook(ptr);
#endif
boost::checked_array_delete(ptr);
checked_array_delete(ptr);
}
void reset(T * p = 0) // never throws
{
BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors
this_type(p).swap(*this);
if (ptr != p)
{
checked_array_delete(ptr);
ptr = p;
}
}
T & operator[](std::ptrdiff_t i) const // never throws
@@ -83,39 +67,6 @@ public:
return ptr;
}
// implicit conversion to "bool"
#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
operator bool () const
{
return ptr != 0;
}
#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
typedef T * (this_type::*unspecified_bool_type)() const;
operator unspecified_bool_type() const // never throws
{
return ptr == 0? 0: &this_type::get;
}
#else
typedef T * this_type::*unspecified_bool_type;
operator unspecified_bool_type() const // never throws
{
return ptr == 0? 0: &this_type::ptr;
}
#endif
bool operator! () const // never throws
{
return ptr == 0;
}
void swap(scoped_array & b) // never throws
{
T * tmp = b.ptr;

View File

@@ -4,83 +4,54 @@
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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/scoped_ptr.htm
// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation.
//
#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
{
// Debug hooks
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
void sp_scalar_constructor_hook(void * p);
void sp_scalar_destructor_hook(void * p);
#endif
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
// of the object pointed to, either on destruction of the scoped_ptr or via
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
// use shared_ptr or std::auto_ptr if your needs are more complex.
template<class T> class scoped_ptr // noncopyable
template<typename T> class scoped_ptr // noncopyable
{
private:
T * ptr;
T* ptr;
scoped_ptr(scoped_ptr const &);
scoped_ptr & operator=(scoped_ptr const &);
typedef scoped_ptr<T> this_type;
public:
typedef T element_type;
explicit scoped_ptr(T * p = 0): ptr(p) // never throws
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_constructor_hook(ptr);
#endif
}
#ifndef BOOST_NO_AUTO_PTR
explicit scoped_ptr(std::auto_ptr<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
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_destructor_hook(ptr);
#endif
boost::checked_delete(ptr);
checked_delete(ptr);
}
void reset(T * p = 0) // never throws
{
BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors
this_type(p).swap(*this);
if (ptr != p)
{
checked_delete(ptr);
ptr = p;
}
}
T & operator*() const // never throws
@@ -100,38 +71,6 @@ public:
return ptr;
}
// implicit conversion to "bool"
#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
operator bool () const
{
return ptr != 0;
}
#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
typedef T * (this_type::*unspecified_bool_type)() const;
operator unspecified_bool_type() const // never throws
{
return ptr == 0? 0: &this_type::get;
}
#else
typedef T * this_type::*unspecified_bool_type;
operator unspecified_bool_type() const // never throws
{
return ptr == 0? 0: &this_type::ptr;
}
#endif
bool operator! () const // never throws
{
return ptr == 0;
}
void swap(scoped_ptr & b) // never throws
{
T * tmp = b.ptr;
@@ -140,18 +79,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);
}
// 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
#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED

View File

@@ -7,16 +7,17 @@
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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/shared_array.htm for documentation.
//
#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>
#else
@@ -24,7 +25,6 @@
#include <boost/checked_delete.hpp>
#include <boost/detail/shared_count.hpp>
#include <boost/detail/workaround.hpp>
#include <cstddef> // for std::ptrdiff_t
#include <algorithm> // for std::swap
@@ -41,7 +41,7 @@ namespace boost
// is destroyed or reset.
//
template<class T> class shared_array
template<typename T> class shared_array
{
private:
@@ -63,7 +63,7 @@ public:
// 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)
{
}
@@ -75,7 +75,7 @@ public:
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);
}
@@ -92,39 +92,6 @@ public:
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
{
return pn.unique();
@@ -148,28 +115,28 @@ private:
}; // 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();
}
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();
}
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());
}
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);
}
} // 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

View File

@@ -5,32 +5,31 @@
// shared_ptr.hpp
//
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002, 2003 Peter Dimov
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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/shared_ptr.htm for documentation.
//
#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>
#else
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/detail/shared_count.hpp>
#include <boost/detail/workaround.hpp>
#include <memory> // for std::auto_ptr
#include <algorithm> // for std::swap
#include <functional> // for std::less
#include <typeinfo> // for std::bad_cast
#include <iosfwd> // for std::basic_ostream
#include <boost/detail/shared_count.hpp>
#include <memory> // for std::auto_ptr
#include <algorithm> // for std::swap
#include <functional> // for std::less
#include <typeinfo> // for std::bad_cast
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
# pragma warning(push)
@@ -40,18 +39,14 @@
namespace boost
{
template<class T> class weak_ptr;
template<class T> class enable_shared_from_this;
namespace detail
{
struct static_cast_tag {};
struct const_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;
};
@@ -61,36 +56,6 @@ template<> struct shared_ptr_traits<void>
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( shared_count const & pn, boost::enable_shared_from_this<T> const * pe, Y const * px )
{
if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn);
}
inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... )
{
}
} // namespace detail
@@ -102,28 +67,28 @@ inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... )
// is destroyed or reset.
//
template<class T> class shared_ptr
template<typename T> class weak_ptr;
template<typename T> class intrusive_ptr;
template<typename T> class shared_ptr
{
private:
// Borland 5.5.1 specific workaround
// Borland 5.5.1 specific workarounds
// typedef checked_deleter<T> deleter;
typedef shared_ptr<T> this_type;
public:
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+
shared_ptr(): px(0), pn()
{
}
template<class Y>
explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
template<typename Y>
explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter<Y>(), p) // Y must be complete
{
detail::sp_enable_shared_from_this( pn, p, p );
}
//
@@ -132,80 +97,62 @@ public:
// 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 Y, typename D> shared_ptr(Y * p, D d): px(p), pn(p, d)
{
detail::sp_enable_shared_from_this( pn, p, p );
}
// 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
#if defined(__BORLANDC__) || defined(__GNUC__)
shared_ptr & operator=(shared_ptr const & r) // never throws
template<typename Y>
explicit shared_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // may throw
{
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>
template<typename Y>
shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
{
}
template<class Y>
template<typename Y>
shared_ptr(intrusive_ptr<Y> const & r): px(r.get()), pn(r.get()) // never throws
{
}
template<typename Y>
shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
{
}
template<class 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>
template<typename Y>
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();
}
}
template<class Y>
template<typename 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)
if (px == 0)
{
boost::throw_exception(std::bad_cast());
throw std::bad_cast();
}
}
#ifndef BOOST_NO_AUTO_PTR
template<class Y>
explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
template<typename Y>
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( pn, tmp, tmp );
}
#endif
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
template<class Y>
template<typename Y>
shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
{
px = r.px;
@@ -217,7 +164,7 @@ public:
#ifndef BOOST_NO_AUTO_PTR
template<class Y>
template<typename Y>
shared_ptr & operator=(std::auto_ptr<Y> & r)
{
this_type(r).swap(*this);
@@ -226,23 +173,23 @@ public:
#endif
void reset() // never throws in 1.30+
void reset()
{
this_type().swap(*this);
}
template<class Y> void reset(Y * p) // Y must be complete
template<typename Y> void reset(Y * p) // Y must be complete
{
BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
this_type(p).swap(*this);
}
template<class Y, class D> void reset(Y * p, D d)
template<typename Y, typename D> void reset(Y * p, D d)
{
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);
return *px;
@@ -259,44 +206,6 @@ public:
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__, < 0x3200) ) || \
( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) )
typedef T * (this_type::*unspecified_bool_type)() const;
operator unspecified_bool_type() const // never throws
{
return px == 0? 0: &this_type::get;
}
#else
typedef T * this_type::*unspecified_bool_type;
operator unspecified_bool_type() const // never throws
{
return px == 0? 0: &this_type::px;
}
#endif
// operator! is redundant, but some compilers need it
bool operator! () const // never throws
{
return px == 0;
}
bool unique() const // never throws
{
return pn.unique();
@@ -307,22 +216,26 @@ public:
return pn.use_count();
}
// implicit conversion to "bool"
typedef long (this_type::*bool_type)() const;
operator bool_type() const // never throws
{
return px == 0? 0: &this_type::use_count;
}
bool operator! () const // never throws
{
return px == 0;
}
void swap(shared_ptr<T> & other) // never throws
{
std::swap(px, other.px);
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
// to work in the absence of member template friends. (Matthew Langston)
@@ -330,8 +243,8 @@ public:
private:
template<class Y> friend class shared_ptr;
template<class Y> friend class weak_ptr;
template<typename Y> friend class shared_ptr;
template<typename Y> friend class weak_ptr;
#endif
@@ -341,12 +254,12 @@ private:
}; // 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();
}
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();
}
@@ -355,56 +268,39 @@ template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, share
// 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)
template<typename T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
{
return a.get() != b.get();
}
#endif
template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
template<typename T> inline bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b)
{
return a._internal_less(b);
return std::less<T*>()(a.get(), b.get());
}
template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
template<typename T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & 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());
}
template<class T, class U> shared_ptr<T> const_pointer_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)
template<typename T, typename U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
{
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)
template<typename T, typename 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)
template<typename T, typename 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);
@@ -412,67 +308,17 @@ template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(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();
}
// 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__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
// g++ 2.9x doesn't allow static_cast<X const *>(void *)
// apparently EDG 2.38 and HP aCC A.03.35 also don'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
#ifdef BOOST_MSVC
# pragma warning(pop)
#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

View File

@@ -1,25 +1,9 @@
//
// smart_ptr.hpp
//
// For convenience, this header includes the rest of the smart
// pointer library headers.
//
// Copyright (c) 2003 Peter Dimov Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// http://www.boost.org/libs/smart_ptr/smart_ptr.htm
//
// Boost smart_ptr.hpp header file -----------------------------------------//
#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/shared_ptr.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,11 +4,12 @@
//
// weak_ptr.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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/weak_ptr.htm for documentation.
//
@@ -23,7 +24,7 @@
namespace boost
{
template<class T> class weak_ptr
template<typename T> class weak_ptr
{
private:
@@ -34,52 +35,33 @@ public:
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
//
// 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
template<typename Y>
weak_ptr(weak_ptr<Y> const & r): px(r.px), 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
{
}
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
template<class Y>
template<typename Y>
weak_ptr & operator=(weak_ptr<Y> const & r) // never throws
{
px = r.lock().get();
px = r.px;
pn = r.pn;
return *this;
}
template<class Y>
template<typename Y>
weak_ptr & operator=(shared_ptr<Y> const & r) // never throws
{
px = r.px;
@@ -89,33 +71,14 @@ public:
#endif
shared_ptr<T> lock() const // never throws
void reset()
{
#if defined(BOOST_HAS_THREADS)
this_type().swap(*this);
}
// optimization: avoid throw overhead
if(expired())
{
return shared_ptr<element_type>();
}
try
{
return shared_ptr<element_type>(*this);
}
catch(bad_weak_ptr const &)
{
// Q: how can we get here?
// A: another thread may have invalidated r after the use_count test above.
return shared_ptr<element_type>();
}
#else
// optimization: avoid try/catch overhead when single threaded
return expired()? shared_ptr<element_type>(): shared_ptr<element_type>(*this);
#endif
T * get() const // never throws; unsafe in multithreaded programs!
{
return pn.use_count() == 0? 0: px;
}
long use_count() const // never throws
@@ -128,24 +91,13 @@ public:
return pn.use_count() == 0;
}
void reset() // never throws in 1.30+
{
this_type().swap(*this);
}
void swap(this_type & other) // never throws
{
std::swap(px, other.px);
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
bool less(this_type const & rhs) const // implementation detail, never throws
{
return pn < rhs.pn;
}
@@ -157,8 +109,8 @@ public:
private:
template<class Y> friend class weak_ptr;
template<class Y> friend class shared_ptr;
template<typename Y> friend class weak_ptr;
template<typename Y> friend class shared_ptr;
#endif
@@ -167,9 +119,30 @@ private:
}; // 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();
}
#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
// Resolve the ambiguity between our op!= and the one in rel_ops
template<typename T> inline bool operator!=(weak_ptr<T> const & a, weak_ptr<T> const & b)
{
return a.get() != b.get();
}
#endif
template<class T> inline bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b)
{
return a.less(b);
}
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
@@ -177,10 +150,22 @@ template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
a.swap(b);
}
// deprecated, provided for backward compatibility
template<class T> shared_ptr<T> make_shared(weak_ptr<T> const & r)
template<class T> shared_ptr<T> make_shared(weak_ptr<T> const & r) // never throws
{
return r.lock();
// optimization: avoid throw overhead
if(r.use_count() == 0)
{
return shared_ptr<T>();
}
try
{
return shared_ptr<T>(r);
}
catch(use_count_is_zero const &)
{
return shared_ptr<T>();
}
}
} // 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="boost.png (6897 bytes)" src="../../boost.png" 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">
<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="../../boost.png" alt="boost.png (6897 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:
typedef T <a href="#element_type">element_type</a>;
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
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
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>
<h2>Members</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="ctor">constructors</a></h3>
<pre>explicit scoped_array(T * p = 0); // never throws</pre>
<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
required be a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p>
<h3><a name="destructor">destructor</a></h3>
<pre>~scoped_array(); // never throws</pre>
<p>Deletes the array pointed to by the stored pointer. Note that <b>delete[]</b> on
a pointer with a value of 0 is harmless. The guarantee that this does not throw
exceptions depends on the requirement that the deleted array's objects'
destructors do not throw exceptions. See the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p>
<h3><a name="reset">reset</a></h3>
<pre>void reset(T * p = 0); // never throws</pre>
<p>
Deletes the array pointed to by the stored pointer and then stores a copy of 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
the deleted array's objects' destructors do not throw exceptions. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="operator[]">subscripting</a></h3>
<pre>T &amp; operator[](std::ptrdiff_t i) const; // never throws</pre>
<p>Returns a reference to element <b>i</b> of the array pointed to by the stored
pointer. Behavior is undefined and almost certainly undesirable if the stored
pointer is 0, or if <b>i</b> is less than 0 or is greater than or equal to the
number of elements in the array.</p>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<p>Returns 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>
<h3><a name="swap">swap</a></h3>
<pre>void swap(scoped_array &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="free-swap">swap</a></h3>
<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>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-->09 January 2003<!--webbot bot="Timestamp" endspan i-checksum="32310"--></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
"as is" without express or implied warranty, and with no claim as to its
suitability for any purpose.</p>
</body>
</html>
<h2>Members</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="ctor">constructors</a></h3>
<pre>explicit scoped_array(T * p = 0); // never throws</pre>
<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 required be a complete type.
See the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h3><a name="~scoped_array">destructor</a></h3>
<pre>~scoped_array(); // never throws</pre>
<p>Deletes the array pointed to by the stored pointer.
Note that <b>delete[]</b> on a pointer with a value of 0 is harmless.
The guarantee that this does not throw exceptions depends on the requirement that the
deleted array's objects' destructors do not throw exceptions.
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h3><a name="reset">reset</a></h3>
<pre>void reset(T * p = 0); // never throws</pre>
<p>If p is not equal to the stored pointer, deletes the array pointed to by the
stored pointer and then stores a copy of p, which must have been allocated via a
C++ <b>new[]</b> expression or be 0.
The guarantee that this does not throw exceptions depends on the requirement that the
deleted array's objects' destructors do not throw exceptions.
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h3><a name="operator[]">subscripting</a></h3>
<pre>T &amp; operator[](std::size_t i) const; // never throws</pre>
<p>Returns a reference to element <b>i</b> of the array pointed to by the
stored pointer.
Behavior is undefined and almost certainly undesirable if the stored pointer is 0,
or if <b>i</b> is less than 0 or is greater than or equal to the number of elements
in the array.</p>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<p>Returns 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>
<h3><a name="swap">swap</a></h3>
<pre>void swap(scoped_array &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="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>

View File

@@ -1,46 +1,59 @@
<!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="../../boost.png" alt="boost.png (6897 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:
typedef T <a href="#element_type">element_type</a>;
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
@@ -51,62 +64,78 @@
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>
<h2>Members</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 scoped_ptr(T * p = 0); // never throws</pre>
<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
a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
requirements</a>.</p>
<h3><a name="destructor">destructor</a></h3>
<pre>~scoped_ptr(); // never throws</pre>
<p>Destroys the object pointed to by the stored pointer, if any, as if by using <tt>delete
this-&gt;get()</tt>.</p>
<P>
The guarantee that this does not throw exceptions depends on the requirement
that the deleted object's destructor does not throw exceptions. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</P>
<h3><a name="reset">reset</a></h3>
<pre>void reset(T * p = 0); // never throws</pre>
<p>
Deletes the object pointed to by the stored pointer and then stores a copy of
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
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="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.</p>
<pre>T * operator-&gt;() const; // never throws</pre>
<p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<p>Returns 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>
<h3><a name="swap">swap</a></h3>
<pre>void swap(scoped_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="free-swap">swap</a></h3>
<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>
<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;
<h2>Members</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 scoped_ptr(T * p = 0); // never throws</pre>
<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 a complete type.
See the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h3><a name="~scoped_ptr">destructor</a></h3>
<pre>~scoped_ptr(); // never throws</pre>
<p>Deletes the object pointed to by the stored pointer.
Note that <b>delete</b> on a pointer with a value of 0 is harmless.
The guarantee that this does not throw exceptions depends on the requirement that the
deleted object's destructor does not throw exceptions.
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h3><a name="reset">reset</a></h3>
<pre>void reset(T * p = 0); // never throws</pre>
<p>If p is not equal to the stored pointer, deletes the object pointed to by the
stored pointer and then stores a copy of p, which must have been allocated via a
C++ <b>new</b> expression or be 0.
The guarantee that this does not throw exceptions depends on the requirement that the
deleted object's destructor does not throw exceptions.
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</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.</p>
<pre>T * operator-&gt;() const; // never throws</pre>
<p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<p>Returns 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>
<h3><a name="swap">swap</a></h3>
<pre>void swap(scoped_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="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;
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 {
boost::scoped_ptr&lt;int&gt; ptr;
@@ -115,62 +144,74 @@ class MyClass {
int add_one() { return ++*ptr; }
};
int main()
void main()
{
boost::scoped_ptr&lt;Shoe&gt; x(new Shoe);
MyClass my_instance;
std::cout &lt;&lt; my_instance.add_one() &lt;&lt; '\n';
std::cout &lt;&lt; my_instance.add_one() &lt;&lt; '\n';
}</pre>
</blockquote>
<p>The example program produces the beginning of a child's nursery rhyme:</p>
<blockquote>
<pre>1
</blockquote>
<p>The example program produces the beginning of a child's nursery rhyme:</p>
<blockquote>
<pre>1
2
Buckle my shoe</pre>
</blockquote>
<h2>Rationale</h2>
<p>The primary reason to use <b>scoped_ptr</b> rather than <b>auto_ptr</b> is to
let readers of your code know that you intend "resource acquisition is
initialization" to be applied only for the current scope, and have no intent to
transfer ownership.</p>
<p>A secondary reason to use <b>scoped_ptr</b> is to prevent a later maintenance
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
could safely be transferred.</p>
<p>Think of <b>bool</b> vs <b>int</b>. We all know that under the covers <b>bool</b>
is usually just an <b>int</b>. Indeed, some argued against including <b>bool</b>
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
using it you are signaling intent.</p>
<p>It has been suggested that <b>scoped_ptr&lt;T&gt;</b> is equivalent to <b>std::auto_ptr&lt;T&gt;
const</b>. Ed Brey pointed out, however, that <b>reset</b> will not work on
a <b>std::auto_ptr&lt;T&gt; const.</b></p>
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
<p>One common usage of <b>scoped_ptr</b> is to implement a handle/body (also called
pimpl) idiom which avoids exposing the body (implementation) in the header
file.</p>
<p>The <a href="example/scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a> sample
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
implementation. The instantiation of member functions which require a complete
type occurs in the <a href="example/scoped_ptr_example.cpp">scoped_ptr_example.cpp</a>
implementation file.</p>
<h2>Frequently Asked Questions</h2>
<p><b>Q</b>. Why doesn't <b>scoped_ptr</b> have a release() member?<br>
<b>A</b>. When reading source code, it is valuable to be able to draw
conclusions about program behavior based on the types being used. If <STRONG>scoped_ptr</STRONG>
had a release() member, it would become possible to transfer ownership of the
held pointer, weakening its role as a way of limiting resource lifetime to a
given context. Use <STRONG>std::auto_ptr</STRONG> where transfer of ownership
is required. (supplied by Dave Abrahams)</p>
<hr>
<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.
Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears in
all copies. This document is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.</p>
</body>
</blockquote>
<h2>Rationale</h2>
<p>The primary reason to use <b>scoped_ptr</b> rather than <b>auto_ptr</b> is to let readers
of your code know that you intend "resource acquisition is initialization" to be applied only
for the current scope, and have no intent to transfer ownership.</p>
<p>A secondary reason to use <b>scoped_ptr</b> is to prevent a later maintenance 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 could safely
be transferred.</p>
<p>Think of <b>bool</b> vs <b>int</b>. We all know that under the covers <b>bool</b> is usually
just an <b>int</b>. Indeed, some argued against including <b>bool</b> 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 using it you are signaling intent.</p>
<p>It has been suggested that <b>scoped_ptr&lt;T&gt;</b> is equivalent to
<b>std::auto_ptr&lt;T> const</b>. Ed Brey pointed out, however, that
<b>reset</b> will not work on a <b>std::auto_ptr&lt;T> const.</b></p>
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
<p>One common usage of <b>scoped_ptr</b> is to implement a handle/body (also
called pimpl) idiom which avoids exposing the body (implementation) in the header
file.</p>
<p>The <a href="scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a>
sample program includes a header file, <a href="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
implementation. The
instantiation of member functions which require a complete type occurs in
the <a href="scoped_ptr_example.cpp">scoped_ptr_example.cpp</a>
implementation file.</p>
<h2>Frequently Asked Questions</h2>
<p><b>Q</b>. Why doesn't <b>scoped_ptr</b> have a release() member?<br>
<b>A</b>. Because the point of <b>scoped_ptr</b> is to signal intent, not
to transfer ownership. Use <b>std::auto_ptr</b> if ownership transfer is
required.</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="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>

View File

@@ -1,12 +1,5 @@
// Boost scoped_ptr_example implementation file -----------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/smart_ptr for documentation.
#include "scoped_ptr_example.hpp"
#include <iostream>

View File

@@ -1,12 +1,5 @@
// Boost scoped_ptr_example header file ------------------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/smart_ptr for documentation.
#include <boost/utility.hpp>
#include <boost/scoped_ptr.hpp>

View File

@@ -0,0 +1,10 @@
// Boost scoped_ptr_example_test main program -------------------------------//
#include "scoped_ptr_example.hpp"
int main()
{
example my_example;
my_example.do_something();
return 0;
}

View File

@@ -1,43 +1,55 @@
<!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="../../boost.png" alt="boost.png (6897 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
single dynamically allocated object. 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:
typedef T <a href="#element_type">element_type</a>;
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="#constructors">shared_array</a>(shared_array const &amp; r); // never throws
@@ -45,7 +57,7 @@
shared_array &amp; <a href="#assignment">operator=</a>(shared_array const &amp; r); // never throws
void <a href="#reset">reset</a>(T * p = 0);
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);
T &amp; <a href="#indexing">operator[]</a>(std::ptrdiff_t i) const() 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
};
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
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
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
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>
<h2>Members</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 shared_array(T * p = 0);</pre>
<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
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
constructor is <b>std::bad_alloc</b>. If an exception is thrown, <b>delete[] p</b>
is called.</p>
<pre>template&lt;class D&gt; shared_array(T * p, D d);</pre>
<p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b> and of <b>d</b>.
Afterwards, the <a href="#use_count">use count</a> is 1. <b>D</b>'s copy
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>.
Invoking the object <b>d</b> with parameter <b>p</b> in this way must not
throw. The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
If an exception is thrown, <b>d(p)</b> is called.</p>
<pre>shared_array(shared_array const &amp; r); // never throws</pre>
<p>Constructs a <b>shared_array</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 1 more than the initial use count.</p>
<h3><a name="destructor">destructor</a></h3>
<pre>~shared_array(); // never throws</pre>
<p>Decrements the <a href="#use_count">use count</a>. Then, if the use count is 0,
deletes the array pointed to by the stored pointer. Note that <b>delete[]</b> on
a pointer with a value of 0 is harmless. <b>T</b> need not be a complete type.
The guarantee that this does not throw exceptions depends on the requirement
that the deleted object's destructor does not throw exceptions. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="assignment">assignment</a></h3>
<pre>shared_array &amp; operator=(shared_array const &amp; r); // never throws</pre>
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
then replaces this <b>shared_array</b> with the new one, destroying the
replaced object.</p>
<h3><a name="reset">reset</a></h3>
<pre>void reset(T * p = 0);</pre>
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
then replaces this <b>shared_array</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, <b>delete[] p</b> is called.</p>
<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>,
then replaces this <b>shared_array</b> with the new one, destroying the
replaced object. <b>D</b>'s copy constructor must not throw. The only exception
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="indexing">indexing</a></h3>
<pre>T &amp; operator[](std::ptrdiff_t i) const; // never throws</pre>
<p>Returns a reference to element <b>i</b> of the array pointed to by the stored
pointer. Behavior is undefined and almost certainly undesirable if the stored
pointer is 0, or if <b>i</b> is less than 0 or is greater than or equal to the
number of elements in the array.</p>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<p>Returns 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>
<h3><a name="unique">unique</a></h3>
<pre>bool unique() const; // never throws</pre>
<p>Returns true if no other <b>shared_array</b> is sharing ownership of the stored
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="use_count">use_count</a></h3>
<pre>long use_count() const; // never throws</pre>
<p>Returns the number of <b>shared_array</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>shared_array</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 not production code.</p>
<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;class T&gt;
<h2>Members</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 shared_array(T * p = 0);</pre>
<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 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 constructor is <b>std::bad_alloc</b>.
If an exception is thrown, <b>delete[] p</b> is called.</p>
<pre>template&lt;typename D&gt; shared_array(T * p, D d);</pre>
<p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b> and of <b>d</b>.
Afterwards, the <a href="#use_count">use count</a> is 1.
<b>D</b>'s copy 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>. Invoking the object <b>d</b> with
parameter <b>p</b> in this way must not throw.
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
If an exception is thrown, <b>d(p)</b> is called.</p>
<pre>shared_array(shared_array const &amp; r); // never throws</pre>
<p>Constructs a <b>shared_array</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 1 more than the initial use count.</p>
<h3><a name="destructor">destructor</a></h3>
<pre>~shared_array(); // never throws</pre>
<p>Decrements the <a href="#use_count">use count</a>. Then, if the use count is 0,
deletes the array pointed to by the stored pointer.
Note that <b>delete[]</b> on a pointer with a value of 0 is harmless.
<b>T</b> need not be a complete type.
The guarantee that this does not throw exceptions depends on the requirement that the
deleted object's destructor does not throw exceptions.
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h3><a name="operator=">assignment</a></h3>
<pre>shared_array &amp; <a href="#assignment">operator=</a>(shared_array const &amp; r); // never throws</pre>
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
then replaces this <b>shared_array</b> with the new one, destroying the replaced object.</p>
<h3><a name="reset">reset</a></h3>
<pre>void reset(T * p = 0);</pre>
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
then replaces this <b>shared_array</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, <b>delete[] p</b> is called.</p>
<pre>template&lt;typename D&gt; void reset(T * p, D d);</pre>
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
then replaces this <b>shared_array</b> with the new one, destroying the replaced object.
<b>D</b>'s copy constructor must not throw.
The only exception 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="indirection">indexing</a></h3>
<pre>T &amp; operator[](std::size_t i) const; // never throws</pre>
<p>Returns a reference to element <b>i</b> of the array pointed to by the stored pointer.
Behavior is undefined and almost certainly undesirable if the stored pointer is 0,
or if <b>i</b> is less than 0 or is greater than or equal to the number of elements
in the array.</p>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<p>Returns 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>
<h3><a name="unique">unique</a></h3>
<pre>bool unique() const; // never throws</pre>
<p>Returns true if no other <b>shared_array</b> is sharing ownership of
the stored 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="use_count">use_count</a></h3>
<pre>long use_count() const; // never throws</pre>
<p>Returns the number of <b>shared_array</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>shared_array</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 not production code.</p>
<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 operator==(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 operator!=(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 operator&lt;(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;class T&gt;
<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>
<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 -->
09 January 2003<!--webbot bot="Timestamp" endspan i-checksum="32310" --></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
"as is" without express or implied warranty, and with no claim as to its
suitability for any purpose.</p>
</body>
<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 -->8 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>
</html>

View File

@@ -5,24 +5,21 @@
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body text="#000000" bgColor="#ffffff">
<h1><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle">shared_ptr
<h1><IMG height="86" alt="c++boost.gif (8819 bytes)" src="../../c++boost.gif" width="277" align="middle">shared_ptr
class template</h1>
<p><A href="#Introduction">Introduction</A><br>
<A href="#BestPractices">Best Practices</A><br>
<A href="#Synopsis">Synopsis</A><br>
<A href="#Members">Members</A><br>
<A href="#functions">Free Functions</A><br>
<A href="#example">Example</A><br>
<A href="#Handle/Body">Handle/Body Idiom</A><br>
<A href="#ThreadSafety">Thread Safety</A><br>
<A href="#FAQ">Frequently Asked Questions</A><br>
<A href="smarttests.htm">Smart Pointer Timings</A><br>
<A href="sp_techniques.html">Programming Techniques</A></p>
<A href="smarttests.htm">Smart Pointer Timings</A></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <b>shared_ptr</b> class template stores a pointer to a dynamically allocated
object, typically with a C++ <EM>new-expression</EM>. The object pointed to is
guaranteed to be deleted when the last <b>shared_ptr</b> pointing to it is
destroyed or reset. See the <A href="#example">example</A>.</p>
object. (Dynamically allocated objects are allocated with the C++ <b>new</b> expression.)
The object pointed to is guaranteed to be deleted when the last <b>shared_ptr</b>
pointing to it is destroyed or reset. See the <A href="#example">example</A>.</p>
<p>Every <b>shared_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>shared_ptr</b>
@@ -30,11 +27,11 @@
<p>Normally, a <b>shared_ptr</b> cannot correctly hold a pointer to a dynamically
allocated array. See <A href="shared_array.htm"><b>shared_array</b></A> for
that usage.</p>
<p>Because the implementation uses reference counting, cycles of <b>shared_ptr</b> instances
will not be reclaimed. For example, if <b>main()</b> holds a <b>shared_ptr</b> to
<b>A</b>, which directly or indirectly holds a <b>shared_ptr</b> back to <b>A</b>,
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_ptr</b> will
leave <b>A</b> dangling with a use count of 1. Use <A href="weak_ptr.htm">weak_ptr</A>
<p>Because the implementation uses reference counting, <b>shared_ptr</b> will not
work correctly with cyclic data structures. For example, if <b>main()</b> holds
a <b>shared_ptr</b> to <b>A</b>, which directly or indirectly holds a <b>shared_ptr</b>
back to <b>A</b>, <b>A</b>'s use count will be 2. Destruction of the original <b>shared_ptr</b>
will leave <b>A</b> dangling with a use count of 1. Use <A href="weak_ptr.htm">weak_ptr</A>
to "break cycles."</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <STRONG>shared_ptr</STRONG> and most of its member functions place no
@@ -47,79 +44,36 @@
to <STRONG>shared_ptr&lt;T const&gt;</STRONG>, to <STRONG>shared_ptr&lt;U&gt;</STRONG>
where <STRONG>U</STRONG> is an accessible base of <STRONG>T</STRONG>, and to <STRONG>
shared_ptr&lt;void&gt;</STRONG>.</P>
<P><STRONG>shared_ptr</STRONG> is now part of <STRONG>TR1</STRONG>, the first C++
Library Technical Report. The latest draft of <STRONG>TR1</STRONG> is available
at the following location:</P>
<P><A href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf">http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf</A>
(1.36Mb PDF)</P>
<P>This implementation conforms to the TR1 specification, with the only exception
that it resides in namespace <code>boost</code> instead of <code>std::tr1</code>.</P>
<h2><a name="BestPractices">Best Practices</a></h2>
<P>A simple guideline that nearly eliminates the possibility of memory leaks is:
always use a named smart pointer variable to hold the result of <STRONG>new. </STRONG>
Every occurence of the <STRONG>new</STRONG> keyword in the code should have the
form:</P>
<PRE>shared_ptr&lt;T&gt; p(new Y);</PRE>
<P>It is, of course, acceptable to use another smart pointer in place of <STRONG>shared_ptr</STRONG>
above; having <STRONG>T</STRONG> and <STRONG>Y</STRONG> be the same type, or
passing arguments to <STRONG>Y</STRONG>'s constructor is also OK.</P>
<P>If you observe this guideline, it naturally follows that you will have no
explicit <STRONG>delete</STRONG>s; <STRONG>try/catch</STRONG> constructs will
be rare.</P>
<P>Avoid using unnamed <STRONG>shared_ptr</STRONG> temporaries to save typing; to
see why this is dangerous, consider this example:</P>
<PRE>void f(shared_ptr&lt;int&gt;, int);
int g();
void ok()
{
shared_ptr&lt;int&gt; p(new int(2));
f(p, g());
}
void bad()
{
f(shared_ptr&lt;int&gt;(new int(2)), g());
}
</PRE>
<P>The function <STRONG>ok</STRONG> follows the guideline to the letter, whereas <STRONG>
bad</STRONG> constructs the temporary <STRONG>shared_ptr</STRONG> in place,
admitting the possibility of a memory leak. Since function arguments are
evaluated in unspecified order, it is possible for <STRONG>new int(2)</STRONG> to
be evaluated first, <STRONG>g()</STRONG> second, and we may never get to the <STRONG>
shared_ptr </STRONG>constructor if <STRONG>g</STRONG> throws an exception.
See <A href="http://www.gotw.ca/gotw/056.htm">Herb Sutter's treatment</A> (also <A href="http://www.cuj.com/reference/articles/2002/0212/0212_sutter.htm">
here</A>) of the issue for more information.</P>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost {
class bad_weak_ptr: public std::exception;
class use_count_is_zero: public std::exception;
template&lt;class T&gt; class <A href="weak_ptr.htm" >weak_ptr</A>;
template&lt;typename T&gt; class <A href="weak_ptr.htm" >weak_ptr</A>;
template&lt;class T&gt; class shared_ptr {
template&lt;typename T&gt; class shared_ptr {
public:
typedef T <A href="#element_type" >element_type</A>;
<A href="#constructors" >shared_ptr</A>(); // never throws
template&lt;class Y&gt; explicit <A href="#constructors" >shared_ptr</A>(Y * p);
template&lt;class Y, class D&gt; <A href="#constructors" >shared_ptr</A>(Y * p, D d);
<A href="#constructors" >shared_ptr</A> ();
template&lt;typename Y&gt; explicit <A href="#constructors" >shared_ptr</A> (Y * p);
template&lt;typename Y, typename D&gt; <A href="#constructors" >shared_ptr</A>(Y * p, D d);
<A href="#destructor" >~shared_ptr</A>(); // never throws
<A href="#constructors" >shared_ptr</A>(shared_ptr const &amp; r); // never throws
template&lt;class Y&gt; <A href="#constructors" >shared_ptr</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;class Y&gt; explicit <A href="#constructors" >shared_ptr</A>(<A href="weak_ptr.htm" >weak_ptr</A>&lt;Y&gt; const &amp; r);
template&lt;class Y&gt; explicit <A href="#constructors" >shared_ptr</A>(std::auto_ptr&lt;Y&gt; &amp; r);
template&lt;typename Y&gt; <A href="#constructors" >shared_ptr</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
explicit <A href="#constructors" >shared_ptr</A>(<A href="weak_ptr.htm" >weak_ptr</A> const &amp; r);
template&lt;typename Y&gt; <A href="#constructors" >shared_ptr</A>(std::auto_ptr&lt;Y&gt; &amp; r);
shared_ptr &amp; <A href="#assignment" >operator=</A>(shared_ptr const &amp; r); // never throws
template&lt;class Y&gt; shared_ptr &amp; <A href="#assignment" >operator=</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;class Y&gt; shared_ptr &amp; <A href="#assignment" >operator=</A>(std::auto_ptr&lt;Y&gt; &amp; r);
template&lt;typename Y&gt; shared_ptr &amp; <A href="#assignment" >operator=</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;typename Y&gt; shared_ptr &amp; <A href="#assignment" >operator=</A>(std::auto_ptr&lt;Y&gt; &amp; r);
void <A href="#reset" >reset</A>(); // never throws
template&lt;class Y&gt; void <A href="#reset" >reset</A>(Y * p);
template&lt;class Y, class D&gt; void <A href="#reset" >reset</A>(Y * p, D d);
void <A href="#reset" >reset</A> ();
template&lt;typename Y&gt; void <A href="#reset" >reset</A> (Y * p);
template&lt;typename Y&gt; template&lt;typename D&gt; void <A href="#reset" >reset</A>(Y * p, D d);
T &amp; <A href="#indirection" >operator*</A>() const; // never throws
T * <A href="#indirection" >operator-&gt;</A>() const; // never throws
@@ -128,38 +82,29 @@ void bad()
bool <A href="#unique" >unique</A>() const; // never throws
long <A href="#use_count" >use_count</A>() const; // never throws
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
operator <a href="#conversions"><i>implementation-defined-type</i></a> () const; // never throws
void <A href="#swap" >swap</A>(shared_ptr &amp; b); // never throws
void <A href="#swap" >swap</A>(shared_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==</A>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class T, class U&gt;
template&lt;typename T, typename U&gt;
bool <A href="#comparison" >operator!=</A>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;typename T&gt;
bool <A href="#comparison" >operator&lt;</A>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;T&gt; const &amp; b); // never throws
template&lt;class T, class U&gt;
bool <A href="#comparison" >operator&lt;</A>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;typename T&gt; void <A href="#free-swap" >swap</A>(shared_ptr&lt;T&gt; &amp; a, shared_ptr&lt;T&gt; &amp; b); // never throws
template&lt;class T&gt; void <A href="#free-swap" >swap</A>(shared_ptr&lt;T&gt; &amp; a, shared_ptr&lt;T&gt; &amp; b); // never throws
template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; <A href="#shared_static_cast" >shared_static_cast</A>(shared_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; <A href="#shared_dynamic_cast" >shared_dynamic_cast</A>(shared_ptr&lt;U&gt; const &amp; r);
template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; <A href="#shared_polymorphic_cast" >shared_polymorphic_cast</A>(shared_ptr&lt;U&gt; const &amp; r);
template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; <A href="#shared_polymorphic_downcast" >shared_polymorphic_downcast</A>(shared_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class T&gt; T * <A href="#get_pointer" >get_pointer</A>(shared_ptr&lt;T&gt; const &amp; p); // never throws
template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; <A href="#static_pointer_cast" >static_pointer_cast</A>(shared_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; <A href="#const_pointer_cast" >const_pointer_cast</A>(shared_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; <A href="#dynamic_pointer_cast" >dynamic_pointer_cast</A>(shared_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, shared_ptr&lt;Y&gt; const &amp; p);
template&lt;class D, class T&gt;
D * <A href="#get_deleter">get_deleter</A>(shared_ptr&lt;T&gt; const &amp; p);
}</pre>
<h2><a name="Members">Members</a></h2>
<h3><a name="element_type">element_type</a></h3>
@@ -168,25 +113,24 @@ void bad()
<p>Provides the type of the template parameter T.</p>
</blockquote>
<h3><a name="constructors">constructors</a></h3>
<pre>shared_ptr(); // never throws</pre>
<pre>shared_ptr();</pre>
<blockquote>
<p><b>Effects:</b> Constructs an <EM>empty</EM> <b>shared_ptr</b>.</p>
<p><b>Postconditions:</b> <code>use_count() == 0 &amp;&amp; get() == 0</code>.</p>
<p><b>Throws:</b> nothing.</p>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>.</p>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> is 1; the stored
pointer is 0.</p>
<p><b>Throws:</b> <b>std::bad_alloc</b>.</p>
<p><b>Exception safety:</b> If an exception is thrown, the constructor has no
effect.</p>
</blockquote>
<P><EM>[The nothrow guarantee is important, since <STRONG>reset()</STRONG> is specified
in terms of the default constructor; this implies that the constructor must not
allocate memory.]</EM></P>
<pre>template&lt;class Y&gt; explicit shared_ptr(Y * p);</pre>
<pre>template&lt;typename Y&gt; explicit shared_ptr(Y * p);</pre>
<blockquote>
<p><b>Requirements:</b> <b>p</b> must be convertible to <b>T *</b>. <STRONG>Y</STRONG>
must be a complete type. The expression <code>delete p</code> must be
well-formed, must not invoke undefined behavior, and must not throw exceptions.
</p>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b> that <EM>owns</EM> the pointer <b>p</b>.</p>
<p><b>Postconditions:</b> <code>use_count() == 1 &amp;&amp; get() == p</code>.</p>
<p><b>Throws:</b> <STRONG>std::bad_alloc</STRONG>, or an implementation-defined
exception when a resource other than memory could not be obtained.</p>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b>.</p>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> is 1.</p>
<p><b>Throws:</b> <b>std::bad_alloc</b>.</p>
<p><b>Exception safety:</b> If an exception is thrown, <code>delete p</code> is
called.</p>
<P><STRONG>Notes:</STRONG> <B>p</B> must be a pointer to an object that was
@@ -194,110 +138,68 @@ void bad()
use count</A> is 1 holds even if <b>p</b> is 0; invoking <STRONG>delete</STRONG>
on a pointer that has a value of 0 is harmless.</P>
</blockquote>
<P><EM>[This constructor has been changed to a template in order to remember the actual
pointer type passed. The destructor will call <STRONG>delete</STRONG> with the
same pointer, complete with its original type, even when <STRONG>T</STRONG> does
not have a virtual destructor, or is <STRONG>void</STRONG>.</EM></P>
<P><EM>The optional intrusive counting support has been dropped as it exposes too much
implementation details and doesn't interact well with <STRONG>weak_ptr</STRONG>.
The current implementation uses a different mechanism, <A href="enable_shared_from_this.html">
enable_shared_from_this</A>, to solve the "<STRONG>shared_ptr</STRONG> from <STRONG>
this</STRONG>" problem.</EM><EM>]</EM></P>
<pre>template&lt;class Y, class D&gt; shared_ptr(Y * p, D d);</pre>
<pre>template&lt;typename Y, typename D&gt; shared_ptr(Y * p, D d);</pre>
<blockquote>
<p><b>Requirements:</b> <B>p</B> must be convertible to <B>T *</B>. <STRONG>D</STRONG>
must be <STRONG>CopyConstructible</STRONG>. The copy constructor and destructor
of <b>D</b> must not throw. The expression <code>d(p)</code> must be
well-formed, must not invoke undefined behavior, and must not throw exceptions.
<p><b>Requirements:</b> <B>p</B> must be convertible to <B>T *</B>. The copy
constructor and destructor of <b>D</b> must not throw. The expression <code>d(p)</code>
must be well-formed, must not invoke undefined behavior, and must not throw
exceptions.
</p>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b> that <EM>owns</EM> the pointer <STRONG>
p</STRONG> and the deleter <b>d</b>.</p>
<p><b>Postconditions:</b> <code>use_count() == 1 &amp;&amp; get() == p</code>.</p>
<p><b>Throws:</b> <STRONG>std::bad_alloc</STRONG>, or an implementation-defined
exception when a resource other than memory could not be obtained.</p>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b> and <b>d</b>.</p>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> is 1.</p>
<p><b>Throws:</b> <b>std::bad_alloc</b>.</p>
<p><b>Exception safety:</b> If an exception is thrown, <code>d(p)</code> is called.</p>
<p><b>Notes:</b> When the the time comes to delete the object pointed to by <b>p</b>,
the stored copy of <STRONG>d</STRONG> is invoked with the stored copy of <STRONG>p</STRONG>
as an argument.</p>
<p><b>Notes:</b> When the the time comes to delete the object pointed to by <b>p</b>,
<code>d(p)</code> is invoked.</p>
</blockquote>
<P><EM>[Custom deallocators allow a factory function returning a <STRONG>shared_ptr</STRONG>
to insulate the user from its memory allocation strategy. Since the deallocator
is not part of the type, changing the allocation strategy does not break source
or binary compatibility, and does not require a client recompilation. For
example, a "no-op" deallocator is useful when returning a <STRONG>shared_ptr</STRONG>
to a statically allocated object, and other variations allow a <STRONG>shared_ptr</STRONG>
to be used as a wrapper for another smart pointer, easing interoperability.</EM></P>
<P><EM>The support for custom deallocators does not impose significant overhead. Other <STRONG>
shared_ptr</STRONG> features still require a deallocator to be kept.</EM></P>
<P><EM>The requirement that the copy constructor of <b>D</b> does not throw comes from
the pass by value. If the copy constructor throws, the pointer is leaked.
Removing the requirement requires a pass by (const) reference.</EM></P>
<P><EM>The main problem with pass by reference lies in its interaction with rvalues. A
const reference may still cause a copy, and will require a const operator(). A
non-const reference won't bind to an rvalue at all. A good solution to this
problem is the rvalue reference proposed in <A href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1377.htm">
N1377</A>/<A href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm">N1385</A>.]</EM></P>
<pre>shared_ptr(shared_ptr const &amp; r); // never throws
template&lt;class Y&gt; shared_ptr(shared_ptr&lt;Y&gt; const &amp; r); // never throws</pre>
template&lt;typename Y&gt; shared_ptr(shared_ptr&lt;Y&gt; const &amp; r); // never throws</pre>
<blockquote>
<p><b>Effects:</b> If <b>r</b> is <EM>empty</EM>, constructs an <EM>empty</EM> <b>shared_ptr</b>;
otherwise, constructs a <b>shared_ptr</b> that <EM>shares ownership</EM> with <b>r</b>.</p>
<p><b>Postconditions:</b> <code>get() == r.get() &amp;&amp; use_count() ==
r.use_count()</code>.</p>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, as if by storing a copy of the
pointer stored in <STRONG>r</STRONG>.</p>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> for all copies is
increased by one.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class Y&gt; explicit shared_ptr(<A href="weak_ptr.htm" >weak_ptr</A>&lt;Y&gt; const &amp; r);</pre>
<pre>explicit shared_ptr(<A href="weak_ptr.htm" >weak_ptr</A> const &amp; r);</pre>
<blockquote>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b> that <EM>shares ownership</EM> with
<b>r</b> and stores a copy of the pointer stored in <STRONG>r</STRONG>.</p>
<p><b>Postconditions:</b> <code>use_count() == r.use_count()</code>.</p>
<p><b>Throws:</b> <b>bad_weak_ptr</b> when <code>r.use_count() == 0</code>.</p>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, as if by storing a copy of the
pointer stored in <STRONG>r</STRONG>.</p>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> for all copies is
increased by one.</p>
<p><b>Throws:</b> <b>use_count_is_zero</b> when <code>r.use_count() == 0</code>.</p>
<p><b>Exception safety:</b> If an exception is thrown, the constructor has no
effect.</p>
</blockquote>
<pre>template&lt;class Y&gt; shared_ptr(std::auto_ptr&lt;Y&gt; &amp; r);</pre>
<pre>template&lt;typename Y&gt; shared_ptr(std::auto_ptr&lt;Y&gt; &amp; r);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Constructs a <B>shared_ptr</B>, as if by storing a copy of <STRONG>r.release()</STRONG>.</P>
<p><b>Postconditions:</b> <code>use_count() == 1</code>.</p>
<p><b>Throws:</b> <STRONG>std::bad_alloc</STRONG>, or an implementation-defined
exception when a resource other than memory could not be obtained.</p>
<P><B>Postconditions:</B> <A href="#use_count">use count</A> for all copies is
increased by one.</P>
<P><B>Throws:</B> <B>std::bad_alloc</B>.</P>
<P><B>Exception safety:</B> If an exception is thrown, the constructor has no
effect.</P>
</BLOCKQUOTE>
<P><EM>[This constructor takes a the source <STRONG>auto_ptr</STRONG> by reference and
not by value, and cannot accept <STRONG>auto_ptr</STRONG> temporaries. This is
by design, as the constructor offers the strong guarantee; an rvalue reference
would solve this problem, too.]</EM></P>
<h3><a name="destructor">destructor</a></h3>
<pre>~shared_ptr(); // never throws</pre>
<BLOCKQUOTE>
<P><B>Effects:</B></P>
<UL>
<LI>
If <STRONG>*this</STRONG> is <EM>empty</EM>, or <EM>shares ownership</EM> with
another <STRONG>shared_ptr</STRONG> instance (<code>use_count() &gt; 1</code>),
there are no side effects.
<LI>
Otherwise, if <STRONG>*this</STRONG> <EM>owns</EM> a pointer <STRONG>p</STRONG>
and a deleter <STRONG>d</STRONG>, <code>d(p)</code>
is called.
<LI>
Otherwise, <STRONG>*this</STRONG> <EM>owns</EM> a pointer <STRONG>p</STRONG>,
and <code>delete p</code> is called.</LI></UL>
<P><B>Effects:</B> If <STRONG>*this</STRONG> is the sole owner (<code>use_count() == 1</code>),
destroys the object pointed to by the stored pointer.</P>
<P><B>Postconditions:</B> <A href="#use_count">use count</A> for all remaining
copies is decreased by one.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<H3><a name="assignment">assignment</a></H3>
<pre>shared_ptr &amp; operator=(shared_ptr const &amp; r); // never throws
template&lt;class Y&gt; shared_ptr &amp; operator=(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;class Y&gt; shared_ptr &amp; operator=(std::auto_ptr&lt;Y&gt; &amp; r);</pre>
template&lt;typename Y&gt; shared_ptr &amp; operator=(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;typename Y&gt; shared_ptr &amp; operator=(std::auto_ptr&lt;Y&gt; &amp; r);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr(r).swap(*this)</code>.</P>
<P><B>Returns:</B> <code>*this</code>.</P>
<P><B>Notes:</B> The use count updates caused by the temporary object construction
and destruction are not considered observable side effects, and the
implementation is free to meet the effects (and the implied guarantees) via
different means, without creating a temporary. In particular, in the example:</P>
<pre>shared_ptr&lt;int&gt; p(new int);
<P><B>Notes:</B> The implementation is free to meet the effects (and the implied
guarantees) via different means, without creating a temporary. In particular,
in the example:</P>
<pre>
shared_ptr&lt;int&gt; p(new int);
shared_ptr&lt;void&gt; q(p);
p = p;
q = p;
@@ -305,15 +207,15 @@ q = p;
<p>both assignments may be no-ops.</p>
</BLOCKQUOTE>
<h3><a name="reset">reset</a></h3>
<pre>void reset(); // never throws</pre>
<pre>void reset();</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr().swap(*this)</code>.</P>
</BLOCKQUOTE>
<pre>template&lt;class Y&gt; void reset(Y * p);</pre>
<pre>template&lt;typename Y&gt; void reset(Y * p);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p).swap(*this)</code>.</P>
</BLOCKQUOTE>
<pre>template&lt;class Y, class D&gt; void reset(Y * p, D d);</pre>
<pre>template&lt;typename Y, typename D&gt; void reset(Y * p, D d);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p, d).swap(*this)</code>.</P>
</BLOCKQUOTE>
@@ -341,34 +243,28 @@ q = p;
<blockquote>
<p><b>Returns:</b> <code>use_count() == 1</code>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <code>unique()</code> may be faster than <code>use_count()</code>.
If you are using <code>unique()</code> to implement copy on write, do not rely
on a specific value when the stored pointer is zero.</P>
<P><B>Notes:</B> <code>unique()</code> may be faster than <code>use_count()</code>.</P>
</blockquote>
<h3><a name="use_count">use_count</a></h3>
<pre>long use_count() const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> the number of <b>shared_ptr</b> objects, <STRONG>*this</STRONG> included,
that <i>share ownership</i> with <b>*this</b>, or an unspecified nonnegative
value when <STRONG>*this</STRONG> is <EM>empty</EM>.</p>
<p><b>Returns:</b> the number of <b>shared_ptr</b> objects sharing ownership of the
stored pointer.</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="conversions">conversions</a></h3>
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
<pre>operator <i>implementation-defined-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>Returns:</b> an implementation defined 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>shared_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
The actual target type is typically a pointer to a member function, avloiding
many of the implicit conversion pitfalls.</P>
</blockquote>
<P><EM>[The conversion to bool is not merely syntactic sugar. It allows <STRONG>shared_ptr</STRONG>s
to be declared in conditions when using <A href="#dynamic_pointer_cast">dynamic_pointer_cast</A>
or <A href="weak_ptr.htm#lock">weak_ptr::lock</A>.]</EM></P>
<h3><a name="swap">swap</a></h3>
<pre>void swap(shared_ptr &amp; b); // never throws</pre>
<blockquote>
@@ -377,96 +273,54 @@ q = 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;
<pre>template&lt;typename T, typename U&gt;
bool operator==(shared_ptr&lt;T&gt; const &amp; a, shared_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;
<pre>template&lt;typename T, typename U&gt;
bool operator!=(shared_ptr&lt;T&gt; const &amp; a, shared_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&lt;(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<pre>template&lt;typename T&gt;
bool operator&lt;(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;T&gt; const &amp; b); // never throws</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>shared_ptr</STRONG> instances
are equivalent if and only if they <EM>share ownership</EM> or are both <EM>empty</EM>.</LI></UL>
<p><b>Returns:</b> an implementation-defined value such that <b>operator&lt;</b> is
a strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
of the C++ standard.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> Allows <STRONG>shared_ptr</STRONG> objects to be used as keys in
associative containers.</P>
</blockquote>
<P><EM>[<STRONG>Operator&lt;</STRONG> has been preferred over a <STRONG>std::less </STRONG>
specialization for consistency and legality reasons, as <STRONG>std::less</STRONG>
is required to return the results of <STRONG>operator&lt;</STRONG>, and many
standard algorithms use <STRONG>operator&lt;</STRONG> instead of <STRONG>std::less</STRONG>
for comparisons when a predicate is not supplied. Composite objects, like <STRONG>std::pair</STRONG>,
also implement their <STRONG>operator&lt;</STRONG> in terms of their contained
subobjects' <STRONG>operator&lt;</STRONG>.</EM></P>
<P><EM>The rest of the comparison operators are omitted by design.]</EM></P>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;class T&gt;
void swap(shared_ptr&lt;T&gt; &amp; a, shared_ptr&lt;T&gt; &amp; b); // never throws</pre>
<pre>template&lt;typename T&gt;
void swap(shared_ptr&lt;T&gt; &amp; a, shared_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>
<P><EM>[<STRONG>swap</STRONG> is defined in the same namespace as <STRONG>shared_ptr</STRONG>
as this is currently the only legal way to supply a <STRONG>swap</STRONG> function
that has a chance to be used by the standard library.]</EM></P>
<h3><a name="get_pointer">get_pointer</a></h3>
<pre>template&lt;class T&gt;
T * get_pointer(shared_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;
shared_ptr&lt;T&gt; static_pointer_cast(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<h3><a name="shared_static_cast">shared_static_cast</a></h3>
<pre>template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; shared_static_cast(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE>
<P><STRONG>Requires:</STRONG> The expression <code>static_cast&lt;T*&gt;(r.get())</code>
must be well-formed.</P>
<P><B>Returns:</B> If <b>r</b> is <i>empty</i>, an <i>empty</i> <b>shared_ptr&lt;T&gt;</b>;
otherwise, a <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy of <code>
static_cast&lt;T*&gt;(r.get())</code> and <i>shares ownership</i> with <b>r</b>.</P>
<P><B>Returns:</B> A <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy
of <code>static_cast&lt;T*&gt;(r.get())</code> and shares ownership with <b>r</b>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> the seemingly equivalent expression</P>
<p><code>shared_ptr&lt;T&gt;(static_cast&lt;T*&gt;(r.get()))</code></p>
<p>will eventually result in undefined behavior, attempting to delete the same
object twice.</p>
</BLOCKQUOTE>
<h3><a name="const_pointer_cast">const_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; const_pointer_cast(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE>
<P><STRONG>Requires:</STRONG> The expression <code>const_cast&lt;T*&gt;(r.get())</code>
must be well-formed.</P>
<P><B>Returns:</B> If <b>r</b> is <i>empty</i>, an <i>empty</i> <b>shared_ptr&lt;T&gt;</b>;
otherwise, a <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy of <code>
const_cast&lt;T*&gt;(r.get())</code> and <i>shares ownership</i> with <b>r</b>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> the seemingly equivalent expression</P>
<p><code>shared_ptr&lt;T&gt;(const_cast&lt;T*&gt;(r.get()))</code></p>
<p>will eventually result in undefined behavior, attempting to delete the same
object twice.</p>
</BLOCKQUOTE>
<h3><a name="dynamic_pointer_cast">dynamic_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; dynamic_pointer_cast(shared_ptr&lt;U&gt; const &amp; r);</pre>
<h3><a name="shared_dynamic_cast">shared_dynamic_cast</a></h3>
<pre>template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; shared_dynamic_cast(shared_ptr&lt;U&gt; const &amp; r);</pre>
<BLOCKQUOTE>
<P><STRONG>Requires:</STRONG> The expression <CODE>dynamic_cast&lt;T*&gt;(r.get())</CODE>
must be well-formed and its behavior defined.</P>
@@ -474,35 +328,47 @@ q = p;
<UL>
<LI>
When <CODE>dynamic_cast&lt;T*&gt;(r.get())</CODE> returns a nonzero value, a <STRONG>
shared_ptr&lt;T&gt;</STRONG> object that stores a copy of it and <i>shares
ownership</i> with <STRONG>r</STRONG>;
shared_ptr&lt;T&gt;</STRONG> object that stores a copy of it and shares
ownership with <STRONG>r</STRONG>;
<LI>
Otherwise, an <i>empty</i> <STRONG>shared_ptr&lt;T&gt;</STRONG> object.</LI></UL>
<P><B>Throws:</B> nothing.</P>
Otherwise, a default-constructed <STRONG>shared_ptr&lt;T&gt;</STRONG> object.</LI></UL>
<P><B>Throws:</B> <STRONG>std::bad_alloc</STRONG>.</P>
<P><B>Exception safety:</B> If an exception is thrown, the function has no effect.</P>
<P><B>Notes:</B> the seemingly equivalent expression</P>
<P><CODE>shared_ptr&lt;T&gt;(dynamic_cast&lt;T*&gt;(r.get()))</CODE></P>
<P>will eventually result in undefined behavior, attempting to delete the same
object twice.</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, shared_ptr&lt;Y&gt; const &amp; p);</pre>
<h3><a name="shared_polymorphic_cast">shared_polymorphic_cast</a></h3>
<pre>template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; shared_polymorphic_cast(shared_ptr&lt;U&gt; const &amp; r);</pre>
<BLOCKQUOTE>
<p><STRONG>Effects:</STRONG> <code>os &lt;&lt; p.get();</code>.</p>
<P><B>Returns:</B> <b>os</b>.</P>
<p><STRONG>Requires:</STRONG> The expression <CODE><A href="../conversion/cast.htm#Polymorphic_cast">
polymorphic_cast</A>&lt;T*&gt;(r.get())</CODE> must be well-formed and
its behavior defined.</p>
<P><B>Returns:</B> A <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy
of <CODE><A href="../conversion/cast.htm#Polymorphic_cast">polymorphic_cast</A>&lt;T*&gt;(r.get())</CODE>
and shares ownership with <B>r</B>.</P>
<P><B>Throws:</B> <STRONG>std::bad_cast</STRONG> when the pointer cannot be
converted.</P>
<P><B>Exception safety:</B> If an exception is thrown, the function has no effect.</P>
</BLOCKQUOTE>
<h3><a name="get_deleter">get_deleter</a></h3>
<pre>template&lt;class D, class T&gt;
D * get_deleter(shared_ptr&lt;T&gt; const &amp; p);</pre>
<h3><a name="shared_polymorphic_downcast">shared_polymorphic_downcast</a></h3>
<pre>template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; shared_polymorphic_downcast(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> If <STRONG>*this</STRONG> <EM>owns</EM> a deleter <STRONG>d</STRONG>
of type (cv-unqualified) <STRONG>D</STRONG>, returns <code>&amp;d</code>;
otherwise returns 0.</P>
<p><STRONG>Requires:</STRONG> The expression <CODE><A href="../conversion/cast.htm#Polymorphic_cast">
polymorphic_downcast</A>&lt;T*&gt;(r.get())</CODE> must be well-formed
and its behavior defined.</p>
<P><B>Returns:</B> A <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy
of <CODE><A href="../conversion/cast.htm#Polymorphic_cast">polymorphic_downcast</A>&lt;T*&gt;(r.get())</CODE>
and shares ownership with <B>r</B>.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<h2><a name="example">Example</a></h2>
<p>See <A href="example/shared_ptr_example.cpp">shared_ptr_example.cpp</A> for a
complete example program. The program builds a <b>std::vector</b> and <b>std::set</b>
of <b>shared_ptr</b> objects.</p>
<p>See <A href="shared_ptr_example.cpp">shared_ptr_example.cpp</A> for a complete
example program. The program builds a <b>std::vector</b> and <b>std::set</b> of <b>shared_ptr</b>
objects.</p>
<p>Note that after the containers have been populated, some of the <b>shared_ptr</b>
objects will have a use count of 1 rather than a use count of 2, since the set
is a <b>std::set</b> rather than a <b>std::multiset</b>, and thus does not
@@ -515,150 +381,57 @@ q = p;
<p>One common usage of <b>shared_ptr</b> is to implement a handle/body (also called
pimpl) idiom which avoids exposing the body (implementation) in the header
file.</p>
<p>The <A href="example/shared_ptr_example2_test.cpp">shared_ptr_example2_test.cpp</A>
sample program includes a header file, <A href="example/shared_ptr_example2.hpp">shared_ptr_example2.hpp</A>,
<p>The <A href="shared_ptr_example2_test.cpp">shared_ptr_example2_test.cpp</A> sample
program includes a header file, <A href="shared_ptr_example2.hpp">shared_ptr_example2.hpp</A>,
which uses a <b>shared_ptr&lt;&gt;</b> to an incomplete type to hide the
implementation. The instantiation of member functions which require a complete
type occurs in the <A href="example/shared_ptr_example2.cpp">shared_ptr_example2.cpp</A>
type occurs in the <A href="shared_ptr_example2.cpp">shared_ptr_example2.cpp</A>
implementation file. Note that there is no need for an explicit destructor.
Unlike ~scoped_ptr, ~shared_ptr does not require that <b>T</b> be a complete
type.</p>
<h2><a name="ThreadSafety">Thread Safety</a></h2>
<p><STRONG>shared_ptr</STRONG> objects offer the same level of thread safety as
built-in types. A <STRONG>shared_ptr</STRONG> instance can be "read" (accessed
using only const operations) simultaneously by multiple threads. Different <STRONG>shared_ptr</STRONG>
instances can be "written to" (accessed using mutable operations such as <STRONG>operator=
</STRONG>or <STRONG>reset</STRONG>) simultaneosly by multiple threads (even
when these instances are copies, and share the same reference count
underneath.)</p>
<P>Any other simultaneous accesses result in undefined behavior.</P>
<P>Examples:</P>
<pre>shared_ptr&lt;int&gt; p(new int(42));
//--- Example 1 ---
// thread A
shared_ptr&lt;int&gt; p2(p); // reads p
// thread B
shared_ptr&lt;int&gt; p3(p); // OK, multiple reads are safe
//--- Example 2 ---
// thread A
p.reset(new int(1912)); // writes p
// thread B
p2.reset(); // OK, writes p2
//--- Example 3 ---
// thread A
p = p3; // reads p3, writes p
// thread B
p3.reset(); // writes p3; undefined, simultaneous read/write
//--- Example 4 ---
// thread A
p3 = p2; // reads p2, writes p3
// thread B
// p2 goes out of scope: undefined, the destructor is considered a "write access"
//--- Example 5 ---
// thread A
p3.reset(new int(1));
// thread B
p3.reset(new int(2)); // undefined, multiple writes
</pre>
<p>&nbsp;</p>
<P>Starting with Boost release 1.33.0, <STRONG>shared_ptr</STRONG> uses a lock-free
implementation on the following platforms:</P>
<UL>
<LI>
GNU GCC on x86 or x86-64;
<LI>
GNU GCC on IA64;
<LI>
Metrowerks CodeWarrior on PowerPC;
<LI>
GNU GCC on PowerPC;
<LI>
Windows.</LI></UL>
<P>If your program is single-threaded and does not link to any libraries that might
have used <STRONG>shared_ptr</STRONG> in its default configuration, you can <STRONG>
#define</STRONG> the macro <STRONG>BOOST_SP_DISABLE_THREADS</STRONG> on a
project-wide basis to switch to ordinary non-atomic reference count updates.</P>
<P>(Defining <STRONG>BOOST_SP_DISABLE_THREADS</STRONG> in some, but not all,
translation units is technically a violation of the One Definition Rule and
undefined behavior. Nevertheless, the implementation attempts to do its best to
accommodate the request to use non-atomic updates in those translation units.
No guarantees, though.)</P>
<P>You can define the macro <STRONG>BOOST_SP_USE_PTHREADS</STRONG> to turn off the
lock-free platform-specific implementation and fall back to the generic <STRONG>pthread_mutex_t</STRONG>-based
code.</P>
<h2><a name="FAQ">Frequently Asked Questions</a></h2>
<P><B>Q.</B> There are several variations of shared pointers, with different
tradeoffs; why does the smart pointer library supply only a single
implementation? It would be useful to be able to experiment with each type so
as to find the most suitable for the job at hand?</P>
<P>
as to find the most suitable for the job at hand?<BR>
<b>A.</b> An important goal of <STRONG>shared_ptr</STRONG> is to provide a
standard shared-ownership pointer. Having a single pointer type is important
for stable library interfaces, since different shared pointers typically cannot
interoperate, i.e. a reference counted pointer (used by library A) cannot share
ownership with a linked pointer (used by library B.)<BR>
</P>
ownership with a linked pointer (used by library B.)</P>
<P><B>Q.</B> Why doesn't <B>shared_ptr</B> have template parameters supplying
traits or policies to allow extensive user customization?</P>
<P>
traits or policies to allow extensive user customization?<BR>
<B>A.</B> Parameterization discourages users. The <B>shared_ptr</B> template is
carefully crafted to meet common needs without extensive parameterization. Some
day a highly configurable smart pointer may be invented that is also very easy
to use and very hard to misuse. Until then, <B>shared_ptr</B> is the smart
pointer of choice for a wide range of applications. (Those interested in policy
based smart pointers should read <A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0201704315&rl=1">
Modern C++ Design</A> by Andrei Alexandrescu.)<BR>
</P>
<P><B>Q.</B> I am not convinced. Default parameters can be used where appropriate
to hide the complexity. Again, why not policies?</P>
<P>
based smart pointers should read <A href="http://cseng.aw.com/book/0,,0201704315,00.html">
Modern C++ Design</A> by Andrei Alexandrescu.)</P>
<P><B>Q.</B> I am not convinced. Default parameters can be used where appropriate to
hide the complexity. Again, why not policies?<BR>
<B>A.</B> Template parameters affect the type. See the answer to the first
question above.<BR>
</P>
<P><B>Q.</B> Why doesn't <b>shared_ptr</b> use a linked list implementation?</P>
<P>
question above.</P>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> use a linked list implementation?<br>
<b>A.</b> A linked list implementation does not offer enough advantages to
offset the added cost of an extra pointer. See <A href="smarttests.htm">timings</A>
page. In addition, it is expensive to make a linked list implementation thread
safe.<BR>
</P>
<P><b>Q.</b> Why doesn't <b>shared_ptr</b> (or any of the other Boost smart
pointers) supply an automatic conversion to <b>T*</b>?</P>
<P>
<b>A.</b> Automatic conversion is believed to be too error prone.<BR>
</P>
<P><B>Q.</B> Why does <b>shared_ptr</b> supply use_count()?</P>
<P>
safe.</p>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> (or any of the other Boost smart
pointers) supply an automatic conversion to <b>T*</b>?<br>
<b>A.</b> Automatic conversion is believed to be too error prone.</p>
<p><b>Q.</b> Why does <b>shared_ptr</b> supply use_count()?<br>
<b>A.</b> As an aid to writing test cases and debugging displays. One of the
progenitors had use_count(), and it was useful in tracking down bugs in a
complex project that turned out to have cyclic-dependencies.<BR>
</P>
<P><B>Q.</B> Why doesn't <b>shared_ptr</b> specify complexity requirements?</P>
<P>
complex project that turned out to have cyclic-dependencies.</p>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> specify complexity requirements?<br>
<b>A.</b> Because complexity requirements limit implementors and complicate the
specification without apparent benefit to <b>shared_ptr</b> users. For example,
error-checking implementations might become non-conforming if they had to meet
stringent complexity requirements.<BR>
</P>
<P><b>Q.</b> Why doesn't <b>shared_ptr</b> provide a release() function?</P>
<P>
stringent complexity requirements.</p>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> provide a release() function?<br>
<b>A.</b> <b>shared_ptr</b> cannot give away ownership unless it's unique()
because the other copy will still destroy the object.</P>
because the other copy will still destroy the object.</p>
<p>Consider:</p>
<blockquote><pre>shared_ptr&lt;int&gt; a(new int);
shared_ptr&lt;int&gt; b(a); // a.use_count() == b.use_count() == 2
@@ -667,27 +440,17 @@ int * p = a.release();
// Who owns p now? b will still call delete on it in its destructor.</pre>
</blockquote>
<p>Furthermore, the pointer returned by <code>release()</code> would be difficult
to deallocate reliably, as the source <b>shared_ptr</b> could have been created
with a custom deleter.<BR>
</p>
<P><b>Q.</b> Why is <code>operator-&gt;()</code> const, but its return value is a
non-const pointer to the element type?</P>
<P>
<b>A.</b> Shallow copy pointers, including raw pointers, typically don't
propagate constness. It makes little sense for them to do so, as you can always
obtain a non-const pointer from a const one and then proceed to modify the
object through it.<b>shared_ptr</b> is "as close to raw pointers as possible
but no closer".<BR>
<BR>
</P>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> provide (your pet feature here)?<br>
<b>A.</b> Because (your pet feature here) would mandate a reference counted
implementation or a linked list implementation, or some other specific
implementation. This is not the intent.</p>
<hr>
<p>
$Date$</p>
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
Copyright 2002-2005 Peter Dimov. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears in
all copies. This document is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.</small></p>
<p>Revised&nbsp; <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->
04&nbsp;May 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears in
all copies. This document is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.</p>
</body>
</html>

View File

@@ -1,6 +1,4 @@
#include <boost/config.hpp>
#if defined(BOOST_MSVC)
#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
@@ -12,9 +10,10 @@
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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>

View File

@@ -1,11 +1,12 @@
// Boost shared_ptr_example.cpp --------------------------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright Beman Dawes 2001. Permission to copy,
// use, modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided "as is"
// without express or implied warranty, and with no claim as to its
// suitability for any purpose.
// See http://www.boost.org/libs/smart_ptr for documentation.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 21 May 01 Initial complete version (Beman Dawes)

View File

@@ -1,12 +1,5 @@
// Boost shared_ptr_example2 implementation file -----------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/smart_ptr for documentation.
#include "shared_ptr_example2.hpp"
#include <iostream>
@@ -17,6 +10,10 @@ class example::implementation
};
example::example() : _imp( new implementation ) {}
example::example( const example & s ) : _imp( s._imp ) {}
example & example::operator=( const example & s )
{ _imp = s._imp; return *this; }
void example::do_something()
{ std::cout << "use_count() is " << _imp.use_count() << "\n"; }

View File

@@ -1,12 +1,5 @@
// Boost shared_ptr_example2 header file -----------------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/smart_ptr for documentation.
#include <boost/shared_ptr.hpp>
// This example demonstrates the handle/body idiom (also called pimpl and
@@ -21,10 +14,12 @@
class example
{
public:
public:
example();
example( const example & );
example & operator=( const example & );
void do_something();
private:
private:
class implementation;
boost::shared_ptr< implementation > _imp; // hide implementation details
};

View File

@@ -1,12 +1,5 @@
// Boost shared_ptr_example2_test main program ------------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/smart_ptr for documentation.
#include "shared_ptr_example2.hpp"
int main()

View File

@@ -1,6 +1,4 @@
#include <boost/config.hpp>
#if defined(BOOST_MSVC)
#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
@@ -12,14 +10,18 @@
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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>
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <vector>
#include <memory>
#include <stdexcept>
@@ -143,15 +145,21 @@ void test(boost::shared_ptr<int> const & pi)
int const m = 16; // threads
int main()
{
using namespace std; // printf, clock_t, clock
#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
printf("%s: %d threads, %d iterations: ", title, m, n);
int test_main( int, char ** )
{
std::printf("%s: %s, %d threads, %d iterations: ", title, implementation, m, n);
boost::shared_ptr<int> pi(new int(42));
clock_t t = clock();
std::clock_t t = std::clock();
pthread_t a[m];
@@ -160,14 +168,14 @@ int main()
a[i] = createThread( boost::bind(test, pi) );
}
for(int j = 0; j < m; ++j)
for(int i = 0; i < m; ++i)
{
pthread_join(a[j], 0);
pthread_join(a[i], 0);
}
t = clock() - t;
t = std::clock() - t;
printf("\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC);
std::printf("\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC);
return 0;
}

View File

@@ -1,46 +1,49 @@
#include <boost/config.hpp>
#if defined(BOOST_MSVC)
#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#pragma warning(disable: 4355) // 'this' : used in base member initializer list
#if (BOOST_MSVC >= 1310)
#pragma warning(disable: 4675) // resolved overload found with Koenig lookup
#endif
#endif
//
// shared_ptr_basic_test.cpp
// shared_ptr_test.cpp - a test for shared_ptr.hpp and weak_ptr.hpp
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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>
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
int cnt = 0;
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";
}
~X() // virtual destructor deliberately omitted
{
--cnt;
std::cout << "X(" << this << ")::~X()\n";
}
virtual int id() const
@@ -59,11 +62,13 @@ struct Y: public X
Y()
{
++cnt;
std::cout << "Y(" << this << ")::Y()\n";
}
~Y()
{
--cnt;
std::cout << "Y(" << this << ")::~Y()\n";
}
virtual int id() const
@@ -80,6 +85,7 @@ private:
int * get_object()
{
++cnt;
std::cout << "get_object()\n";
return &cnt;
}
@@ -87,8 +93,31 @@ void release_object(int * p)
{
BOOST_TEST(p == &cnt);
--cnt;
std::cout << "release_object()\n";
}
class Z: public virtual boost::counted_base
{
public:
Z()
{
++cnt;
std::cout << "Z(" << this << ")::Z()\n";
}
~Z()
{
--cnt;
std::cout << "Z(" << this << ")::~Z()\n";
}
private:
Z(Z const &);
Z & operator= (Z const &);
};
template<class T> void test_is_X(boost::shared_ptr<T> const & p)
{
BOOST_TEST(p->id() == 1);
@@ -109,9 +138,8 @@ template<class T> void test_is_Y(boost::shared_ptr<T> const & p)
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);
BOOST_TEST(p.get() != 0);
BOOST_TEST(p.get()->id() == 2);
}
template<class T> void test_eq(T const & a, T const & b)
@@ -130,18 +158,6 @@ template<class T> void test_ne(T const & a, T const & b)
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);
@@ -162,14 +178,11 @@ template<class T> void test_is_zero(boost::shared_ptr<T> const & p)
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);
BOOST_TEST(p.get() != 0);
}
int main()
int test_main(int, char * [])
{
using namespace boost;
@@ -188,8 +201,8 @@ int main()
test_eq(p, q);
}
shared_ptr<Y> p3 = dynamic_pointer_cast<Y>(p);
shared_ptr<Y> p4 = dynamic_pointer_cast<Y>(p2);
shared_ptr<Y> p3 = shared_dynamic_cast<Y>(p);
shared_ptr<Y> p4 = shared_dynamic_cast<Y>(p2);
test_is_nonzero(p3);
test_is_zero(p4);
@@ -197,6 +210,7 @@ int main()
BOOST_TEST(p.use_count() == 2);
BOOST_TEST(p2.use_count() == 1);
BOOST_TEST(p3.use_count() == 2);
BOOST_TEST(p4.use_count() == 1);
test_is_Y(p3);
test_eq2(p, p3);
@@ -207,10 +221,7 @@ int main()
test_is_nonzero(p5);
test_eq2(p, p5);
weak_ptr<X> wp1(p2);
BOOST_TEST(!wp1.expired());
BOOST_TEST(wp1.use_count() != 0);
std::cout << "--\n";
p.reset();
p2.reset();
@@ -222,53 +233,74 @@ int main()
test_is_zero(p3);
test_is_zero(p4);
std::cout << "--\n";
BOOST_TEST(p5.use_count() == 1);
BOOST_TEST(wp1.expired());
weak_ptr<X> wp1;
BOOST_TEST(wp1.use_count() == 0);
BOOST_TEST(wp1.get() == 0);
try
{
shared_ptr<X> sp1(wp1);
BOOST_ERROR("shared_ptr<X> sp1(wp1) failed to throw");
}
catch(boost::bad_weak_ptr const &)
catch(boost::use_count_is_zero const &)
{
}
test_is_zero(wp1.lock());
test_is_zero(boost::make_shared(wp1));
weak_ptr<X> wp2 = static_pointer_cast<X>(p5);
weak_ptr<X> wp2 = shared_static_cast<X>(p5);
BOOST_TEST(wp2.use_count() == 1);
BOOST_TEST(wp2.get() != 0);
test_is_Y(wp2);
test_nonshared(wp1, wp2);
test_ne(wp1, wp2);
// Scoped to not affect the subsequent use_count() tests.
{
shared_ptr<X> sp2(wp2);
test_is_nonzero(wp2.lock());
test_is_nonzero(boost::make_shared(wp2));
}
weak_ptr<Y> wp3 = dynamic_pointer_cast<Y>(wp2.lock());
weak_ptr<Y> wp3 = shared_dynamic_cast<Y>(boost::make_shared(wp2));
BOOST_TEST(wp3.use_count() == 1);
test_shared(wp2, wp3);
BOOST_TEST(wp3.get() != 0);
test_eq2(wp2, wp3);
weak_ptr<X> wp4(wp3);
BOOST_TEST(wp4.use_count() == 1);
test_shared(wp2, wp4);
BOOST_TEST(wp4.get() != 0);
test_eq(wp2, wp4);
wp1 = p2;
test_is_zero(wp1.lock());
BOOST_TEST(wp1.get() == 0);
// Note the following test. Construction succeeds,
// but make_shared() returns a null shared_ptr with
// use_count() == 2.
shared_ptr<X> sp1(wp1);
test_is_zero(boost::make_shared(wp1));
BOOST_TEST(p2.use_count() == 2);
BOOST_TEST(sp1.use_count() == 2);
BOOST_TEST(wp1.use_count() == 2);
//
wp1 = p4;
wp1 = wp3;
wp1 = wp2;
BOOST_TEST(wp1.use_count() == 1);
test_shared(wp1, wp2);
BOOST_TEST(wp1.get() != 0);
test_eq(wp1, wp2);
weak_ptr<X> wp5;
@@ -278,8 +310,13 @@ int main()
p5.reset();
BOOST_TEST(wp1.use_count() == 0);
BOOST_TEST(wp1.get() == 0);
BOOST_TEST(wp2.use_count() == 0);
BOOST_TEST(wp2.get() == 0);
BOOST_TEST(wp3.use_count() == 0);
BOOST_TEST(wp3.get() == 0);
// Test operator< stability for std::set< weak_ptr<> >
// Thanks to Joe Gottman for pointing this out
@@ -291,9 +328,16 @@ int main()
// note that both get_object and release_object deal with int*
shared_ptr<void> p6(get_object(), release_object);
}
{
// test intrusive counting
boost::shared_ptr<void> pv(new Z);
boost::shared_ptr<Z> pz = boost::shared_static_cast<Z>(pv);
BOOST_TEST(pz.use_count() == pz->use_count());
}
}
BOOST_TEST(cnt == 0);
return boost::report_errors();
return 0;
}

View File

@@ -1,6 +1,4 @@
#include <boost/config.hpp>
#if defined(BOOST_MSVC)
#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
@@ -12,9 +10,10 @@
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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>
@@ -26,21 +25,17 @@ 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();
std::clock_t t = std::clock();
for(int i = 0; i < n; ++i)
{
v.push_back(pi);
}
t = clock() - t;
t = std::clock() - t;
std::cout << static_cast<double>(t) / CLOCKS_PER_SEC << '\n';
return 0;
}

View File

@@ -1,186 +1,207 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Smart Pointers</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#ffffff" text="#000000">
<h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86">Smart
Pointers</h1>
<p><a href="#Introduction">Introduction</a><br>
<a href="#common_requirements">Common Requirements</a><br>
<a href="#Exception_Safety">Exception Safety</a><br>
<a href="#Exception-specifications">Exception-specifications</a><br>
<a href="#History">History and Acknowledgements</a><br>
<a href="#References">References</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>Smart pointers are objects which store pointers to dynamically allocated (heap)
objects. They behave much like built-in C++ pointers except that they
automatically delete the object pointed to at the appropriate time. Smart
pointers are particularly useful in the face of exceptions as they ensure
proper destruction of dynamically allocated objects. They can also be used to
keep track of dynamically allocated objects shared by multiple owners.</p>
<p>Conceptually, smart pointers are seen as owning the object pointed to, and thus
responsible for deletion of the object when it is no longer needed.</p>
<p>The smart pointer library provides five smart pointer class templates:</p>
<div align="left">
<table border="1" cellpadding="4" cellspacing="0">
<tr>
<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>Simple sole ownership of single objects. Noncopyable.</td>
</tr>
<tr>
<td><a href="scoped_array.htm"><b>scoped_array</b></a></td>
<td><a href="../../boost/scoped_array.hpp">&lt;boost/scoped_array.hpp&gt;</a></td>
<td>Simple sole ownership of arrays. Noncopyable.</td>
</tr>
<tr>
<td><a href="shared_ptr.htm"><b>shared_ptr</b></a></td>
<td><a href="../../boost/shared_ptr.hpp">&lt;boost/shared_ptr.hpp&gt;</a></td>
<td>Object ownership shared among multiple pointers</td>
</tr>
<tr>
<td><a href="shared_array.htm"><b>shared_array</b></a></td>
<td><a href="../../boost/shared_array.hpp">&lt;boost/shared_array.hpp&gt;</a></td>
<td>Array ownership shared among multiple pointers.</td>
</tr>
<tr>
<td><a href="weak_ptr.htm"><b>weak_ptr</b></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>
</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>
</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
described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition,
Section 14.4, Resource Management.</p>
<p>A test program, <a href="test/smart_ptr_test.cpp">smart_ptr_test.cpp</a>, is
provided to verify correct operation.</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
versions of the smart pointer implementation.</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="sp_techniques.html">smart pointer programming techniques</A> lists
some advanced applications of <code>shared_ptr</code> and <code>weak_ptr</code>.</P>
<h2><a name="common_requirements">Common Requirements</a></h2>
<p>These smart pointer class templates have a template parameter, <b>T</b>, which
specifies the type of the object pointed to by the smart pointer. The behavior
of the smart pointer templates is undefined if the destructor or <b>operator delete</b>
for objects of type <b>T</b> throw exceptions.</p>
<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
points of smart pointer instantiation. Implementations are required to diagnose
(treat as an error) all violations of this requirement, including deletion of
an incomplete type. See the description of the <a href="../utility/utility.htm#checked_delete">
<b>checked_delete</b></a> function template.</p>
<P>Note that <STRONG>shared_ptr</STRONG> does not have this restriction, as most of
its member functions do not require <STRONG>T</STRONG> to be a complete type.</P>
<h3>Rationale</h3>
<p>The requirements on <b>T</b> are carefully crafted to maximize safety yet allow
handle-body (also called pimpl) and similar idioms. In these idioms a smart
pointer may appear in translation units where <b>T</b> is an incomplete type.
This separates interface from implementation and hides implementation from
translation units which merely use the interface. Examples described in the
documentation for specific smart pointers illustrate use of smart pointers in
these idioms.</p>
<p>Note that <b>scoped_ptr</b> requires that <b>T</b> be a complete type at
destruction time, but <b>shared_ptr</b> does not.</p>
<h2><a name="Exception_Safety">Exception Safety</a></h2>
<p>Several functions in these smart pointer classes are specified as having "no
effect" or "no effect except such-and-such" if an exception is thrown. This
means that when an exception is thrown by an object of one of these classes,
the entire program state remains the same as it was prior to the function call
which resulted in the exception being thrown. This amounts to a guarantee that
there are no detectable side effects. Other functions never throw exceptions.
The only exception ever thrown by functions which do throw (assuming <b>T</b> meets
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
possibly throwing <b>std::bad_alloc</b>.</p>
<h2><a name="Exception-specifications">Exception-specifications</a></h2>
<p>Exception-specifications are not used; see <a href="../../more/lib_guide.htm#Exception-specification">
exception-specification rationale</a>.</p>
<p>All the smart pointer templates contain member functions which can never throw
exceptions, because they neither throw exceptions themselves nor call other
functions which may throw exceptions. These members are indicated by a comment: <code>
// never throws</code>.
</p>
<p>Functions which destroy objects of the pointed to type are prohibited from
throwing exceptions by the <a href="#common_requirements">common requirements</a>.</p>
<h2><a name="History">History</a> and Acknowledgements</h2>
<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>.
See the <a href="compatibility.htm">compatibility</a> page for a summary of the
changes.</p>
<p>May 2001. Vladimir Prus suggested requiring a complete type on destruction.
Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman
Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and
others.</p>
<p>November 1999. Darin Adler provided <b>operator ==</b>, <b>operator !=</b>, and <b>std::swap</b>
and <b>std::less</b> specializations for shared types.</p>
<p>September 1999. Luis Coelho provided <b>shared_ptr::swap</b> and <b>shared_array::swap</b></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>October 1998. Beman Dawes proposed reviving the original semantics under the
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,
Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new
class names were finalized, it was decided that there was no need to exactly
follow the <b>std::auto_ptr</b> interface, and various function signatures and
semantics were finalized.</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.
The implementation questions revolved around the reference count which must be
kept, either attached to the pointed to object, or detached elsewhere. Each of
those variants have themselves two major variants:
<ul>
<li>
Direct detached: the shared_ptr contains a pointer to the object, and a pointer
to the count.
<li>
Indirect detached: the shared_ptr contains a pointer to a helper object, which
in turn contains a pointer to the object and the count.
<li>
Embedded attached: the count is a member of the object pointed to.
<li>
Placement attached: the count is attached via operator new manipulations.</li>
</ul>
<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 "Counted Body Techniques." Dietmar
K<EFBFBD>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 "parameterization will discourage
users", and in the end we choose to supply only the direct implementation.</p>
<p>Summer, 1994. Greg Colvin proposed to the C++ Standards Committee classes named <b>auto_ptr</b>
and <b>counted_ptr</b> which were very similar to what we now call <b>scoped_ptr</b>
and <b>shared_ptr</b>. <a href="#Col-94">[Col-94]</a> In one of the very few
cases where the Library Working Group's recommendations were not followed by
the full committee, <b>counted_ptr</b> was rejected and surprising
transfer-of-ownership semantics were added to <b>auto_ptr</b>.</p>
<h2><a name="References">References</a></h2>
<p>[<a name="Col-94">Col-94</a>] Gregory Colvin, <a href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/1994/N0555.pdf">
Exception Safe Smart Pointers</a>, C++ committee document 94-168/N0555,
July, 1994.</p>
<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">
Safe, Efficient Garbage Collection for C++</a>, Usenix Proceedings,
February, 1994. This paper includes an extensive discussion of weak pointers
and an extensive bibliography.</p>
<hr>
<p>$Date$</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
"as is" without express or implied warranty, and with no claim as to its
suitability for any purpose.</p>
</body>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Smart Pointers</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">Smart
Pointers</h1>
<p>Smart pointers are objects which store pointers to dynamically allocated
(heap) objects. They behave much like built-in C++ pointers except that
they automatically delete the object pointed to at the appropriate
time. Smart pointers are particularly useful in the face of exceptions as
they ensure proper destruction of dynamically allocated objects. They can also
be used to keep track of dynamically allocated objects shared by multiple
owners.</p>
<p>Conceptually, smart pointers are seen as owning the object pointed to, and
thus responsible for deletion of the object when it is no longer needed.</p>
<p>The smart pointer library provides five smart pointer class templates:</p>
<div align="left">
<table border="1" cellpadding="4" cellspacing="4">
<tr>
<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>Simple sole ownership of single objects. Noncopyable.</td>
</tr>
<tr>
<td><a href="scoped_array.htm"><b>scoped_array</b></a></td>
<td><a href="../../boost/scoped_array.hpp">&lt;boost/scoped_array.hpp&gt;</a></td>
<td>Simple sole ownership of arrays. Noncopyable.</td>
</tr>
<tr>
<td><a href="shared_ptr.htm"><b>shared_ptr</b></a></td>
<td><a href="../../boost/shared_ptr.hpp">&lt;boost/shared_ptr.hpp&gt;</a></td>
<td>Object ownership shared among multiple pointers</td>
</tr>
<tr>
<td><a href="shared_array.htm"><b>shared_array</b></a></td>
<td><a href="../../boost/shared_array.hpp">&lt;boost/shared_array.hpp&gt;</a></td>
<td>Array ownership shared among multiple pointers.</td>
</tr>
<tr>
<td><a href="weak_ptr.htm"><b>weak_ptr</b></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>
</tr>
</table>
</div>
<p>These templates are designed to complement the <b>std::auto_ptr</b> template.</p>
<p>They are examples of the &quot;resource acquisition is initialization&quot;
idiom described in Bjarne Stroustrup's &quot;The C++ Programming Language&quot;,
3rd edition, Section 14.4, Resource Management.</p>
<p>A test program, <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>, is
provided to verify correct operation.</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 versions
of the smart pointer implementation.</p>
<p>A page on <a href="smarttests.htm">smart pointer timings</a> will be of
interest to those curious about performance issues.</p>
<h2><a name="Common requirements">Common Requirements</a></h2>
<p>These smart pointer class templates have a template parameter, <b>T</b>, which
specifies the type of the object pointed to by the smart pointer. The
behavior of the smart pointer templates is undefined if the destructor or <b>operator delete</b>
for objects of type <b>T</b> throw exceptions.</p>
<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 points of smart pointer instantiation. Implementations are
required to diagnose (treat as an error) all violations of this requirement,
including deletion of an incomplete type.
See the description of the <a href="../utility/utility.htm#checked_delete"><b>checked_delete</b></a>
function template.</p>
<h3>Rationale</h3>
<p>The requirements on <b>T</b> are carefully crafted to maximize safety
yet allow handle-body (also called pimpl) and similar idioms. In these idioms a
smart pointer may appear in translation units where <b>T</b> is an
incomplete type. This separates interface from implementation and hides
implementation from translation units which merely use the interface.
Examples described in the documentation for specific smart pointers illustrate
use of smart pointers in these idioms.</p>
<p>Note that <b>scoped_ptr</b> requires that <b>T</b> be a complete type
at destruction time, but <b>shared_ptr</b> does not.</p>
<h2>Exception Safety</h2>
<p>Several functions in these smart pointer classes are specified as having
&quot;no effect&quot; or &quot;no effect except such-and-such&quot; if an
exception is thrown. This means that when an exception is thrown by
an object of one of these classes, the entire program state remains the same as
it was prior to the function call which resulted in the exception being
thrown. This amounts to a guarantee that there are no detectable side
effects. Other functions never throw exceptions. The only exception
ever thrown by functions which do throw (assuming <b>T</b> meets 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 possibly
throwing <b>std::bad_alloc</b>.</p>
<h2>Exception-specifications</h2>
<p>Exception-specifications are not used; see
<a href="../../more/lib_guide.htm#Exception-specification">exception-specification
rationale</a>.</p>
<p>All the smart pointer templates contain member functions which can never throw exceptions,
because they neither throw exceptions themselves nor call other functions which
may throw exceptions. These members are indicated by a comment:
<code>// never throws</code>. </p>
<p>Functions which destroy objects of the pointed to type are prohibited from
throwing exceptions by the <a href="#Common requirements">common requirements</a>.</p>
<h2>History and Acknowledgements</h2>
<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>. See the
<a href="compatibility.htm">compatibility</a> page for a summary of the changes.</p>
<p>May 2001. Vladimir Prus suggested requiring a complete type on
destruction. Refinement evolved in discussions including Dave Abrahams,
Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus,
Shankar Sai, and others.</p>
<p>November 1999. Darin Adler provided <b>operator ==</b>, <b>operator !=</b>, and <b>std::swap</b>
and <b>std::less</b> specializations for shared types.</p>
<p>September 1999. Luis Coelho provided <b>shared_ptr::swap</b> and <b>shared_array::swap</b></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>October 1998. In 1994 Greg Colvin proposed to the C++ Standards Committee
classes named <b>auto_ptr</b> and <b>counted_ptr</b> which
were very similar to what we now call <b>scoped_ptr</b> and <b>shared_ptr</b>.
The committee document was 94-168/N0555, Exception Safe Smart Pointers. In
one of the very few cases where the Library Working Group's recommendations were
not followed by the full committee, <b>counted_ptr</b> was rejected
and surprising transfer-of-ownership semantics were added to <b>auto_ptr</b>.</p>
<p>Beman Dawes proposed reviving the original semantics under the names <b>safe_ptr</b>
and <b>counted_ptr</b> at an October, 1998, meeting of Per Andersson,
Matt Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar
K<EFBFBD>hl, Nathan Myers, Chichiang Wan and Judy Ward. During the discussion,
the four class names were finalized, it was decided that there was no need to
exactly follow the <b>std::auto_ptr</b> interface, and various
function signatures and semantics were finalized.</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. The implementation questions revolved around the reference count
which must be kept, either attached to the pointed to object, or detached
elsewhere. Each of those variants have themselves two major variants:
<ul>
<li>Direct detached: the shared_ptr contains a pointer to the object, and a
pointer to the count.</li>
<li>Indirect detached: the shared_ptr contains a pointer to a helper object,
which in turn contains a pointer to the object and the count.</li>
<li>Embedded attached: the count is a member of the object pointed to.</li>
<li>Placement attached: the count is attached via operator new manipulations.</li>
</ul>
<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>
<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>

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

@@ -9,7 +9,7 @@
<body bgcolor="#FFFFFF">
<h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" WIDTH="277" HEIGHT="86">Smart Pointer Timings</h1>
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" WIDTH="277" HEIGHT="86">Smart Pointer Timings</h1>
<p>In late January 2000, Mark Borgerding put forward a suggestion to boost for
a new design of smart pointer whereby an intrusive doubly linked list is used
@@ -22,7 +22,7 @@
a guide for current and future investigations into smart pointer implementation
strategies.</p>
<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/beman_dawes.html">Beman Dawes</a>
for test code and trial implementations, the final version of which can be found

View File

@@ -1,763 +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="boost.png (6897 bytes)" src="../../boost.png" 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>
<P>As <A href="../bind/mem_fn.html#Q3">explained</A> in the <code>mem_fn</code> documentation,
you need to <A href="../bind/mem_fn.html#stdcall">#define
BOOST_MEM_FN_ENABLE_STDCALL</A> first.</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,268 +0,0 @@
//
// sp_collector.cpp
//
// Copyright (c) 2002, 2003 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#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,243 +0,0 @@
//
// sp_debug_hooks.cpp
//
// Copyright (c) 2002, 2003 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#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,44 +0,0 @@
# Boost.SmartPtr Library test Jamfile
#
# Copyright (c) 2003-2005 Peter Dimov
# Copyright (c) 2003 Dave Abrahams
#
# Permission to copy, use, modify, sell and distribute this software
# is granted provided this copyright notice appears in all copies.
# This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
subproject libs/smart_ptr/test ;
# bring in rules for testing
import testing ;
# Make tests run by default.
DEPENDS all : smart_ptr ;
{
test-suite "smart_ptr"
: [ run smart_ptr_test.cpp ]
[ run shared_ptr_basic_test.cpp : : : <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 ]
[ run atomic_count_test.cpp ]
[ run lw_mutex_test.cpp ]
[ compile-fail shared_ptr_assign_fail.cpp ]
[ compile-fail shared_ptr_delete_fail.cpp ]
;
# this one is too slow to run unless explicitly requested, and ALL
# tests are run by default when this file is subincluded from
# boost/status, so it's guarded from that case. It will only be
# built from this directory when the targets "test" (all tests) or
# "shared_ptr_alloc_test" are requested.
if [ in-invocation-subdir ]
{
run shared_ptr_alloc_test.cpp ;
}
}

View File

@@ -1,28 +0,0 @@
# Boost.SmartPtr Library test Jamfile
#
# Copyright (c) 2003-2005 Peter Dimov
# Copyright (c) 2003 Dave Abrahams
#
# Permission to copy, use, modify, sell and distribute this software
# is granted provided this copyright notice appears in all copies.
# This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
# 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 ]
[ run atomic_count_test.cpp ]
[ run lw_mutex_test.cpp ]
[ compile-fail shared_ptr_assign_fail.cpp ]
[ compile-fail shared_ptr_delete_fail.cpp ]
;
}

View File

@@ -1,40 +0,0 @@
//
// atomic_count_test.cpp
//
// Copyright 2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/detail/atomic_count.hpp>
#include <boost/detail/lightweight_test.hpp>
int main()
{
boost::detail::atomic_count n( 4 );
BOOST_TEST( n == 4L );
++n;
BOOST_TEST( n == 5L );
BOOST_TEST( --n != 0L );
boost::detail::atomic_count m( 0 );
BOOST_TEST( m == 0 );
++m;
BOOST_TEST( m == 1 );
++m;
BOOST_TEST( m == 2 );
BOOST_TEST( --m != 0 );
BOOST_TEST( --m == 0 );
return boost::report_errors();
}

View File

@@ -1,99 +0,0 @@
//
// collector_test.cpp
//
// Copyright (c) 2003 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <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,95 +0,0 @@
//
// get_deleter_test.cpp
//
// Copyright (c) 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#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-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/detail/lightweight_test.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/detail/atomic_count.hpp>
#include <boost/config.hpp>
#include <algorithm>
#include <functional>
//
namespace N
{
class base
{
private:
boost::detail::atomic_count 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,28 +0,0 @@
//
// lw_mutex_test.cpp
//
// Copyright 2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/detail/lightweight_mutex.hpp>
// Sanity check only
boost::detail::lightweight_mutex m1;
int main()
{
boost::detail::lightweight_mutex::scoped_lock lock1( m1 );
boost::detail::lightweight_mutex m2;
boost::detail::lightweight_mutex m3;
boost::detail::lightweight_mutex::scoped_lock lock2( m2 );
boost::detail::lightweight_mutex::scoped_lock lock3( m3 );
return 0;
}

View File

@@ -1,153 +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
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/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,166 +0,0 @@
//
// shared_ptr_alloc_test.cpp - use to evaluate the impact of count allocations
//
// Copyright (c) 2002, 2003 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#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,27 +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_delete_fail.cpp - a negative test for "delete sp;"
//
// Copyright 2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/shared_ptr.hpp>
int main()
{
boost::shared_ptr<int> p;
delete p; // must fail
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,310 +0,0 @@
// smart pointer test program ----------------------------------------------//
// Copyright Beman Dawes 1998, 1999. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/smart_ptr for documentation.
// 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();
}

View File

@@ -1,214 +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
//
// weak_ptr_mt_test.cpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
// Copyright 2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/bind.hpp>
#include <vector>
#include <memory>
#include <stdexcept>
#include <cstdio>
#include <ctime>
#include <cstdlib>
// '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 = 16384;
int const k = 512; // vector size
int const m = 16; // threads
void test( std::vector< boost::shared_ptr<int> > & v )
{
using namespace std; // printf, rand
std::vector< boost::weak_ptr<int> > w( v.begin(), v.end() );
int s = 0, f = 0, r = 0;
for( int i = 0; i < n; ++i )
{
// randomly kill a pointer
v[ rand() % k ].reset();
++s;
for( int j = 0; j < k; ++j )
{
if( boost::shared_ptr<int> px = w[ j ].lock() )
{
++s;
if( rand() & 4 )
{
continue;
}
// rebind anyway with prob. 50% for add_ref_lock() against weak_release() contention
++f;
}
else
{
++r;
}
w[ j ] = v[ rand() % k ];
}
}
printf( "\n%d locks, %d forced rebinds, %d normal rebinds.", s, f, r );
}
int main()
{
using namespace std; // printf, clock_t, clock
printf("%s: %d threads, %d * %d iterations: ", title, m, n, k );
std::vector< boost::shared_ptr<int> > v( k );
for( int i = 0; i < k; ++i )
{
v[ i ].reset( new int( 0 ) );
}
clock_t t = clock();
pthread_t a[m];
for(int i = 0; i < m; ++i)
{
a[i] = createThread( boost::bind( test, v ) );
}
v.resize( 0 ); // kill original copies
for(int j = 0; j < m; ++j)
{
pthread_join( a[j], 0 );
}
t = clock() - t;
printf("\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,85 +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
//
// weak_ptr_timing_test.cpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
// Copyright 2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <vector>
#include <cstdio>
#include <ctime>
#include <cstdlib>
//
int const n = 29000;
int const k = 2048;
void test( std::vector< boost::shared_ptr<int> > & v )
{
using namespace std; // printf, rand
std::vector< boost::weak_ptr<int> > w( v.begin(), v.end() );
int s = 0, r = 0;
for( int i = 0; i < n; ++i )
{
// randomly kill a pointer
v[ rand() % k ].reset();
for( int j = 0; j < k; ++j )
{
if( boost::shared_ptr<int> px = w[ j ].lock() )
{
++s;
}
else
{
++r;
w[ j ] = v[ rand() % k ];
}
}
}
printf( "\n%d locks, %d rebinds.", s, r );
}
int main()
{
using namespace std; // printf, clock_t, clock
std::vector< boost::shared_ptr<int> > v( k );
for( int i = 0; i < k; ++i )
{
v[ i ].reset( new int( 0 ) );
}
clock_t t = clock();
test( v );
t = clock() - t;
printf( "\n\n%.3f seconds.\n", static_cast<double>( t ) / CLOCKS_PER_SEC );
return 0;
}

View File

@@ -4,46 +4,33 @@
<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="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle">weak_ptr
<body bgcolor="#ffffff" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">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>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 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 set to 0.</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));
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">
common requirements</a>.</p>
<P>Compared to&nbsp;<STRONG>shared_ptr</STRONG>, <STRONG>weak_ptr</STRONG> provides
a very limited subset of operations since accessing its stored pointer is
unsafe in multithreaded&nbsp;programs (that is, it may invoke undefined
behavior.) Consider, for example, 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
if(int * r = q.get())
{
// use *r
// use *r
}
</pre>
<P>Imagine that after the <STRONG>if</STRONG>, but immediately before <STRONG>r</STRONG>
@@ -51,54 +38,60 @@ if(int * r = q.get())
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));
<pre>
shared_ptr&lt;int&gt; p(new int(5));
weak_ptr&lt;int&gt; q(p);
// some time later
if(shared_ptr&lt;int&gt; r = q.<A href="#lock" >lock</A>())
if(shared_ptr&lt;int&gt; r = <a href="#make_shared">make_shared</a>(q))
{
// use *r
// use *r
}
</pre>
<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>
stay alive until <STRONG>r</STRONG> goes out of scope (or is reset.)</p>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost {
template&lt;class T&gt; class weak_ptr {
template&lt;typename T&gt; class weak_ptr {
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>();
<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);
template&lt;class Y&gt; <A href="#constructors" >weak_ptr</A>(weak_ptr&lt;Y&gt; const &amp; r);
<a href="#constructors">weak_ptr</a>(weak_ptr const &amp; r); // never throws
template&lt;typename Y&gt; <a href="#constructors">weak_ptr</a>(weak_ptr&lt;Y&gt; const &amp; r); // never throws
<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);
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);
void <a href="#reset">reset</a>();
T * <a href="#get">get</a>() const; // never throws; unsafe in multithreaded code!
long <A href="#use_count" >use_count</A>() const;
bool <A href="#expired" >expired</A>() const;
shared_ptr&lt;T&gt; <A href="#lock" >lock</A>() const;
long <a href="#use_count">use_count</a>() const; // never throws
bool <a href="#expired">expired</a>() const; // never throws
void <A href="#reset" >reset</A>();
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;
bool <A href="#comparison" >operator&lt;</A>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b);
template&lt;typename T, typename U&gt;
bool <a href="#comparison">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="#comparison">operator!=</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;typename T&gt;
bool <a href="#comparison">operator&lt;</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;T&gt; const &amp; b); // never throws
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
template&lt;typename T&gt;
shared_ptr&lt;T&gt; <a href="#make_shared">make_shared</a>(weak_ptr&lt;T&gt; const &amp; r); // never throws
template&lt;class T&gt;
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>
@@ -107,138 +100,144 @@ if(shared_ptr&lt;int&gt; r = q.<A href="#lock" >lock</A>())
<blockquote>
<p>Provides the type of the template parameter T.</p>
</blockquote>
<h3><a name="default-constructor">constructors</a></h3>
<pre>weak_ptr();</pre>
<h3><a name="constructors">constructors</a></h3>
<pre>explicit 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>
<p><b>Effects:</b> Constructs a <b>weak_ptr</b>.</p>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> is 0; the stored
pointer is 0.</p>
<p><b>Throws:</b> <b>std::bad_alloc</b>.</p>
<p><b>Exception safety:</b> If an exception is thrown, the constructor has no
effect.</p>
<P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
common requirements</A>.</P>
</blockquote>
<pre>template&lt;typename Y&gt; weak_ptr</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws</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
<p><b>Effects:</b> Constructs a <b>weak_ptr</b>, 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>
<P><B>Notes:</B> 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>
</blockquote>
<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>
<blockquote>
<p><b>Effects:</b> Constructs a <b>weak_ptr</b>, as if by storing a copy of the
pointer stored in <b>r</b>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> The <a href="#use_count">use count</a> for all copies is
unchanged.</P>
</blockquote>
<h3><a name="destructor">destructor</a></h3>
<pre>~weak_ptr();</pre>
<pre>~weak_ptr(); // never throws</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>
<P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
common requirements</A>.</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>
<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>
<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> 0 if <STRONG>*this</STRONG> is <EM>empty</EM>; 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="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> the stored pointer (0 if all <b>shared_ptr</b> objects for that
pointer are destroyed.)</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> Using <b>get</b> in multithreaded code is dangerous. After the
function returns, the pointed-to object may be destroyed by a different thread,
since the <b>weak_ptr</b> doesn't affect its <b>use_count</b>.</P>
</blockquote>
<h3><a name="use_count">use_count</a></h3>
<pre>long use_count() const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> the number of <b>shared_ptr</b> objects sharing ownership of the
stored pointer.</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. <B>T</B> need not
be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
common requirements</A>.</P>
</blockquote>
<h3><a name="expired">expired</a></h3>
<pre>bool expired() const; // never throws</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>.
<B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
common requirements</A>.</P>
</blockquote>
<h3><a name="swap">swap</a></h3>
<pre>void swap(weak_ptr &amp; b);</pre>
<pre>void swap(weak_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>
<P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
common requirements</A>.</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>
<pre>template&lt;typename T, typename U&gt;
bool operator==(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 operator!=(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws</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> or are both <EM>empty</EM>.</LI></UL>
<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
common requirements</A>.</P>
</blockquote>
<pre>template&lt;typename T&gt;
bool operator&lt;(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;T&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> an implementation-defined value such that <b>operator&lt;</b> is
a strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
of the C++ standard.</p>
<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>
associative containers. <B>T</B> need not be a complete type. See the smart
pointer <A href="smart_ptr.htm#Common requirements">common requirements</A>.</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>
<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>
<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();
public:
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>
<h3><a name="make_shared">make_shared</a></h3>
<pre>template&lt;typename T&gt;
shared_ptr&lt;T&gt; make_shared(weak_ptr&lt;T&gt; &amp; const r) // never throws</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> <code>r.expired()? shared_ptr&lt;T&gt;(): shared_ptr&lt;T&gt;(r)</code>.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<hr>
<p>$Date$</p>
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
Copyright 2002-2005 Peter Dimov. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears in
all copies. This document is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.</small></p>
<p>Revised 12 March 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears in
all copies. This document is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.</p>
</A>
</body>
</html>