mirror of
				https://github.com/boostorg/smart_ptr.git
				synced 2025-11-03 17:21:51 +01:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			boost-1.33
			...
			boost-1.20
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					7726976deb | 
@@ -1,105 +0,0 @@
 | 
			
		||||
<!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>Smart Pointer Changes</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
<h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86">Smart
 | 
			
		||||
Pointer Changes</h1>
 | 
			
		||||
 | 
			
		||||
<p>The February 2002 change to the Boost smart pointers introduced a number
 | 
			
		||||
of changes. Since the previous version of the smart pointers was in use for
 | 
			
		||||
a long time, it's useful to have a detailed list of what changed from a library
 | 
			
		||||
user's point of view.</p>
 | 
			
		||||
 | 
			
		||||
<p>Note that for compilers that don't support member templates well enough,
 | 
			
		||||
a separate implementation is used that lacks many of the new features and is
 | 
			
		||||
more like the old version.</p>
 | 
			
		||||
 | 
			
		||||
<h2>Features Requiring Code Changes to Take Advantage</h2>
 | 
			
		||||
 | 
			
		||||
<ul>
 | 
			
		||||
 | 
			
		||||
<li>The smart pointer class templates now each have their own header file.
 | 
			
		||||
For compatibility, the
 | 
			
		||||
<a href="../../boost/smart_ptr.hpp"><boost/smart_ptr.hpp></a>
 | 
			
		||||
header now includes the headers for the four classic smart pointer class templates.</li>
 | 
			
		||||
 | 
			
		||||
<li>The <b>weak_ptr</b> template was added.</li>
 | 
			
		||||
 | 
			
		||||
<li>The new <b>shared_ptr</b> and <b>shared_array</b> relax the requirement that the pointed-to object's
 | 
			
		||||
destructor must be visible when instantiating the <b>shared_ptr</b> destructor.
 | 
			
		||||
This makes it easier to have shared_ptr members in classes without explicit destructors.</li>
 | 
			
		||||
 | 
			
		||||
<li>A custom deallocator can be passed in when creating a <b>shared_ptr</b> or <b>shared_array</b>.</li>
 | 
			
		||||
 | 
			
		||||
<li><b>shared_static_cast</b> and <b>shared_dynamic_cast</b> function templates are
 | 
			
		||||
provided which work for <b>shared_ptr</b> and <b>weak_ptr</b> as <b>static_cast</b> and
 | 
			
		||||
<b>dynamic_cast</b> do for pointers.</li>
 | 
			
		||||
 | 
			
		||||
<li>The self-assignment misfeature has been removed from <b>shared_ptr::reset</b>,
 | 
			
		||||
although it is still present in <b>scoped_ptr</b>, and in <b>std::auto_ptr</b>.
 | 
			
		||||
Calling <b>reset</b> with a pointer to the object that's already owned by the
 | 
			
		||||
<b>shared_ptr</b> results in undefined behavior
 | 
			
		||||
(an assertion, or eventually a double-delete if assertions are off).</li>
 | 
			
		||||
 | 
			
		||||
<li>The <b>BOOST_SMART_PTR_CONVERSION</b> feature has been removed.</li>
 | 
			
		||||
 | 
			
		||||
<li><b>shared_ptr<void></b> is now allowed.</li>
 | 
			
		||||
 | 
			
		||||
</ul>
 | 
			
		||||
 | 
			
		||||
<h2>Features That Improve Robustness</h2>
 | 
			
		||||
 | 
			
		||||
<ul>
 | 
			
		||||
 | 
			
		||||
<li>The manipulation of use counts is now <a name="threadsafe">thread safe</a> on Windows, Linux, and platforms
 | 
			
		||||
that support pthreads. See the
 | 
			
		||||
<a href="../../boost/detail/atomic_count.hpp"><boost/detail/atomic_count.hpp></a>
 | 
			
		||||
file for details</li>
 | 
			
		||||
 | 
			
		||||
<li>The new shared_ptr will always delete the object using the pointer it was originally constructed with.
 | 
			
		||||
This prevents subtle problems that could happen if the last <b>shared_ptr</b> was a pointer to a sub-object
 | 
			
		||||
of a class that did not have a virtual destructor.</li>
 | 
			
		||||
 | 
			
		||||
</ul>
 | 
			
		||||
 | 
			
		||||
<h2>Implementation Details</h2>
 | 
			
		||||
 | 
			
		||||
<ul>
 | 
			
		||||
 | 
			
		||||
<li>Some bugs in the assignment operator implementations and in <b>reset</b>
 | 
			
		||||
have been fixed by using the "copy and swap" idiom.</li>
 | 
			
		||||
 | 
			
		||||
<li>Assertions have been added to check preconditions of various functions;
 | 
			
		||||
however, since these use the new
 | 
			
		||||
<a href="../../boost/assert.hpp"><boost/assert.hpp></a>
 | 
			
		||||
header, the assertions are disabled by default.</li>
 | 
			
		||||
 | 
			
		||||
<li>The partial specialization of <b>std::less</b> has been replaced by <b>operator<</b>
 | 
			
		||||
overloads which accomplish the same thing without relying on undefined behavior.</li>
 | 
			
		||||
 | 
			
		||||
<li>The incorrect overload of <b>std::swap</b> has been replaced by <b>boost::swap</b>, which
 | 
			
		||||
has many of the same advantages for generic programming but does not violate the C++ standard.</li>
 | 
			
		||||
 | 
			
		||||
</ul>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
<p>Revised 1 February 2002</p>
 | 
			
		||||
 | 
			
		||||
<p>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>
 | 
			
		||||
@@ -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"> </td>
 | 
			
		||||
			</tr>
 | 
			
		||||
		</table>
 | 
			
		||||
		<h3><a name="Purpose">Purpose</a></h3>
 | 
			
		||||
		<p>
 | 
			
		||||
			The header <STRONG><boost/enable_shared_from_this.hpp></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<T></STRONG> defines two member functions 
 | 
			
		||||
			called <STRONG>shared_from_this</STRONG> that return a <STRONG>shared_ptr<T></STRONG>
 | 
			
		||||
			and <STRONG>shared_ptr<T const></STRONG>, depending on constness, to <STRONG>this</STRONG>.</P>
 | 
			
		||||
		<h3><a name="Example">Example</a></h3>
 | 
			
		||||
		<pre>
 | 
			
		||||
class Y: public enable_shared_from_this<Y>
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    shared_ptr<Y> f()
 | 
			
		||||
    {
 | 
			
		||||
        return shared_from_this();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    shared_ptr<Y> p(new Y);
 | 
			
		||||
    shared_ptr<Y> q = p->f();
 | 
			
		||||
    assert(p == q);
 | 
			
		||||
    assert(!(p < q || q < p)); // p and q must share ownership
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
		<h3><a name="Synopsis">Synopsis</a></h3>
 | 
			
		||||
		<pre>
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
template<class T> class enable_shared_from_this
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    shared_ptr<T> shared_from_this();
 | 
			
		||||
    shared_ptr<T const> shared_from_this() const;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
		<h4>template<class T> shared_ptr<T> 
 | 
			
		||||
			enable_shared_from_this<T>::shared_from_this();</h4>
 | 
			
		||||
		<h4>template<class T> shared_ptr<T const> 
 | 
			
		||||
			enable_shared_from_this<T>::shared_from_this() const;</h4>
 | 
			
		||||
		<blockquote>
 | 
			
		||||
			<p>
 | 
			
		||||
				<b>Requires:</b> <STRONG>enable_shared_from_this<T></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<T></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>
 | 
			
		||||
@@ -1,23 +0,0 @@
 | 
			
		||||
// 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>
 | 
			
		||||
 | 
			
		||||
class example::implementation
 | 
			
		||||
{
 | 
			
		||||
 public:
 | 
			
		||||
  ~implementation() { std::cout << "destroying implementation\n"; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
example::example() : _imp( new implementation ) {}
 | 
			
		||||
 | 
			
		||||
void example::do_something() { std::cout << "did something\n"; }
 | 
			
		||||
 | 
			
		||||
example::~example() {}
 | 
			
		||||
@@ -1,29 +0,0 @@
 | 
			
		||||
//  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>
 | 
			
		||||
 | 
			
		||||
//  The point of this example is to prove that even though
 | 
			
		||||
//  example::implementation is an incomplete type in translation units using
 | 
			
		||||
//  this header, scoped_ptr< implementation > is still valid because the type
 | 
			
		||||
//  is complete where it counts - in the inplementation translation unit where
 | 
			
		||||
//  destruction is actually instantiated.
 | 
			
		||||
 | 
			
		||||
class example : private boost::noncopyable
 | 
			
		||||
{
 | 
			
		||||
 public:
 | 
			
		||||
  example();
 | 
			
		||||
  ~example();
 | 
			
		||||
  void do_something();
 | 
			
		||||
 private:
 | 
			
		||||
  class implementation;
 | 
			
		||||
  boost::scoped_ptr< implementation > _imp; // hide implementation details
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,95 +0,0 @@
 | 
			
		||||
//  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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org/libs/smart_ptr for documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  21 May 01  Initial complete version (Beman Dawes)
 | 
			
		||||
 | 
			
		||||
//  The original code for this example appeared in the shared_ptr documentation.
 | 
			
		||||
//  Ray Gallimore pointed out that foo_set was missing a Compare template
 | 
			
		||||
//  argument, so would not work as intended.  At that point the code was
 | 
			
		||||
//  turned into an actual .cpp file so it could be compiled and tested.
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <set>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <boost/shared_ptr.hpp>
 | 
			
		||||
 | 
			
		||||
//  The application will produce a series of
 | 
			
		||||
//  objects of type Foo which later must be
 | 
			
		||||
//  accessed both by occurrence (std::vector)
 | 
			
		||||
//  and by ordering relationship (std::set).
 | 
			
		||||
 | 
			
		||||
struct Foo
 | 
			
		||||
{ 
 | 
			
		||||
  Foo( int _x ) : x(_x) {}
 | 
			
		||||
  ~Foo() { std::cout << "Destructing a Foo with x=" << x << "\n"; }
 | 
			
		||||
  int x;
 | 
			
		||||
  /* ... */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef boost::shared_ptr<Foo> FooPtr;
 | 
			
		||||
 | 
			
		||||
struct FooPtrOps
 | 
			
		||||
{
 | 
			
		||||
  bool operator()( const FooPtr & a, const FooPtr & b )
 | 
			
		||||
    { return a->x > b->x; }
 | 
			
		||||
  void operator()( const FooPtr & a )
 | 
			
		||||
    { std::cout << a->x << "\n"; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
  std::vector<FooPtr>         foo_vector;
 | 
			
		||||
  std::set<FooPtr,FooPtrOps>  foo_set; // NOT multiset!
 | 
			
		||||
 | 
			
		||||
  FooPtr foo_ptr( new Foo( 2 ) );
 | 
			
		||||
  foo_vector.push_back( foo_ptr );
 | 
			
		||||
  foo_set.insert( foo_ptr );
 | 
			
		||||
 | 
			
		||||
  foo_ptr.reset( new Foo( 1 ) );
 | 
			
		||||
  foo_vector.push_back( foo_ptr );
 | 
			
		||||
  foo_set.insert( foo_ptr );
 | 
			
		||||
 | 
			
		||||
  foo_ptr.reset( new Foo( 3 ) );
 | 
			
		||||
  foo_vector.push_back( foo_ptr );
 | 
			
		||||
  foo_set.insert( foo_ptr );
 | 
			
		||||
 | 
			
		||||
  foo_ptr.reset ( new Foo( 2 ) );
 | 
			
		||||
  foo_vector.push_back( foo_ptr );
 | 
			
		||||
  foo_set.insert( foo_ptr );
 | 
			
		||||
 | 
			
		||||
  std::cout << "foo_vector:\n";
 | 
			
		||||
  std::for_each( foo_vector.begin(), foo_vector.end(), FooPtrOps() );
 | 
			
		||||
  
 | 
			
		||||
  std::cout << "\nfoo_set:\n"; 
 | 
			
		||||
  std::for_each( foo_set.begin(), foo_set.end(), FooPtrOps() );
 | 
			
		||||
  std::cout << "\n";
 | 
			
		||||
 | 
			
		||||
//  Expected output:
 | 
			
		||||
//
 | 
			
		||||
//   foo_vector:
 | 
			
		||||
//   2
 | 
			
		||||
//   1
 | 
			
		||||
//   3
 | 
			
		||||
//   2
 | 
			
		||||
//   
 | 
			
		||||
//   foo_set:
 | 
			
		||||
//   3
 | 
			
		||||
//   2
 | 
			
		||||
//   1
 | 
			
		||||
//
 | 
			
		||||
//   Destructing a Foo with x=2
 | 
			
		||||
//   Destructing a Foo with x=1
 | 
			
		||||
//   Destructing a Foo with x=3
 | 
			
		||||
//   Destructing a Foo with x=2
 | 
			
		||||
   
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
// 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>
 | 
			
		||||
 | 
			
		||||
class example::implementation
 | 
			
		||||
{
 | 
			
		||||
 public:
 | 
			
		||||
  ~implementation() { std::cout << "destroying implementation\n"; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
example::example() : _imp( new implementation ) {}
 | 
			
		||||
 | 
			
		||||
void example::do_something()
 | 
			
		||||
  { std::cout << "use_count() is " << _imp.use_count() << "\n"; }
 | 
			
		||||
@@ -1,31 +0,0 @@
 | 
			
		||||
//  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
 | 
			
		||||
//  several other names).  It separates the interface (in this header file)
 | 
			
		||||
//  from the implementation (in shared_ptr_example2.cpp).
 | 
			
		||||
 | 
			
		||||
//  Note that even though example::implementation is an incomplete type in
 | 
			
		||||
//  some translation units using this header, shared_ptr< implementation >
 | 
			
		||||
//  is still valid because the type is complete where it counts - in the
 | 
			
		||||
//  shared_ptr_example2.cpp translation unit where functions requiring a
 | 
			
		||||
//  complete type are actually instantiated.
 | 
			
		||||
 | 
			
		||||
class example
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  example();
 | 
			
		||||
  void do_something();
 | 
			
		||||
private:
 | 
			
		||||
  class implementation;
 | 
			
		||||
  boost::shared_ptr< implementation > _imp; // hide implementation details
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
// 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()
 | 
			
		||||
{
 | 
			
		||||
  example a;
 | 
			
		||||
  a.do_something();
 | 
			
		||||
  example b(a);
 | 
			
		||||
  b.do_something();
 | 
			
		||||
  example c;
 | 
			
		||||
  c = a;
 | 
			
		||||
  c.do_something();
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,108 +0,0 @@
 | 
			
		||||
#ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
 | 
			
		||||
#define BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
// MS compatible compilers support #pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 | 
			
		||||
# pragma once
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  boost/detail/atomic_count.hpp - thread/SMP safe reference counter
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
 | 
			
		||||
//
 | 
			
		||||
// Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
// accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
// http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
//  typedef <implementation-defined> boost::detail::atomic_count;
 | 
			
		||||
//
 | 
			
		||||
//  atomic_count a(n);
 | 
			
		||||
//
 | 
			
		||||
//    (n is convertible to long)
 | 
			
		||||
//
 | 
			
		||||
//    Effects: Constructs an atomic_count with an initial value of n
 | 
			
		||||
//
 | 
			
		||||
//  a;
 | 
			
		||||
//
 | 
			
		||||
//    Returns: (long) the current value of a
 | 
			
		||||
//
 | 
			
		||||
//  ++a;
 | 
			
		||||
//
 | 
			
		||||
//    Effects: Atomically increments the value of a
 | 
			
		||||
//    Returns: nothing
 | 
			
		||||
//
 | 
			
		||||
//  --a;
 | 
			
		||||
//
 | 
			
		||||
//    Effects: Atomically decrements the value of a
 | 
			
		||||
//    Returns: (long) zero if the new value of a is zero,
 | 
			
		||||
//      unspecified non-zero value otherwise (usually the new value)
 | 
			
		||||
//
 | 
			
		||||
//    Important note: when --a returns zero, it must act as a
 | 
			
		||||
//      read memory barrier (RMB); i.e. the calling thread must
 | 
			
		||||
//      have a synchronized view of the memory
 | 
			
		||||
//
 | 
			
		||||
//    On Intel IA-32 (x86) memory is always synchronized, so this
 | 
			
		||||
//      is not a problem.
 | 
			
		||||
//
 | 
			
		||||
//    On many architectures the atomic instructions already act as
 | 
			
		||||
//      a memory barrier.
 | 
			
		||||
//
 | 
			
		||||
//    This property is necessary for proper reference counting, since
 | 
			
		||||
//      a thread can update the contents of a shared object, then
 | 
			
		||||
//      release its reference, and another thread may immediately
 | 
			
		||||
//      release the last reference causing object destruction.
 | 
			
		||||
//
 | 
			
		||||
//    The destructor needs to have a synchronized view of the
 | 
			
		||||
//      object to perform proper cleanup.
 | 
			
		||||
//
 | 
			
		||||
//    Original example by Alexander Terekhov:
 | 
			
		||||
//
 | 
			
		||||
//    Given:
 | 
			
		||||
//
 | 
			
		||||
//    - a mutable shared object OBJ;
 | 
			
		||||
//    - two threads THREAD1 and THREAD2 each holding 
 | 
			
		||||
//      a private smart_ptr object pointing to that OBJ.
 | 
			
		||||
//
 | 
			
		||||
//    t1: THREAD1 updates OBJ (thread-safe via some synchronization)
 | 
			
		||||
//      and a few cycles later (after "unlock") destroys smart_ptr;
 | 
			
		||||
//
 | 
			
		||||
//    t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization 
 | 
			
		||||
//      with respect to shared mutable object OBJ; OBJ destructors
 | 
			
		||||
//      are called driven by smart_ptr interface...
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_HAS_THREADS
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
typedef long atomic_count;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -1,96 +0,0 @@
 | 
			
		||||
#ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
 | 
			
		||||
#define BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  boost/detail/atomic_count_pthreads.hpp
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
 | 
			
		||||
//
 | 
			
		||||
// Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
// accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
// http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  The generic pthread_mutex-based implementation sometimes leads to
 | 
			
		||||
//    inefficiencies. Example: a class with two atomic_count members
 | 
			
		||||
//    can get away with a single mutex.
 | 
			
		||||
//
 | 
			
		||||
//  Users can detect this situation by checking BOOST_AC_USE_PTHREADS.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
class atomic_count
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    class scoped_lock
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
 | 
			
		||||
        scoped_lock(pthread_mutex_t & m): m_(m)
 | 
			
		||||
        {
 | 
			
		||||
            pthread_mutex_lock(&m_);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ~scoped_lock()
 | 
			
		||||
        {
 | 
			
		||||
            pthread_mutex_unlock(&m_);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
 | 
			
		||||
        pthread_mutex_t & m_;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    explicit atomic_count(long v): value_(v)
 | 
			
		||||
    {
 | 
			
		||||
        pthread_mutex_init(&mutex_, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~atomic_count()
 | 
			
		||||
    {
 | 
			
		||||
        pthread_mutex_destroy(&mutex_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void operator++()
 | 
			
		||||
    {
 | 
			
		||||
        scoped_lock lock(mutex_);
 | 
			
		||||
        ++value_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    long operator--()
 | 
			
		||||
    {
 | 
			
		||||
        scoped_lock lock(mutex_);
 | 
			
		||||
        return --value_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    operator long() const
 | 
			
		||||
    {
 | 
			
		||||
        scoped_lock lock(mutex_);
 | 
			
		||||
        return value_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    atomic_count(atomic_count const &);
 | 
			
		||||
    atomic_count & operator=(atomic_count const &);
 | 
			
		||||
 | 
			
		||||
    mutable pthread_mutex_t mutex_;
 | 
			
		||||
    long value_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace detail
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
 | 
			
		||||
@@ -1,63 +0,0 @@
 | 
			
		||||
#ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
 | 
			
		||||
#define BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
// MS compatible compilers support #pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 | 
			
		||||
# pragma once
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  boost/detail/atomic_count_win32.hpp
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2001-2005 Peter Dimov
 | 
			
		||||
//
 | 
			
		||||
// Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
// accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
// http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <boost/detail/interlocked.hpp>
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
class atomic_count
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    explicit atomic_count( long v ): value_( v )
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    long operator++()
 | 
			
		||||
    {
 | 
			
		||||
        return BOOST_INTERLOCKED_INCREMENT( &value_ );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    long operator--()
 | 
			
		||||
    {
 | 
			
		||||
        return BOOST_INTERLOCKED_DECREMENT( &value_ );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    operator long() const
 | 
			
		||||
    {
 | 
			
		||||
        return static_cast<long const volatile &>( value_ );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    atomic_count( atomic_count const & );
 | 
			
		||||
    atomic_count & operator=( atomic_count const & );
 | 
			
		||||
 | 
			
		||||
    long value_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace detail
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -1,42 +0,0 @@
 | 
			
		||||
#ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
 | 
			
		||||
#define BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
// MS compatible compilers support #pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 | 
			
		||||
# pragma once
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  boost/detail/lightweight_mutex.hpp - lightweight mutex
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd.
 | 
			
		||||
//
 | 
			
		||||
// Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
// accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
// http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
//  typedef <unspecified> boost::detail::lightweight_mutex;
 | 
			
		||||
//
 | 
			
		||||
//  boost::detail::lightweight_mutex is a header-only implementation of
 | 
			
		||||
//  a subset of the Mutex concept requirements:
 | 
			
		||||
//
 | 
			
		||||
//  http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex
 | 
			
		||||
//
 | 
			
		||||
//  It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
 | 
			
		||||
#if !defined(BOOST_HAS_THREADS)
 | 
			
		||||
# include <boost/detail/lwm_nop.hpp>
 | 
			
		||||
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
 | 
			
		||||
#  include <boost/detail/lwm_win32_cs.hpp>
 | 
			
		||||
#elif defined(BOOST_HAS_PTHREADS)
 | 
			
		||||
#  include <boost/detail/lwm_pthreads.hpp>
 | 
			
		||||
#else
 | 
			
		||||
// Use #define BOOST_DISABLE_THREADS to avoid the error
 | 
			
		||||
#  error Unrecognized threading platform
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
 | 
			
		||||
@@ -1,37 +0,0 @@
 | 
			
		||||
#ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED
 | 
			
		||||
#define BOOST_DETAIL_LWM_NOP_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
// MS compatible compilers support #pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 | 
			
		||||
# pragma once
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  boost/detail/lwm_nop.hpp
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
 | 
			
		||||
//
 | 
			
		||||
// Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
// accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
// http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
class lightweight_mutex
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    typedef lightweight_mutex scoped_lock;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace detail
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED
 | 
			
		||||
@@ -1,86 +0,0 @@
 | 
			
		||||
#ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED
 | 
			
		||||
#define BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
// MS compatible compilers support #pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 | 
			
		||||
# pragma once
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  boost/detail/lwm_pthreads.hpp
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
 | 
			
		||||
//
 | 
			
		||||
// Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
// accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
// http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
class lightweight_mutex
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_t m_;
 | 
			
		||||
 | 
			
		||||
    lightweight_mutex(lightweight_mutex const &);
 | 
			
		||||
    lightweight_mutex & operator=(lightweight_mutex const &);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    lightweight_mutex()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
 | 
			
		||||
 | 
			
		||||
#if defined(__hpux) && defined(_DECTHREADS_)
 | 
			
		||||
        pthread_mutex_init(&m_, pthread_mutexattr_default);
 | 
			
		||||
#else
 | 
			
		||||
        pthread_mutex_init(&m_, 0);
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~lightweight_mutex()
 | 
			
		||||
    {
 | 
			
		||||
        pthread_mutex_destroy(&m_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class scoped_lock;
 | 
			
		||||
    friend class scoped_lock;
 | 
			
		||||
 | 
			
		||||
    class scoped_lock
 | 
			
		||||
    {
 | 
			
		||||
    private:
 | 
			
		||||
 | 
			
		||||
        pthread_mutex_t & m_;
 | 
			
		||||
 | 
			
		||||
        scoped_lock(scoped_lock const &);
 | 
			
		||||
        scoped_lock & operator=(scoped_lock const &);
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
 | 
			
		||||
        scoped_lock(lightweight_mutex & m): m_(m.m_)
 | 
			
		||||
        {
 | 
			
		||||
            pthread_mutex_lock(&m_);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ~scoped_lock()
 | 
			
		||||
        {
 | 
			
		||||
            pthread_mutex_unlock(&m_);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace detail
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED
 | 
			
		||||
@@ -1,104 +0,0 @@
 | 
			
		||||
#ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
 | 
			
		||||
#define BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
// MS compatible compilers support #pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 | 
			
		||||
# pragma once
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  boost/detail/lwm_win32_cs.hpp
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2002, 2003 Peter Dimov
 | 
			
		||||
//
 | 
			
		||||
// Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
// accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
// http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#ifdef BOOST_USE_WINDOWS_H
 | 
			
		||||
#  include <windows.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_USE_WINDOWS_H
 | 
			
		||||
 | 
			
		||||
struct CRITICAL_SECTION
 | 
			
		||||
{
 | 
			
		||||
    struct critical_section_debug * DebugInfo;
 | 
			
		||||
    long LockCount;
 | 
			
		||||
    long RecursionCount;
 | 
			
		||||
    void * OwningThread;
 | 
			
		||||
    void * LockSemaphore;
 | 
			
		||||
#if defined(_WIN64)
 | 
			
		||||
    unsigned __int64 SpinCount;
 | 
			
		||||
#else
 | 
			
		||||
    unsigned long SpinCount;
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(CRITICAL_SECTION *);
 | 
			
		||||
extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(CRITICAL_SECTION *);
 | 
			
		||||
extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(CRITICAL_SECTION *);
 | 
			
		||||
extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(CRITICAL_SECTION *);
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef BOOST_USE_WINDOWS_H
 | 
			
		||||
 | 
			
		||||
class lightweight_mutex
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    CRITICAL_SECTION cs_;
 | 
			
		||||
 | 
			
		||||
    lightweight_mutex(lightweight_mutex const &);
 | 
			
		||||
    lightweight_mutex & operator=(lightweight_mutex const &);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    lightweight_mutex()
 | 
			
		||||
    {
 | 
			
		||||
        InitializeCriticalSection(&cs_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~lightweight_mutex()
 | 
			
		||||
    {
 | 
			
		||||
        DeleteCriticalSection(&cs_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class scoped_lock;
 | 
			
		||||
    friend class scoped_lock;
 | 
			
		||||
 | 
			
		||||
    class scoped_lock
 | 
			
		||||
    {
 | 
			
		||||
    private:
 | 
			
		||||
 | 
			
		||||
        lightweight_mutex & m_;
 | 
			
		||||
 | 
			
		||||
        scoped_lock(scoped_lock const &);
 | 
			
		||||
        scoped_lock & operator=(scoped_lock const &);
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
 | 
			
		||||
        explicit scoped_lock(lightweight_mutex & m): m_(m)
 | 
			
		||||
        {
 | 
			
		||||
            EnterCriticalSection(&m_.cs_);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ~scoped_lock()
 | 
			
		||||
        {
 | 
			
		||||
            LeaveCriticalSection(&m_.cs_);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace detail
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
 | 
			
		||||
@@ -1,151 +0,0 @@
 | 
			
		||||
#ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED
 | 
			
		||||
#define BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  detail/shared_array_nmt.hpp - shared_array.hpp without member templates
 | 
			
		||||
//
 | 
			
		||||
//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
 | 
			
		||||
//  Copyright (c) 2001, 2002 Peter Dimov
 | 
			
		||||
//
 | 
			
		||||
//  Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
//  accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
//  http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <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
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
template<class T> class shared_array
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    typedef detail::atomic_count count_type;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    typedef T element_type;
 | 
			
		||||
      
 | 
			
		||||
    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);
 | 
			
		||||
            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);
 | 
			
		||||
            delete pn;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    shared_array(shared_array const & r) : px(r.px)  // never throws
 | 
			
		||||
    {
 | 
			
		||||
        pn = r.pn;
 | 
			
		||||
        ++*pn;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    shared_array & operator=(shared_array const & r)
 | 
			
		||||
    {
 | 
			
		||||
        shared_array(r).swap(*this);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void reset(T * p = 0)
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(p == 0 || p != px);
 | 
			
		||||
        shared_array(p).swap(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T * get() const  // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T & operator[](std::ptrdiff_t i) const  // never throws
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(px != 0);
 | 
			
		||||
        BOOST_ASSERT(i >= 0);
 | 
			
		||||
        return px[i];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    long use_count() const  // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return *pn;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool unique() const  // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return *pn == 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void swap(shared_array<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
 | 
			
		||||
      
 | 
			
		||||
};  // shared_array
 | 
			
		||||
 | 
			
		||||
template<class T, class U> inline bool operator==(shared_array<T> const & a, shared_array<U> const & b)
 | 
			
		||||
{
 | 
			
		||||
    return a.get() == b.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> inline bool operator!=(shared_array<T> const & a, shared_array<U> const & b)
 | 
			
		||||
{
 | 
			
		||||
    return a.get() != b.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b)
 | 
			
		||||
{
 | 
			
		||||
    return std::less<T*>()(a.get(), b.get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> void swap(shared_array<T> & a, shared_array<T> & b)
 | 
			
		||||
{
 | 
			
		||||
    a.swap(b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif  // #ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED
 | 
			
		||||
@@ -1,330 +0,0 @@
 | 
			
		||||
#ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
 | 
			
		||||
#define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
// MS compatible compilers support #pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 | 
			
		||||
# pragma once
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  detail/shared_count.hpp
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
 | 
			
		||||
//  Copyright 2004-2005 Peter Dimov
 | 
			
		||||
//
 | 
			
		||||
// Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
// accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
// http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
 | 
			
		||||
 | 
			
		||||
int const shared_count_id = 0x2C35F101;
 | 
			
		||||
int const   weak_count_id = 0x298C38A4;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
class weak_count;
 | 
			
		||||
 | 
			
		||||
class shared_count
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    sp_counted_base * pi_;
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
 | 
			
		||||
    int id_;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    friend class weak_count;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    shared_count(): pi_(0) // nothrow
 | 
			
		||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
 | 
			
		||||
        , id_(shared_count_id)
 | 
			
		||||
#endif
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class Y> explicit shared_count( Y * p ): pi_( 0 )
 | 
			
		||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
 | 
			
		||||
        , id_(shared_count_id)
 | 
			
		||||
#endif
 | 
			
		||||
    {
 | 
			
		||||
#ifndef BOOST_NO_EXCEPTIONS
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            pi_ = new sp_counted_impl_p<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
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class P, class D> shared_count(P p, D d): pi_(0)
 | 
			
		||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
 | 
			
		||||
        , id_(shared_count_id)
 | 
			
		||||
#endif
 | 
			
		||||
    {
 | 
			
		||||
#ifndef BOOST_NO_EXCEPTIONS
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            pi_ = new sp_counted_impl_pd<P, D>(p, d);
 | 
			
		||||
        }
 | 
			
		||||
        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
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
    {
 | 
			
		||||
#ifdef BOOST_NO_EXCEPTIONS
 | 
			
		||||
 | 
			
		||||
        if( pi_ == 0 )
 | 
			
		||||
        {
 | 
			
		||||
            boost::throw_exception(std::bad_alloc());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        r.release();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif 
 | 
			
		||||
 | 
			
		||||
    ~shared_count() // nothrow
 | 
			
		||||
    {
 | 
			
		||||
        if( pi_ != 0 ) pi_->release();
 | 
			
		||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
 | 
			
		||||
        id_ = 0;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    explicit shared_count(weak_count const & r); // throws bad_weak_ptr 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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void swap(shared_count & r) // nothrow
 | 
			
		||||
    {
 | 
			
		||||
        sp_counted_base * tmp = r.pi_;
 | 
			
		||||
        r.pi_ = pi_;
 | 
			
		||||
        pi_ = tmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    long use_count() const // nothrow
 | 
			
		||||
    {
 | 
			
		||||
        return pi_ != 0? pi_->use_count(): 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool unique() const // nothrow
 | 
			
		||||
    {
 | 
			
		||||
        return use_count() == 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    friend inline bool operator==(shared_count const & a, shared_count const & b)
 | 
			
		||||
    {
 | 
			
		||||
        return a.pi_ == b.pi_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    friend inline bool operator<(shared_count const & a, shared_count const & b)
 | 
			
		||||
    {
 | 
			
		||||
        return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void * get_deleter(std::type_info const & ti) const
 | 
			
		||||
    {
 | 
			
		||||
        return pi_? pi_->get_deleter( ti ): 0;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class weak_count
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    sp_counted_base * pi_;
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
 | 
			
		||||
    int id_;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    friend class shared_count;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    weak_count(): pi_(0) // nothrow
 | 
			
		||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
 | 
			
		||||
        , id_(weak_count_id)
 | 
			
		||||
#endif
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    weak_count(shared_count const & r): pi_(r.pi_) // nothrow
 | 
			
		||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
 | 
			
		||||
        , id_(shared_count_id)
 | 
			
		||||
#endif
 | 
			
		||||
    {
 | 
			
		||||
        if(pi_ != 0) pi_->weak_add_ref();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    weak_count(weak_count const & r): pi_(r.pi_) // nothrow
 | 
			
		||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
 | 
			
		||||
        , id_(shared_count_id)
 | 
			
		||||
#endif
 | 
			
		||||
    {
 | 
			
		||||
        if(pi_ != 0) pi_->weak_add_ref();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~weak_count() // nothrow
 | 
			
		||||
    {
 | 
			
		||||
        if(pi_ != 0) pi_->weak_release();
 | 
			
		||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
 | 
			
		||||
        id_ = 0;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    weak_count & operator= (shared_count const & r) // nothrow
 | 
			
		||||
    {
 | 
			
		||||
        sp_counted_base * tmp = r.pi_;
 | 
			
		||||
        if(tmp != 0) tmp->weak_add_ref();
 | 
			
		||||
        if(pi_ != 0) pi_->weak_release();
 | 
			
		||||
        pi_ = tmp;
 | 
			
		||||
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    weak_count & operator= (weak_count const & r) // nothrow
 | 
			
		||||
    {
 | 
			
		||||
        sp_counted_base * tmp = r.pi_;
 | 
			
		||||
        if(tmp != 0) tmp->weak_add_ref();
 | 
			
		||||
        if(pi_ != 0) pi_->weak_release();
 | 
			
		||||
        pi_ = tmp;
 | 
			
		||||
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void swap(weak_count & r) // nothrow
 | 
			
		||||
    {
 | 
			
		||||
        sp_counted_base * tmp = r.pi_;
 | 
			
		||||
        r.pi_ = pi_;
 | 
			
		||||
        pi_ = tmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    long use_count() const // nothrow
 | 
			
		||||
    {
 | 
			
		||||
        return pi_ != 0? pi_->use_count(): 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    friend inline bool operator==(weak_count const & a, weak_count const & b)
 | 
			
		||||
    {
 | 
			
		||||
        return a.pi_ == b.pi_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    friend inline bool operator<(weak_count const & a, weak_count const & b)
 | 
			
		||||
    {
 | 
			
		||||
        return std::less<sp_counted_base *>()(a.pi_, b.pi_);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
 | 
			
		||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
 | 
			
		||||
        , id_(shared_count_id)
 | 
			
		||||
#endif
 | 
			
		||||
{
 | 
			
		||||
    if( pi_ == 0 || !pi_->add_ref_lock() )
 | 
			
		||||
    {
 | 
			
		||||
        boost::throw_exception( boost::bad_weak_ptr() );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // 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
 | 
			
		||||
@@ -1,182 +0,0 @@
 | 
			
		||||
#ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED
 | 
			
		||||
#define BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  detail/shared_ptr_nmt.hpp - shared_ptr.hpp without member templates
 | 
			
		||||
//
 | 
			
		||||
//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
 | 
			
		||||
//  Copyright (c) 2001, 2002 Peter Dimov
 | 
			
		||||
//
 | 
			
		||||
//  Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
//  accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
//  http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <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
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <algorithm>        // for std::swap
 | 
			
		||||
#include <functional>       // for std::less
 | 
			
		||||
#include <new>              // for std::bad_alloc
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
template<class T> class shared_ptr
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    typedef detail::atomic_count count_type;
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
            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);
 | 
			
		||||
            delete pn;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    shared_ptr(shared_ptr const & r): px(r.px)  // never throws
 | 
			
		||||
    {
 | 
			
		||||
        pn = r.pn;
 | 
			
		||||
        ++*pn;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    shared_ptr & operator=(shared_ptr const & r)
 | 
			
		||||
    {
 | 
			
		||||
        shared_ptr(r).swap(*this);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_AUTO_PTR
 | 
			
		||||
 | 
			
		||||
    explicit shared_ptr(std::auto_ptr<T> & r)
 | 
			
		||||
    { 
 | 
			
		||||
        pn = new count_type(1); // may throw
 | 
			
		||||
        px = r.release(); // fix: moved here to stop leak if new throws
 | 
			
		||||
    } 
 | 
			
		||||
 | 
			
		||||
    shared_ptr & operator=(std::auto_ptr<T> & r)
 | 
			
		||||
    {
 | 
			
		||||
        shared_ptr(r).swap(*this);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    void reset(T * p = 0)
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(p == 0 || p != px);
 | 
			
		||||
        shared_ptr(p).swap(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T & operator*() const  // never throws
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(px != 0);
 | 
			
		||||
        return *px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T * operator->() const  // never throws
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(px != 0);
 | 
			
		||||
        return px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T * get() const  // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    long use_count() const  // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return *pn;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool unique() const  // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return *pn == 1;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    void swap(shared_ptr<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
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<class T, class 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)
 | 
			
		||||
{
 | 
			
		||||
    return a.get() != b.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> inline bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b)
 | 
			
		||||
{
 | 
			
		||||
    return std::less<T*>()(a.get(), b.get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b)
 | 
			
		||||
{
 | 
			
		||||
    a.swap(b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// get_pointer() enables boost::mem_fn to recognize shared_ptr
 | 
			
		||||
 | 
			
		||||
template<class T> inline T * get_pointer(shared_ptr<T> const & p)
 | 
			
		||||
{
 | 
			
		||||
    return p.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif  // #ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -1,272 +0,0 @@
 | 
			
		||||
#ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED
 | 
			
		||||
#define BOOST_INTRUSIVE_PTR_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  intrusive_ptr.hpp
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2001, 2002 Peter Dimov
 | 
			
		||||
//
 | 
			
		||||
// Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
// accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
// http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
 | 
			
		||||
#ifdef BOOST_MSVC  // moved here to work around VC++ compiler crash
 | 
			
		||||
# pragma warning(push)
 | 
			
		||||
# pragma warning(disable:4284) // odd return type for operator->
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <boost/assert.hpp>
 | 
			
		||||
#include <boost/detail/workaround.hpp>
 | 
			
		||||
 | 
			
		||||
#include <functional>           // for std::less
 | 
			
		||||
#include <iosfwd>               // for std::basic_ostream
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  intrusive_ptr
 | 
			
		||||
//
 | 
			
		||||
//  A smart pointer that uses intrusive reference counting.
 | 
			
		||||
//
 | 
			
		||||
//  Relies on unqualified calls to
 | 
			
		||||
//  
 | 
			
		||||
//      void intrusive_ptr_add_ref(T * p);
 | 
			
		||||
//      void intrusive_ptr_release(T * p);
 | 
			
		||||
//
 | 
			
		||||
//          (p != 0)
 | 
			
		||||
//
 | 
			
		||||
//  The object is responsible for destroying itself.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
template<class T> class intrusive_ptr
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    typedef intrusive_ptr this_type;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    typedef T element_type;
 | 
			
		||||
 | 
			
		||||
    intrusive_ptr(): p_(0)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    intrusive_ptr(T * p, bool add_ref = true): p_(p)
 | 
			
		||||
    {
 | 
			
		||||
        if(p_ != 0 && add_ref) intrusive_ptr_add_ref(p_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
 | 
			
		||||
 | 
			
		||||
    template<class U> intrusive_ptr(intrusive_ptr<U> const & rhs): p_(rhs.get())
 | 
			
		||||
    {
 | 
			
		||||
        if(p_ != 0) intrusive_ptr_add_ref(p_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_)
 | 
			
		||||
    {
 | 
			
		||||
        if(p_ != 0) intrusive_ptr_add_ref(p_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~intrusive_ptr()
 | 
			
		||||
    {
 | 
			
		||||
        if(p_ != 0) intrusive_ptr_release(p_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
 | 
			
		||||
 | 
			
		||||
    template<class U> intrusive_ptr & operator=(intrusive_ptr<U> const & rhs)
 | 
			
		||||
    {
 | 
			
		||||
        this_type(rhs).swap(*this);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    intrusive_ptr & operator=(intrusive_ptr const & rhs)
 | 
			
		||||
    {
 | 
			
		||||
        this_type(rhs).swap(*this);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    intrusive_ptr & operator=(T * rhs)
 | 
			
		||||
    {
 | 
			
		||||
        this_type(rhs).swap(*this);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T * get() const
 | 
			
		||||
    {
 | 
			
		||||
        return p_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T & operator*() const
 | 
			
		||||
    {
 | 
			
		||||
        return *p_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T * operator->() const
 | 
			
		||||
    {
 | 
			
		||||
        return p_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
 | 
			
		||||
 | 
			
		||||
    operator bool () const
 | 
			
		||||
    {
 | 
			
		||||
        return p_ != 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
 | 
			
		||||
    typedef T * (this_type::*unspecified_bool_type)() const;
 | 
			
		||||
    
 | 
			
		||||
    operator unspecified_bool_type() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return p_ == 0? 0: &this_type::get;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#else 
 | 
			
		||||
 | 
			
		||||
    typedef T * this_type::*unspecified_bool_type;
 | 
			
		||||
 | 
			
		||||
    operator unspecified_bool_type () const
 | 
			
		||||
    {
 | 
			
		||||
        return p_ == 0? 0: &this_type::p_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // operator! is a Borland-specific workaround
 | 
			
		||||
    bool operator! () const
 | 
			
		||||
    {
 | 
			
		||||
        return p_ == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void swap(intrusive_ptr & rhs)
 | 
			
		||||
    {
 | 
			
		||||
        T * tmp = p_;
 | 
			
		||||
        p_ = rhs.p_;
 | 
			
		||||
        rhs.p_ = tmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    T * p_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
 | 
			
		||||
{
 | 
			
		||||
    return a.get() == b.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
 | 
			
		||||
{
 | 
			
		||||
    return a.get() != b.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> inline bool operator==(intrusive_ptr<T> const & a, T * b)
 | 
			
		||||
{
 | 
			
		||||
    return a.get() == b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> inline bool operator!=(intrusive_ptr<T> const & a, T * b)
 | 
			
		||||
{
 | 
			
		||||
    return a.get() != b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> inline bool operator==(T * a, intrusive_ptr<T> const & b)
 | 
			
		||||
{
 | 
			
		||||
    return a == b.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> inline bool operator!=(T * a, intrusive_ptr<T> const & b)
 | 
			
		||||
{
 | 
			
		||||
    return a != b.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
 | 
			
		||||
 | 
			
		||||
// Resolve the ambiguity between our op!= and the one in rel_ops
 | 
			
		||||
 | 
			
		||||
template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
 | 
			
		||||
{
 | 
			
		||||
    return a.get() != b.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
 | 
			
		||||
{
 | 
			
		||||
    return std::less<T *>()(a.get(), b.get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)
 | 
			
		||||
{
 | 
			
		||||
    lhs.swap(rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mem_fn support
 | 
			
		||||
 | 
			
		||||
template<class T> T * get_pointer(intrusive_ptr<T> const & p)
 | 
			
		||||
{
 | 
			
		||||
    return p.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
 | 
			
		||||
{
 | 
			
		||||
    return static_cast<T *>(p.get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
 | 
			
		||||
{
 | 
			
		||||
    return const_cast<T *>(p.get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
 | 
			
		||||
{
 | 
			
		||||
    return dynamic_cast<T *>(p.get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// operator<<
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__) &&  (__GNUC__ < 3)
 | 
			
		||||
 | 
			
		||||
template<class Y> std::ostream & operator<< (std::ostream & os, intrusive_ptr<Y> const & p)
 | 
			
		||||
{
 | 
			
		||||
    os << p.get();
 | 
			
		||||
    return os;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT)
 | 
			
		||||
// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
 | 
			
		||||
using std::basic_ostream;
 | 
			
		||||
template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
 | 
			
		||||
# else
 | 
			
		||||
template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
 | 
			
		||||
# endif 
 | 
			
		||||
{
 | 
			
		||||
    os << p.get();
 | 
			
		||||
    return os;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
# pragma warning(pop)
 | 
			
		||||
#endif    
 | 
			
		||||
 | 
			
		||||
#endif  // #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED
 | 
			
		||||
@@ -1,135 +0,0 @@
 | 
			
		||||
#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
 | 
			
		||||
#define BOOST_SCOPED_ARRAY_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
 | 
			
		||||
//  Copyright (c) 2001, 2002 Peter Dimov
 | 
			
		||||
//
 | 
			
		||||
//  Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
//  accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
//  http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
//  http://www.boost.org/libs/smart_ptr/scoped_array.htm
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <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
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    T * ptr;
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void reset(T * p = 0) // never throws
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors
 | 
			
		||||
        this_type(p).swap(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T & operator[](std::ptrdiff_t i) const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(ptr != 0);
 | 
			
		||||
        BOOST_ASSERT(i >= 0);
 | 
			
		||||
        return ptr[i];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T * get() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return ptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // implicit conversion to "bool"
 | 
			
		||||
 | 
			
		||||
#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
 | 
			
		||||
 | 
			
		||||
    operator bool () const
 | 
			
		||||
    {
 | 
			
		||||
        return ptr != 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
 | 
			
		||||
    typedef T * (this_type::*unspecified_bool_type)() const;
 | 
			
		||||
    
 | 
			
		||||
    operator unspecified_bool_type() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return ptr == 0? 0: &this_type::get;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#else 
 | 
			
		||||
 | 
			
		||||
    typedef T * this_type::*unspecified_bool_type;
 | 
			
		||||
 | 
			
		||||
    operator unspecified_bool_type() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return ptr == 0? 0: &this_type::ptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    bool operator! () const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return ptr == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void swap(scoped_array & b) // never throws
 | 
			
		||||
    {
 | 
			
		||||
        T * tmp = b.ptr;
 | 
			
		||||
        b.ptr = ptr;
 | 
			
		||||
        ptr = tmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) // never throws
 | 
			
		||||
{
 | 
			
		||||
    a.swap(b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif  // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
 | 
			
		||||
@@ -1,157 +0,0 @@
 | 
			
		||||
#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
 | 
			
		||||
#define BOOST_SCOPED_PTR_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
 | 
			
		||||
//  Copyright (c) 2001, 2002 Peter Dimov
 | 
			
		||||
//
 | 
			
		||||
//  Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
//  accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
//  http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
//  http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <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
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void reset(T * p = 0) // never throws
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors
 | 
			
		||||
        this_type(p).swap(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T & operator*() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(ptr != 0);
 | 
			
		||||
        return *ptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T * operator->() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(ptr != 0);
 | 
			
		||||
        return ptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T * get() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return ptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // implicit conversion to "bool"
 | 
			
		||||
 | 
			
		||||
#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
 | 
			
		||||
 | 
			
		||||
    operator bool () const
 | 
			
		||||
    {
 | 
			
		||||
        return ptr != 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
 | 
			
		||||
    typedef T * (this_type::*unspecified_bool_type)() const;
 | 
			
		||||
    
 | 
			
		||||
    operator unspecified_bool_type() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return ptr == 0? 0: &this_type::get;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#else 
 | 
			
		||||
    typedef T * this_type::*unspecified_bool_type;
 | 
			
		||||
 | 
			
		||||
    operator unspecified_bool_type() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return ptr == 0? 0: &this_type::ptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    bool operator! () const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return ptr == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void swap(scoped_ptr & b) // never throws
 | 
			
		||||
    {
 | 
			
		||||
        T * tmp = b.ptr;
 | 
			
		||||
        b.ptr = ptr;
 | 
			
		||||
        ptr = tmp;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<class 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
 | 
			
		||||
@@ -1,175 +0,0 @@
 | 
			
		||||
#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED
 | 
			
		||||
#define BOOST_SHARED_ARRAY_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  shared_array.hpp
 | 
			
		||||
//
 | 
			
		||||
//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
 | 
			
		||||
//  Copyright (c) 2001, 2002 Peter Dimov
 | 
			
		||||
//
 | 
			
		||||
//  Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
//  accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
//  http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>   // for broken compiler workarounds
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
 | 
			
		||||
#include <boost/detail/shared_array_nmt.hpp>
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#include <boost/assert.hpp>
 | 
			
		||||
#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
 | 
			
		||||
#include <functional>         // for std::less
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  shared_array
 | 
			
		||||
//
 | 
			
		||||
//  shared_array extends shared_ptr to arrays.
 | 
			
		||||
//  The array pointed to is deleted when the last shared_array pointing to it
 | 
			
		||||
//  is destroyed or reset.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
template<class T> class shared_array
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // Borland 5.5.1 specific workarounds
 | 
			
		||||
    typedef checked_array_deleter<T> deleter;
 | 
			
		||||
    typedef shared_array<T> this_type;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    typedef T element_type;
 | 
			
		||||
 | 
			
		||||
    explicit shared_array(T * p = 0): px(p), pn(p, deleter())
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // Requirements: D's copy constructor must not throw
 | 
			
		||||
    //
 | 
			
		||||
    // shared_array will release p by calling d(p)
 | 
			
		||||
    //
 | 
			
		||||
 | 
			
		||||
    template<class D> shared_array(T * p, D d): px(p), pn(p, d)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
//  generated copy constructor, assignment, destructor are fine
 | 
			
		||||
 | 
			
		||||
    void reset(T * p = 0)
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(p == 0 || p != px);
 | 
			
		||||
        this_type(p).swap(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <class D> void reset(T * p, D d)
 | 
			
		||||
    {
 | 
			
		||||
        this_type(p, d).swap(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T & operator[] (std::ptrdiff_t i) const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(px != 0);
 | 
			
		||||
        BOOST_ASSERT(i >= 0);
 | 
			
		||||
        return px[i];
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    T * get() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // implicit conversion to "bool"
 | 
			
		||||
 | 
			
		||||
#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
 | 
			
		||||
 | 
			
		||||
    operator bool () const
 | 
			
		||||
    {
 | 
			
		||||
        return px != 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#elif defined(__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();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    long use_count() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return pn.use_count();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void swap(shared_array<T> & other) // never throws
 | 
			
		||||
    {
 | 
			
		||||
        std::swap(px, other.px);
 | 
			
		||||
        pn.swap(other.pn);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    T * px;                     // contained pointer
 | 
			
		||||
    detail::shared_count pn;    // reference counter
 | 
			
		||||
 | 
			
		||||
};  // shared_array
 | 
			
		||||
 | 
			
		||||
template<class 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
 | 
			
		||||
{
 | 
			
		||||
    return a.get() != b.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class 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
 | 
			
		||||
{
 | 
			
		||||
    a.swap(b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif  // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
 | 
			
		||||
 | 
			
		||||
#endif  // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED
 | 
			
		||||
@@ -1,478 +0,0 @@
 | 
			
		||||
#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
 | 
			
		||||
#define BOOST_SHARED_PTR_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  shared_ptr.hpp
 | 
			
		||||
//
 | 
			
		||||
//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
 | 
			
		||||
//  Copyright (c) 2001, 2002, 2003 Peter Dimov
 | 
			
		||||
//
 | 
			
		||||
//  Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
//  accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
//  http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>   // for broken compiler workarounds
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(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
 | 
			
		||||
 | 
			
		||||
#ifdef BOOST_MSVC  // moved here to work around VC++ compiler crash
 | 
			
		||||
# pragma warning(push)
 | 
			
		||||
# pragma warning(disable:4284) // odd return type for operator->
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
template<class 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
 | 
			
		||||
{
 | 
			
		||||
    typedef T & reference;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  shared_ptr
 | 
			
		||||
//
 | 
			
		||||
//  An enhanced relative of scoped_ptr with reference counted copy semantics.
 | 
			
		||||
//  The object pointed to is deleted when the last shared_ptr pointing to it
 | 
			
		||||
//  is destroyed or reset.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
template<class T> class shared_ptr
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // Borland 5.5.1 specific workaround
 | 
			
		||||
    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+
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class Y>
 | 
			
		||||
    explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
 | 
			
		||||
    {
 | 
			
		||||
        detail::sp_enable_shared_from_this( pn, p, p );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // Requirements: D's copy constructor must not throw
 | 
			
		||||
    //
 | 
			
		||||
    // shared_ptr will release p by calling d(p)
 | 
			
		||||
    //
 | 
			
		||||
 | 
			
		||||
    template<class Y, class 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...
 | 
			
		||||
 | 
			
		||||
//  except that Borland C++ has a bug, and g++ with -Wsynth warns
 | 
			
		||||
#if defined(__BORLANDC__) || defined(__GNUC__)
 | 
			
		||||
 | 
			
		||||
    shared_ptr & operator=(shared_ptr const & r) // never throws
 | 
			
		||||
    {
 | 
			
		||||
        px = r.px;
 | 
			
		||||
        pn = r.pn; // shared_count::op= doesn't throw
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    template<class Y>
 | 
			
		||||
    explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
 | 
			
		||||
    {
 | 
			
		||||
        // it is now safe to copy r.px, as pn(r.pn) did not throw
 | 
			
		||||
        px = r.px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class Y>
 | 
			
		||||
    shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class 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>
 | 
			
		||||
    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
 | 
			
		||||
        {
 | 
			
		||||
            pn = detail::shared_count();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class Y>
 | 
			
		||||
    shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
 | 
			
		||||
    {
 | 
			
		||||
        if(px == 0)
 | 
			
		||||
        {
 | 
			
		||||
            boost::throw_exception(std::bad_cast());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_AUTO_PTR
 | 
			
		||||
 | 
			
		||||
    template<class Y>
 | 
			
		||||
    explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
 | 
			
		||||
    {
 | 
			
		||||
        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>
 | 
			
		||||
    shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
 | 
			
		||||
    {
 | 
			
		||||
        px = r.px;
 | 
			
		||||
        pn = r.pn; // shared_count::op= doesn't throw
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_AUTO_PTR
 | 
			
		||||
 | 
			
		||||
    template<class Y>
 | 
			
		||||
    shared_ptr & operator=(std::auto_ptr<Y> & r)
 | 
			
		||||
    {
 | 
			
		||||
        this_type(r).swap(*this);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    void reset() // never throws in 1.30+
 | 
			
		||||
    {
 | 
			
		||||
        this_type().swap(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class Y> void reset(Y * p) // Y must be complete
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
 | 
			
		||||
        this_type(p).swap(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class Y, class D> void reset(Y * p, D d)
 | 
			
		||||
    {
 | 
			
		||||
        this_type(p, d).swap(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    reference operator* () const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(px != 0);
 | 
			
		||||
        return *px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T * operator-> () const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT(px != 0);
 | 
			
		||||
        return px;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    T * get() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // implicit conversion to "bool"
 | 
			
		||||
 | 
			
		||||
#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 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();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    long use_count() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return pn.use_count();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    template<class Y> friend class shared_ptr;
 | 
			
		||||
    template<class Y> friend class weak_ptr;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    T * px;                     // contained pointer
 | 
			
		||||
    detail::shared_count pn;    // reference counter
 | 
			
		||||
 | 
			
		||||
};  // shared_ptr
 | 
			
		||||
 | 
			
		||||
template<class T, class 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)
 | 
			
		||||
{
 | 
			
		||||
    return a.get() != 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!=(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)
 | 
			
		||||
{
 | 
			
		||||
    return a._internal_less(b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class 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)
 | 
			
		||||
{
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    return shared_ptr<T>(r, detail::dynamic_cast_tag());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// shared_*_cast names are deprecated. Use *_pointer_cast instead.
 | 
			
		||||
 | 
			
		||||
template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
 | 
			
		||||
{
 | 
			
		||||
    return shared_ptr<T>(r, detail::static_cast_tag());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
 | 
			
		||||
{
 | 
			
		||||
    return shared_ptr<T>(r, detail::dynamic_cast_tag());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
 | 
			
		||||
{
 | 
			
		||||
    return shared_ptr<T>(r, detail::polymorphic_cast_tag());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
 | 
			
		||||
    return shared_static_cast<T>(r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// get_pointer() enables boost::mem_fn to recognize shared_ptr
 | 
			
		||||
 | 
			
		||||
template<class 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_SHARED_PTR_HPP_INCLUDED
 | 
			
		||||
@@ -1,25 +1,394 @@
 | 
			
		||||
//
 | 
			
		||||
//  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>
 | 
			
		||||
//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. Permission to copy,
 | 
			
		||||
//  use, modify, sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided "as is"
 | 
			
		||||
//  without express or implied warranty, and with no claim as to its
 | 
			
		||||
//  suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
#include <boost/scoped_ptr.hpp>
 | 
			
		||||
#include <boost/scoped_array.hpp>
 | 
			
		||||
#include <boost/shared_ptr.hpp>
 | 
			
		||||
#include <boost/shared_array.hpp>
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
#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>
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  21 Jan 01  Suppress some useless warnings with MSVC (David Abrahams)
 | 
			
		||||
//  19 Oct 00  Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts) 
 | 
			
		||||
//  24 Jul 00  Change throw() to // never throws.  See lib guidelines
 | 
			
		||||
//             Exception-specification rationale. (Beman Dawes)
 | 
			
		||||
//  22 Jun 00  Remove #if continuations to fix GCC 2.95.2 problem (Beman Dawes)
 | 
			
		||||
//   1 Feb 00  Additional shared_ptr BOOST_NO_MEMBER_TEMPLATES workarounds
 | 
			
		||||
//             (Dave Abrahams)
 | 
			
		||||
//  31 Dec 99  Condition tightened for no member template friend workaround
 | 
			
		||||
//             (Dave Abrahams)
 | 
			
		||||
//  30 Dec 99  Moved BOOST_NMEMBER_TEMPLATES compatibility code to config.hpp
 | 
			
		||||
//             (Dave Abrahams)
 | 
			
		||||
//  30 Nov 99  added operator ==, operator !=, and std::swap and std::less
 | 
			
		||||
//             specializations for shared types (Darin Adler)
 | 
			
		||||
//  11 Oct 99  replaced op[](int) with op[](std::size_t) (Ed Brey, Valentin
 | 
			
		||||
//             Bonnard), added shared_ptr workaround for no member template
 | 
			
		||||
//             friends (Matthew Langston)
 | 
			
		||||
//  25 Sep 99  added shared_ptr::swap and shared_array::swap (Luis Coelho).
 | 
			
		||||
//  20 Jul 99  changed name to smart_ptr.hpp, #include <boost/config.hpp>,
 | 
			
		||||
//             #include <boost/utility.hpp> and use boost::noncopyable
 | 
			
		||||
//  17 May 99  remove scoped_array and shared_array operator*() as
 | 
			
		||||
//             unnecessary (Beman Dawes)
 | 
			
		||||
//  14 May 99  reorder code so no effects when bad_alloc thrown (Abrahams/Dawes)
 | 
			
		||||
//  13 May 99  remove certain throw() specifiers to avoid generated try/catch
 | 
			
		||||
//             code cost (Beman Dawes)
 | 
			
		||||
//  11 May 99  get() added, conversion to T* placed in macro guard (Valentin
 | 
			
		||||
//             Bonnard, Dave Abrahams, and others argued for elimination
 | 
			
		||||
//             of the automatic conversion)
 | 
			
		||||
//  28 Apr 99  #include <memory> fix (Valentin Bonnard)
 | 
			
		||||
//  28 Apr 99  rename transfer() to share() for clarity (Dave Abrahams)
 | 
			
		||||
//  28 Apr 99  remove unsafe shared_array template conversions(Valentin Bonnard)
 | 
			
		||||
//  28 Apr 99  p(r) changed to p(r.px) for clarity (Dave Abrahams)
 | 
			
		||||
//  21 Apr 99  reset() self assignment fix (Valentin Bonnard)
 | 
			
		||||
//  21 Apr 99  dispose() provided to improve clarity (Valentin Bonnard)
 | 
			
		||||
//  27 Apr 99  leak when new throws fixes (Dave Abrahams)
 | 
			
		||||
//  21 Oct 98  initial Version (Greg Colvin/Beman Dawes)
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_SMART_PTR_HPP
 | 
			
		||||
#define BOOST_SMART_PTR_HPP
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>   // for broken compiler workarounds
 | 
			
		||||
#include <cstddef>            // for std::size_t
 | 
			
		||||
#include <memory>             // for std::auto_ptr
 | 
			
		||||
#include <algorithm>          // for std::swap
 | 
			
		||||
#include <boost/utility.hpp>  // for boost::noncopyable
 | 
			
		||||
#include <functional>         // for std::less
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
//  scoped_ptr  --------------------------------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  scoped_ptr mimics a built-in pointer except that it guarantees deletion
 | 
			
		||||
//  of the object pointed to, either on destruction of the scoped_ptr or via
 | 
			
		||||
//  an explicit reset().  scoped_ptr is a simple solution for simple needs;
 | 
			
		||||
//  see shared_ptr (below) or std::auto_ptr if your needs are more complex.
 | 
			
		||||
 | 
			
		||||
template<typename T> class scoped_ptr : noncopyable {
 | 
			
		||||
 | 
			
		||||
  T* ptr;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  typedef T element_type;
 | 
			
		||||
 | 
			
		||||
  explicit scoped_ptr( T* p=0 ) : ptr(p) {}  // never throws
 | 
			
		||||
  ~scoped_ptr()                 { delete ptr; }
 | 
			
		||||
 | 
			
		||||
  void reset( T* p=0 )          { if ( ptr != p ) { delete ptr; ptr = p; } }
 | 
			
		||||
  T& operator*() const          { return *ptr; }  // never throws
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
# pragma warning(push)
 | 
			
		||||
# pragma warning(disable:4284) // return type for 'identifier::operator->' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation
 | 
			
		||||
#endif    
 | 
			
		||||
  T* operator->() const         { return ptr; }  // never throws
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
# pragma warning(pop)
 | 
			
		||||
#endif    
 | 
			
		||||
  T* get() const                { return ptr; }  // never throws
 | 
			
		||||
#ifdef BOOST_SMART_PTR_CONVERSION
 | 
			
		||||
  // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
 | 
			
		||||
  operator T*() const           { return ptr; }  // never throws 
 | 
			
		||||
#endif
 | 
			
		||||
  };  // scoped_ptr
 | 
			
		||||
 | 
			
		||||
//  scoped_array  ------------------------------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
 | 
			
		||||
//  is guaranteed, either on destruction of the scoped_array or via an explicit
 | 
			
		||||
//  reset(). See shared_array or std::vector if your needs are more complex.
 | 
			
		||||
 | 
			
		||||
template<typename T> class scoped_array : noncopyable {
 | 
			
		||||
 | 
			
		||||
  T* ptr;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  typedef T element_type;
 | 
			
		||||
 | 
			
		||||
  explicit scoped_array( T* p=0 ) : ptr(p) {}  // never throws
 | 
			
		||||
  ~scoped_array()                    { delete [] ptr; }
 | 
			
		||||
 | 
			
		||||
  void reset( T* p=0 )               { if ( ptr != p ) {delete [] ptr; ptr=p;} }
 | 
			
		||||
 | 
			
		||||
  T* get() const                     { return ptr; }  // never throws
 | 
			
		||||
#ifdef BOOST_SMART_PTR_CONVERSION
 | 
			
		||||
  // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
 | 
			
		||||
  operator T*() const                { return ptr; }  // never throws
 | 
			
		||||
#else 
 | 
			
		||||
  T& operator[](std::size_t i) const { return ptr[i]; }  // never throws
 | 
			
		||||
#endif
 | 
			
		||||
  };  // scoped_array
 | 
			
		||||
 | 
			
		||||
//  shared_ptr  --------------------------------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  An enhanced relative of scoped_ptr with reference counted copy semantics.
 | 
			
		||||
//  The object pointed to is deleted when the last shared_ptr pointing to it
 | 
			
		||||
//  is destroyed or reset.
 | 
			
		||||
 | 
			
		||||
template<typename T> class shared_ptr {
 | 
			
		||||
  public:
 | 
			
		||||
   typedef T element_type;
 | 
			
		||||
 | 
			
		||||
   explicit shared_ptr(T* p =0) : px(p) {
 | 
			
		||||
      try { pn = new long(1); }  // fix: prevent leak if new throws
 | 
			
		||||
      catch (...) { delete p; throw; } 
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   shared_ptr(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); }  // never throws
 | 
			
		||||
 | 
			
		||||
   ~shared_ptr() { dispose(); }
 | 
			
		||||
 | 
			
		||||
   shared_ptr& operator=(const shared_ptr& r) {
 | 
			
		||||
      share(r.px,r.pn);
 | 
			
		||||
      return *this;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
#if !defined( BOOST_NO_MEMBER_TEMPLATES )
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      shared_ptr(const shared_ptr<Y>& r) : px(r.px) {  // never throws 
 | 
			
		||||
         ++*(pn = r.pn); 
 | 
			
		||||
      }
 | 
			
		||||
#ifndef BOOST_NO_AUTO_PTR
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      explicit shared_ptr(std::auto_ptr<Y>& r) { 
 | 
			
		||||
         pn = new long(1); // may throw
 | 
			
		||||
         px = r.release(); // fix: moved here to stop leak if new throws
 | 
			
		||||
      }
 | 
			
		||||
#endif 
 | 
			
		||||
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      shared_ptr& operator=(const shared_ptr<Y>& r) { 
 | 
			
		||||
         share(r.px,r.pn);
 | 
			
		||||
         return *this;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_AUTO_PTR
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      shared_ptr& operator=(std::auto_ptr<Y>& r) {
 | 
			
		||||
         // code choice driven by guarantee of "no effect if new throws"
 | 
			
		||||
         if (*pn == 1) { delete px; }
 | 
			
		||||
         else { // allocate new reference counter
 | 
			
		||||
           long * tmp = new long(1); // may throw
 | 
			
		||||
           --*pn; // only decrement once danger of new throwing is past
 | 
			
		||||
           pn = tmp;
 | 
			
		||||
         } // allocate new reference counter
 | 
			
		||||
         px = r.release(); // fix: moved here so doesn't leak if new throws 
 | 
			
		||||
         return *this;
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
#else
 | 
			
		||||
#ifndef BOOST_NO_AUTO_PTR
 | 
			
		||||
      explicit shared_ptr(std::auto_ptr<T>& r) { 
 | 
			
		||||
         pn = new long(1); // may throw
 | 
			
		||||
         px = r.release(); // fix: moved here to stop leak if new throws
 | 
			
		||||
      } 
 | 
			
		||||
 | 
			
		||||
      shared_ptr& operator=(std::auto_ptr<T>& r) {
 | 
			
		||||
         // code choice driven by guarantee of "no effect if new throws"
 | 
			
		||||
         if (*pn == 1) { delete px; }
 | 
			
		||||
         else { // allocate new reference counter
 | 
			
		||||
           long * tmp = new long(1); // may throw
 | 
			
		||||
           --*pn; // only decrement once danger of new throwing is past
 | 
			
		||||
           pn = tmp;
 | 
			
		||||
         } // allocate new reference counter
 | 
			
		||||
         px = r.release(); // fix: moved here so doesn't leak if new throws 
 | 
			
		||||
         return *this;
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   void reset(T* p=0) {
 | 
			
		||||
      if ( px == p ) return;  // fix: self-assignment safe
 | 
			
		||||
      if (--*pn == 0) { delete px; }
 | 
			
		||||
      else { // allocate new reference counter
 | 
			
		||||
        try { pn = new long; }  // fix: prevent leak if new throws
 | 
			
		||||
        catch (...) {
 | 
			
		||||
          ++*pn;  // undo effect of --*pn above to meet effects guarantee 
 | 
			
		||||
          delete p;
 | 
			
		||||
          throw;
 | 
			
		||||
        } // catch
 | 
			
		||||
      } // allocate new reference counter
 | 
			
		||||
      *pn = 1;
 | 
			
		||||
      px = p;
 | 
			
		||||
   } // reset
 | 
			
		||||
 | 
			
		||||
   T& operator*() const          { return *px; }  // never throws
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
# pragma warning(push)
 | 
			
		||||
# pragma warning(disable:4284) // return type for 'identifier::operator->' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation
 | 
			
		||||
#endif    
 | 
			
		||||
   T* operator->() const         { return px; }  // never throws
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
# pragma warning(pop)
 | 
			
		||||
#endif    
 | 
			
		||||
   T* get() const                { return px; }  // never throws
 | 
			
		||||
 #ifdef BOOST_SMART_PTR_CONVERSION
 | 
			
		||||
   // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
 | 
			
		||||
   operator T*() const           { return px; }  // never throws 
 | 
			
		||||
 #endif
 | 
			
		||||
 | 
			
		||||
   long use_count() const        { return *pn; }  // never throws
 | 
			
		||||
   bool unique() const           { return *pn == 1; }  // never throws
 | 
			
		||||
 | 
			
		||||
   void swap(shared_ptr<T>& other)  // never throws
 | 
			
		||||
     { std::swap(px,other.px); std::swap(pn,other.pn); }
 | 
			
		||||
 | 
			
		||||
// Tasteless as this may seem, making all members public allows member templates
 | 
			
		||||
// to work in the absence of member template friends. (Matthew Langston)
 | 
			
		||||
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
 | 
			
		||||
#if defined(BOOST_NO_MEMBER_TEMPLATES) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
 | 
			
		||||
   private:
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   T*     px;     // contained pointer
 | 
			
		||||
   long*  pn;     // ptr to reference counter
 | 
			
		||||
 | 
			
		||||
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
 | 
			
		||||
#if !defined( BOOST_NO_MEMBER_TEMPLATES ) && !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
 | 
			
		||||
   template<typename Y> friend class shared_ptr;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   void dispose() { if (--*pn == 0) { delete px; delete pn; } }
 | 
			
		||||
 | 
			
		||||
   void share(T* rpx, long* rpn) {
 | 
			
		||||
      if (pn != rpn) {
 | 
			
		||||
         dispose();
 | 
			
		||||
         px = rpx;
 | 
			
		||||
         ++*(pn = rpn);
 | 
			
		||||
      }
 | 
			
		||||
   } // share
 | 
			
		||||
};  // shared_ptr
 | 
			
		||||
 | 
			
		||||
template<typename T, typename U>
 | 
			
		||||
  inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b)
 | 
			
		||||
    { return a.get() == b.get(); }
 | 
			
		||||
 | 
			
		||||
template<typename T, typename U>
 | 
			
		||||
  inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b)
 | 
			
		||||
    { return a.get() != b.get(); }
 | 
			
		||||
 | 
			
		||||
//  shared_array  ------------------------------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  shared_array extends shared_ptr to arrays.
 | 
			
		||||
//  The array pointed to is deleted when the last shared_array pointing to it
 | 
			
		||||
//  is destroyed or reset.
 | 
			
		||||
 | 
			
		||||
template<typename T> class shared_array {
 | 
			
		||||
  public:
 | 
			
		||||
   typedef T element_type;
 | 
			
		||||
 | 
			
		||||
   explicit shared_array(T* p =0) : px(p) {
 | 
			
		||||
      try { pn = new long(1); }  // fix: prevent leak if new throws
 | 
			
		||||
      catch (...) { delete [] p; throw; } 
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   shared_array(const shared_array& r) : px(r.px)  // never throws
 | 
			
		||||
      { ++*(pn = r.pn); }
 | 
			
		||||
 | 
			
		||||
   ~shared_array() { dispose(); }
 | 
			
		||||
 | 
			
		||||
   shared_array& operator=(const shared_array& r) {
 | 
			
		||||
      if (pn != r.pn) {
 | 
			
		||||
         dispose();
 | 
			
		||||
         px = r.px;
 | 
			
		||||
         ++*(pn = r.pn);
 | 
			
		||||
      }
 | 
			
		||||
      return *this;
 | 
			
		||||
   } // operator=
 | 
			
		||||
 | 
			
		||||
   void reset(T* p=0) {
 | 
			
		||||
      if ( px == p ) return;  // fix: self-assignment safe
 | 
			
		||||
      if (--*pn == 0) { delete [] px; }
 | 
			
		||||
      else { // allocate new reference counter
 | 
			
		||||
        try { pn = new long; }  // fix: prevent leak if new throws
 | 
			
		||||
        catch (...) {
 | 
			
		||||
          ++*pn;  // undo effect of --*pn above to meet effects guarantee 
 | 
			
		||||
          delete [] p;
 | 
			
		||||
          throw;
 | 
			
		||||
        } // catch
 | 
			
		||||
      } // allocate new reference counter
 | 
			
		||||
      *pn = 1;
 | 
			
		||||
      px = p;
 | 
			
		||||
   } // reset
 | 
			
		||||
 | 
			
		||||
   T* get() const                     { return px; }  // never throws
 | 
			
		||||
 #ifdef BOOST_SMART_PTR_CONVERSION
 | 
			
		||||
   // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
 | 
			
		||||
   operator T*() const                { return px; }  // never throws
 | 
			
		||||
 #else 
 | 
			
		||||
   T& operator[](std::size_t i) const { return px[i]; }  // never throws
 | 
			
		||||
 #endif
 | 
			
		||||
 | 
			
		||||
   long use_count() const             { return *pn; }  // never throws
 | 
			
		||||
   bool unique() const                { return *pn == 1; }  // never throws
 | 
			
		||||
 | 
			
		||||
   void swap(shared_array<T>& other)  // never throws
 | 
			
		||||
     { std::swap(px,other.px); std::swap(pn,other.pn); }
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
 | 
			
		||||
   T*     px;     // contained pointer
 | 
			
		||||
   long*  pn;     // ptr to reference counter
 | 
			
		||||
 | 
			
		||||
   void dispose() { if (--*pn == 0) { delete [] px; delete pn; } }
 | 
			
		||||
 | 
			
		||||
};  // shared_array
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
 | 
			
		||||
    { return a.get() == b.get(); }
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
 | 
			
		||||
    { return a.get() != b.get(); }
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
//  specializations for things in namespace std  -----------------------------//
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
 | 
			
		||||
namespace std {
 | 
			
		||||
 | 
			
		||||
// Specialize std::swap to use the fast, non-throwing swap that's provided
 | 
			
		||||
// as a member function instead of using the default algorithm which creates
 | 
			
		||||
// a temporary and uses assignment.
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b)
 | 
			
		||||
    { a.swap(b); }
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b)
 | 
			
		||||
    { a.swap(b); }
 | 
			
		||||
 | 
			
		||||
// Specialize std::less so we can use shared pointers and arrays as keys in
 | 
			
		||||
// associative collections.
 | 
			
		||||
 | 
			
		||||
// It's still a controversial question whether this is better than supplying
 | 
			
		||||
// a full range of comparison operators (<, >, <=, >=).
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  struct less< boost::shared_ptr<T> >
 | 
			
		||||
    : binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool>
 | 
			
		||||
  {
 | 
			
		||||
    bool operator()(const boost::shared_ptr<T>& a,
 | 
			
		||||
        const boost::shared_ptr<T>& b) const
 | 
			
		||||
      { return less<T*>()(a.get(),b.get()); }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  struct less< boost::shared_array<T> >
 | 
			
		||||
    : binary_function<boost::shared_array<T>, boost::shared_array<T>, bool>
 | 
			
		||||
  {
 | 
			
		||||
    bool operator()(const boost::shared_array<T>& a,
 | 
			
		||||
        const boost::shared_array<T>& b) const
 | 
			
		||||
      { return less<T*>()(a.get(),b.get()); }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
} // namespace std
 | 
			
		||||
 | 
			
		||||
#endif  // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
 | 
			
		||||
#endif  // BOOST_SMART_PTR_HPP
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,192 +0,0 @@
 | 
			
		||||
#ifndef BOOST_WEAK_PTR_HPP_INCLUDED
 | 
			
		||||
#define BOOST_WEAK_PTR_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  weak_ptr.hpp
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2001, 2002, 2003 Peter Dimov
 | 
			
		||||
//
 | 
			
		||||
// Distributed under the Boost Software License, Version 1.0. (See
 | 
			
		||||
// accompanying file LICENSE_1_0.txt or copy at
 | 
			
		||||
// http://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <boost/shared_ptr.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
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
template<class T> class weak_ptr
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // Borland 5.5.1 specific workarounds
 | 
			
		||||
    typedef weak_ptr<T> this_type;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    typedef T element_type;
 | 
			
		||||
 | 
			
		||||
    weak_ptr(): px(0), pn() // never throws in 1.30+
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
//  generated copy constructor, assignment, destructor are fine
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  The "obvious" converting constructor implementation:
 | 
			
		||||
//
 | 
			
		||||
//  template<class Y>
 | 
			
		||||
//  weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
 | 
			
		||||
//  {
 | 
			
		||||
//  }
 | 
			
		||||
//
 | 
			
		||||
//  has a serious problem.
 | 
			
		||||
//
 | 
			
		||||
//  r.px may already have been invalidated. The px(r.px)
 | 
			
		||||
//  conversion may require access to *r.px (virtual inheritance).
 | 
			
		||||
//
 | 
			
		||||
//  It is not possible to avoid spurious access violations since
 | 
			
		||||
//  in multithreaded programs r.px may be invalidated at any point.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
    template<class Y>
 | 
			
		||||
    weak_ptr(weak_ptr<Y> const & r): pn(r.pn) // never throws
 | 
			
		||||
    {
 | 
			
		||||
        px = r.lock().get();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class Y>
 | 
			
		||||
    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>
 | 
			
		||||
    weak_ptr & operator=(weak_ptr<Y> const & r) // never throws
 | 
			
		||||
    {
 | 
			
		||||
        px = r.lock().get();
 | 
			
		||||
        pn = r.pn;
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class Y>
 | 
			
		||||
    weak_ptr & operator=(shared_ptr<Y> const & r) // never throws
 | 
			
		||||
    {
 | 
			
		||||
        px = r.px;
 | 
			
		||||
        pn = r.pn;
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    shared_ptr<T> lock() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
#if defined(BOOST_HAS_THREADS)
 | 
			
		||||
 | 
			
		||||
        // 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
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    long use_count() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return pn.use_count();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool expired() const // never throws
 | 
			
		||||
    {
 | 
			
		||||
        return pn.use_count() == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void reset() // never throws in 1.30+
 | 
			
		||||
    {
 | 
			
		||||
        this_type().swap(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void swap(this_type & other) // never throws
 | 
			
		||||
    {
 | 
			
		||||
        std::swap(px, other.px);
 | 
			
		||||
        pn.swap(other.pn);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void _internal_assign(T * px2, detail::shared_count const & pn2)
 | 
			
		||||
    {
 | 
			
		||||
        px = px2;
 | 
			
		||||
        pn = pn2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class Y> bool _internal_less(weak_ptr<Y> const & rhs) const
 | 
			
		||||
    {
 | 
			
		||||
        return pn < rhs.pn;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
// Tasteless as this may seem, making all members public allows member templates
 | 
			
		||||
// to work in the absence of member template friends. (Matthew Langston)
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    template<class Y> friend class weak_ptr;
 | 
			
		||||
    template<class Y> friend class shared_ptr;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    T * px;                     // contained pointer
 | 
			
		||||
    detail::weak_count pn;      // reference counter
 | 
			
		||||
 | 
			
		||||
};  // weak_ptr
 | 
			
		||||
 | 
			
		||||
template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b)
 | 
			
		||||
{
 | 
			
		||||
    return a._internal_less(b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
    return r.lock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
# pragma warning(pop)
 | 
			
		||||
#endif    
 | 
			
		||||
 | 
			
		||||
#endif  // #ifndef BOOST_WEAK_PTR_HPP_INCLUDED
 | 
			
		||||
							
								
								
									
										39
									
								
								index.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								index.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 | 
			
		||||
<title>Boost Smart Pointer Library</title>
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
</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 header smart_ptr.hpp provides four smart pointer classes.  Smart
 | 
			
		||||
pointers ease the management of memory dynamically allocated with C++ <strong>new</strong>
 | 
			
		||||
expressions.
 | 
			
		||||
<ul>
 | 
			
		||||
  <li><a href="smart_ptr.htm">Documentation</a> (HTML).</li>
 | 
			
		||||
  <li>Header <a href="../../boost/smart_ptr.hpp">smart_ptr.hpp</a></li>
 | 
			
		||||
  <li>Test program <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.</li>
 | 
			
		||||
  <li>Download <a href="../../boost_all.zip">all of Boost</a> (ZIP format).</li>
 | 
			
		||||
  <li>Submitted by <a href="../../people/greg_colvin.htm">Greg Colvin</a> and <a href="../../people/beman_dawes.html">Beman
 | 
			
		||||
    Dawes</a>.</li>
 | 
			
		||||
</ul>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->10 Nov 2000<!--webbot bot="Timestamp" endspan i-checksum="15233" -->
 | 
			
		||||
</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
@@ -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>
 | 
			
		||||
@@ -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<T></STRONG> can be implicitly converted to <STRONG>intrusive_ptr<U></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<T></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<class T> 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 & r);
 | 
			
		||||
      template<class Y> <A href="#constructors" >intrusive_ptr</A>(intrusive_ptr<Y> const & r);
 | 
			
		||||
 | 
			
		||||
      <A href="#destructor" >~intrusive_ptr</A>();
 | 
			
		||||
 | 
			
		||||
      intrusive_ptr & <A href="#assignment" >operator=</A>(intrusive_ptr const & r);
 | 
			
		||||
      template<class Y> intrusive_ptr & <A href="#assignment" >operator=</A>(intrusive_ptr<Y> const & r);
 | 
			
		||||
      template<class Y> intrusive_ptr & <A href="#assignment" >operator=</A>(T * r);
 | 
			
		||||
 | 
			
		||||
      T & <A href="#indirection" >operator*</A>() const; // never throws
 | 
			
		||||
      T * <A href="#indirection" >operator-></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 & b); // never throws
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  template<class T, class U>
 | 
			
		||||
    bool <A href="#comparison" >operator==</A>(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class T, class U>
 | 
			
		||||
    bool <A href="#comparison" >operator!=</A>(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class T>
 | 
			
		||||
    bool <A href="#comparison" >operator==</A>(intrusive_ptr<T> const & a, T * b); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class T>
 | 
			
		||||
    bool <A href="#comparison" >operator!=</A>(intrusive_ptr<T> const & a, T * b); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class T>
 | 
			
		||||
    bool <A href="#comparison" >operator==</A>(T * a, intrusive_ptr<T> const & b); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class T>
 | 
			
		||||
    bool <A href="#comparison" >operator!=</A>(T * a, intrusive_ptr<T> const & b); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class T, class U>
 | 
			
		||||
    bool <A href="#comparison" >operator<</A>(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class T> void <A href="#free-swap" >swap</A>(intrusive_ptr<T> & a, intrusive_ptr<T> & b); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class T> T * <A href="#get_pointer" >get_pointer</A>(intrusive_ptr<T> const & p); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class T, class U>
 | 
			
		||||
    intrusive_ptr<T> <A href="#static_pointer_cast" >static_pointer_cast</A>(intrusive_ptr<U> const & r); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class T, class U>
 | 
			
		||||
    intrusive_ptr<T> <A href="#const_pointer_cast" >const_pointer_cast</A>(intrusive_ptr<U> const & r); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class T, class U>
 | 
			
		||||
    intrusive_ptr<T> <A href="#dynamic_pointer_cast" >dynamic_pointer_cast</A>(intrusive_ptr<U> const & r); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class E, class T, class Y>
 | 
			
		||||
    std::basic_ostream<E, T> & <A href="#insertion-operator" >operator<<</A> (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & 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 && 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 & r); // never throws
 | 
			
		||||
template<class Y> intrusive_ptr(intrusive_ptr<Y> const & 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 & operator=(intrusive_ptr const & r); // never throws
 | 
			
		||||
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r); // never throws
 | 
			
		||||
intrusive_ptr & operator=(T * r);</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 & 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->() 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 && p->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 & 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<class T, class U>
 | 
			
		||||
  bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & 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<class T, class U>
 | 
			
		||||
  bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & 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<class T>
 | 
			
		||||
  bool operator==(intrusive_ptr<T> const & 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<class T>
 | 
			
		||||
  bool operator!=(intrusive_ptr<T> const & 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<class T>
 | 
			
		||||
  bool operator==(T * a, intrusive_ptr<T> const & b); // never throws</pre>
 | 
			
		||||
		<blockquote>
 | 
			
		||||
			<p><b>Returns:</b> <code>a == b.get()</code>.</p>
 | 
			
		||||
			<p><b>Throws:</b> nothing.</p>
 | 
			
		||||
		</blockquote>
 | 
			
		||||
		<pre>template<class T>
 | 
			
		||||
  bool operator!=(T * a, intrusive_ptr<T> const & b); // never throws</pre>
 | 
			
		||||
		<blockquote>
 | 
			
		||||
			<p><b>Returns:</b> <code>a != b.get()</code>.</p>
 | 
			
		||||
			<p><b>Throws:</b> nothing.</p>
 | 
			
		||||
		</blockquote>
 | 
			
		||||
		<pre>template<class T, class U>
 | 
			
		||||
  bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws</pre>
 | 
			
		||||
		<blockquote>
 | 
			
		||||
			<p><b>Returns:</b> <code>std::less<T *>()(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<class T>
 | 
			
		||||
  void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & 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<class T>
 | 
			
		||||
  T * get_pointer(intrusive_ptr<T> const & 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<class T, class U>
 | 
			
		||||
  intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r); // never throws</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<P><B>Returns:</B> <code>intrusive_ptr<T>(static_cast<T*>(r.get()))</code>.</P>
 | 
			
		||||
			<P><B>Throws:</B> nothing.</P>
 | 
			
		||||
		</BLOCKQUOTE>
 | 
			
		||||
		<h3><a name="const_pointer_cast">const_pointer_cast</a></h3>
 | 
			
		||||
		<pre>template<class T, class U>
 | 
			
		||||
  intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r); // never throws</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<P><B>Returns:</B> <code>intrusive_ptr<T>(const_cast<T*>(r.get()))</code>.</P>
 | 
			
		||||
			<P><B>Throws:</B> nothing.</P>
 | 
			
		||||
		</BLOCKQUOTE>
 | 
			
		||||
		<h3><a name="dynamic_pointer_cast">dynamic_pointer_cast</a></h3>
 | 
			
		||||
		<pre>template<class T, class U>
 | 
			
		||||
  intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r);</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<P><B>Returns:</B> <code>intrusive_ptr<T>(dynamic_cast<T*>(r.get()))</code>.</P>
 | 
			
		||||
			<P><B>Throws:</B> nothing.</P>
 | 
			
		||||
		</BLOCKQUOTE>
 | 
			
		||||
		<h3><a name="insertion-operator">operator<<</a></h3>
 | 
			
		||||
		<pre>template<class E, class T, class Y>
 | 
			
		||||
    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p);</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<p><STRONG>Effects:</STRONG> <code>os << 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>
 | 
			
		||||
							
								
								
									
										183
									
								
								scoped_array.htm
									
									
									
									
									
								
							
							
						
						
									
										183
									
								
								scoped_array.htm
									
									
									
									
									
								
							@@ -1,111 +1,90 @@
 | 
			
		||||
<!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<class T> class scoped_array : <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a> {
 | 
			
		||||
<head>
 | 
			
		||||
<title>scoped_array</title>
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      typedef T <a href="#element_type">element_type</a>;
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
      explicit <a href="#ctor">scoped_array</a>(T * p = 0); // never throws
 | 
			
		||||
      <a href="#destructor">~scoped_array</a>(); // never throws
 | 
			
		||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
 | 
			
		||||
<a name="scoped_array">scoped_array</a></h1>
 | 
			
		||||
<p>Class <strong>scoped_array</strong> stores a pointer to a dynamically
 | 
			
		||||
allocated array. (Dynamically allocated arrays are allocated with the C++ <tt>new[]</tt>
 | 
			
		||||
expression.)   The array pointed to is guaranteed to be deleted,
 | 
			
		||||
either on destruction of the <strong>scoped_array</strong>, or via an explicit <strong>scoped_array::reset()</strong>.</p>
 | 
			
		||||
<p>Class<strong> scoped_array</strong> is a simple solution for simple
 | 
			
		||||
needs.  It cannot be used in C++ Standard Library containers.  See <a href="shared_array.htm"><strong>shared_array</strong></a>
 | 
			
		||||
if <strong>scoped_array</strong> does not meet your needs.</p>
 | 
			
		||||
<p>Class<strong> scoped_array</strong> cannot correctly hold a pointer to a
 | 
			
		||||
single object.  See <a href="scoped_ptr.htm"><strong>scoped_ptr</strong></a>
 | 
			
		||||
for that usage.</p>
 | 
			
		||||
<p>Because <strong>scoped_array</strong> is so simple, in its usual
 | 
			
		||||
implementation every operation is as fast as a built-in array pointer and has no
 | 
			
		||||
more space overhead that a built-in array pointer.</p>
 | 
			
		||||
<p>A heavier duty alternative to a <strong>scoped_array</strong> is a <strong>scoped_ptr</strong>
 | 
			
		||||
to a C++ Standard Library <strong>vector</strong>.</p>
 | 
			
		||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
 | 
			
		||||
pointed to.   <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common
 | 
			
		||||
requirements</a>.</p>
 | 
			
		||||
<h2>Class scoped_array Synopsis</h2>
 | 
			
		||||
<pre>#include <boost/smart_ptr.hpp>
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
      void <a href="#reset">reset</a>(T * p = 0); // never throws
 | 
			
		||||
template<typename T> class scoped_array : <a href="../utility/utility.htm#noncopyable">noncopyable</a> {
 | 
			
		||||
 | 
			
		||||
      T & <a href="#operator[]">operator[]</a>(std::ptrdiff_t i) const; // never throws
 | 
			
		||||
      T * <a href="#get">get</a>() const; // never throws
 | 
			
		||||
     
 | 
			
		||||
      void <a href="#swap">swap</a>(scoped_array & b); // never throws
 | 
			
		||||
  };
 | 
			
		||||
 public:
 | 
			
		||||
   typedef T <a href="#scoped_array_element_type">element_type</a>;
 | 
			
		||||
 | 
			
		||||
  template<class T> void <a href="#free-swap">swap</a>(scoped_array<T> & a, scoped_array<T> & b); // never throws
 | 
			
		||||
   explicit <a href="#scoped_array_ctor">scoped_array</a>( T* p=0 );  // never throws
 | 
			
		||||
  <strong> </strong><a href="#scoped_array_~scoped_array">~scoped_array</a>();
 | 
			
		||||
 | 
			
		||||
   void <a href="#scoped_array_reset">reset</a>( T* p=0 );
 | 
			
		||||
 | 
			
		||||
   T& <a href="#scoped_array_operator[]">operator[]</a>(std::size_t i) const;  // never throws
 | 
			
		||||
   T* <a href="#scoped_array_get">get</a>() const;  // 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 & 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 & 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<class T> void swap(scoped_array<T> & a, scoped_array<T> & 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>Class scoped_array Members</h2>
 | 
			
		||||
<h3>scoped_array <a name="scoped_array_element_type">element_type</a></h3>
 | 
			
		||||
<pre>typedef T element_type;</pre>
 | 
			
		||||
<p>Provides the type of the stored pointer.</p>
 | 
			
		||||
<h3><a name="scoped_array_ctor">scoped_array constructors</a></h3>
 | 
			
		||||
<pre>explicit scoped_array( T* p=0 );  // never throws</pre>
 | 
			
		||||
<p>Constructs a <tt>scoped_array</tt>, storing a copy of <tt>p</tt>, which must
 | 
			
		||||
have been allocated via a C++ <tt>new</tt>[] expression or be 0.</p>
 | 
			
		||||
<h3><a name="scoped_array_~scoped_array">scoped_array destructor</a></h3>
 | 
			
		||||
<pre>~scoped_array();</pre>
 | 
			
		||||
<p>Deletes the array pointed to by the stored pointer.  Note that in C++ <tt>delete</tt>[]
 | 
			
		||||
on a pointer with a value of 0 is harmless.</p>
 | 
			
		||||
<p>Does not throw exceptions.</p>
 | 
			
		||||
<h3>scoped_array <a name="scoped_array_reset">reset</a></h3>
 | 
			
		||||
<pre>void reset( T* p=0 )();</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++ <tt>new[]</tt> expression or be 0.</p>
 | 
			
		||||
<p>Does not throw exceptions.</p>
 | 
			
		||||
<h3>scoped_array <a name="scoped_array_operator[]">operator[]</a></h3>
 | 
			
		||||
<p><tt>T& operator[](std::size_t i) const; // never throws</tt></p>
 | 
			
		||||
<p>Returns a reference to element <tt>i</tt> of the array pointed to by the
 | 
			
		||||
stored pointer.</p>
 | 
			
		||||
<p>Behavior is undefined (and almost certainly undesirable) if <tt>get()==0</tt>,
 | 
			
		||||
or if <tt>i</tt> is less than 0 or is greater or equal to the number of elements
 | 
			
		||||
in the array.</p>
 | 
			
		||||
<h3>scoped_array <a name="scoped_array_get">get</a></h3>
 | 
			
		||||
<pre>T* get() const;  // never throws</pre>
 | 
			
		||||
<p>Returns the stored pointer.</p>
 | 
			
		||||
<h2>Class <a name="shared_array_example">scoped_array example</a></h2>
 | 
			
		||||
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised  December 8, 1999</p>
 | 
			
		||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
without express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
any purpose.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										260
									
								
								scoped_ptr.htm
									
									
									
									
									
								
							
							
						
						
									
										260
									
								
								scoped_ptr.htm
									
									
									
									
									
								
							@@ -1,176 +1,128 @@
 | 
			
		||||
<!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<class T> class scoped_ptr : <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a> {
 | 
			
		||||
<head>
 | 
			
		||||
<title>scoped_ptr</title>
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
   public:
 | 
			
		||||
     typedef T <a href="#element_type">element_type</a>;
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
     explicit <a href="#constructors">scoped_ptr</a>(T * p = 0); // never throws
 | 
			
		||||
     <a href="#destructor">~scoped_ptr</a>(); // never throws
 | 
			
		||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
 | 
			
		||||
<a name="scoped_ptr">scoped_ptr</a></h1>
 | 
			
		||||
<p>Class <strong>scoped_ptr</strong> stores a pointer to a dynamically allocated
 | 
			
		||||
object. (Dynamically allocated objects are allocated with the C++ <tt>new</tt>
 | 
			
		||||
expression.)   The object pointed to is guaranteed to be deleted,
 | 
			
		||||
either on destruction of the <strong>scoped_ptr</strong>, or via an explicit <strong>scoped_ptr::reset()</strong>. 
 | 
			
		||||
See <a href="#scoped_ptr_example">example</a>.</p>
 | 
			
		||||
<p>Class<strong> scoped_ptr</strong> is a simple solution for simple
 | 
			
		||||
needs.  It cannot be used in C++ Standard Library containers.  See <a href="shared_ptr.htm"><strong>shared_ptr</strong></a>
 | 
			
		||||
or std::auto_ptr if <strong>scoped_ptr</strong> does not meet your needs.</p>
 | 
			
		||||
<p>Class<strong> scoped_ptr</strong> cannot correctly hold a pointer to a
 | 
			
		||||
dynamically allocated array.  See <a href="scoped_array.htm"><strong>scoped_array</strong></a>
 | 
			
		||||
for that usage.</p>
 | 
			
		||||
<p>Because <strong>scoped_ptr</strong> is so simple, in its usual implementation
 | 
			
		||||
every operation is as fast as a built-in pointer and has no more space overhead
 | 
			
		||||
that a built-in pointer.</p>
 | 
			
		||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
 | 
			
		||||
pointed to.   <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common
 | 
			
		||||
requirements</a>.</p>
 | 
			
		||||
<h2>Class scoped_ptr Synopsis</h2>
 | 
			
		||||
<pre>#include <boost/smart_ptr.hpp>
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
     void <a href="#reset">reset</a>(T * p = 0); // never throws
 | 
			
		||||
template<typename T> class scoped_ptr : <a href="../utility/utility.htm#class noncopyable">noncopyable</a> {
 | 
			
		||||
 | 
			
		||||
     T & <a href="#indirection">operator*</a>() const; // never throws
 | 
			
		||||
     T * <a href="#indirection">operator-></a>() const; // never throws
 | 
			
		||||
     T * <a href="#get">get</a>() const; // never throws
 | 
			
		||||
     
 | 
			
		||||
     void <a href="#swap">swap</a>(scoped_ptr & b); // never throws
 | 
			
		||||
  };
 | 
			
		||||
 public:
 | 
			
		||||
   typedef T <a href="#scoped_ptr_element_type">element_type</a>;
 | 
			
		||||
 | 
			
		||||
  template<class T> void <a href="#free-swap">swap</a>(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
 | 
			
		||||
   explicit <a href="#scoped_ptr_ctor">scoped_ptr</a>( T* p=0 );  // never throws
 | 
			
		||||
  <strong> </strong><a href="#scoped_ptr_~scoped_ptr">~scoped_ptr</a>();
 | 
			
		||||
 | 
			
		||||
   void <a href="#scoped_ptr_reset">reset</a>( T* p=0 );
 | 
			
		||||
 | 
			
		||||
   T& <a href="#scoped_ptr_operator*">operator*</a>() const;  // never throws
 | 
			
		||||
   T* <a href="#scoped_ptr_operator->">operator-></a>() const;  // never throws
 | 
			
		||||
   T* <a href="#scoped_ptr_get">get</a>() const;  // 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->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 & 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->() 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 & 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<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & 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 <boost/scoped_ptr.hpp>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
<h2>Class scoped_ptr Members</h2>
 | 
			
		||||
<h3>scoped_ptr <a name="scoped_ptr_element_type">element_type</a></h3>
 | 
			
		||||
<pre>typedef T element_type;</pre>
 | 
			
		||||
<p>Provides the type of the stored pointer.</p>
 | 
			
		||||
<h3><a name="scoped_ptr_ctor">scoped_ptr constructors</a></h3>
 | 
			
		||||
<pre>explicit scoped_ptr( T* p=0 );  // never throws</pre>
 | 
			
		||||
<p>Constructs a <tt>scoped_ptr</tt>, storing a copy of <tt>p</tt>, which must
 | 
			
		||||
have been allocated via a C++ <tt>new</tt> expression or be 0..</p>
 | 
			
		||||
<h3><a name="scoped_ptr_~scoped_ptr">scoped_ptr destructor</a></h3>
 | 
			
		||||
<pre>~scoped_ptr();</pre>
 | 
			
		||||
<p>Deletes the object pointed to by the stored pointer.  Note that in C++, <tt>delete</tt>
 | 
			
		||||
on a pointer with a value of 0 is harmless.</p>
 | 
			
		||||
<p>Does not throw exceptions.</p>
 | 
			
		||||
<h3>scoped_ptr <a name="scoped_ptr_reset">reset</a></h3>
 | 
			
		||||
<pre>void reset( T* p=0 );</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++ <tt>new</tt> expression or be 0.</p>
 | 
			
		||||
<p>Does not throw exceptions.</p>
 | 
			
		||||
<h3>scoped_ptr <a name="scoped_ptr_operator*">operator*</a></h3>
 | 
			
		||||
<pre>T& operator*() const;  // never throws</pre>
 | 
			
		||||
<p>Returns a reference to the object pointed to by the stored pointer.</p>
 | 
			
		||||
<h3>scoped_ptr <a name="scoped_ptr_operator->">operator-></a> and <a name="scoped_ptr_get">get</a></h3>
 | 
			
		||||
<pre>T* operator->() const;  // never throws
 | 
			
		||||
T* get() const;  // never throws</pre>
 | 
			
		||||
<p>Both return the stored pointer.</p>
 | 
			
		||||
<h2>Class <a name="scoped_ptr_example">scoped_ptr example</a>s</h2>
 | 
			
		||||
<pre>#include <iostream>
 | 
			
		||||
#include <boost/smart_ptr.h>
 | 
			
		||||
 | 
			
		||||
struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } };
 | 
			
		||||
struct Shoe { ~Shoe(){ std::cout << "Buckle my shoe" << std::endl; } };
 | 
			
		||||
 | 
			
		||||
class MyClass {
 | 
			
		||||
    boost::scoped_ptr<int> ptr;
 | 
			
		||||
  public:
 | 
			
		||||
    MyClass() : ptr(new int) { *ptr = 0; }
 | 
			
		||||
    int add_one() { return ++*ptr; }
 | 
			
		||||
};
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
void main() {
 | 
			
		||||
    boost::scoped_ptr<Shoe> x(new Shoe);
 | 
			
		||||
    MyClass my_instance;
 | 
			
		||||
    std::cout << my_instance.add_one() << '\n';
 | 
			
		||||
    std::cout << my_instance.add_one() << '\n';
 | 
			
		||||
}</pre>
 | 
			
		||||
		</blockquote>
 | 
			
		||||
		<p>The example program produces the beginning of a child's nursery rhyme:</p>
 | 
			
		||||
		<blockquote>
 | 
			
		||||
			<pre>1
 | 
			
		||||
    std::cout << my_instance.add_one() << std::endl;
 | 
			
		||||
    std::cout << my_instance.add_one() << std::endl;
 | 
			
		||||
    }</pre>
 | 
			
		||||
<p>The example program produces the beginning of a child's nursery rhyme as
 | 
			
		||||
output:</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<T></b> is equivalent to <b>std::auto_ptr<T> 
 | 
			
		||||
				const</b>. Ed Brey pointed out, however, that <b>reset</b> will not work on 
 | 
			
		||||
			a <b>std::auto_ptr<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="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<></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>Handle/Body Idiom</h2>
 | 
			
		||||
<p>One common usage of <b>shared_pointer</b> is to implement a handle/body
 | 
			
		||||
structure which avoids exposing the body (implementation) in the header file:</p>
 | 
			
		||||
<pre>class handle
 | 
			
		||||
{
 | 
			
		||||
public:    // simple forwarding functions to the body class
 | 
			
		||||
    void f();
 | 
			
		||||
    void g(int);
 | 
			
		||||
private:
 | 
			
		||||
    friend class body;  //incomplete class hides implementation
 | 
			
		||||
    boost::scoped_ptr<body> imp;
 | 
			
		||||
};</pre>
 | 
			
		||||
<p>This code requires that <code>class body</code> have a trivial destructor to
 | 
			
		||||
avoid undefined behavior.  This is because the definition of <code>class
 | 
			
		||||
body</code> is not visible at the time scoped_ptr<> deletes it. See ISO
 | 
			
		||||
5.3.5/5.  Note that some compilers will issue a warning even though the
 | 
			
		||||
above code is well defined.</p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->24 July 2000<!--webbot bot="Timestamp" endspan i-checksum="18764" --></p>
 | 
			
		||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
without express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
any purpose.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										330
									
								
								shared_array.htm
									
									
									
									
									
								
							
							
						
						
									
										330
									
								
								shared_array.htm
									
									
									
									
									
								
							@@ -1,180 +1,180 @@
 | 
			
		||||
<!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<class T> class shared_array {
 | 
			
		||||
<head>
 | 
			
		||||
<title>shared_array</title>
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      typedef T <a href="#element_type">element_type</a>;
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
      explicit <a href="#constructors">shared_array</a>(T * p = 0);
 | 
			
		||||
      template<class D> <a href="#constructors">shared_array</a>(T * p, D d);
 | 
			
		||||
      <a href="#destructor">~shared_array</a>(); // never throws
 | 
			
		||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
 | 
			
		||||
<a name="shared_array">shared_array</a></h1>
 | 
			
		||||
<p>Class <strong>shared_array</strong> stores a pointer to a dynamically
 | 
			
		||||
allocated array. (Dynamically allocated arrays are allocated with the C++ <tt>new[]</tt>
 | 
			
		||||
expression.)   The array pointed to is guaranteed to be deleted,
 | 
			
		||||
either on destruction of the <strong>shared_array</strong>, on <strong>shared_array::operator=()</strong>,
 | 
			
		||||
or via an explicit <strong>shared_array::reset()</strong>.  See <a href="#shared_array_example">example</a>.</p>
 | 
			
		||||
<p>Class<strong> shared_array</strong> meets the <strong>CopyConstuctible</strong>
 | 
			
		||||
and <strong>Assignable</strong> requirements of the C++ Standard Library, and so
 | 
			
		||||
can be used in C++ Standard Library containers.  A specialization of std::
 | 
			
		||||
less< > for  boost::shared_ptr<Y> is supplied so that <strong>
 | 
			
		||||
shared_array</strong> works by default for Standard Library's Associative
 | 
			
		||||
Container Compare template parameter.  For compilers not supporting partial
 | 
			
		||||
specialization, the user must explicitly pass the less<> functor.</p>
 | 
			
		||||
<p>Class<strong> shared_array</strong> cannot correctly hold a pointer to a
 | 
			
		||||
single object.  See <a href="shared_ptr.htm"><strong>shared_ptr</strong></a>
 | 
			
		||||
for that usage.</p>
 | 
			
		||||
<p>Class<strong> shared_array</strong> will not work correctly with cyclic data
 | 
			
		||||
structures. For example, if main() holds a shared_array pointing to array A,
 | 
			
		||||
which directly or indirectly holds a shared_array pointing back to array A, then
 | 
			
		||||
array A's use_count() will be 2, and destruction of the main() shared_array will
 | 
			
		||||
leave array A dangling with a use_count() of 1.</p>
 | 
			
		||||
<p>A heavier duty alternative to a <strong>shared_array</strong> is a <strong>shared_ptr</strong>
 | 
			
		||||
to a C++ Standard Library <strong>vector</strong>.</p>
 | 
			
		||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
 | 
			
		||||
pointed to.   <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
 | 
			
		||||
requirements</a>.</p>
 | 
			
		||||
<h2>Class shared_array Synopsis</h2>
 | 
			
		||||
<pre>#include <boost/smart_ptr.hpp>
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
      <a href="#constructors">shared_array</a>(shared_array const & r); // never throws
 | 
			
		||||
template<typename T> class shared_array {
 | 
			
		||||
 | 
			
		||||
      shared_array & <a href="#assignment">operator=</a>(shared_array const & r); // never throws
 | 
			
		||||
 public:
 | 
			
		||||
   typedef T <a href="#shared_array_element_type">element_type</a>;
 | 
			
		||||
 | 
			
		||||
      void <a href="#reset">reset</a>(T * p = 0);
 | 
			
		||||
      template<class D> void <a href="#reset">reset</a>(T * p, D d);
 | 
			
		||||
   explicit <a href="#shared_array_ctor">shared_array</a>( T* p=0 );
 | 
			
		||||
   <a href="#shared_array_ctor">shared_array</a>( const shared_array& );  // never throws   
 | 
			
		||||
  <strong> </strong><a href="#shared_array_~shared_array">~shared_array</a>();
 | 
			
		||||
 | 
			
		||||
      T & <a href="#indexing">operator[]</a>(std::ptrdiff_t i) const() const; // never throws
 | 
			
		||||
      T * <a href="#get">get</a>() const; // never throws
 | 
			
		||||
   shared_array& <a href="#shared_array_operator=">operator=</a>( const shared_array& );  // never throws  
 | 
			
		||||
 | 
			
		||||
      bool <a href="#unique">unique</a>() const; // never throws
 | 
			
		||||
      long <a href="#use_count">use_count</a>() const; // never throws
 | 
			
		||||
   void <a href="#shared_array_reset">reset</a>( T* p=0 );
 | 
			
		||||
 | 
			
		||||
      void <a href="#swap">swap</a>(shared_array<T> & b); // never throws
 | 
			
		||||
   T& <a href="#shared_array_operator[]">operator[]</a>(std::size_t i) const;  // never throws
 | 
			
		||||
   T* <a href="#shared_array_get">get</a>() const;  // never throws
 | 
			
		||||
 | 
			
		||||
   long <a href="#shared_array_use_count">use_count</a>() const;  // never throws
 | 
			
		||||
   bool <a href="#shared_array_unique">unique</a>() const;  // never throws
 | 
			
		||||
 | 
			
		||||
   void <a href="#shared_array_swap">swap</a>( shared_array<T>& other ) throw()
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
 | 
			
		||||
    { return a.get() == b.get(); }
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
 | 
			
		||||
    { return a.get() != b.get(); }
 | 
			
		||||
}</pre>
 | 
			
		||||
<pre>namespace std {
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b)
 | 
			
		||||
    { a.swap(b); }
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  struct less< boost::shared_array<T> >
 | 
			
		||||
    : binary_function<boost::shared_array<T>, boost::shared_array<T>, bool>
 | 
			
		||||
  {
 | 
			
		||||
    bool operator()(const boost::shared_array<T>& a,
 | 
			
		||||
        const boost::shared_array<T>& b) const
 | 
			
		||||
      { return less<T*>()(a.get(),b.get()); }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  template<class T>
 | 
			
		||||
    bool <a href="#comparison">operator==</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
 | 
			
		||||
  template<class T>
 | 
			
		||||
    bool <a href="#comparison">operator!=</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
 | 
			
		||||
  template<class T>
 | 
			
		||||
    bool <a href="#comparison">operator<</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
 | 
			
		||||
} // namespace std </pre>
 | 
			
		||||
<p>Specialization of std::swap uses the fast, non-throwing swap that's provided
 | 
			
		||||
as a member function instead of using the default algorithm which creates a
 | 
			
		||||
temporary and uses assignment.<br>
 | 
			
		||||
<br>
 | 
			
		||||
Specialization of std::less allows use of shared arrays as keys in C++
 | 
			
		||||
Standard Library associative collections.<br>
 | 
			
		||||
<br>
 | 
			
		||||
The std::less specializations use std::less<T*> to perform the
 | 
			
		||||
comparison.  This insures that pointers are handled correctly, since the
 | 
			
		||||
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel]
 | 
			
		||||
paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons]
 | 
			
		||||
paragraph 8).<br>
 | 
			
		||||
<br>
 | 
			
		||||
It's still a controversial question whether supplying only std::less is better
 | 
			
		||||
than supplying a full range of comparison operators (<, >, <=, >=).</p>
 | 
			
		||||
<p>The current implementation does not supply the specializations if the macro
 | 
			
		||||
name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.</p>
 | 
			
		||||
<h2>Class shared_array Members</h2>
 | 
			
		||||
<h3>shared_array <a name="shared_array_element_type">element_type</a></h3>
 | 
			
		||||
<pre>typedef T element_type;</pre>
 | 
			
		||||
<p>Provides the type of the stored pointer.</p>
 | 
			
		||||
<h3><a name="shared_array_ctor">shared_array constructors</a></h3>
 | 
			
		||||
<pre>explicit shared_array( T* p=0 );</pre>
 | 
			
		||||
<p>Constructs a <strong>shared_array</strong>, storing a copy of <tt>p</tt>,
 | 
			
		||||
which must have been allocated via a C++ <tt>new</tt>[] expression or be 0.
 | 
			
		||||
Afterwards, use_count() is 1 (even if p==0; see <a href="#shared_array_~shared_array">~shared_array</a>).</p>
 | 
			
		||||
<p>The only exception which may be thrown is <tt>std::bad_alloc</tt>.  If
 | 
			
		||||
an exception is thrown,  <tt>delete[] p</tt> is called.</p>
 | 
			
		||||
<pre>shared_array( const shared_array& r);  // never throws</pre>
 | 
			
		||||
<p>Constructs a <strong>shared_array</strong>, as if by storing a copy of the
 | 
			
		||||
pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
 | 
			
		||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>.</p>
 | 
			
		||||
<h3><a name="shared_array_~shared_array">shared_array destructor</a></h3>
 | 
			
		||||
<pre>~shared_array();</pre>
 | 
			
		||||
<p>If <strong>use_count()</strong> == 1, deletes the array pointed to by the
 | 
			
		||||
stored pointer. Otherwise, <strong>use_count()</strong> for any remaining
 | 
			
		||||
copies is decremented by 1. Note that in C++ <tt>delete</tt>[] on a pointer with
 | 
			
		||||
a value of 0 is harmless.</p>
 | 
			
		||||
<p>Does not throw exceptions.</p>
 | 
			
		||||
<h3>shared_array <a name="shared_array_operator=">operator=</a></h3>
 | 
			
		||||
<pre>shared_array& operator=( const shared_array& r);  // never throws</pre>
 | 
			
		||||
<p>First, if <strong>use_count()</strong> == 1, deletes the array pointed to by
 | 
			
		||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
 | 
			
		||||
remaining copies is decremented by 1. Note that in C++ <tt>delete</tt>[] on a
 | 
			
		||||
pointer with a value of 0 is harmless.</p>
 | 
			
		||||
<p>Then replaces the contents of <strong>this</strong>, as if by storing a copy
 | 
			
		||||
of the pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
 | 
			
		||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>. </p>
 | 
			
		||||
<h3>shared_array <a name="shared_array_reset">reset</a></h3>
 | 
			
		||||
<pre>void reset( T* p=0 );</pre>
 | 
			
		||||
<p>First, if <strong>use_count()</strong> == 1, deletes the array pointed to by
 | 
			
		||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
 | 
			
		||||
remaining copies is decremented by 1. Note that in C++  <tt>delete</tt>[]
 | 
			
		||||
on a pointer with a value of 0 is harmless.</p>
 | 
			
		||||
<p>Then replaces the contents of <strong>this</strong>, as if by storing a copy
 | 
			
		||||
of <strong>p</strong>, which must have been allocated via a C++ <tt>new</tt>[]
 | 
			
		||||
expression or be 0. Afterwards, <strong>use_count()</strong> is 1 (even if p==0;
 | 
			
		||||
see <a href="#shared_array_~shared_array">~shared_array</a>).</p>
 | 
			
		||||
<p>The only exception which may be thrown is <tt>std::bad_alloc</tt>.  If
 | 
			
		||||
an exception is thrown,  <tt>delete[] p</tt> is called.</p>
 | 
			
		||||
<h3>shared_array <a name="shared_array_operator[]">operator[]</a></h3>
 | 
			
		||||
<p><tt>T& operator[](std::size_t i) const; // never throws</tt></p>
 | 
			
		||||
<p>Returns a reference to element <tt>i</tt> of the array pointed to by the
 | 
			
		||||
stored pointer.</p>
 | 
			
		||||
<p>Behavior is undefined (and almost certainly undesirable) if <tt>get()==0</tt>,
 | 
			
		||||
or if <tt>i</tt> is less than 0 or is greater or equal to the number of elements
 | 
			
		||||
in the array.</p>
 | 
			
		||||
<h3>shared_array <a name="shared_array_get">get</a></h3>
 | 
			
		||||
<pre>T* get() const;  // never throws</pre>
 | 
			
		||||
<p>Returns the stored pointer.</p>
 | 
			
		||||
<h3>shared_array<a name="shared_array_use_count"> use_count</a></h3>
 | 
			
		||||
<p><tt>long use_count() const; // never throws</tt></p>
 | 
			
		||||
<p>Returns the number of <strong>shared_arrays</strong> sharing ownership of the
 | 
			
		||||
stored pointer.</p>
 | 
			
		||||
<h3>shared_array <a name="shared_array_unique">unique</a></h3>
 | 
			
		||||
<p><tt>bool unique() const; // never throws</tt></p>
 | 
			
		||||
<p>Returns <strong>use_count()</strong> == 1.</p>
 | 
			
		||||
<h3><a name="shared_array_swap">shared_array swap</a></h3>
 | 
			
		||||
<p><code>void swap( shared_array<T>& other ) throw()</code></p>
 | 
			
		||||
<p>Swaps the two smart pointers, as if by std::swap.</p>
 | 
			
		||||
<h2>Class <a name="shared_array_example">shared_array example</a></h2>
 | 
			
		||||
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised December 8, 1999</p>
 | 
			
		||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
without express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
any purpose.</p>
 | 
			
		||||
 | 
			
		||||
  template<class T> void <a href="#free-swap">swap</a>(shared_array<T> & a, shared_array<T> & b); // never throws
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
}</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<class D> 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 & 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 & operator=(shared_array const & 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<class D> 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 & 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 & 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<class T>
 | 
			
		||||
  bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws
 | 
			
		||||
template<class T>
 | 
			
		||||
  bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws
 | 
			
		||||
template<class T>
 | 
			
		||||
  bool operator<(shared_array<T> const & a, shared_array<T> const & 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<</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<T *></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<></b> on pointers is well-defined (20.3.3 
 | 
			
		||||
			[lib.comparisons] paragraph 8).</p>
 | 
			
		||||
		<h3><a name="free-swap">swap</a></h3>
 | 
			
		||||
		<pre>template<class T>
 | 
			
		||||
  void swap(shared_array<T> & a, shared_array<T> & 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>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										872
									
								
								shared_ptr.htm
									
									
									
									
									
								
							
							
						
						
									
										872
									
								
								shared_ptr.htm
									
									
									
									
									
								
							@@ -1,693 +1,231 @@
 | 
			
		||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 | 
			
		||||
<html>
 | 
			
		||||
	<head>
 | 
			
		||||
		<title>shared_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">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>
 | 
			
		||||
		<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>
 | 
			
		||||
		<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> 
 | 
			
		||||
			works with the standard library's associative containers.</p>
 | 
			
		||||
		<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>
 | 
			
		||||
			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 
 | 
			
		||||
			requirements on <STRONG>T</STRONG>; it is allowed to be an incomplete type, or <STRONG>
 | 
			
		||||
				void</STRONG>. Member functions that do place additional requirements (<A href="#constructors">constructors</A>,
 | 
			
		||||
			<A href="#reset">reset</A>) are explicitly documented below.</p>
 | 
			
		||||
		<P><STRONG>shared_ptr<T></STRONG> can be implicitly converted to <STRONG>shared_ptr<U></STRONG>
 | 
			
		||||
			whenever <STRONG>T*</STRONG> can be implicitly converted to <STRONG>U*</STRONG>. 
 | 
			
		||||
			In particular, <STRONG>shared_ptr<T></STRONG> is implicitly convertible 
 | 
			
		||||
			to <STRONG>shared_ptr<T const></STRONG>, to <STRONG>shared_ptr<U></STRONG>
 | 
			
		||||
			where <STRONG>U</STRONG> is an accessible base of <STRONG>T</STRONG>, and to <STRONG>
 | 
			
		||||
				shared_ptr<void></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<T> 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<int>, int);
 | 
			
		||||
int g();
 | 
			
		||||
 | 
			
		||||
void ok()
 | 
			
		||||
{
 | 
			
		||||
    shared_ptr<int> p(new int(2));
 | 
			
		||||
    f(p, g());
 | 
			
		||||
}
 | 
			
		||||
<head>
 | 
			
		||||
<title>shared_ptr</title>
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
void bad()
 | 
			
		||||
{
 | 
			
		||||
    f(shared_ptr<int>(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 {
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
  class bad_weak_ptr: public std::exception;
 | 
			
		||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
 | 
			
		||||
<a name="shared_ptr">shared_ptr</a></h1>
 | 
			
		||||
<p>Class <strong>shared_ptr</strong> stores a pointer to a dynamically allocated
 | 
			
		||||
object. (Dynamically allocated objects are allocated with the C++ <tt>new</tt>
 | 
			
		||||
expression.)   The object pointed to is guaranteed to be deleted when
 | 
			
		||||
the last <strong>shared_ptr</strong> pointing to it is deleted or reset. 
 | 
			
		||||
See <a href="#shared_ptr_example">example</a>.</p>
 | 
			
		||||
<p>Class<strong> shared_ptr</strong> meets the <strong>CopyConstuctible</strong>
 | 
			
		||||
and <strong>Assignable</strong> requirements of the C++ Standard Library, and so
 | 
			
		||||
can be used in C++ Standard Library containers.  A specialization of std::
 | 
			
		||||
less< > for  boost::shared_ptr<Y> is supplied so that <strong>
 | 
			
		||||
shared_ptr</strong> works by default for Standard Library's Associative
 | 
			
		||||
Container Compare template parameter.  For compilers not supporting partial
 | 
			
		||||
specialization, the user must explicitly pass the less<> functor.</p>
 | 
			
		||||
<p>Class<strong> shared_ptr</strong> cannot correctly hold a pointer to a
 | 
			
		||||
dynamically allocated array.  See <a href="shared_array.htm"><strong>shared_array</strong></a>
 | 
			
		||||
for that usage.</p>
 | 
			
		||||
<p>Class<strong> shared_ptr</strong> will not work correctly with cyclic data
 | 
			
		||||
structures. For example, if main() holds a shared_ptr to object A, which
 | 
			
		||||
directly or indirectly holds a shared_ptr back to object A, then object A's
 | 
			
		||||
use_count() will be 2, and destruction of the main() shared_ptr will leave
 | 
			
		||||
object A dangling with a use_count() of 1.</p>
 | 
			
		||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
 | 
			
		||||
pointed to.   <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
 | 
			
		||||
requirements</a>.</p>
 | 
			
		||||
<h2>Class shared_ptr Synopsis</h2>
 | 
			
		||||
<pre>#include <boost/smart_ptr.hpp>
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
  template<class T> class <A href="weak_ptr.htm" >weak_ptr</A>;
 | 
			
		||||
template<typename T> class shared_ptr {
 | 
			
		||||
 | 
			
		||||
  template<class T> class shared_ptr {
 | 
			
		||||
 public:
 | 
			
		||||
   typedef T <a href="#shared_ptr_element_type">element_type</a>;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
   explicit <a href="#shared_ptr_ctor">shared_ptr</a>( T* p=0 );
 | 
			
		||||
  <strong> </strong><a href="#shared_ptr_~shared_ptr">~shared_ptr</a>();
 | 
			
		||||
 | 
			
		||||
      typedef T <A href="#element_type" >element_type</A>;
 | 
			
		||||
   <a href="#shared_ptr_ctor">shared_ptr</a>( const shared_ptr& );   
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      <a href="#shared_ptr_ctor">shared_ptr</a>(const shared_ptr<Y>& r);  // never throws
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      <a href="#shared_ptr_ctor">shared_ptr</a>(std::auto_ptr<Y>& r);
 | 
			
		||||
 | 
			
		||||
      <A href="#constructors" >shared_ptr</A>(); // never throws
 | 
			
		||||
      template<class Y> explicit <A href="#constructors" >shared_ptr</A>(Y * p);
 | 
			
		||||
      template<class Y, class D> <A href="#constructors" >shared_ptr</A>(Y * p, D d);
 | 
			
		||||
      <A href="#destructor" >~shared_ptr</A>(); // never throws
 | 
			
		||||
   shared_ptr& <a href="#shared_ptr_operator=">operator=</a>( const shared_ptr& );  // never throws  
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      shared_ptr& <a href="#shared_ptr_operator=">operator=</a>(const shared_ptr<Y>& r);  // never throws
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      shared_ptr& <a href="#shared_ptr_operator=">operator=</a>(std::auto_ptr<Y>& r);
 | 
			
		||||
 | 
			
		||||
      <A href="#constructors" >shared_ptr</A>(shared_ptr const & r); // never throws
 | 
			
		||||
      template<class Y> <A href="#constructors" >shared_ptr</A>(shared_ptr<Y> const & r); // never throws
 | 
			
		||||
      template<class Y> explicit <A href="#constructors" >shared_ptr</A>(<A href="weak_ptr.htm" >weak_ptr</A><Y> const & r);
 | 
			
		||||
      template<class Y> explicit <A href="#constructors" >shared_ptr</A>(std::auto_ptr<Y> & r);
 | 
			
		||||
   void <a href="#shared_ptr_reset">reset</a>( T* p=0 );
 | 
			
		||||
 | 
			
		||||
      shared_ptr & <A href="#assignment" >operator=</A>(shared_ptr const & r); // never throws  
 | 
			
		||||
      template<class Y> shared_ptr & <A href="#assignment" >operator=</A>(shared_ptr<Y> const & r); // never throws
 | 
			
		||||
      template<class Y> shared_ptr & <A href="#assignment" >operator=</A>(std::auto_ptr<Y> & r);
 | 
			
		||||
   T& <a href="#shared_ptr_operator*">operator*</a>() const;  // never throws
 | 
			
		||||
   T* <a href="#shared_ptr_operator->">operator-></a>() const;  // never throws
 | 
			
		||||
   T* <a href="#shared_ptr_get">get</a>() const;  // never throws
 | 
			
		||||
 | 
			
		||||
      void <A href="#reset" >reset</A>(); // never throws
 | 
			
		||||
      template<class Y> void <A href="#reset" >reset</A>(Y * p);
 | 
			
		||||
      template<class Y, class D> void <A href="#reset" >reset</A>(Y * p, D d);
 | 
			
		||||
   long <a href="#shared_ptr_use_count">use_count</a>() const;  // never throws
 | 
			
		||||
   bool <a href="#shared_ptr_unique">unique</a>() const;  // never throws
 | 
			
		||||
 | 
			
		||||
      T & <A href="#indirection" >operator*</A>() const; // never throws
 | 
			
		||||
      T * <A href="#indirection" >operator-></A>() const; // never throws
 | 
			
		||||
      T * <A href="#get" >get</A>() const; // never throws
 | 
			
		||||
   void <a href="#shared_ptr_swap">swap</a>( shared_ptr<T>& other ) throw()
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
      bool <A href="#unique" >unique</A>() const; // never throws
 | 
			
		||||
      long <A href="#use_count" >use_count</A>() const; // never throws
 | 
			
		||||
template<typename T, typename U>
 | 
			
		||||
  inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b)
 | 
			
		||||
    { return a.get() == b.get(); }
 | 
			
		||||
 | 
			
		||||
      operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
 | 
			
		||||
template<typename T, typename U>
 | 
			
		||||
  inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b)
 | 
			
		||||
    { return a.get() != b.get(); }
 | 
			
		||||
}</pre>
 | 
			
		||||
<pre>namespace std {
 | 
			
		||||
 | 
			
		||||
      void <A href="#swap" >swap</A>(shared_ptr & b); // never throws
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b)
 | 
			
		||||
    { a.swap(b); }
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  struct less< boost::shared_ptr<T> >
 | 
			
		||||
    : binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool>
 | 
			
		||||
  {
 | 
			
		||||
    bool operator()(const boost::shared_ptr<T>& a,
 | 
			
		||||
        const boost::shared_ptr<T>& b) const
 | 
			
		||||
      { return less<T*>()(a.get(),b.get()); }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  template<class T, class U>
 | 
			
		||||
    bool <A href="#comparison" >operator==</A>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
 | 
			
		||||
} // namespace std </pre>
 | 
			
		||||
<p>Specialization of std::swap uses the fast, non-throwing swap that's provided
 | 
			
		||||
as a member function instead of using the default algorithm which creates a
 | 
			
		||||
temporary and uses assignment.<br>
 | 
			
		||||
<br>
 | 
			
		||||
Specialization of std::less allows use of shared pointers as keys in C++
 | 
			
		||||
Standard Library associative collections.<br>
 | 
			
		||||
<br>
 | 
			
		||||
The std::less specializations use std::less<T*> to perform the
 | 
			
		||||
comparison.  This insures that pointers are handled correctly, since the
 | 
			
		||||
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel]
 | 
			
		||||
paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons]
 | 
			
		||||
paragraph 8).<br>
 | 
			
		||||
<br>
 | 
			
		||||
It's still a controversial question whether supplying only std::less is better
 | 
			
		||||
than supplying a full range of comparison operators (<, >, <=, >=).</p>
 | 
			
		||||
<p>The current implementation does not supply the specializations if the macro
 | 
			
		||||
name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.</p>
 | 
			
		||||
<p>The current implementation does not supply the member template functions if
 | 
			
		||||
the macro name BOOST_NO_MEMBER_TEMPLATES is defined.</p>
 | 
			
		||||
<h2>Class shared_ptr Members</h2>
 | 
			
		||||
<h3>shared_ptr <a name="shared_ptr_element_type">element_type</a></h3>
 | 
			
		||||
<pre>typedef T element_type;</pre>
 | 
			
		||||
<p>Provides the type of the stored pointer.</p>
 | 
			
		||||
<h3><a name="shared_ptr_ctor">shared_ptr constructors</a></h3>
 | 
			
		||||
<pre>explicit shared_ptr( T* p=0 );</pre>
 | 
			
		||||
<p>Constructs a <strong>shared_ptr</strong>, storing a copy of <tt>p</tt>, which
 | 
			
		||||
must have been allocated via a C++ <tt>new</tt> expression or be 0. Afterwards, <strong>use_count()</strong>
 | 
			
		||||
is 1 (even if p==0; see <a href="#shared_ptr_~shared_ptr">~shared_ptr</a>).</p>
 | 
			
		||||
<p>The only exception which may be thrown by this constructor is <tt>std::bad_alloc</tt>.  
 | 
			
		||||
If an exception is thrown,  <tt>delete p</tt> is called.</p>
 | 
			
		||||
<pre>shared_ptr( const shared_ptr& r);  // never throws   
 | 
			
		||||
template<typename Y>
 | 
			
		||||
   shared_ptr(const shared_ptr<Y>& r);  // never throws
 | 
			
		||||
template<typename Y>
 | 
			
		||||
   shared_ptr(std::auto_ptr<Y>& r);</pre>
 | 
			
		||||
<p>Constructs a <strong>shared_ptr</strong>, as if by storing a copy of the
 | 
			
		||||
pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
 | 
			
		||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>, or 1
 | 
			
		||||
in the <strong>auto_ptr</strong> case. In the <strong>auto_ptr</strong> case, <strong>r.release()</strong>
 | 
			
		||||
is called.</p>
 | 
			
		||||
<p>The only exception which may be thrown by the constructor from <strong>auto_ptr</strong>
 | 
			
		||||
is <tt>std::bad_alloc</tt>.   If an exception is thrown, that
 | 
			
		||||
constructor has no effect.</p>
 | 
			
		||||
<h3><a name="shared_ptr_~shared_ptr">shared_ptr destructor</a></h3>
 | 
			
		||||
<pre>~shared_ptr();</pre>
 | 
			
		||||
<p>If <strong>use_count()</strong> == 1, deletes the object pointed to by the
 | 
			
		||||
stored pointer. Otherwise, <strong>use_count()</strong> for any remaining
 | 
			
		||||
copies is decremented by 1. Note that in C++  <tt>delete</tt> on a pointer
 | 
			
		||||
with a value of 0 is harmless.</p>
 | 
			
		||||
<p>Does not throw exceptions.</p>
 | 
			
		||||
<h3>shared_ptr <a name="shared_ptr_operator=">operator=</a></h3>
 | 
			
		||||
<pre>shared_ptr& operator=( const shared_ptr& r);  
 | 
			
		||||
template<typename Y>
 | 
			
		||||
   shared_ptr& operator=(const shared_ptr<Y>& r);
 | 
			
		||||
template<typename Y>
 | 
			
		||||
   shared_ptr& operator=(std::auto_ptr<Y>& r);</pre>
 | 
			
		||||
<p>First, if <strong>use_count()</strong> == 1, deletes the object pointed to by
 | 
			
		||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
 | 
			
		||||
remaining copies is decremented by 1. Note that in C++  <tt>delete</tt> on
 | 
			
		||||
a pointer with a value of 0 is harmless.</p>
 | 
			
		||||
<p>Then replaces the contents of <strong>this</strong>, as if by storing a copy
 | 
			
		||||
of the pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
 | 
			
		||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>, or 1
 | 
			
		||||
in the <strong>auto_ptr</strong> case. In the <strong>auto_ptr</strong> case, <strong>r.release()</strong>
 | 
			
		||||
is called.</p>
 | 
			
		||||
<p>The first two forms of <tt>operator=</tt> above do not throw exceptions.</p>
 | 
			
		||||
<p>The only exception which may be thrown by the <strong>auto_ptr</strong> form
 | 
			
		||||
is <tt>std::bad_alloc</tt>.   If an exception is thrown, the function
 | 
			
		||||
has no effect.</p>
 | 
			
		||||
<h3>shared_ptr <a name="shared_ptr_reset">reset</a></h3>
 | 
			
		||||
<pre>void reset( T* p=0 );</pre>
 | 
			
		||||
<p>First, if <strong>use_count()</strong> == 1, deletes the object pointed to by
 | 
			
		||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
 | 
			
		||||
remaining copies is decremented by 1. </p>
 | 
			
		||||
<p>Then replaces the contents of <strong>this</strong>, as if by storing a copy
 | 
			
		||||
of <strong>p</strong>, which must have been allocated via a C++ <tt>new</tt>
 | 
			
		||||
expression or be 0. Afterwards, <strong>use_count()</strong> is 1 (even if p==0;
 | 
			
		||||
see <a href="#shared_ptr_~shared_ptr">~shared_ptr</a>). Note that in C++  <tt>delete</tt>
 | 
			
		||||
on a pointer with a value of 0 is harmless.</p>
 | 
			
		||||
<p>The only exception which may be thrown is <tt>std::bad_alloc</tt>.  If
 | 
			
		||||
an exception is thrown,  <tt>delete p</tt> is called.</p>
 | 
			
		||||
<h3>shared_ptr <a name="shared_ptr_operator*">operator*</a></h3>
 | 
			
		||||
<pre>T& operator*() const;  // never throws</pre>
 | 
			
		||||
<p>Returns a reference to the object pointed to by the stored pointer.</p>
 | 
			
		||||
<h3>shared_ptr <a name="shared_ptr_operator->">operator-></a> and <a name="shared_ptr_get">get</a></h3>
 | 
			
		||||
<pre>T* operator->() const;  // never throws
 | 
			
		||||
T* get() const;  // never throws</pre>
 | 
			
		||||
<p>Both return the stored pointer.</p>
 | 
			
		||||
<h3>shared_ptr<a name="shared_ptr_use_count"> use_count</a></h3>
 | 
			
		||||
<p><tt>long use_count() const; // never throws</tt></p>
 | 
			
		||||
<p>Returns the number of <strong>shared_ptrs</strong> sharing ownership of the
 | 
			
		||||
stored pointer.</p>
 | 
			
		||||
<h3>shared_ptr <a name="shared_ptr_unique">unique</a></h3>
 | 
			
		||||
<p><tt>bool unique() const; // never throws</tt></p>
 | 
			
		||||
<p>Returns <strong>use_count()</strong> == 1.</p>
 | 
			
		||||
<h3><a name="shared_ptr_swap">shared_ptr swap</a></h3>
 | 
			
		||||
<p><code>void swap( shared_ptr<T>& other ) throw()</code></p>
 | 
			
		||||
<p>Swaps the two smart pointers, as if by std::swap.</p>
 | 
			
		||||
<h2>Class <a name="shared_ptr_example">shared_ptr example</a></h2>
 | 
			
		||||
<pre>//  The application will produce a series of
 | 
			
		||||
//  objects of type Foo which later must be
 | 
			
		||||
//  accessed both by occurrence (std::vector)
 | 
			
		||||
//  and by ordering relationship (std::set).
 | 
			
		||||
 | 
			
		||||
  template<class T, class U>
 | 
			
		||||
    bool <A href="#comparison" >operator!=</A>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
 | 
			
		||||
class Foo { ... };
 | 
			
		||||
 | 
			
		||||
  template<class T, class U>
 | 
			
		||||
    bool <A href="#comparison" >operator<</A>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
 | 
			
		||||
typedef boost::shared_ptr<Foo> FooPtr;
 | 
			
		||||
 | 
			
		||||
  template<class T> void <A href="#free-swap" >swap</A>(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
 | 
			
		||||
std::vector<FooPtr> foo_vector;
 | 
			
		||||
std::set<FooPtr>    foo_set; // NOT multiset!
 | 
			
		||||
 | 
			
		||||
  template<class T> T * <A href="#get_pointer" >get_pointer</A>(shared_ptr<T> const & p); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class T, class U>
 | 
			
		||||
    shared_ptr<T> <A href="#static_pointer_cast" >static_pointer_cast</A>(shared_ptr<U> const & r); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class T, class U>
 | 
			
		||||
    shared_ptr<T> <A href="#const_pointer_cast" >const_pointer_cast</A>(shared_ptr<U> const & r); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class T, class U>
 | 
			
		||||
    shared_ptr<T> <A href="#dynamic_pointer_cast" >dynamic_pointer_cast</A>(shared_ptr<U> const & r); // never throws
 | 
			
		||||
 | 
			
		||||
  template<class E, class T, class Y>
 | 
			
		||||
    std::basic_ostream<E, T> & <A href="#insertion-operator" >operator<<</A> (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
 | 
			
		||||
 | 
			
		||||
  template<class D, class T>
 | 
			
		||||
    D * <A href="#get_deleter">get_deleter</A>(shared_ptr<T> const & p);
 | 
			
		||||
...
 | 
			
		||||
{ // creation loop
 | 
			
		||||
  FooPtr foo_ptr ( new Foo( ... ) );
 | 
			
		||||
  foo_vector.push_back( foo_ptr );
 | 
			
		||||
  foo_set.insert( foo_ptr );
 | 
			
		||||
}</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>shared_ptr(); // never throws</pre>
 | 
			
		||||
		<blockquote>
 | 
			
		||||
			<p><b>Effects:</b> Constructs an <EM>empty</EM> <b>shared_ptr</b>.</p>
 | 
			
		||||
			<p><b>Postconditions:</b> <code>use_count() == 0 && get() == 0</code>.</p>
 | 
			
		||||
			<p><b>Throws:</b> nothing.</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<class Y> 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 && 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>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 
 | 
			
		||||
				allocated via a C++ <B>new</B> expression or be 0. The postcondition that <A href="#use_count">
 | 
			
		||||
					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<class Y, class D> 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>
 | 
			
		||||
			<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 && 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>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>
 | 
			
		||||
		</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 & r); // never throws
 | 
			
		||||
template<class Y> shared_ptr(shared_ptr<Y> const & 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() && use_count() == 
 | 
			
		||||
					r.use_count()</code>.</p>
 | 
			
		||||
			<p><b>Throws:</b> nothing.</p>
 | 
			
		||||
		</blockquote>
 | 
			
		||||
		<pre>template<class Y> explicit shared_ptr(<A href="weak_ptr.htm" >weak_ptr</A><Y> const & 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>Exception safety:</b> If an exception is thrown, the constructor has no 
 | 
			
		||||
				effect.</p>
 | 
			
		||||
		</blockquote>
 | 
			
		||||
		<pre>template<class Y> shared_ptr(std::auto_ptr<Y> & 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>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() > 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>Throws:</B> nothing.</P>
 | 
			
		||||
		</BLOCKQUOTE>
 | 
			
		||||
		<H3><a name="assignment">assignment</a></H3>
 | 
			
		||||
		<pre>shared_ptr & operator=(shared_ptr const & r); // never throws
 | 
			
		||||
template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
 | 
			
		||||
template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);</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<int> p(new int);
 | 
			
		||||
shared_ptr<void> q(p);
 | 
			
		||||
p = p;
 | 
			
		||||
q = p;
 | 
			
		||||
</pre>
 | 
			
		||||
			<p>both assignments may be no-ops.</p>
 | 
			
		||||
		</BLOCKQUOTE>
 | 
			
		||||
		<h3><a name="reset">reset</a></h3>
 | 
			
		||||
		<pre>void reset(); // never throws</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<P><B>Effects:</B> Equivalent to <code>shared_ptr().swap(*this)</code>.</P>
 | 
			
		||||
		</BLOCKQUOTE>
 | 
			
		||||
		<pre>template<class Y> void reset(Y * p);</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<P><B>Effects:</B> Equivalent to <code>shared_ptr(p).swap(*this)</code>.</P>
 | 
			
		||||
		</BLOCKQUOTE>
 | 
			
		||||
		<pre>template<class Y, class D> void reset(Y * p, D d);</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<P><B>Effects:</B> Equivalent to <code>shared_ptr(p, d).swap(*this)</code>.</P>
 | 
			
		||||
		</BLOCKQUOTE>
 | 
			
		||||
		<h3><a name="indirection">indirection</a></h3>
 | 
			
		||||
		<pre>T & operator*() const; // never throws</pre>
 | 
			
		||||
		<blockquote>
 | 
			
		||||
			<p><b>Requirements:</b> The stored pointer must not be 0.</p>
 | 
			
		||||
			<p><b>Returns:</b> a reference to the object pointed to by the stored pointer.</p>
 | 
			
		||||
			<p><b>Throws:</b> nothing.</p>
 | 
			
		||||
		</blockquote>
 | 
			
		||||
		<pre>T * operator->() const; // never throws</pre>
 | 
			
		||||
		<blockquote>
 | 
			
		||||
			<p><b>Requirements:</b> The stored pointer must not be 0.</p>
 | 
			
		||||
			<p><b>Returns:</b> the stored pointer.</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="unique">unique</a></h3>
 | 
			
		||||
		<pre>bool unique() const; // never throws</pre>
 | 
			
		||||
		<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>
 | 
			
		||||
		</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>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>
 | 
			
		||||
		<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>shared_ptr</b> objects to be 
 | 
			
		||||
				used in boolean contexts, like <code>if (p && p->valid()) {}</code>. 
 | 
			
		||||
				The actual target type is typically a pointer to a member function, avoiding 
 | 
			
		||||
				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 & 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<class T, class U>
 | 
			
		||||
  bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & 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<class T, class U>
 | 
			
		||||
  bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & 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<class T, class U>
 | 
			
		||||
  bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre>
 | 
			
		||||
		<blockquote>
 | 
			
		||||
			<p><b>Returns:</b> an unspecified value such that</p>
 | 
			
		||||
			<UL>
 | 
			
		||||
				<LI>
 | 
			
		||||
					<b>operator<</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<</STRONG>, <code>!(a 
 | 
			
		||||
						< b) && !(b < 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>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<</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<</STRONG>, and many 
 | 
			
		||||
				standard algorithms use <STRONG>operator<</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<</STRONG> in terms of their contained 
 | 
			
		||||
				subobjects' <STRONG>operator<</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<class T>
 | 
			
		||||
  void swap(shared_ptr<T> & a, shared_ptr<T> & 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<class T>
 | 
			
		||||
  T * get_pointer(shared_ptr<T> const & 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<class T, class U>
 | 
			
		||||
  shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<P><STRONG>Requires:</STRONG> The expression <code>static_cast<T*>(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<T></b>; 
 | 
			
		||||
				otherwise, a <STRONG>shared_ptr<T></STRONG> object that stores a copy of <code>
 | 
			
		||||
					static_cast<T*>(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<T>(static_cast<T*>(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<class T, class U>
 | 
			
		||||
  shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<P><STRONG>Requires:</STRONG> The expression <code>const_cast<T*>(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<T></b>; 
 | 
			
		||||
				otherwise, a <STRONG>shared_ptr<T></STRONG> object that stores a copy of <code>
 | 
			
		||||
					const_cast<T*>(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<T>(const_cast<T*>(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<class T, class U>
 | 
			
		||||
  shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r);</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<P><STRONG>Requires:</STRONG> The expression <CODE>dynamic_cast<T*>(r.get())</CODE>
 | 
			
		||||
				must be well-formed and its behavior defined.</P>
 | 
			
		||||
			<P><B>Returns:</B></P>
 | 
			
		||||
			<UL>
 | 
			
		||||
				<LI>
 | 
			
		||||
					When <CODE>dynamic_cast<T*>(r.get())</CODE> returns a nonzero value, a <STRONG>
 | 
			
		||||
						shared_ptr<T></STRONG> object that stores a copy of it and <i>shares 
 | 
			
		||||
						ownership</i> with <STRONG>r</STRONG>;
 | 
			
		||||
				<LI>
 | 
			
		||||
					Otherwise, an <i>empty</i> <STRONG>shared_ptr<T></STRONG> object.</LI></UL>
 | 
			
		||||
			<P><B>Throws:</B> nothing.</P>
 | 
			
		||||
			<P><B>Notes:</B> the seemingly equivalent expression</P>
 | 
			
		||||
			<P><CODE>shared_ptr<T>(dynamic_cast<T*>(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<<</a></h3>
 | 
			
		||||
		<pre>template<class E, class T, class Y>
 | 
			
		||||
    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<p><STRONG>Effects:</STRONG> <code>os << p.get();</code>.</p>
 | 
			
		||||
			<P><B>Returns:</B> <b>os</b>.</P>
 | 
			
		||||
		</BLOCKQUOTE>
 | 
			
		||||
		<h3><a name="get_deleter">get_deleter</a></h3>
 | 
			
		||||
		<pre>template<class D, class T>
 | 
			
		||||
    D * get_deleter(shared_ptr<T> const & p);</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>&d</code>; 
 | 
			
		||||
				otherwise returns 0.</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>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 
 | 
			
		||||
			contain duplicate entries. Furthermore, the use count may be even higher at 
 | 
			
		||||
			various times while <b>push_back</b> and <b>insert</b> container operations are 
 | 
			
		||||
			performed. More complicated yet, the container operations may throw exceptions 
 | 
			
		||||
			under a variety of circumstances. Getting the memory management and exception 
 | 
			
		||||
			handling in this example right without a smart pointer would be a nightmare.</p>
 | 
			
		||||
		<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
 | 
			
		||||
		<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>, 
 | 
			
		||||
			which uses a <b>shared_ptr<></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>
 | 
			
		||||
			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<int> p(new int(42));
 | 
			
		||||
<p>Note that at the termination of the creation loop, some of the FooPtr objects
 | 
			
		||||
may have use_count()==1 rather than use_count()==2, since foo_set is a std::set
 | 
			
		||||
rather than a std::multiset.  Furthermore, use_count() will be even higher
 | 
			
		||||
at various times inside the loop, as container operations are performed. 
 | 
			
		||||
More complicated yet, the container operations may throw exceptions under a
 | 
			
		||||
variety of circumstances.  Without using a smart pointer, memory and
 | 
			
		||||
exception management would be a nightmare.</p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->09 February, 2001<!--webbot bot="Timestamp" endspan i-checksum="40412" -->
 | 
			
		||||
</p>
 | 
			
		||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
without express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
any purpose.</p>
 | 
			
		||||
 | 
			
		||||
//--- Example 1 ---
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
// thread A
 | 
			
		||||
shared_ptr<int> p2(p); // reads p
 | 
			
		||||
 | 
			
		||||
// thread B
 | 
			
		||||
shared_ptr<int> p3(p); // OK, multiple reads are safe
 | 
			
		||||
 | 
			
		||||
//--- Example 2 ---
 | 
			
		||||
 | 
			
		||||
// thread A
 | 
			
		||||
p.reset(new int(1912)); // writes p
 | 
			
		||||
 | 
			
		||||
// thread B
 | 
			
		||||
p2.reset(); // OK, writes p2
 | 
			
		||||
 | 
			
		||||
//--- Example 3 ---
 | 
			
		||||
 | 
			
		||||
// thread A
 | 
			
		||||
p = p3; // reads p3, writes p
 | 
			
		||||
 | 
			
		||||
// thread B
 | 
			
		||||
p3.reset(); // writes p3; undefined, simultaneous read/write
 | 
			
		||||
 | 
			
		||||
//--- Example 4 ---
 | 
			
		||||
 | 
			
		||||
// thread A
 | 
			
		||||
p3 = p2; // reads p2, writes p3
 | 
			
		||||
 | 
			
		||||
// thread B
 | 
			
		||||
// p2 goes out of scope: undefined, the destructor is considered a "write access"
 | 
			
		||||
 | 
			
		||||
//--- Example 5 ---
 | 
			
		||||
 | 
			
		||||
// thread A
 | 
			
		||||
p3.reset(new int(1));
 | 
			
		||||
 | 
			
		||||
// thread B
 | 
			
		||||
p3.reset(new int(2)); // undefined, multiple writes
 | 
			
		||||
</pre>
 | 
			
		||||
		<p> </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>
 | 
			
		||||
			<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>
 | 
			
		||||
		<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>
 | 
			
		||||
			<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>
 | 
			
		||||
			<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>
 | 
			
		||||
			<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>
 | 
			
		||||
			<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>
 | 
			
		||||
			<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>
 | 
			
		||||
			<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>
 | 
			
		||||
		<p>Consider:</p>
 | 
			
		||||
		<blockquote><pre>shared_ptr<int> a(new int);
 | 
			
		||||
shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
 | 
			
		||||
 | 
			
		||||
int * p = a.release();
 | 
			
		||||
 | 
			
		||||
// Who owns p now? b will still call delete on it in its destructor.</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->()</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>
 | 
			
		||||
		<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>
 | 
			
		||||
	</body>
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										320
									
								
								smart_ptr.htm
									
									
									
									
									
								
							
							
						
						
									
										320
									
								
								smart_ptr.htm
									
									
									
									
									
								
							@@ -1,186 +1,138 @@
 | 
			
		||||
<!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"><boost/scoped_ptr.hpp></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"><boost/scoped_array.hpp></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"><boost/shared_ptr.hpp></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"><boost/shared_array.hpp></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"><boost/weak_ptr.hpp></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"><boost/intrusive_ptr.hpp></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<>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&D-94">E&D-94</a>] John R. Ellis & 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">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
<title>Smart Pointer Classes</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Smart
 | 
			
		||||
Pointers</h1>
 | 
			
		||||
<p>Smart pointers are classes which store pointers to dynamically allocated
 | 
			
		||||
(heap) objects.  They behave much like built-in C++ pointers except that
 | 
			
		||||
they automatically delete the object pointed to at the appropriate
 | 
			
		||||
time. Smart pointers are particularly useful in the face of exceptions as
 | 
			
		||||
they ensure proper destruction of dynamically allocated objects. They can also
 | 
			
		||||
be used to keep track of dynamically allocated objects shared by multiple
 | 
			
		||||
owners.</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 header <a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>
 | 
			
		||||
provides four smart pointer template classes:</p>
 | 
			
		||||
<div align="left">
 | 
			
		||||
  <table border="1" cellpadding="4" cellspacing="4">
 | 
			
		||||
    <tr>
 | 
			
		||||
      <td>
 | 
			
		||||
        <p align="left"><a href="scoped_ptr.htm"><strong>scoped_ptr</strong></a></td>
 | 
			
		||||
      <td>Simple sole ownership of single objects.</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
      <td><a href="scoped_array.htm"><strong>scoped_array</strong></a></td>
 | 
			
		||||
      <td>Simple sole ownership of arrays.</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
      <td><a href="shared_ptr.htm"><strong>shared_ptr</strong></a></td>
 | 
			
		||||
      <td>Object ownership shared among multiple pointers</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
      <td><a href="shared_array.htm"><strong>shared_array</strong></a></td>
 | 
			
		||||
      <td>Array ownership shared among multiple pointers.</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
  </table>
 | 
			
		||||
</div>
 | 
			
		||||
<p>These classes are designed to complement the C++ Standard Library <tt>auto_ptr</tt>
 | 
			
		||||
class.</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="smart_ptr_test.cpp">smart_ptr_test.cpp</a>) is
 | 
			
		||||
provided to verify correct operation.</p>
 | 
			
		||||
<p>A page on <a href="smarttests.htm">Smart Pointer Timings</a> will be of
 | 
			
		||||
interest to those curious about performance issues.</p>
 | 
			
		||||
<h2><a name="Common requirements">Common requirements</a></h2>
 | 
			
		||||
<p>These smart pointer classes have a template parameter, <tt>T</tt>, which
 | 
			
		||||
specifies the type of the object pointed to by the smart pointer.  The
 | 
			
		||||
behavior of all four classes is undefined if the destructor or operator delete
 | 
			
		||||
for objects of type <tt>T</tt> throws exceptions.</p>
 | 
			
		||||
<h2>Exception safety</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 <tt>T</tt> meets the <a href="#Common requirements">Common
 | 
			
		||||
requirements</a>)  is <tt>std::bad_alloc</tt>, and that is thrown only by
 | 
			
		||||
functions which are explicitly documented as possibly throwing <tt>std::bad_alloc</tt>.</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 four classes contain member functions which can never throw exceptions,
 | 
			
		||||
because they neither throw exceptions themselves nor call other functions which
 | 
			
		||||
may throw exceptions.  These members are indicated by a comment: <kbd>//
 | 
			
		||||
never throws</kbd>. </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>November, 1999. Darin Adler provided operator ==, operator !=, and std::swap
 | 
			
		||||
and std::less specializations for shared types.</p>
 | 
			
		||||
<p>September, 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap</p>
 | 
			
		||||
<p>May, 1999.  In April and May, 1999, Valentin Bonnard and David Abrahams
 | 
			
		||||
made a number of suggestions resulting in numerous improvements.  See the
 | 
			
		||||
revision history in <a href="../../boost/smart_ptr.hpp"><tt>smart_ptr.hpp</tt></a>
 | 
			
		||||
for the specific changes made as a result of their constructive criticism.</p>
 | 
			
		||||
<p>Oct, 1998.  In 1994 Greg Colvin proposed to the C++ Standards Committee
 | 
			
		||||
classes named <strong>auto_ptr</strong> and <strong>counted_ptr</strong> which
 | 
			
		||||
were very similar to what we now call <strong>scoped_ptr</strong> and <strong>shared_ptr</strong>. 
 | 
			
		||||
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, <strong>counted_ptr</strong> was rejected
 | 
			
		||||
and surprising transfer-of-ownership semantics were added to <strong>auto-ptr</strong>.</p>
 | 
			
		||||
<p>Beman Dawes proposed reviving the original semantics under the names <strong>safe_ptr</strong>
 | 
			
		||||
and <strong>counted_ptr</strong> 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 <strong>std::auto_ptr</strong> interface, and various
 | 
			
		||||
function signatures and semantics were finalized.</p>
 | 
			
		||||
<p>Over the next three months, several implementations were considered for <strong>shared_ptr</strong>,
 | 
			
		||||
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 "Counted Body
 | 
			
		||||
Techniques."  Dietmar K<>hl suggested an elegant partial template
 | 
			
		||||
specialization technique to allow users to choose which implementation they
 | 
			
		||||
preferred, and that was also experimented with.</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>See the Revision History section of the header for further contributors.</p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised  <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan
 | 
			
		||||
-->24 Jul 2000<!--webbot bot="Timestamp" endspan i-checksum="14986"
 | 
			
		||||
--></p>
 | 
			
		||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
without express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
any purpose.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										263
									
								
								smart_ptr_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								smart_ptr_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,263 @@
 | 
			
		||||
//  smart pointer test program  ----------------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Beman Dawes 1998, 1999. Permission to copy, use, modify, sell
 | 
			
		||||
//  and distribute this software is granted provided this copyright notice
 | 
			
		||||
//  appears in all copies. This software is provided "as is" without express or
 | 
			
		||||
//  implied warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  29 Nov 99  added std::swap and associative container tests (Darin Adler)
 | 
			
		||||
//  25 Sep 99  added swap tests
 | 
			
		||||
//  20 Jul 99  header name changed to .hpp
 | 
			
		||||
//  20 Apr 99  additional error tests added.
 | 
			
		||||
 | 
			
		||||
#include <boost/smart_ptr.hpp>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <set>
 | 
			
		||||
 | 
			
		||||
#ifdef NDEBUG
 | 
			
		||||
#error This test program makes no sense if NDEBUG is defined
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
using boost::scoped_ptr;
 | 
			
		||||
using boost::scoped_array;
 | 
			
		||||
using boost::shared_ptr;
 | 
			
		||||
using boost::shared_array;
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
void ck( const T* v1, T v2 ) { assert( *v1 == v2 ); }
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
  int UDT_use_count;  // independent of pointer maintained counts
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
//  user defined type  -------------------------------------------------------//
 | 
			
		||||
 | 
			
		||||
class UDT {
 | 
			
		||||
  long value_;
 | 
			
		||||
 public:
 | 
			
		||||
  explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; }
 | 
			
		||||
  ~UDT() {
 | 
			
		||||
    --UDT_use_count;
 | 
			
		||||
    cout << "UDT with value " << value_ << " being destroyed" << endl;
 | 
			
		||||
    }
 | 
			
		||||
  long value() const { return value_; }
 | 
			
		||||
  void value( long v ) { value_ = v;; }
 | 
			
		||||
  };  // UDT
 | 
			
		||||
 | 
			
		||||
//  main  --------------------------------------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  This isn't a very systematic test; it just hits some of the basics.
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
 | 
			
		||||
  assert( UDT_use_count == 0 );  // reality check
 | 
			
		||||
 | 
			
		||||
  //  test scoped_ptr with a built-in type
 | 
			
		||||
  long * lp = new long;
 | 
			
		||||
  scoped_ptr<long> sp ( lp );
 | 
			
		||||
  assert( sp.get() == lp );
 | 
			
		||||
  assert( lp == sp.get() );
 | 
			
		||||
  assert( &*sp == lp );
 | 
			
		||||
 | 
			
		||||
  *sp = 1234568901L;
 | 
			
		||||
  assert( *sp == 1234568901L );
 | 
			
		||||
  assert( *lp == 1234568901L );
 | 
			
		||||
  ck( static_cast<long*>(sp.get()), 1234568901L );
 | 
			
		||||
  ck( lp, *sp );
 | 
			
		||||
 | 
			
		||||
  sp.reset();
 | 
			
		||||
  assert( sp.get() == 0 );
 | 
			
		||||
 | 
			
		||||
  //  test scoped_ptr with a user defined type
 | 
			
		||||
  scoped_ptr<UDT> udt_sp ( new UDT( 999888777 ) );
 | 
			
		||||
  assert( udt_sp->value() == 999888777 );
 | 
			
		||||
  udt_sp.reset();
 | 
			
		||||
  udt_sp.reset( new UDT( 111222333 ) );
 | 
			
		||||
  assert( udt_sp->value() == 111222333 );
 | 
			
		||||
  udt_sp.reset( new UDT( 333222111 ) );
 | 
			
		||||
  assert( udt_sp->value() == 333222111 );
 | 
			
		||||
 | 
			
		||||
  //  test scoped_array with a build-in type
 | 
			
		||||
  char * sap = new char [ 100 ];
 | 
			
		||||
  scoped_array<char> sa ( sap );
 | 
			
		||||
  assert( sa.get() == sap );
 | 
			
		||||
  assert( sap == sa.get() );
 | 
			
		||||
 | 
			
		||||
  strcpy( sa.get(), "Hot Dog with mustard and relish" );
 | 
			
		||||
  assert( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 );
 | 
			
		||||
  assert( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 );
 | 
			
		||||
 | 
			
		||||
  assert( sa[0] == 'H' );
 | 
			
		||||
  assert( sa[30] == 'h' );
 | 
			
		||||
 | 
			
		||||
  sa[0] = 'N';
 | 
			
		||||
  sa[4] = 'd';
 | 
			
		||||
  assert( strcmp( sap, "Not dog with mustard and relish" ) == 0 );
 | 
			
		||||
 | 
			
		||||
  sa.reset();
 | 
			
		||||
  assert( sa.get() == 0 );
 | 
			
		||||
 | 
			
		||||
  //  test shared_ptr with a built-in type
 | 
			
		||||
  int * ip = new int;
 | 
			
		||||
  shared_ptr<int> cp ( ip );
 | 
			
		||||
  assert( ip == cp.get() );
 | 
			
		||||
  assert( cp.use_count() == 1 );
 | 
			
		||||
 | 
			
		||||
  *cp = 54321;
 | 
			
		||||
  assert( *cp == 54321 );
 | 
			
		||||
  assert( *ip == 54321 );
 | 
			
		||||
  ck( static_cast<int*>(cp.get()), 54321 );
 | 
			
		||||
  ck( static_cast<int*>(ip), *cp );
 | 
			
		||||
 | 
			
		||||
  shared_ptr<int> cp2 ( cp );
 | 
			
		||||
  assert( ip == cp2.get() );
 | 
			
		||||
  assert( cp.use_count() == 2 );
 | 
			
		||||
  assert( cp2.use_count() == 2 );
 | 
			
		||||
 | 
			
		||||
  assert( *cp == 54321 );
 | 
			
		||||
  assert( *cp2 == 54321 );
 | 
			
		||||
  ck( static_cast<int*>(cp2.get()), 54321 );
 | 
			
		||||
  ck( static_cast<int*>(ip), *cp2 );
 | 
			
		||||
  
 | 
			
		||||
  shared_ptr<int> cp3 ( cp );
 | 
			
		||||
  assert( cp.use_count() == 3 );
 | 
			
		||||
  assert( cp2.use_count() == 3 );
 | 
			
		||||
  assert( cp3.use_count() == 3 );
 | 
			
		||||
  cp.reset();
 | 
			
		||||
  assert( cp2.use_count() == 2 );
 | 
			
		||||
  assert( cp3.use_count() == 2 );
 | 
			
		||||
  assert( cp.use_count() == 1 );
 | 
			
		||||
  cp.reset( new int );
 | 
			
		||||
  *cp =  98765;
 | 
			
		||||
  assert( *cp == 98765 );
 | 
			
		||||
  *cp3 = 87654;
 | 
			
		||||
  assert( *cp3 == 87654 );
 | 
			
		||||
  assert( *cp2 == 87654 );
 | 
			
		||||
  cp.swap( cp3 );
 | 
			
		||||
  assert( *cp == 87654 );
 | 
			
		||||
  assert( *cp2 == 87654 );
 | 
			
		||||
  assert( *cp3 == 98765 );
 | 
			
		||||
  cp.swap( cp3 );
 | 
			
		||||
  assert( *cp == 98765 );
 | 
			
		||||
  assert( *cp2 == 87654 );
 | 
			
		||||
  assert( *cp3 == 87654 );
 | 
			
		||||
  cp2 = cp2;
 | 
			
		||||
  assert( cp2.use_count() == 2 );
 | 
			
		||||
  assert( *cp2 == 87654 );
 | 
			
		||||
  cp = cp2;
 | 
			
		||||
  assert( cp2.use_count() == 3 );
 | 
			
		||||
  assert( *cp2 == 87654 );
 | 
			
		||||
  assert( cp.use_count() == 3 );
 | 
			
		||||
  assert( *cp == 87654 );
 | 
			
		||||
  
 | 
			
		||||
  shared_ptr<int> cp4;
 | 
			
		||||
  swap( cp2, cp4 );
 | 
			
		||||
  assert( cp4.use_count() == 3 );
 | 
			
		||||
  assert( *cp4 == 87654 );
 | 
			
		||||
  assert( cp2.get() == 0 );
 | 
			
		||||
  
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
  set< shared_ptr<int> > scp;
 | 
			
		||||
  scp.insert(cp4);
 | 
			
		||||
  assert( scp.find(cp4) != scp.end() );
 | 
			
		||||
  assert( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) );
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  //  test shared_array with a built-in type
 | 
			
		||||
  char * cap = new char [ 100 ];
 | 
			
		||||
  shared_array<char> ca ( cap );
 | 
			
		||||
  assert( ca.get() == cap );
 | 
			
		||||
  assert( cap == ca.get() );
 | 
			
		||||
  assert( &ca[0] == cap );
 | 
			
		||||
 | 
			
		||||
  strcpy( ca.get(), "Hot Dog with mustard and relish" );
 | 
			
		||||
  assert( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 );
 | 
			
		||||
  assert( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 );
 | 
			
		||||
 | 
			
		||||
  assert( ca[0] == 'H' );
 | 
			
		||||
  assert( ca[30] == 'h' );
 | 
			
		||||
  
 | 
			
		||||
  shared_array<char> ca2 ( ca );
 | 
			
		||||
  shared_array<char> ca3 ( ca2 );
 | 
			
		||||
 | 
			
		||||
  ca[0] = 'N';
 | 
			
		||||
  ca[4] = 'd';
 | 
			
		||||
  assert( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 );
 | 
			
		||||
  assert( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 );
 | 
			
		||||
  assert( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 );
 | 
			
		||||
  assert( ca.use_count() == 3 );
 | 
			
		||||
  assert( ca2.use_count() == 3 );
 | 
			
		||||
  assert( ca3.use_count() == 3 );
 | 
			
		||||
  ca2.reset();
 | 
			
		||||
  assert( ca.use_count() == 2 );
 | 
			
		||||
  assert( ca3.use_count() == 2 );
 | 
			
		||||
  assert( ca2.use_count() == 1 );
 | 
			
		||||
 | 
			
		||||
  ca.reset();
 | 
			
		||||
  assert( ca.get() == 0 );
 | 
			
		||||
 | 
			
		||||
  shared_array<char> ca4;
 | 
			
		||||
  swap( ca3, ca4 );
 | 
			
		||||
  assert( ca4.use_count() == 1 );
 | 
			
		||||
  assert( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 );
 | 
			
		||||
  assert( ca3.get() == 0 );
 | 
			
		||||
  
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
  set< shared_array<char> > sca;
 | 
			
		||||
  sca.insert(ca4);
 | 
			
		||||
  assert( sca.find(ca4) != sca.end() );
 | 
			
		||||
  assert( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) );
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  //  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 );
 | 
			
		||||
 | 
			
		||||
  assert( udta[0].value() == 111 );
 | 
			
		||||
  assert( udta[1].value() == 222 );
 | 
			
		||||
  assert( udta[2].value() == 333 );
 | 
			
		||||
  assert( udta2[0].value() == 111 );
 | 
			
		||||
  assert( udta2[1].value() == 222 );
 | 
			
		||||
  assert( udta2[2].value() == 333 );
 | 
			
		||||
  udta2.reset();
 | 
			
		||||
  assert( udta2.get() == 0 );
 | 
			
		||||
  assert( udta.use_count() == 1 );
 | 
			
		||||
  assert( udta2.use_count() == 1 );
 | 
			
		||||
 | 
			
		||||
  assert( UDT_use_count == 4 );  // reality check
 | 
			
		||||
 | 
			
		||||
  //  test shared_ptr with a user defined type
 | 
			
		||||
  UDT * up = new UDT;
 | 
			
		||||
  shared_ptr<UDT> sup ( up );
 | 
			
		||||
  assert( up == sup.get() );
 | 
			
		||||
  assert( sup.use_count() == 1 );
 | 
			
		||||
 | 
			
		||||
  sup->value( 54321 ) ;
 | 
			
		||||
  assert( sup->value() == 54321 );
 | 
			
		||||
  assert( up->value() == 54321 );
 | 
			
		||||
 | 
			
		||||
  shared_ptr<UDT> sup2;
 | 
			
		||||
  sup2 = sup;
 | 
			
		||||
  assert( sup2->value() == 54321 );
 | 
			
		||||
  assert( sup.use_count() == 2 );
 | 
			
		||||
  assert( sup2.use_count() == 2 );
 | 
			
		||||
  sup2 = sup2;
 | 
			
		||||
  assert( sup2->value() == 54321 );
 | 
			
		||||
  assert( sup.use_count() == 2 );
 | 
			
		||||
  assert( sup2.use_count() == 2 );
 | 
			
		||||
 | 
			
		||||
  cout << "OK" << endl;
 | 
			
		||||
 | 
			
		||||
  new char[12345]; // deliberate memory leak to verify leaks detected
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
  } // main
 | 
			
		||||
 | 
			
		||||
@@ -1,15 +1,13 @@
 | 
			
		||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 | 
			
		||||
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<title>Smart Pointer Timings</title>
 | 
			
		||||
<title>boost: smart pointer tests</title>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<!--
 | 
			
		||||
-->
 | 
			
		||||
<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="center" WIDTH="277" HEIGHT="86">Smart
 | 
			
		||||
Pointers 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 
 | 
			
		||||
@@ -21,10 +19,9 @@
 | 
			
		||||
  mailing list and the tests which this page describes were performed to provide 
 | 
			
		||||
  a guide for current and future investigations into smart pointer implementation 
 | 
			
		||||
  strategies.</p>
 | 
			
		||||
<p>Thanks are due to <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>,
 | 
			
		||||
Gavin Collings,
 | 
			
		||||
<a href="../../people/greg_colvin.htm">Greg Colvin</a> and
 | 
			
		||||
<a href="../../people/beman_dawes.html">Beman Dawes</a> 
 | 
			
		||||
<p>Thanks are due to <a href="../../people/dave_abrahams.htm"> Dave Abrahams</a>,
 | 
			
		||||
<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 
 | 
			
		||||
  in .zip format <a href="smarttest.zip">here</a>.</p>
 | 
			
		||||
<h2>Description</h2>
 | 
			
		||||
@@ -78,7 +75,7 @@ Gavin Collings,
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr> 
 | 
			
		||||
    <td width="20">  </td>
 | 
			
		||||
    <td><img src="msvcspeed.gif" width="560" height="355" alt="MSVC speed graph"></td>
 | 
			
		||||
    <td><img src="msvcspeed.gif" width="560" height="355"></td>
 | 
			
		||||
    <td width="20"> </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr> 
 | 
			
		||||
@@ -88,7 +85,7 @@ Gavin Collings,
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr> 
 | 
			
		||||
    <td> </td>
 | 
			
		||||
    <td><img src="gccspeed.gif" width="560" height="355" alt="GCC speed graph"></td>
 | 
			
		||||
    <td><img src="gccspeed.gif" width="560" height="355"></td>
 | 
			
		||||
    <td> </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr> 
 | 
			
		||||
@@ -533,7 +530,7 @@ Gavin Collings,
 | 
			
		||||
    spreads its information as in the case of linked pointer.</li>
 | 
			
		||||
</ul>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->19 August 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" -->
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %b %Y" startspan -->21 Feb 2000<!--webbot bot="Timestamp" endspan i-checksum="14372" -->
 | 
			
		||||
</p>
 | 
			
		||||
<p><EFBFBD> Copyright Gavin Collings 2000. Permission to copy, use, modify, sell
 | 
			
		||||
and distribute this document is granted provided this copyright notice appears in all
 | 
			
		||||
 
 | 
			
		||||
@@ -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<void></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<FILE> fopen(char const * name, char const * mode);
 | 
			
		||||
void fread(shared_ptr<FILE> 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<X></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<impl> 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 &);
 | 
			
		||||
    impl & operator=(impl const &);
 | 
			
		||||
 | 
			
		||||
    // private data
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    impl(char const * name, char const * mode) { ... }
 | 
			
		||||
    ~impl() { ... }
 | 
			
		||||
    void read(void * data, size_t size) { ... }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
file::file(char const * name, char const * mode): pimpl_(new impl(name, mode))
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void file::read(void * data, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    pimpl_->read(data, size);
 | 
			
		||||
}
 | 
			
		||||
</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<X> createX();
 | 
			
		||||
</pre>
 | 
			
		||||
		<pre>-- X.cpp:
 | 
			
		||||
 | 
			
		||||
class X_impl: public X
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    X_impl(X_impl const &);
 | 
			
		||||
    X_impl & operator=(X_impl const &);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    virtual void f()
 | 
			
		||||
    {
 | 
			
		||||
      // ...
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void g()
 | 
			
		||||
    {
 | 
			
		||||
      // ...
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
shared_ptr<X> createX()
 | 
			
		||||
{
 | 
			
		||||
    shared_ptr<X> px(new X_impl);
 | 
			
		||||
    return px;
 | 
			
		||||
}
 | 
			
		||||
</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<X></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<X> create()
 | 
			
		||||
    {
 | 
			
		||||
        shared_ptr<X> 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<X> px(new X[1], <A href="../utility/checked_delete.html" >checked_array_deleter</A><X>());
 | 
			
		||||
</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-></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<X> createX()
 | 
			
		||||
{
 | 
			
		||||
    shared_ptr<X> 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<X> 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<X> createX()
 | 
			
		||||
{
 | 
			
		||||
    shared_ptr<X> px(&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<IWhatever> make_shared_from_COM(IWhatever * p)
 | 
			
		||||
{
 | 
			
		||||
    p->AddRef();
 | 
			
		||||
    shared_ptr<IWhatever> pw(p, <A href="../bind/mem_fn.html" >mem_fn</A>(&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<class T> struct intrusive_deleter
 | 
			
		||||
{
 | 
			
		||||
    void operator()(T * p)
 | 
			
		||||
    {
 | 
			
		||||
        if(p) intrusive_ptr_release(p);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
shared_ptr<X> make_shared_from_intrusive(X * p)
 | 
			
		||||
{
 | 
			
		||||
    if(p) intrusive_ptr_add_ref(p);
 | 
			
		||||
    shared_ptr<X> px(p, intrusive_deleter<X>());
 | 
			
		||||
    return px;
 | 
			
		||||
}
 | 
			
		||||
</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<class P> struct smart_pointer_deleter
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    P p_;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    smart_pointer_deleter(P const & p): p_(p)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void operator()(void const *)
 | 
			
		||||
    {
 | 
			
		||||
        p_.reset();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    P const & get() const
 | 
			
		||||
    {
 | 
			
		||||
        return p_;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
shared_ptr<X> make_shared_from_another(another_ptr<X> qx)
 | 
			
		||||
{
 | 
			
		||||
    shared_ptr<X> px(qx.get(), smart_pointer_deleter< another_ptr<X> >(qx));
 | 
			
		||||
    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<X> px)
 | 
			
		||||
{
 | 
			
		||||
    typedef smart_pointer_deleter< another_ptr<X> > deleter;
 | 
			
		||||
 | 
			
		||||
    if(deleter const * pd = get_deleter<deleter>(px))
 | 
			
		||||
    {
 | 
			
		||||
        another_ptr<X> qx = pd->get();
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        // not one of ours
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
</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<X> 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<X> 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<X> 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<X> 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<X> 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<X> create()
 | 
			
		||||
    {
 | 
			
		||||
        shared_ptr<X> 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<X> getX() = 0;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
    ~Y() {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// --
 | 
			
		||||
 | 
			
		||||
class impl: public X, public Y
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    impl() { ... }
 | 
			
		||||
 | 
			
		||||
    virtual void f() { ... }
 | 
			
		||||
 | 
			
		||||
    virtual shared_ptr<X> getX()
 | 
			
		||||
    {
 | 
			
		||||
        shared_ptr<X> px(<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<impl> weak_this;
 | 
			
		||||
 | 
			
		||||
    impl(impl const &);
 | 
			
		||||
    impl & operator=(impl const &);
 | 
			
		||||
 | 
			
		||||
    impl() { ... }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    static shared_ptr<impl> create()
 | 
			
		||||
    {
 | 
			
		||||
        shared_ptr<impl> pi(new impl);
 | 
			
		||||
        pi->weak_this = pi;
 | 
			
		||||
        return pi;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void f() { ... }
 | 
			
		||||
 | 
			
		||||
    virtual shared_ptr<X> getX()
 | 
			
		||||
    {
 | 
			
		||||
        shared_ptr<X> px(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<impl>
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    impl(impl const &);
 | 
			
		||||
    impl & operator=(impl const &);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    virtual void f() { ... }
 | 
			
		||||
 | 
			
		||||
    virtual shared_ptr<X> 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<void> handle;
 | 
			
		||||
 | 
			
		||||
handle createProcess()
 | 
			
		||||
{
 | 
			
		||||
    shared_ptr<void> 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<void></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<void> guard(p, f);
 | 
			
		||||
</pre>
 | 
			
		||||
		<UL>
 | 
			
		||||
			<LI>
 | 
			
		||||
				Executing arbitrary code: <code>f(x, y)</code>:</LI></UL>
 | 
			
		||||
		<pre>    shared_ptr<void> guard(static_cast<void*>(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<void></code> to hold an arbitrary 
 | 
			
		||||
				object</A></h2>
 | 
			
		||||
		<p><code>shared_ptr<void></code> can act as a generic object pointer similar 
 | 
			
		||||
			to <code>void*</code>. When a <code>shared_ptr<void></code> instance 
 | 
			
		||||
			constructed as:</p>
 | 
			
		||||
		<pre>    shared_ptr<void> 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<void></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<</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< shared_ptr<void>, Data > userData;
 | 
			
		||||
// or std::map< weak_ptr<void>, Data > userData; to not affect the lifetime
 | 
			
		||||
 | 
			
		||||
shared_ptr<X> px(new X);
 | 
			
		||||
shared_ptr<int> pi(new int(3));
 | 
			
		||||
 | 
			
		||||
userData[px] = 42;
 | 
			
		||||
userData[pi] = 91;
 | 
			
		||||
</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<mutex> lock(mutex & m)
 | 
			
		||||
{
 | 
			
		||||
    m.lock();
 | 
			
		||||
    return shared_ptr<mutex>(&m, mem_fn(&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<void> pv;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    template<class Mutex> explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&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<void></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<class T> class pointer
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    T * p_;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    explicit pointer(T * p): p_(p)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    shared_ptr<T> operator->() const
 | 
			
		||||
    {
 | 
			
		||||
        p_->prefix();
 | 
			
		||||
        return shared_ptr<T>(p_, <A href="../bind/mem_fn.html" >mem_fn</A>(&T::suffix));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class X
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    void prefix();
 | 
			
		||||
    void suffix();
 | 
			
		||||
    friend class pointer<X>;
 | 
			
		||||
    
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    void f();
 | 
			
		||||
    void g();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    X x;
 | 
			
		||||
 | 
			
		||||
    pointer<X> px(&x);
 | 
			
		||||
 | 
			
		||||
    px->f();
 | 
			
		||||
    px->g();
 | 
			
		||||
}
 | 
			
		||||
</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<X> 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< shared_ptr<void> > free_list;
 | 
			
		||||
 | 
			
		||||
class Y
 | 
			
		||||
{
 | 
			
		||||
    shared_ptr<X> px;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    void f()
 | 
			
		||||
    {
 | 
			
		||||
        free_list.push_back(px);
 | 
			
		||||
        px.reset();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// periodically invoke free_list.clear() when convenient
 | 
			
		||||
</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<class T> void operator()(T * p)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            shared_ptr<void> 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<X> this_;
 | 
			
		||||
    int i_;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    explicit X(int i): this_(this, null_deleter()), i_(i)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // repeat in all constructors (including the copy constructor!)
 | 
			
		||||
 | 
			
		||||
    X(X const & rhs): this_(this, null_deleter()), i_(rhs.i_)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // do not forget to not assign this_ in the copy assignment
 | 
			
		||||
 | 
			
		||||
    X & operator=(X const & rhs)
 | 
			
		||||
    {
 | 
			
		||||
	    i_ = rhs.i_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    weak_ptr<X> get_weak_ptr() const { return this_; }
 | 
			
		||||
};
 | 
			
		||||
</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>
 | 
			
		||||
@@ -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)
 | 
			
		||||
@@ -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)
 | 
			
		||||
							
								
								
									
										44
									
								
								test/Jamfile
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								test/Jamfile
									
									
									
									
									
								
							@@ -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 ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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 ]
 | 
			
		||||
        ;
 | 
			
		||||
}
 | 
			
		||||
@@ -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();
 | 
			
		||||
}
 | 
			
		||||
@@ -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();
 | 
			
		||||
}
 | 
			
		||||
@@ -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();
 | 
			
		||||
}
 | 
			
		||||
@@ -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();
 | 
			
		||||
}
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
@@ -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()");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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>();
 | 
			
		||||
}
 | 
			
		||||
@@ -1,32 +0,0 @@
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC)
 | 
			
		||||
#pragma warning(disable: 4786)  // identifier truncated in debug info
 | 
			
		||||
#pragma warning(disable: 4710)  // function not inlined
 | 
			
		||||
#pragma warning(disable: 4711)  // function selected for automatic inline expansion
 | 
			
		||||
#pragma warning(disable: 4514)  // unreferenced inline removed
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  shared_ptr_assign_fail.cpp - a negative test for shared_ptr assignment
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
 | 
			
		||||
//
 | 
			
		||||
// Distributed under the Boost 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>
 | 
			
		||||
 | 
			
		||||
bool boost_error(char const *, char const *, char const *, long)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    boost::shared_ptr<int> p;
 | 
			
		||||
    p = new int(42); // assignment must fail
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,299 +0,0 @@
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC)
 | 
			
		||||
 | 
			
		||||
#pragma warning(disable: 4786)  // identifier truncated in debug info
 | 
			
		||||
#pragma warning(disable: 4710)  // function not inlined
 | 
			
		||||
#pragma warning(disable: 4711)  // function selected for automatic inline expansion
 | 
			
		||||
#pragma warning(disable: 4514)  // unreferenced inline removed
 | 
			
		||||
#pragma warning(disable: 4355)  // 'this' : used in base member initializer list
 | 
			
		||||
 | 
			
		||||
#if (BOOST_MSVC >= 1310)
 | 
			
		||||
#pragma warning(disable: 4675)  // resolved overload found with Koenig lookup
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  shared_ptr_basic_test.cpp
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
 | 
			
		||||
//
 | 
			
		||||
// Distributed under the Boost 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/shared_ptr.hpp>
 | 
			
		||||
#include <boost/weak_ptr.hpp>
 | 
			
		||||
 | 
			
		||||
int cnt = 0;
 | 
			
		||||
 | 
			
		||||
struct X
 | 
			
		||||
{
 | 
			
		||||
    X()
 | 
			
		||||
    {
 | 
			
		||||
        ++cnt;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~X() // virtual destructor deliberately omitted
 | 
			
		||||
    {
 | 
			
		||||
        --cnt;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int id() const
 | 
			
		||||
    {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    X(X const &);
 | 
			
		||||
    X & operator= (X const &);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Y: public X
 | 
			
		||||
{
 | 
			
		||||
    Y()
 | 
			
		||||
    {
 | 
			
		||||
        ++cnt;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~Y()
 | 
			
		||||
    {
 | 
			
		||||
        --cnt;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual int id() const
 | 
			
		||||
    {
 | 
			
		||||
        return 2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    Y(Y const &);
 | 
			
		||||
    Y & operator= (Y const &);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int * get_object()
 | 
			
		||||
{
 | 
			
		||||
    ++cnt;
 | 
			
		||||
    return &cnt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void release_object(int * p)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_TEST(p == &cnt);
 | 
			
		||||
    --cnt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> void test_is_X(boost::shared_ptr<T> const & p)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_TEST(p->id() == 1);
 | 
			
		||||
    BOOST_TEST((*p).id() == 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> void test_is_X(boost::weak_ptr<T> const & p)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_TEST(p.get() != 0);
 | 
			
		||||
    BOOST_TEST(p.get()->id() == 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> void test_is_Y(boost::shared_ptr<T> const & p)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_TEST(p->id() == 2);
 | 
			
		||||
    BOOST_TEST((*p).id() == 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> void test_is_Y(boost::weak_ptr<T> const & p)
 | 
			
		||||
{
 | 
			
		||||
    boost::shared_ptr<T> q = p.lock();
 | 
			
		||||
    BOOST_TEST(q.get() != 0);
 | 
			
		||||
    BOOST_TEST(q->id() == 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> void test_eq(T const & a, T const & b)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_TEST(a == b);
 | 
			
		||||
    BOOST_TEST(!(a != b));
 | 
			
		||||
    BOOST_TEST(!(a < b));
 | 
			
		||||
    BOOST_TEST(!(b < a));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> void test_ne(T const & a, T const & b)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_TEST(!(a == b));
 | 
			
		||||
    BOOST_TEST(a != b);
 | 
			
		||||
    BOOST_TEST(a < b || b < a);
 | 
			
		||||
    BOOST_TEST(!(a < b && b < a));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> void test_shared(boost::weak_ptr<T> const & a, boost::weak_ptr<U> const & b)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_TEST(!(a < b));
 | 
			
		||||
    BOOST_TEST(!(b < a));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> void test_nonshared(boost::weak_ptr<T> const & a, boost::weak_ptr<U> const & b)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_TEST(a < b || b < a);
 | 
			
		||||
    BOOST_TEST(!(a < b && b < a));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> void test_eq2(T const & a, U const & b)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_TEST(a == b);
 | 
			
		||||
    BOOST_TEST(!(a != b));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> void test_ne2(T const & a, U const & b)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_TEST(!(a == b));
 | 
			
		||||
    BOOST_TEST(a != b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> void test_is_zero(boost::shared_ptr<T> const & p)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_TEST(!p);
 | 
			
		||||
    BOOST_TEST(p.get() == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> void test_is_nonzero(boost::shared_ptr<T> const & p)
 | 
			
		||||
{
 | 
			
		||||
    // p? true: false is used to test p in a boolean context.
 | 
			
		||||
    // BOOST_TEST(p) is not guaranteed to test the conversion,
 | 
			
		||||
    // as the macro might test !!p instead.
 | 
			
		||||
    BOOST_TEST(p? true: false);
 | 
			
		||||
    BOOST_TEST(p.get() != 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    using namespace boost;
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        shared_ptr<X> p(new Y);
 | 
			
		||||
        shared_ptr<X> p2(new X);
 | 
			
		||||
 | 
			
		||||
        test_is_nonzero(p);
 | 
			
		||||
        test_is_nonzero(p2);
 | 
			
		||||
        test_is_Y(p);
 | 
			
		||||
        test_is_X(p2);
 | 
			
		||||
        test_ne(p, p2);
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            shared_ptr<X> q(p);
 | 
			
		||||
            test_eq(p, q);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        shared_ptr<Y> p3 = dynamic_pointer_cast<Y>(p);
 | 
			
		||||
        shared_ptr<Y> p4 = dynamic_pointer_cast<Y>(p2);
 | 
			
		||||
 | 
			
		||||
        test_is_nonzero(p3);
 | 
			
		||||
        test_is_zero(p4);
 | 
			
		||||
 | 
			
		||||
        BOOST_TEST(p.use_count() == 2);
 | 
			
		||||
        BOOST_TEST(p2.use_count() == 1);
 | 
			
		||||
        BOOST_TEST(p3.use_count() == 2);
 | 
			
		||||
 | 
			
		||||
        test_is_Y(p3);
 | 
			
		||||
        test_eq2(p, p3);
 | 
			
		||||
        test_ne2(p2, p4);
 | 
			
		||||
 | 
			
		||||
        shared_ptr<void> p5(p);
 | 
			
		||||
 | 
			
		||||
        test_is_nonzero(p5);
 | 
			
		||||
        test_eq2(p, p5);
 | 
			
		||||
 | 
			
		||||
        weak_ptr<X> wp1(p2);
 | 
			
		||||
 | 
			
		||||
        BOOST_TEST(!wp1.expired());
 | 
			
		||||
        BOOST_TEST(wp1.use_count() != 0);
 | 
			
		||||
 | 
			
		||||
        p.reset();
 | 
			
		||||
        p2.reset();
 | 
			
		||||
        p3.reset();
 | 
			
		||||
        p4.reset();
 | 
			
		||||
 | 
			
		||||
        test_is_zero(p);
 | 
			
		||||
        test_is_zero(p2);
 | 
			
		||||
        test_is_zero(p3);
 | 
			
		||||
        test_is_zero(p4);
 | 
			
		||||
 | 
			
		||||
        BOOST_TEST(p5.use_count() == 1);
 | 
			
		||||
 | 
			
		||||
        BOOST_TEST(wp1.expired());
 | 
			
		||||
        BOOST_TEST(wp1.use_count() == 0);
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            shared_ptr<X> sp1(wp1);
 | 
			
		||||
            BOOST_ERROR("shared_ptr<X> sp1(wp1) failed to throw");
 | 
			
		||||
        }
 | 
			
		||||
        catch(boost::bad_weak_ptr const &)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        test_is_zero(wp1.lock());
 | 
			
		||||
 | 
			
		||||
        weak_ptr<X> wp2 = static_pointer_cast<X>(p5);
 | 
			
		||||
 | 
			
		||||
        BOOST_TEST(wp2.use_count() == 1);
 | 
			
		||||
        test_is_Y(wp2);
 | 
			
		||||
        test_nonshared(wp1, wp2);
 | 
			
		||||
 | 
			
		||||
        // Scoped to not affect the subsequent use_count() tests.
 | 
			
		||||
        {
 | 
			
		||||
            shared_ptr<X> sp2(wp2);
 | 
			
		||||
            test_is_nonzero(wp2.lock());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        weak_ptr<Y> wp3 = dynamic_pointer_cast<Y>(wp2.lock());
 | 
			
		||||
 | 
			
		||||
        BOOST_TEST(wp3.use_count() == 1);
 | 
			
		||||
        test_shared(wp2, wp3);
 | 
			
		||||
 | 
			
		||||
        weak_ptr<X> wp4(wp3);
 | 
			
		||||
 | 
			
		||||
        BOOST_TEST(wp4.use_count() == 1);
 | 
			
		||||
        test_shared(wp2, wp4);
 | 
			
		||||
 | 
			
		||||
        wp1 = p2;
 | 
			
		||||
        test_is_zero(wp1.lock());
 | 
			
		||||
 | 
			
		||||
        wp1 = p4;
 | 
			
		||||
        wp1 = wp3;
 | 
			
		||||
        wp1 = wp2;
 | 
			
		||||
 | 
			
		||||
        BOOST_TEST(wp1.use_count() == 1);
 | 
			
		||||
        test_shared(wp1, wp2);
 | 
			
		||||
 | 
			
		||||
        weak_ptr<X> wp5;
 | 
			
		||||
 | 
			
		||||
        bool b1 = wp1 < wp5;
 | 
			
		||||
        bool b2 = wp5 < wp1;
 | 
			
		||||
 | 
			
		||||
        p5.reset();
 | 
			
		||||
 | 
			
		||||
        BOOST_TEST(wp1.use_count() == 0);
 | 
			
		||||
        BOOST_TEST(wp2.use_count() == 0);
 | 
			
		||||
        BOOST_TEST(wp3.use_count() == 0);
 | 
			
		||||
 | 
			
		||||
        // Test operator< stability for std::set< weak_ptr<> >
 | 
			
		||||
        // Thanks to Joe Gottman for pointing this out
 | 
			
		||||
 | 
			
		||||
        BOOST_TEST(b1 == (wp1 < wp5));
 | 
			
		||||
        BOOST_TEST(b2 == (wp5 < wp1));
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            // note that both get_object and release_object deal with int*
 | 
			
		||||
            shared_ptr<void> p6(get_object(), release_object);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST(cnt == 0);
 | 
			
		||||
 | 
			
		||||
    return boost::report_errors();
 | 
			
		||||
}
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,173 +0,0 @@
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC)
 | 
			
		||||
#pragma warning(disable: 4786)  // identifier truncated in debug info
 | 
			
		||||
#pragma warning(disable: 4710)  // function not inlined
 | 
			
		||||
#pragma warning(disable: 4711)  // function selected for automatic inline expansion
 | 
			
		||||
#pragma warning(disable: 4514)  // unreferenced inline removed
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  shared_ptr_mt_test.cpp - tests shared_ptr with multiple threads
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
 | 
			
		||||
//
 | 
			
		||||
// Distributed under the Boost 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/bind.hpp>
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <ctime>
 | 
			
		||||
 | 
			
		||||
// 'portable' thread framework
 | 
			
		||||
 | 
			
		||||
class abstract_thread
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    virtual ~abstract_thread() {}
 | 
			
		||||
    virtual void run() = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if !defined(BOOST_HAS_PTHREADS) && defined(BOOST_HAS_WINTHREADS)
 | 
			
		||||
 | 
			
		||||
char const * title = "Using Windows threads";
 | 
			
		||||
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
#include <process.h>
 | 
			
		||||
 | 
			
		||||
typedef HANDLE pthread_t;
 | 
			
		||||
 | 
			
		||||
unsigned __stdcall common_thread_routine(void * pv)
 | 
			
		||||
{
 | 
			
		||||
    abstract_thread * pt = static_cast<abstract_thread *>(pv);
 | 
			
		||||
    pt->run();
 | 
			
		||||
    delete pt;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pthread_create(pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg)
 | 
			
		||||
{
 | 
			
		||||
    HANDLE h = (HANDLE)_beginthreadex(0, 0, start_routine, arg, 0, 0);
 | 
			
		||||
 | 
			
		||||
    if(h != 0)
 | 
			
		||||
    {
 | 
			
		||||
        *thread = h;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        return 1; // return errno;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pthread_join(pthread_t thread, void ** /*value_ptr*/)
 | 
			
		||||
{
 | 
			
		||||
    ::WaitForSingleObject(thread, INFINITE);
 | 
			
		||||
    ::CloseHandle(thread);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
char const * title = "Using POSIX threads";
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
extern "C" void * common_thread_routine(void * pv)
 | 
			
		||||
{
 | 
			
		||||
    abstract_thread * pt = static_cast<abstract_thread *>(pv);
 | 
			
		||||
    pt->run();
 | 
			
		||||
    delete pt;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
template<class F> class thread: public abstract_thread
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    explicit thread(F f): f_(f)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void run()
 | 
			
		||||
    {
 | 
			
		||||
        f_();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    F f_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<class F> pthread_t createThread(F f)
 | 
			
		||||
{
 | 
			
		||||
    std::auto_ptr<abstract_thread> p(new thread<F>(f));
 | 
			
		||||
 | 
			
		||||
    pthread_t r;
 | 
			
		||||
 | 
			
		||||
    if(pthread_create(&r, 0, common_thread_routine, p.get()) == 0)
 | 
			
		||||
    {
 | 
			
		||||
        p.release();
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    throw std::runtime_error("createThread failed.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
int const n = 1024 * 1024;
 | 
			
		||||
 | 
			
		||||
void test(boost::shared_ptr<int> const & pi)
 | 
			
		||||
{
 | 
			
		||||
    std::vector< boost::shared_ptr<int> > v;
 | 
			
		||||
 | 
			
		||||
    for(int i = 0; i < n; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        v.push_back(pi);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int const m = 16; // threads
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    using namespace std; // printf, clock_t, clock
 | 
			
		||||
 | 
			
		||||
    printf("%s: %d threads, %d iterations: ", title, m, n);
 | 
			
		||||
 | 
			
		||||
    boost::shared_ptr<int> pi(new int(42));
 | 
			
		||||
 | 
			
		||||
    clock_t t = clock();
 | 
			
		||||
 | 
			
		||||
    pthread_t a[m];
 | 
			
		||||
 | 
			
		||||
    for(int i = 0; i < m; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        a[i] = createThread( boost::bind(test, pi) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for(int j = 0; j < m; ++j)
 | 
			
		||||
    {
 | 
			
		||||
        pthread_join(a[j], 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    t = clock() - t;
 | 
			
		||||
 | 
			
		||||
    printf("\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,46 +0,0 @@
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC)
 | 
			
		||||
#pragma warning(disable: 4786)  // identifier truncated in debug info
 | 
			
		||||
#pragma warning(disable: 4710)  // function not inlined
 | 
			
		||||
#pragma warning(disable: 4711)  // function selected for automatic inline expansion
 | 
			
		||||
#pragma warning(disable: 4514)  // unreferenced inline removed
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  shared_ptr_timing_test.cpp - use to evaluate the impact of thread safety
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
 | 
			
		||||
//
 | 
			
		||||
// Distributed under the Boost 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 <iostream>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <ctime>
 | 
			
		||||
 | 
			
		||||
int const n = 8 * 1024 * 1024;
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    using namespace std;
 | 
			
		||||
 | 
			
		||||
    std::vector< boost::shared_ptr<int> > v;
 | 
			
		||||
    boost::shared_ptr<int> pi(new int);
 | 
			
		||||
 | 
			
		||||
    clock_t t = clock();
 | 
			
		||||
 | 
			
		||||
    for(int i = 0; i < n; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        v.push_back(pi);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    t = clock() - t;
 | 
			
		||||
 | 
			
		||||
    std::cout << static_cast<double>(t) / CLOCKS_PER_SEC << '\n';
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -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();
 | 
			
		||||
}
 | 
			
		||||
@@ -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
											
										
									
								
							@@ -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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										244
									
								
								weak_ptr.htm
									
									
									
									
									
								
							
							
						
						
									
										244
									
								
								weak_ptr.htm
									
									
									
									
									
								
							@@ -1,244 +0,0 @@
 | 
			
		||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 | 
			
		||||
<html>
 | 
			
		||||
	<head>
 | 
			
		||||
		<title>weak_ptr</title>
 | 
			
		||||
		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 | 
			
		||||
	</head>
 | 
			
		||||
	<body text="#000000" bgColor="#ffffff">
 | 
			
		||||
		<h1><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle">weak_ptr 
 | 
			
		||||
			class template</h1>
 | 
			
		||||
		<p><A href="#Introduction">Introduction</A><br>
 | 
			
		||||
			<A href="#Synopsis">Synopsis</A><br>
 | 
			
		||||
			<A href="#Members">Members</A><br>
 | 
			
		||||
			<A href="#functions">Free Functions</A><br>
 | 
			
		||||
			<A href="#FAQ">Frequently Asked Questions</A>
 | 
			
		||||
		</p>
 | 
			
		||||
		<h2><a name="Introduction">Introduction</a></h2>
 | 
			
		||||
		<p>The <b>weak_ptr</b> class template stores a "weak reference" to an object that's 
 | 
			
		||||
			already managed by a <b>shared_ptr</b>. To access the object, a <STRONG>weak_ptr</STRONG>
 | 
			
		||||
			can be converted to a <STRONG>shared_ptr</STRONG> using <A href="shared_ptr.htm#constructors">
 | 
			
		||||
				the <STRONG>shared_ptr</STRONG> constructor</A> or the member function <STRONG><A href="#lock">
 | 
			
		||||
					lock</A></STRONG>. When the last <b>shared_ptr</b> to the object goes 
 | 
			
		||||
			away and the object is deleted, the attempt to obtain a <STRONG>shared_ptr</STRONG>
 | 
			
		||||
			from the <b>weak_ptr</b> instances that refer to the deleted object will fail: 
 | 
			
		||||
			the constructor will throw an exception of type <STRONG>boost::bad_weak_ptr</STRONG>, 
 | 
			
		||||
			and <STRONG>weak_ptr::lock</STRONG> will return an <EM>empty</EM> <STRONG>shared_ptr</STRONG>.</p>
 | 
			
		||||
		<p>Every <b>weak_ptr</b> meets the <b>CopyConstructible</b> and <b>Assignable</b> requirements 
 | 
			
		||||
			of the C++ Standard Library, and so can be used in standard library containers. 
 | 
			
		||||
			Comparison operators are supplied so that <b>weak_ptr</b> works with the 
 | 
			
		||||
			standard library's associative containers.</p>
 | 
			
		||||
		<P><STRONG>weak_ptr</STRONG> operations never throw 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<int> p(new int(5));
 | 
			
		||||
weak_ptr<int> q(p);
 | 
			
		||||
 | 
			
		||||
// some time later
 | 
			
		||||
 | 
			
		||||
if(int * r = q.get())
 | 
			
		||||
{
 | 
			
		||||
    // use *r
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
		<P>Imagine that after the <STRONG>if</STRONG>, but immediately before <STRONG>r</STRONG>
 | 
			
		||||
			is used, another thread executes the statement <code>p.reset()</code>. Now <STRONG>r</STRONG>
 | 
			
		||||
			is a dangling pointer.</P>
 | 
			
		||||
		<P>The solution to this problem is to create a temporary <STRONG>shared_ptr</STRONG>
 | 
			
		||||
			from <STRONG>q</STRONG>:</P>
 | 
			
		||||
		<pre>shared_ptr<int> p(new int(5));
 | 
			
		||||
weak_ptr<int> q(p);
 | 
			
		||||
 | 
			
		||||
// some time later
 | 
			
		||||
 | 
			
		||||
if(shared_ptr<int> r = q.<A href="#lock" >lock</A>())
 | 
			
		||||
{
 | 
			
		||||
    // 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>
 | 
			
		||||
		<h2><a name="Synopsis">Synopsis</a></h2>
 | 
			
		||||
		<pre>namespace boost {
 | 
			
		||||
 | 
			
		||||
  template<class T> class weak_ptr {
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      typedef T <A href="#element_type" >element_type</A>;
 | 
			
		||||
 | 
			
		||||
      <A href="#default-constructor" >weak_ptr</A>();
 | 
			
		||||
 | 
			
		||||
      template<class Y> <A href="#constructors" >weak_ptr</A>(shared_ptr<Y> const & r);
 | 
			
		||||
      <A href="#constructors" >weak_ptr</A>(weak_ptr const & r);
 | 
			
		||||
      template<class Y> <A href="#constructors" >weak_ptr</A>(weak_ptr<Y> const & r);
 | 
			
		||||
 | 
			
		||||
      <A href="#destructor" >~weak_ptr</A>();
 | 
			
		||||
 | 
			
		||||
      weak_ptr & <A href="#assignment" >operator=</A>(weak_ptr const & r);
 | 
			
		||||
      template<class Y> weak_ptr & <A href="#assignment" >operator=</A>(weak_ptr<Y> const & r);
 | 
			
		||||
      template<class Y> weak_ptr & <A href="#assignment" >operator=</A>(shared_ptr<Y> const & r);
 | 
			
		||||
 | 
			
		||||
      long <A href="#use_count" >use_count</A>() const;
 | 
			
		||||
      bool <A href="#expired" >expired</A>() const;
 | 
			
		||||
      shared_ptr<T> <A href="#lock" >lock</A>() const;
 | 
			
		||||
 | 
			
		||||
      void <A href="#reset" >reset</A>();
 | 
			
		||||
      void <A href="#swap" >swap</A>(weak_ptr<T> & b);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  template<class T, class U>
 | 
			
		||||
    bool <A href="#comparison" >operator<</A>(weak_ptr<T> const & a, weak_ptr<U> const & b);
 | 
			
		||||
 | 
			
		||||
  template<class T>
 | 
			
		||||
    void <A href="#free-swap" >swap</A>(weak_ptr<T> & a, weak_ptr<T> & b);
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
		<h2><a name="Members">Members</a></h2>
 | 
			
		||||
		<h3><a name="element_type">element_type</a></h3>
 | 
			
		||||
		<pre>typedef T element_type;</pre>
 | 
			
		||||
		<blockquote>
 | 
			
		||||
			<p>Provides the type of the template parameter T.</p>
 | 
			
		||||
		</blockquote>
 | 
			
		||||
		<h3><a name="default-constructor">constructors</a></h3>
 | 
			
		||||
		<pre>weak_ptr();</pre>
 | 
			
		||||
		<blockquote>
 | 
			
		||||
			<p><b>Effects:</b> Constructs an <EM>empty</EM> <b>weak_ptr</b>.</p>
 | 
			
		||||
			<p><b>Postconditions:</b> <code>use_count() == 0</code>.</p>
 | 
			
		||||
			<p><b>Throws:</b> nothing.</p>
 | 
			
		||||
		</blockquote><a name="constructors"></a>
 | 
			
		||||
		<pre>template<class Y> weak_ptr</A>(shared_ptr<Y> const & r);
 | 
			
		||||
weak_ptr(weak_ptr const & r);
 | 
			
		||||
template<class Y> weak_ptr(weak_ptr<Y> const & r);</pre>
 | 
			
		||||
		<blockquote>
 | 
			
		||||
			<p><b>Effects:</b> If <STRONG>r</STRONG> is <EM>empty</EM>, constructs an <EM>empty</EM>
 | 
			
		||||
				<STRONG>weak_ptr</STRONG>; otherwise, constructs a <b>weak_ptr</b> that <EM>shares 
 | 
			
		||||
					ownership</EM> with <STRONG>r</STRONG> as if by storing a copy of the 
 | 
			
		||||
				pointer stored in <b>r</b>.</p>
 | 
			
		||||
			<p><b>Postconditions:</b> <code>use_count() == r.use_count()</code>.</p>
 | 
			
		||||
			<p><b>Throws:</b> nothing.</p>
 | 
			
		||||
		</blockquote>
 | 
			
		||||
		<h3><a name="destructor">destructor</a></h3>
 | 
			
		||||
		<pre>~weak_ptr();</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<P><B>Effects:</B> Destroys this <b>weak_ptr</b> but has no effect on the object 
 | 
			
		||||
				its stored pointer points to.</P>
 | 
			
		||||
			<P><B>Throws:</B> nothing.</P>
 | 
			
		||||
		</BLOCKQUOTE>
 | 
			
		||||
		<h3><a name="assignment">assignment</a></h3>
 | 
			
		||||
		<pre>weak_ptr & operator=(weak_ptr const & r);
 | 
			
		||||
template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
 | 
			
		||||
template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);</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<T> lock() const;</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<P><B>Returns:</B> <code>expired()? shared_ptr<T>(): shared_ptr<T>(*this)</code>.</P>
 | 
			
		||||
			<P><B>Throws:</B> nothing.</P>
 | 
			
		||||
		</BLOCKQUOTE>
 | 
			
		||||
		<h3><a name="reset">reset</a></h3>
 | 
			
		||||
		<pre>void reset();</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<P><B>Effects:</B> Equivalent to <code>weak_ptr().swap(*this)</code>.</P>
 | 
			
		||||
		</BLOCKQUOTE>
 | 
			
		||||
		<h3><a name="swap">swap</a></h3>
 | 
			
		||||
		<pre>void swap(weak_ptr & b);</pre>
 | 
			
		||||
		<blockquote>
 | 
			
		||||
			<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
 | 
			
		||||
			<p><b>Throws:</b> nothing.</p>
 | 
			
		||||
		</blockquote>
 | 
			
		||||
		<h2><a name="functions">Free Functions</a></h2>
 | 
			
		||||
		<h3><a name="comparison">comparison</a></h3>
 | 
			
		||||
		<pre>template<class T, class U>
 | 
			
		||||
  bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);</pre>
 | 
			
		||||
		<blockquote>
 | 
			
		||||
			<p><b>Returns:</b> an unspecified value such that</p>
 | 
			
		||||
			<UL>
 | 
			
		||||
				<LI>
 | 
			
		||||
					<b>operator<</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<</STRONG>, <code>!(a 
 | 
			
		||||
						< b) && !(b < 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>Throws:</b> nothing.</p>
 | 
			
		||||
			<P><B>Notes:</B> Allows <STRONG>weak_ptr</STRONG> objects to be used as keys in 
 | 
			
		||||
				associative containers.</P>
 | 
			
		||||
		</blockquote>
 | 
			
		||||
		<h3><a name="free-swap">swap</a></h3>
 | 
			
		||||
		<pre>template<class T>
 | 
			
		||||
  void swap(weak_ptr<T> & a, weak_ptr<T> & b)</pre>
 | 
			
		||||
		<BLOCKQUOTE>
 | 
			
		||||
			<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
 | 
			
		||||
			<P><B>Throws:</B> nothing.</P>
 | 
			
		||||
			<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to 
 | 
			
		||||
				generic programming.</P>
 | 
			
		||||
		</BLOCKQUOTE>
 | 
			
		||||
		<h2><a name="FAQ">Frequently Asked Questions</a></h2>
 | 
			
		||||
		<P><B>Q.</B> Can an object create a <STRONG>weak_ptr</STRONG> to itself in its 
 | 
			
		||||
			constructor?</P>
 | 
			
		||||
		<P><b>A.</b> No. A <STRONG>weak_ptr</STRONG> can only be created from a <STRONG>shared_ptr</STRONG>, 
 | 
			
		||||
			and at object construction time no <STRONG>shared_ptr</STRONG> to the object 
 | 
			
		||||
			exists yet. Even if you could create a temporary <STRONG>shared_ptr</STRONG> to <STRONG>
 | 
			
		||||
				this</STRONG>, it would go out of scope at the end of the constructor, and 
 | 
			
		||||
			all <STRONG>weak_ptr</STRONG> instances would instantly expire.</P>
 | 
			
		||||
		<P>The solution is to make the constructor private, and supply a factory function 
 | 
			
		||||
			that returns a <STRONG>shared_ptr</STRONG>:<BR>
 | 
			
		||||
		</P>
 | 
			
		||||
		<pre>
 | 
			
		||||
class X
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    X();
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    static shared_ptr<X> create()
 | 
			
		||||
    {
 | 
			
		||||
        shared_ptr<X> px(new X);
 | 
			
		||||
        // create weak pointers from px here
 | 
			
		||||
        return px;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
</pre>
 | 
			
		||||
		<p><br>
 | 
			
		||||
		</p>
 | 
			
		||||
		<hr>
 | 
			
		||||
		<p>$Date$</p>
 | 
			
		||||
		<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. 
 | 
			
		||||
				Copyright 2002-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>
 | 
			
		||||
		</A>
 | 
			
		||||
	</body>
 | 
			
		||||
</html>
 | 
			
		||||
		Reference in New Issue
	
	Block a user