mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-11-02 16:51:59 +01:00
Compare commits
3 Commits
boost-1.34
...
boost-1.32
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
337e414515 | ||
|
|
aa00436b68 | ||
|
|
8a47b48f0e |
@@ -1,89 +1,105 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Smart Pointer Changes</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body bgcolor="#ffffff" text="#000000">
|
||||
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
|
||||
border="0"></A>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>
|
||||
The <b>weak_ptr</b>
|
||||
template was added.
|
||||
<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>
|
||||
A custom deallocator can be passed in when creating a <b>shared_ptr</b> or <b>shared_array</b>.
|
||||
<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>
|
||||
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>
|
||||
The <b>BOOST_SMART_PTR_CONVERSION</b>
|
||||
feature has been removed.
|
||||
<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>
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
|
||||
<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>
|
||||
|
||||
@@ -7,9 +7,10 @@
|
||||
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
|
||||
<table border="0" width="100%">
|
||||
<tr>
|
||||
<td width="277"><A href="../../index.htm"> <img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86" border="0"></A>
|
||||
<td width="277">
|
||||
<img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86">
|
||||
</td>
|
||||
<td align="center">
|
||||
<td align="middle">
|
||||
<h1>enable_shared_from_this.hpp</h1>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -84,8 +85,9 @@ public:
|
||||
</blockquote>
|
||||
<p>
|
||||
<br>
|
||||
<small>Copyright <20> 2002, 2003 by Peter Dimov. Distributed under the Boost Software License, Version
|
||||
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||
<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>
|
||||
|
||||
@@ -73,6 +73,9 @@
|
||||
// are called driven by smart_ptr interface...
|
||||
//
|
||||
|
||||
// Note: atomic_count_linux.hpp has been disabled by default; see the
|
||||
// comments inside for more info.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
@@ -89,11 +92,13 @@ typedef long atomic_count;
|
||||
|
||||
}
|
||||
|
||||
#elif defined(BOOST_USE_ASM_ATOMIC_H)
|
||||
# include <boost/detail/atomic_count_linux.hpp>
|
||||
#elif defined(BOOST_AC_USE_PTHREADS)
|
||||
# include <boost/detail/atomic_count_pthreads.hpp>
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||
# include <boost/detail/atomic_count_win32.hpp>
|
||||
#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
|
||||
#elif defined(__GLIBCPP__)
|
||||
# include <boost/detail/atomic_count_gcc.hpp>
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
# define BOOST_AC_USE_PTHREADS
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
//
|
||||
// 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
|
||||
@@ -25,13 +24,6 @@ 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:
|
||||
|
||||
69
include/boost/detail/atomic_count_linux.hpp
Normal file
69
include/boost/detail/atomic_count_linux.hpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count_linux.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
//
|
||||
// This implementation uses <asm/atomic.h>. This is a kernel header;
|
||||
// using kernel headers in a user program may cause a number of problems,
|
||||
// and not all flavors of Linux provide the atomic instructions.
|
||||
//
|
||||
// This file is only provided because the performance of this implementation
|
||||
// is significantly higher than the pthreads version. Use at your own risk
|
||||
// (by defining BOOST_USE_ASM_ATOMIC_H.)
|
||||
//
|
||||
|
||||
#include <asm/atomic.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class atomic_count
|
||||
{
|
||||
public:
|
||||
|
||||
explicit atomic_count(long v)
|
||||
{
|
||||
atomic_t init = ATOMIC_INIT(v);
|
||||
value_ = init;
|
||||
}
|
||||
|
||||
void operator++()
|
||||
{
|
||||
atomic_inc(&value_);
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
return !atomic_dec_and_test(&value_);
|
||||
}
|
||||
|
||||
operator long() const
|
||||
{
|
||||
return atomic_read(&value_);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic_count(atomic_count const &);
|
||||
atomic_count & operator=(atomic_count const &);
|
||||
|
||||
atomic_t value_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED
|
||||
@@ -10,14 +10,16 @@
|
||||
//
|
||||
// boost/detail/atomic_count_win32.hpp
|
||||
//
|
||||
// Copyright (c) 2001-2005 Peter Dimov
|
||||
// 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)
|
||||
//
|
||||
|
||||
#include <boost/detail/interlocked.hpp>
|
||||
#ifdef BOOST_USE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -25,35 +27,67 @@ namespace boost
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#ifndef BOOST_USE_WINDOWS_H
|
||||
|
||||
#ifdef _WIN64
|
||||
|
||||
// Intel 6.0 on Win64 version, posted by Tim Fenders to [boost-users]
|
||||
|
||||
extern "C" long_type __cdecl _InterlockedIncrement(long volatile *);
|
||||
extern "C" long_type __cdecl _InterlockedDecrement(long volatile *);
|
||||
|
||||
#pragma intrinsic(_InterlockedIncrement)
|
||||
#pragma intrinsic(_InterlockedDecrement)
|
||||
|
||||
inline long InterlockedIncrement(long volatile * lp)
|
||||
{
|
||||
return _InterlockedIncrement(lp);
|
||||
}
|
||||
|
||||
inline long InterlockedDecrement(long volatile* lp)
|
||||
{
|
||||
return _InterlockedDecrement(lp);
|
||||
}
|
||||
|
||||
#else // _WIN64
|
||||
|
||||
extern "C" __declspec(dllimport) long __stdcall InterlockedIncrement(long volatile *);
|
||||
extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement(long volatile *);
|
||||
|
||||
#endif // _WIN64
|
||||
|
||||
#endif // #ifndef BOOST_USE_WINDOWS_H
|
||||
|
||||
class atomic_count
|
||||
{
|
||||
public:
|
||||
|
||||
explicit atomic_count( long v ): value_( v )
|
||||
explicit atomic_count(long v): value_(v)
|
||||
{
|
||||
}
|
||||
|
||||
long operator++()
|
||||
{
|
||||
return BOOST_INTERLOCKED_INCREMENT( &value_ );
|
||||
// Some older <windows.h> versions do not accept volatile
|
||||
return InterlockedIncrement(const_cast<long*>(&value_));
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
return BOOST_INTERLOCKED_DECREMENT( &value_ );
|
||||
return InterlockedDecrement(const_cast<long*>(&value_));
|
||||
}
|
||||
|
||||
operator long() const
|
||||
{
|
||||
return static_cast<long const volatile &>( value_ );
|
||||
return value_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic_count( atomic_count const & );
|
||||
atomic_count & operator=( atomic_count const & );
|
||||
atomic_count(atomic_count const &);
|
||||
atomic_count & operator=(atomic_count const &);
|
||||
|
||||
long value_;
|
||||
volatile long value_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -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 "tr1::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
|
||||
@@ -18,21 +18,77 @@
|
||||
//
|
||||
// typedef <unspecified> boost::detail::lightweight_mutex;
|
||||
//
|
||||
// boost::detail::lightweight_mutex is a header-only implementation of
|
||||
// a subset of the Mutex concept requirements:
|
||||
// boost::detail::lightweight_mutex meets a subset of the Mutex concept
|
||||
// requirements: http://www.boost.org/libs/thread/doc/mutex_concept.html#Mutex
|
||||
//
|
||||
// http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex
|
||||
// * Used by the smart pointer library
|
||||
// * Performance oriented
|
||||
// * Header-only implementation
|
||||
// * Small memory footprint
|
||||
// * Not a general purpose mutex, use boost::mutex, CRITICAL_SECTION or
|
||||
// pthread_mutex instead.
|
||||
// * Never spin in a tight lock/do-something/unlock loop, since
|
||||
// lightweight_mutex does not guarantee fairness.
|
||||
// * Never keep a lightweight_mutex locked for long periods.
|
||||
//
|
||||
// It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX.
|
||||
// The current implementation can use a pthread_mutex, a CRITICAL_SECTION,
|
||||
// or a platform-specific spinlock.
|
||||
//
|
||||
// You can force a particular implementation by defining BOOST_LWM_USE_PTHREADS,
|
||||
// BOOST_LWM_USE_CRITICAL_SECTION, or BOOST_LWM_USE_SPINLOCK.
|
||||
//
|
||||
// If neither macro has been defined, the default is to use a spinlock on Win32,
|
||||
// and a pthread_mutex otherwise.
|
||||
//
|
||||
// Note that a spinlock is not a general synchronization primitive. In particular,
|
||||
// it is not guaranteed to be a memory barrier, and it is possible to "livelock"
|
||||
// if a lower-priority thread has acquired the spinlock but a higher-priority
|
||||
// thread is spinning trying to acquire the same lock.
|
||||
//
|
||||
// For these reasons, spinlocks have been disabled by default except on Windows,
|
||||
// where a spinlock can be several orders of magnitude faster than a CRITICAL_SECTION.
|
||||
|
||||
|
||||
// Note: lwm_linux.hpp has been disabled by default; see the comments
|
||||
// inside for more info.
|
||||
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// Note to implementors: if you write a platform-specific spinlock
|
||||
// for a platform that supports pthreads, be sure to test its performance
|
||||
// against the pthreads-based version using shared_ptr_timing_test.cpp and
|
||||
// shared_ptr_mt_test.cpp. Custom versions are usually not worth the trouble
|
||||
// _unless_ the performance gains are substantial.
|
||||
//
|
||||
// Be sure to compare against a "real" pthreads library;
|
||||
// shared_ptr_timing_test.cpp will compile succesfully with a stub do-nothing
|
||||
// pthreads library, since it doesn't create any threads.
|
||||
|
||||
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(BOOST_LWM_USE_CRITICAL_SECTION) && !defined(BOOST_LWM_USE_PTHREADS)
|
||||
# define BOOST_LWM_WIN32
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_HAS_THREADS)
|
||||
# include <boost/detail/lwm_nop.hpp>
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||
# if defined(BOOST_LWM_WIN32)
|
||||
# include <boost/detail/lwm_win32_nt.hpp>
|
||||
# else
|
||||
# include <boost/detail/lwm_nop.hpp>
|
||||
# endif
|
||||
#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(BOOST_USE_ASM_ATOMIC_H)
|
||||
# include <boost/detail/lwm_linux.hpp>
|
||||
#elif defined(BOOST_LWM_USE_CRITICAL_SECTION)
|
||||
# include <boost/detail/lwm_win32_cs.hpp>
|
||||
#elif defined(BOOST_LWM_USE_PTHREADS)
|
||||
# include <boost/detail/lwm_pthreads.hpp>
|
||||
#elif defined(BOOST_LWM_WIN32)
|
||||
# include <boost/detail/lwm_win32.hpp>
|
||||
#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(__sgi)
|
||||
# include <boost/detail/lwm_irix.hpp>
|
||||
#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(__GLIBCPP__)
|
||||
# include <boost/detail/lwm_gcc.hpp>
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
# define BOOST_LWM_USE_PTHREADS
|
||||
# include <boost/detail/lwm_pthreads.hpp>
|
||||
#else
|
||||
// Use #define BOOST_DISABLE_THREADS to avoid the error
|
||||
|
||||
77
include/boost/detail/lwm_gcc.hpp
Normal file
77
include/boost/detail/lwm_gcc.hpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#ifndef BOOST_DETAIL_LWM_GCC_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_LWM_GCC_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// boost/detail/lwm_gcc.hpp
|
||||
//
|
||||
// lightweight_mutex for GNU libstdc++ v3
|
||||
//
|
||||
// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright (c) 2002 Lars Gullik Bj<42>nnes <larsbj@lyx.org>
|
||||
//
|
||||
// Distributed under the 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>
|
||||
#include <sched.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class lightweight_mutex
|
||||
{
|
||||
private:
|
||||
|
||||
_Atomic_word a_;
|
||||
|
||||
lightweight_mutex(lightweight_mutex const &);
|
||||
lightweight_mutex & operator=(lightweight_mutex const &);
|
||||
|
||||
public:
|
||||
|
||||
lightweight_mutex(): a_(0)
|
||||
{
|
||||
}
|
||||
|
||||
class scoped_lock;
|
||||
friend class scoped_lock;
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
private:
|
||||
|
||||
lightweight_mutex & m_;
|
||||
|
||||
scoped_lock(scoped_lock const &);
|
||||
scoped_lock & operator=(scoped_lock const &);
|
||||
|
||||
public:
|
||||
|
||||
explicit scoped_lock(lightweight_mutex & m): m_(m)
|
||||
{
|
||||
while( __exchange_and_add(&m_.a_, 1) )
|
||||
{
|
||||
__atomic_add(&m_.a_, -1);
|
||||
sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
__atomic_add(&m_.a_, -1);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_LWM_GCC_HPP_INCLUDED
|
||||
73
include/boost/detail/lwm_irix.hpp
Normal file
73
include/boost/detail/lwm_irix.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#ifndef BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// boost/detail/lwm_irix.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright (c) 2002 Dan Gohman
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include <sgidefs.h>
|
||||
#include <mutex.h>
|
||||
#include <sched.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class lightweight_mutex
|
||||
{
|
||||
private:
|
||||
|
||||
__uint32_t l_;
|
||||
|
||||
lightweight_mutex(lightweight_mutex const &);
|
||||
lightweight_mutex & operator=(lightweight_mutex const &);
|
||||
|
||||
public:
|
||||
|
||||
lightweight_mutex(): l_(0)
|
||||
{
|
||||
}
|
||||
|
||||
class scoped_lock;
|
||||
friend class scoped_lock;
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
private:
|
||||
|
||||
lightweight_mutex & m_;
|
||||
|
||||
scoped_lock(scoped_lock const &);
|
||||
scoped_lock & operator=(scoped_lock const &);
|
||||
|
||||
public:
|
||||
|
||||
explicit scoped_lock(lightweight_mutex & m): m_(m)
|
||||
{
|
||||
while( test_and_set32(&m_.l_, 1) )
|
||||
{
|
||||
sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
m_.l_ = 0;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED
|
||||
84
include/boost/detail/lwm_linux.hpp
Normal file
84
include/boost/detail/lwm_linux.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#ifndef BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// boost/detail/lwm_linux.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
//
|
||||
// This implementation uses <asm/atomic.h>. This is a kernel header;
|
||||
// using kernel headers in a user program may cause a number of problems,
|
||||
// and not all flavors of Linux provide the atomic instructions.
|
||||
//
|
||||
// This file is only provided because the performance of this implementation
|
||||
// is about 3.5 times higher than the pthreads version. Use at your own risk
|
||||
// (by defining BOOST_USE_ASM_ATOMIC_H.)
|
||||
//
|
||||
|
||||
#include <asm/atomic.h>
|
||||
#include <sched.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class lightweight_mutex
|
||||
{
|
||||
private:
|
||||
|
||||
atomic_t a_;
|
||||
|
||||
lightweight_mutex(lightweight_mutex const &);
|
||||
lightweight_mutex & operator=(lightweight_mutex const &);
|
||||
|
||||
public:
|
||||
|
||||
lightweight_mutex()
|
||||
{
|
||||
atomic_t a = ATOMIC_INIT(1);
|
||||
a_ = a;
|
||||
}
|
||||
|
||||
class scoped_lock;
|
||||
friend class scoped_lock;
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
private:
|
||||
|
||||
lightweight_mutex & m_;
|
||||
|
||||
scoped_lock(scoped_lock const &);
|
||||
scoped_lock & operator=(scoped_lock const &);
|
||||
|
||||
public:
|
||||
|
||||
explicit scoped_lock(lightweight_mutex & m): m_(m)
|
||||
{
|
||||
while( !atomic_dec_and_test(&m_.a_) )
|
||||
{
|
||||
atomic_inc(&m_.a_);
|
||||
sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
atomic_inc(&m_.a_);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED
|
||||
122
include/boost/detail/lwm_win32.hpp
Normal file
122
include/boost/detail/lwm_win32.hpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/lwm_win32.hpp
|
||||
//
|
||||
// Copyright (c) 2002, 2003 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifdef BOOST_USE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
# pragma warn -8027 // Functions containing while are not expanded inline
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#ifndef BOOST_USE_WINDOWS_H
|
||||
|
||||
#ifdef _WIN64
|
||||
|
||||
// Intel 6.0 on Win64 version, posted by Tim Fenders to [boost-users]
|
||||
|
||||
extern "C" long_type __cdecl _InterlockedExchange(long volatile *, long);
|
||||
|
||||
#pragma intrinsic(_InterlockedExchange)
|
||||
|
||||
inline long InterlockedExchange(long volatile* lp, long l)
|
||||
{
|
||||
return _InterlockedExchange(lp, l);
|
||||
}
|
||||
|
||||
#else // _WIN64
|
||||
|
||||
extern "C" __declspec(dllimport) long __stdcall InterlockedExchange(long volatile *, long);
|
||||
|
||||
#endif // _WIN64
|
||||
|
||||
extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long);
|
||||
|
||||
#endif // #ifndef BOOST_USE_WINDOWS_H
|
||||
|
||||
class lightweight_mutex
|
||||
{
|
||||
private:
|
||||
|
||||
long l_;
|
||||
|
||||
lightweight_mutex(lightweight_mutex const &);
|
||||
lightweight_mutex & operator=(lightweight_mutex const &);
|
||||
|
||||
public:
|
||||
|
||||
lightweight_mutex(): l_(0)
|
||||
{
|
||||
}
|
||||
|
||||
class scoped_lock;
|
||||
friend class scoped_lock;
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
private:
|
||||
|
||||
lightweight_mutex & m_;
|
||||
|
||||
scoped_lock(scoped_lock const &);
|
||||
scoped_lock & operator=(scoped_lock const &);
|
||||
|
||||
public:
|
||||
|
||||
explicit scoped_lock(lightweight_mutex & m): m_(m)
|
||||
{
|
||||
while( InterlockedExchange(&m_.l_, 1) )
|
||||
{
|
||||
// Note: changed to Sleep(1) from Sleep(0).
|
||||
// According to MSDN, Sleep(0) will never yield
|
||||
// to a lower-priority thread, whereas Sleep(1)
|
||||
// will. Performance seems not to be affected.
|
||||
|
||||
Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
InterlockedExchange(&m_.l_, 0);
|
||||
|
||||
// Note: adding a yield here will make
|
||||
// the spinlock more fair and will increase the overall
|
||||
// performance of some applications substantially in
|
||||
// high contention situations, but will penalize the
|
||||
// low contention / single thread case up to 5x
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
# pragma warn .8027 // Functions containing while are not expanded inline
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED
|
||||
63
include/boost/detail/lwm_win32_nt.hpp
Normal file
63
include/boost/detail/lwm_win32_nt.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef BOOST_DETAIL_LWM_WIN32_NT_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_LWM_WIN32_NT_HPP_INCLUDED
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/lwm_win32_nt.hpp
|
||||
//
|
||||
// Copyright (c) 2002, 2003 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// "No threads" version of lwm_win32.hpp; binary compatible but no-op.
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class lightweight_mutex
|
||||
{
|
||||
private:
|
||||
|
||||
long l_;
|
||||
|
||||
lightweight_mutex(lightweight_mutex const &);
|
||||
lightweight_mutex & operator=(lightweight_mutex const &);
|
||||
|
||||
public:
|
||||
|
||||
lightweight_mutex(): l_(0)
|
||||
{
|
||||
}
|
||||
|
||||
class scoped_lock;
|
||||
friend class scoped_lock;
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
private:
|
||||
|
||||
scoped_lock(scoped_lock const &);
|
||||
scoped_lock & operator=(scoped_lock const &);
|
||||
|
||||
public:
|
||||
|
||||
explicit scoped_lock(lightweight_mutex &)
|
||||
{
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_LWM_WIN32_NT_HPP_INCLUDED
|
||||
@@ -11,35 +11,293 @@
|
||||
// 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
|
||||
#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/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 <boost/detail/lightweight_mutex.hpp>
|
||||
|
||||
#include <memory> // std::auto_ptr
|
||||
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
|
||||
#include <boost/detail/quick_allocator.hpp>
|
||||
#endif
|
||||
|
||||
#include <memory> // std::auto_ptr, std::allocator
|
||||
#include <functional> // std::less
|
||||
#include <exception> // std::exception
|
||||
#include <new> // std::bad_alloc
|
||||
#include <typeinfo> // std::type_info in get_deleter
|
||||
#include <cstddef> // std::size_t
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
# pragma warn -8026 // Functions with excep. spec. are not expanded inline
|
||||
# pragma warn -8027 // Functions containing try are not expanded inline
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
// Debug hooks
|
||||
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
|
||||
void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn);
|
||||
void sp_array_constructor_hook(void * px);
|
||||
void sp_scalar_destructor_hook(void * px, std::size_t size, void * pn);
|
||||
void sp_array_destructor_hook(void * px);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// The standard library that comes with Borland C++ 5.5.1
|
||||
// defines std::exception and its members as having C calling
|
||||
// convention (-pc). When the definition of bad_weak_ptr
|
||||
// is compiled with -ps, the compiler issues an error.
|
||||
// Hence, the temporary #pragma option -pc below. The version
|
||||
// check is deliberately conservative.
|
||||
|
||||
#if defined(__BORLANDC__) && __BORLANDC__ == 0x551
|
||||
# pragma option push -pc
|
||||
#endif
|
||||
|
||||
class bad_weak_ptr: public std::exception
|
||||
{
|
||||
public:
|
||||
|
||||
virtual char const * what() const throw()
|
||||
{
|
||||
return "boost::bad_weak_ptr";
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__BORLANDC__) && __BORLANDC__ == 0x551
|
||||
# pragma option pop
|
||||
#endif
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
typedef detail::lightweight_mutex mutex_type;
|
||||
|
||||
public:
|
||||
|
||||
sp_counted_base(): use_count_(1), weak_count_(1)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~sp_counted_base() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
|
||||
virtual void dispose() = 0; // nothrow
|
||||
|
||||
// destruct() is called when weak_count_ drops to zero.
|
||||
|
||||
virtual void destruct() // nothrow
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual void * get_deleter(std::type_info const & ti) = 0;
|
||||
|
||||
void add_ref_copy()
|
||||
{
|
||||
#if defined(BOOST_HAS_THREADS)
|
||||
mutex_type::scoped_lock lock(mtx_);
|
||||
#endif
|
||||
++use_count_;
|
||||
}
|
||||
|
||||
void add_ref_lock()
|
||||
{
|
||||
#if defined(BOOST_HAS_THREADS)
|
||||
mutex_type::scoped_lock lock(mtx_);
|
||||
#endif
|
||||
if(use_count_ == 0) boost::throw_exception(boost::bad_weak_ptr());
|
||||
++use_count_;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
{
|
||||
#if defined(BOOST_HAS_THREADS)
|
||||
mutex_type::scoped_lock lock(mtx_);
|
||||
#endif
|
||||
long new_use_count = --use_count_;
|
||||
|
||||
if(new_use_count != 0) return;
|
||||
}
|
||||
|
||||
dispose();
|
||||
weak_release();
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
#if defined(BOOST_HAS_THREADS)
|
||||
mutex_type::scoped_lock lock(mtx_);
|
||||
#endif
|
||||
++weak_count_;
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
long new_weak_count;
|
||||
|
||||
{
|
||||
#if defined(BOOST_HAS_THREADS)
|
||||
mutex_type::scoped_lock lock(mtx_);
|
||||
#endif
|
||||
new_weak_count = --weak_count_;
|
||||
}
|
||||
|
||||
if(new_weak_count == 0)
|
||||
{
|
||||
destruct();
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
#if defined(BOOST_HAS_THREADS)
|
||||
mutex_type::scoped_lock lock(mtx_);
|
||||
#endif
|
||||
return use_count_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
sp_counted_base(sp_counted_base const &);
|
||||
sp_counted_base & operator= (sp_counted_base const &);
|
||||
|
||||
long use_count_; // #shared
|
||||
long weak_count_; // #weak + (#shared != 0)
|
||||
|
||||
#if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32)
|
||||
mutable mutex_type mtx_;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
|
||||
template<class T> void cbi_call_constructor_hook(sp_counted_base * pn, T * px, checked_deleter<T> const &, int)
|
||||
{
|
||||
boost::sp_scalar_constructor_hook(px, sizeof(T), pn);
|
||||
}
|
||||
|
||||
template<class T> void cbi_call_constructor_hook(sp_counted_base *, T * px, checked_array_deleter<T> const &, int)
|
||||
{
|
||||
boost::sp_array_constructor_hook(px);
|
||||
}
|
||||
|
||||
template<class P, class D> void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T> void cbi_call_destructor_hook(sp_counted_base * pn, T * px, checked_deleter<T> const &, int)
|
||||
{
|
||||
boost::sp_scalar_destructor_hook(px, sizeof(T), pn);
|
||||
}
|
||||
|
||||
template<class T> void cbi_call_destructor_hook(sp_counted_base *, T * px, checked_array_deleter<T> const &, int)
|
||||
{
|
||||
boost::sp_array_destructor_hook(px);
|
||||
}
|
||||
|
||||
template<class P, class D> void cbi_call_destructor_hook(sp_counted_base *, P const &, D const &, long)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// Borland's Codeguard trips up over the -Vx- option here:
|
||||
//
|
||||
#ifdef __CODEGUARD__
|
||||
# pragma option push -Vx-
|
||||
#endif
|
||||
|
||||
template<class P, class D> class sp_counted_base_impl: public sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
P ptr; // copy constructor must not throw
|
||||
D del; // copy constructor must not throw
|
||||
|
||||
sp_counted_base_impl(sp_counted_base_impl const &);
|
||||
sp_counted_base_impl & operator= (sp_counted_base_impl const &);
|
||||
|
||||
typedef sp_counted_base_impl<P, D> this_type;
|
||||
|
||||
public:
|
||||
|
||||
// pre: initial_use_count <= initial_weak_count, d(p) must not throw
|
||||
|
||||
sp_counted_base_impl(P p, D d): ptr(p), del(d)
|
||||
{
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
detail::cbi_call_constructor_hook(this, p, d, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void dispose() // nothrow
|
||||
{
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
detail::cbi_call_destructor_hook(this, ptr, del, 0);
|
||||
#endif
|
||||
del(ptr);
|
||||
}
|
||||
|
||||
virtual void * get_deleter(std::type_info const & ti)
|
||||
{
|
||||
return ti == typeid(D)? &del: 0;
|
||||
}
|
||||
|
||||
#if defined(BOOST_SP_USE_STD_ALLOCATOR)
|
||||
|
||||
void * operator new(std::size_t)
|
||||
{
|
||||
return std::allocator<this_type>().allocate(1, static_cast<this_type *>(0));
|
||||
}
|
||||
|
||||
void operator delete(void * p)
|
||||
{
|
||||
std::allocator<this_type>().deallocate(static_cast<this_type *>(p), 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
|
||||
|
||||
void * operator new(std::size_t)
|
||||
{
|
||||
return quick_allocator<this_type>::alloc();
|
||||
}
|
||||
|
||||
void operator delete(void * p)
|
||||
{
|
||||
quick_allocator<this_type>::dealloc(p);
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
|
||||
int const shared_count_id = 0x2C35F101;
|
||||
@@ -70,36 +328,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -109,7 +337,7 @@ public:
|
||||
|
||||
try
|
||||
{
|
||||
pi_ = new sp_counted_impl_pd<P, D>(p, d);
|
||||
pi_ = new sp_counted_base_impl<P, D>(p, d);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
@@ -119,7 +347,7 @@ public:
|
||||
|
||||
#else
|
||||
|
||||
pi_ = new sp_counted_impl_pd<P, D>(p, d);
|
||||
pi_ = new sp_counted_base_impl<P, D>(p, d);
|
||||
|
||||
if(pi_ == 0)
|
||||
{
|
||||
@@ -127,52 +355,6 @@ public:
|
||||
boost::throw_exception(std::bad_alloc());
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 )
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
typedef sp_counted_impl_pda<P, D, A> impl_type;
|
||||
typedef typename A::template rebind< impl_type >::other A2;
|
||||
|
||||
A2 a2( a );
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
|
||||
try
|
||||
{
|
||||
pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
|
||||
new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
d( p );
|
||||
|
||||
if( pi_ != 0 )
|
||||
{
|
||||
a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
|
||||
|
||||
if( pi_ != 0 )
|
||||
{
|
||||
new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
|
||||
}
|
||||
else
|
||||
{
|
||||
d( p );
|
||||
boost::throw_exception( std::bad_alloc() );
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -181,20 +363,11 @@ public:
|
||||
// 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() ) )
|
||||
explicit shared_count(std::auto_ptr<Y> & r): pi_(new sp_counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>()))
|
||||
#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();
|
||||
}
|
||||
|
||||
@@ -202,7 +375,7 @@ public:
|
||||
|
||||
~shared_count() // nothrow
|
||||
{
|
||||
if( pi_ != 0 ) pi_->release();
|
||||
if(pi_ != 0) pi_->release();
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
id_ = 0;
|
||||
#endif
|
||||
@@ -213,7 +386,7 @@ public:
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
if( pi_ != 0 ) pi_->add_ref_copy();
|
||||
if(pi_ != 0) pi_->add_ref_copy();
|
||||
}
|
||||
|
||||
explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
|
||||
@@ -222,10 +395,10 @@ public:
|
||||
{
|
||||
sp_counted_base * tmp = r.pi_;
|
||||
|
||||
if( tmp != pi_ )
|
||||
if(tmp != pi_)
|
||||
{
|
||||
if( tmp != 0 ) tmp->add_ref_copy();
|
||||
if( pi_ != 0 ) pi_->release();
|
||||
if(tmp != 0) tmp->add_ref_copy();
|
||||
if(pi_ != 0) pi_->release();
|
||||
pi_ = tmp;
|
||||
}
|
||||
|
||||
@@ -256,15 +429,19 @@ public:
|
||||
|
||||
friend inline bool operator<(shared_count const & a, shared_count const & b)
|
||||
{
|
||||
return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
|
||||
return std::less<sp_counted_base *>()(a.pi_, b.pi_);
|
||||
}
|
||||
|
||||
void * get_deleter(std::type_info const & ti) const
|
||||
{
|
||||
return pi_? pi_->get_deleter( ti ): 0;
|
||||
return pi_? pi_->get_deleter(ti): 0;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __CODEGUARD__
|
||||
# pragma option pop
|
||||
#endif
|
||||
|
||||
|
||||
class weak_count
|
||||
{
|
||||
@@ -354,14 +531,18 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
|
||||
inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
if( pi_ == 0 || !pi_->add_ref_lock() )
|
||||
if(pi_ != 0)
|
||||
{
|
||||
boost::throw_exception( boost::bad_weak_ptr() );
|
||||
pi_->add_ref_lock();
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::throw_exception(boost::bad_weak_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,6 +552,7 @@ inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
# pragma warn .8027 // Functions containing try are not expanded inline
|
||||
# pragma warn .8026 // Functions with excep. spec. are not expanded inline
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
|
||||
|
||||
@@ -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-2006 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( int * pw )
|
||||
{
|
||||
// ++*pw;
|
||||
|
||||
int tmp;
|
||||
|
||||
// No barrier is required here but fetchadd always has an acquire or
|
||||
// release barrier associated with it. We choose release as it should be
|
||||
// cheaper.
|
||||
__asm__ ("fetchadd4.rel %0=%1,1" :
|
||||
"=r"(tmp), "=m"(*pw) :
|
||||
"m"( *pw ));
|
||||
}
|
||||
|
||||
inline int atomic_decrement( int * pw )
|
||||
{
|
||||
// return --*pw;
|
||||
|
||||
int rv;
|
||||
|
||||
__asm__ (" fetchadd4.rel %0=%1,-1 ;; \n"
|
||||
" cmp.eq p7,p0=1,%0 ;; \n"
|
||||
"(p7) ld4.acq %0=%1 " :
|
||||
"=&r"(rv), "=m"(*pw) :
|
||||
"m"( *pw ) :
|
||||
"p7");
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
inline int atomic_conditional_increment( int * pw )
|
||||
{
|
||||
// if( *pw != 0 ) ++*pw;
|
||||
// return *pw;
|
||||
|
||||
int rv, tmp, tmp2;
|
||||
|
||||
__asm__ ("0: ld4 %0=%3 ;; \n"
|
||||
" cmp.eq p7,p0=0,%0 ;; \n"
|
||||
"(p7) br.cond.spnt 1f \n"
|
||||
" mov ar.ccv=%0 \n"
|
||||
" add %1=1,%0 ;; \n"
|
||||
" cmpxchg4.acq %2=%3,%1,ar.ccv ;; \n"
|
||||
" cmp.ne p7,p0=%0,%2 ;; \n"
|
||||
"(p7) br.cond.spnt 0b \n"
|
||||
" mov %0=%1 ;; \n"
|
||||
"1:" :
|
||||
"=&r"(rv), "=&r"(tmp), "=&r"(tmp2), "=m"(*pw) :
|
||||
"m"( *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 & );
|
||||
|
||||
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_ ); // TODO use ld.acq here
|
||||
}
|
||||
};
|
||||
|
||||
} // 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 ), "m"( *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 ), "m"( *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 ), "m"( *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,130 +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 <boost/detail/workaround.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 defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1200 )
|
||||
|
||||
// work around a code generation bug
|
||||
|
||||
long tmp2 = tmp + 1;
|
||||
if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true;
|
||||
|
||||
#else
|
||||
|
||||
if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true;
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
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,232 +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
|
||||
|
||||
#if defined(BOOST_SP_USE_STD_ALLOCATOR)
|
||||
#include <memory> // std::allocator
|
||||
#endif
|
||||
|
||||
#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
|
||||
};
|
||||
|
||||
template<class P, class D, class A> class sp_counted_impl_pda: public sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
P p_; // copy constructor must not throw
|
||||
D d_; // copy constructor must not throw
|
||||
A a_; // copy constructor must not throw
|
||||
|
||||
sp_counted_impl_pda( sp_counted_impl_pda const & );
|
||||
sp_counted_impl_pda & operator= ( sp_counted_impl_pda const & );
|
||||
|
||||
typedef sp_counted_impl_pda<P, D, A> this_type;
|
||||
|
||||
public:
|
||||
|
||||
// pre: d( p ) must not throw
|
||||
|
||||
sp_counted_impl_pda( P p, D d, A a ): p_( p ), d_( d ), a_( a )
|
||||
{
|
||||
}
|
||||
|
||||
virtual void dispose() // nothrow
|
||||
{
|
||||
d_( p_ );
|
||||
}
|
||||
|
||||
virtual void destroy() // nothrow
|
||||
{
|
||||
typedef typename A::template rebind< this_type >::other A2;
|
||||
|
||||
A2 a2( a_ );
|
||||
|
||||
this->~this_type();
|
||||
a2.deallocate( this, 1 );
|
||||
}
|
||||
|
||||
virtual void * get_deleter( std::type_info const & ti )
|
||||
{
|
||||
return ti == typeid( D )? &d_: 0;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __CODEGUARD__
|
||||
# pragma option pop
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
|
||||
@@ -58,12 +58,6 @@ public:
|
||||
return p;
|
||||
}
|
||||
|
||||
// Note: No, you don't need to initialize _internal_weak_this
|
||||
//
|
||||
// Please read the documentation, not the code
|
||||
//
|
||||
// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
|
||||
|
||||
typedef T _internal_element_type; // for bcc 5.5.1
|
||||
mutable weak_ptr<_internal_element_type> _internal_weak_this;
|
||||
};
|
||||
|
||||
@@ -174,22 +174,22 @@ template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, in
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b)
|
||||
template<class T> inline bool operator==(intrusive_ptr<T> const & a, T * b)
|
||||
{
|
||||
return a.get() == b;
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b)
|
||||
template<class T> inline bool operator!=(intrusive_ptr<T> const & a, T * b)
|
||||
{
|
||||
return a.get() != b;
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b)
|
||||
template<class T> inline bool operator==(T * a, intrusive_ptr<T> const & b)
|
||||
{
|
||||
return a == b.get();
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b)
|
||||
template<class T> inline bool operator!=(T * a, intrusive_ptr<T> const & b)
|
||||
{
|
||||
return a != b.get();
|
||||
}
|
||||
@@ -249,10 +249,7 @@ template<class Y> std::ostream & operator<< (std::ostream & os, intrusive_ptr<Y>
|
||||
|
||||
#else
|
||||
|
||||
// in STLport's no-iostreams mode no iostream symbols can be used
|
||||
#ifndef _STLP_NO_IOSTREAMS
|
||||
|
||||
# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
|
||||
# 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)
|
||||
@@ -264,9 +261,7 @@ template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::
|
||||
return os;
|
||||
}
|
||||
|
||||
#endif // _STLP_NO_IOSTREAMS
|
||||
|
||||
#endif // __GNUC__ < 3
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gazta<74>aga 2005.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_POINTER_CAST_HPP
|
||||
#define BOOST_POINTER_CAST_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
//static_pointer_cast overload for raw pointers
|
||||
template<class T, class U>
|
||||
inline T* static_pointer_cast(U *ptr)
|
||||
{
|
||||
return static_cast<T*>(ptr);
|
||||
}
|
||||
|
||||
//dynamic_pointer_cast overload for raw pointers
|
||||
template<class T, class U>
|
||||
inline T* dynamic_pointer_cast(U *ptr)
|
||||
{
|
||||
return dynamic_cast<T*>(ptr);
|
||||
}
|
||||
|
||||
//const_pointer_cast overload for raw pointers
|
||||
template<class T, class U>
|
||||
inline T* const_pointer_cast(U *ptr)
|
||||
{
|
||||
return const_cast<T*>(ptr);
|
||||
}
|
||||
|
||||
//reinterpret_pointer_cast overload for raw pointers
|
||||
template<class T, class U>
|
||||
inline T* reinterpret_pointer_cast(U *ptr)
|
||||
{
|
||||
return reinterpret_cast<T*>(ptr);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //BOOST_POINTER_CAST_HPP
|
||||
@@ -1,55 +0,0 @@
|
||||
#ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED
|
||||
#define BOOST_POINTER_TO_OTHER_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// pointer_to_other.hpp
|
||||
//
|
||||
// (C) Copyright Ion Gazta<74>aga 2005.
|
||||
// Copyright (c) 2005 Peter Dimov.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/smart_ptr/pointer_to_other.html
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
// Defines the same pointer type (raw or smart) to another pointee type
|
||||
|
||||
template<class T, class U>
|
||||
struct pointer_to_other;
|
||||
|
||||
template<class T, class U,
|
||||
template<class> class Sp>
|
||||
struct pointer_to_other< Sp<T>, U >
|
||||
{
|
||||
typedef Sp<U> type;
|
||||
};
|
||||
|
||||
template<class T, class T2, class U,
|
||||
template<class, class> class Sp>
|
||||
struct pointer_to_other< Sp<T, T2>, U >
|
||||
{
|
||||
typedef Sp<U, T2> type;
|
||||
};
|
||||
|
||||
template<class T, class T2, class T3, class U,
|
||||
template<class, class, class> class Sp>
|
||||
struct pointer_to_other< Sp<T, T2, T3>, U >
|
||||
{
|
||||
typedef Sp<U, T2, T3> type;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
struct pointer_to_other< T*, U >
|
||||
{
|
||||
typedef U* type;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED
|
||||
@@ -20,8 +20,6 @@
|
||||
#include <boost/detail/shared_array_nmt.hpp>
|
||||
#else
|
||||
|
||||
#include <memory> // TR1 cyclic inclusion fix
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/checked_delete.hpp>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// shared_ptr.hpp
|
||||
//
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
||||
// Copyright (c) 2001-2006 Peter Dimov
|
||||
// Copyright (c) 2001, 2002, 2003 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -20,14 +20,13 @@
|
||||
#include <boost/detail/shared_ptr_nmt.hpp>
|
||||
#else
|
||||
|
||||
#include <memory> // for std::auto_ptr
|
||||
|
||||
#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
|
||||
@@ -88,34 +87,10 @@ template<class T, class Y> void sp_enable_shared_from_this( shared_count const &
|
||||
if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn);
|
||||
}
|
||||
|
||||
#ifdef sgi
|
||||
// Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed
|
||||
# pragma set woff 3506
|
||||
#endif
|
||||
|
||||
inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... )
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef sgi
|
||||
# pragma reset woff 3506
|
||||
#endif
|
||||
|
||||
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
|
||||
|
||||
// rvalue auto_ptr support based on a technique by Dave Abrahams
|
||||
|
||||
template< class T, class R > struct sp_enable_if_auto_ptr
|
||||
{
|
||||
};
|
||||
|
||||
template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
@@ -139,16 +114,16 @@ public:
|
||||
typedef T element_type;
|
||||
typedef T value_type;
|
||||
typedef T * pointer;
|
||||
typedef typename boost::detail::shared_ptr_traits<T>::reference reference;
|
||||
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
|
||||
explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter<Y>()) // Y must be complete
|
||||
{
|
||||
boost::detail::sp_enable_shared_from_this( pn, p, p );
|
||||
detail::sp_enable_shared_from_this( pn, p, p );
|
||||
}
|
||||
|
||||
//
|
||||
@@ -159,14 +134,7 @@ public:
|
||||
|
||||
template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
|
||||
{
|
||||
boost::detail::sp_enable_shared_from_this( pn, p, p );
|
||||
}
|
||||
|
||||
// As above, but with allocator. A's copy constructor shall not throw.
|
||||
|
||||
template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
|
||||
{
|
||||
boost::detail::sp_enable_shared_from_this( pn, p, p );
|
||||
detail::sp_enable_shared_from_this( pn, p, p );
|
||||
}
|
||||
|
||||
// generated copy constructor, assignment, destructor are fine...
|
||||
@@ -196,26 +164,26 @@ public:
|
||||
}
|
||||
|
||||
template<class Y>
|
||||
shared_ptr(shared_ptr<Y> const & r, boost::detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
|
||||
shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
|
||||
{
|
||||
}
|
||||
|
||||
template<class Y>
|
||||
shared_ptr(shared_ptr<Y> const & r, boost::detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
|
||||
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, boost::detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
|
||||
shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
|
||||
{
|
||||
if(px == 0) // need to allocate new counter -- the cast failed
|
||||
{
|
||||
pn = boost::detail::shared_count();
|
||||
pn = detail::shared_count();
|
||||
}
|
||||
}
|
||||
|
||||
template<class Y>
|
||||
shared_ptr(shared_ptr<Y> const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
|
||||
shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
|
||||
{
|
||||
if(px == 0)
|
||||
{
|
||||
@@ -229,26 +197,13 @@ public:
|
||||
explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
|
||||
{
|
||||
Y * tmp = r.get();
|
||||
pn = boost::detail::shared_count(r);
|
||||
boost::detail::sp_enable_shared_from_this( pn, tmp, tmp );
|
||||
pn = detail::shared_count(r);
|
||||
detail::sp_enable_shared_from_this( pn, tmp, tmp );
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
|
||||
#endif
|
||||
|
||||
template<class Ap>
|
||||
explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
|
||||
{
|
||||
typename Ap::element_type * tmp = r.get();
|
||||
pn = boost::detail::shared_count( r );
|
||||
boost::detail::sp_enable_shared_from_this( pn, tmp, tmp );
|
||||
}
|
||||
|
||||
|
||||
#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
#endif // BOOST_NO_AUTO_PTR
|
||||
|
||||
#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
|
||||
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
|
||||
|
||||
template<class Y>
|
||||
shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
|
||||
@@ -263,25 +218,13 @@ public:
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
|
||||
template<class Y>
|
||||
shared_ptr & operator=( std::auto_ptr<Y> & r )
|
||||
shared_ptr & operator=(std::auto_ptr<Y> & r)
|
||||
{
|
||||
this_type(r).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
|
||||
|
||||
template<class Ap>
|
||||
typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
|
||||
{
|
||||
this_type( r ).swap( *this );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
#endif // BOOST_NO_AUTO_PTR
|
||||
#endif
|
||||
|
||||
void reset() // never throws in 1.30+
|
||||
{
|
||||
@@ -294,14 +237,9 @@ public:
|
||||
this_type(p).swap(*this);
|
||||
}
|
||||
|
||||
template<class Y, class D> void reset( Y * p, D d )
|
||||
template<class Y, class D> void reset(Y * p, D d)
|
||||
{
|
||||
this_type( p, d ).swap( *this );
|
||||
}
|
||||
|
||||
template<class Y, class D, class A> void reset( Y * p, D d, A a )
|
||||
{
|
||||
this_type( p, d, a ).swap( *this );
|
||||
this_type(p, d).swap(*this);
|
||||
}
|
||||
|
||||
reference operator* () const // never throws
|
||||
@@ -323,30 +261,14 @@ public:
|
||||
|
||||
// implicit conversion to "bool"
|
||||
|
||||
#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580)
|
||||
#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
|
||||
|
||||
operator bool () const
|
||||
{
|
||||
return px != 0;
|
||||
}
|
||||
|
||||
#elif defined( _MANAGED )
|
||||
|
||||
static void unspecified_bool( this_type*** )
|
||||
{
|
||||
}
|
||||
|
||||
typedef void (*unspecified_bool_type)( this_type*** );
|
||||
|
||||
operator unspecified_bool_type() const // never throws
|
||||
{
|
||||
return px == 0? 0: unspecified_bool;
|
||||
}
|
||||
|
||||
#elif \
|
||||
( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \
|
||||
( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) )
|
||||
|
||||
#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
|
||||
@@ -412,7 +334,7 @@ private:
|
||||
#endif
|
||||
|
||||
T * px; // contained pointer
|
||||
boost::detail::shared_count pn; // reference counter
|
||||
detail::shared_count pn; // reference counter
|
||||
|
||||
}; // shared_ptr
|
||||
|
||||
@@ -449,34 +371,34 @@ template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
|
||||
|
||||
template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
|
||||
{
|
||||
return shared_ptr<T>(r, boost::detail::static_cast_tag());
|
||||
return shared_ptr<T>(r, detail::static_cast_tag());
|
||||
}
|
||||
|
||||
template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
|
||||
{
|
||||
return shared_ptr<T>(r, boost::detail::const_cast_tag());
|
||||
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, boost::detail::dynamic_cast_tag());
|
||||
return shared_ptr<T>(r, detail::dynamic_cast_tag());
|
||||
}
|
||||
|
||||
// shared_*_cast names are deprecated. Use *_pointer_cast instead.
|
||||
|
||||
template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
|
||||
{
|
||||
return shared_ptr<T>(r, boost::detail::static_cast_tag());
|
||||
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, boost::detail::dynamic_cast_tag());
|
||||
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, boost::detail::polymorphic_cast_tag());
|
||||
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)
|
||||
@@ -504,10 +426,7 @@ template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> co
|
||||
|
||||
#else
|
||||
|
||||
// in STLport's no-iostreams mode no iostream symbols can be used
|
||||
#ifndef _STLP_NO_IOSTREAMS
|
||||
|
||||
# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
|
||||
# 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)
|
||||
@@ -519,18 +438,14 @@ template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::
|
||||
return os;
|
||||
}
|
||||
|
||||
#endif // _STLP_NO_IOSTREAMS
|
||||
|
||||
#endif // __GNUC__ < 3
|
||||
#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) )
|
||||
#if (defined(__GNUC__) && (__GNUC__ < 3)) || (defined(__EDG_VERSION__) && (__EDG_VERSION__ <= 238))
|
||||
|
||||
// g++ 2.9x doesn't allow static_cast<X const *>(void *)
|
||||
// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
|
||||
// apparently EDG 2.38 also doesn't accept it
|
||||
|
||||
template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
|
||||
{
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
// See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation.
|
||||
//
|
||||
|
||||
#include <memory> // boost.TR1 include order fix
|
||||
#include <boost/detail/shared_count.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
|
||||
@@ -71,7 +69,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
|
||||
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
|
||||
|
||||
template<class Y>
|
||||
weak_ptr & operator=(weak_ptr<Y> const & r) // never throws
|
||||
@@ -141,7 +139,7 @@ public:
|
||||
pn.swap(other.pn);
|
||||
}
|
||||
|
||||
void _internal_assign(T * px2, boost::detail::shared_count const & pn2)
|
||||
void _internal_assign(T * px2, detail::shared_count const & pn2)
|
||||
{
|
||||
px = px2;
|
||||
pn = pn2;
|
||||
@@ -164,8 +162,8 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
T * px; // contained pointer
|
||||
boost::detail::weak_count pn; // reference counter
|
||||
T * px; // contained pointer
|
||||
detail::weak_count pn; // reference counter
|
||||
|
||||
}; // weak_ptr
|
||||
|
||||
|
||||
@@ -7,9 +7,3 @@ Automatic redirection failed, please go to
|
||||
<a href="smart_ptr.htm">smart_ptr.htm</a>.
|
||||
</body>
|
||||
</html>
|
||||
<!--
|
||||
<09> 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
|
||||
-->
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgColor="#ffffff">
|
||||
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle"
|
||||
border="0"></A>intrusive_ptr class template</h1>
|
||||
<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>
|
||||
@@ -31,11 +31,11 @@
|
||||
<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;
|
||||
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;
|
||||
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>
|
||||
@@ -127,8 +127,8 @@
|
||||
<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);
|
||||
template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);</pre>
|
||||
<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>
|
||||
@@ -139,8 +139,8 @@ template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);</pr
|
||||
<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);
|
||||
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
|
||||
<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>
|
||||
@@ -196,26 +196,26 @@ intrusive_ptr & operator=(T * r);</pre>
|
||||
<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, U * b); // never throws</pre>
|
||||
<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, class U>
|
||||
bool operator!=(intrusive_ptr<T> const & a, U * b); // never throws</pre>
|
||||
<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, class U>
|
||||
bool operator==(T * a, intrusive_ptr<U> const & b); // never throws</pre>
|
||||
<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!=(T * a, intrusive_ptr<U> const & b); // never throws</pre>
|
||||
<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>
|
||||
@@ -278,8 +278,9 @@ intrusive_ptr & operator=(T * r);</pre>
|
||||
<p>
|
||||
$Date$</p>
|
||||
<p>
|
||||
<small>Copyright <20> 2003-2005 Peter Dimov. Distributed under the Boost Software License, Version
|
||||
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></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,105 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>pointer_cast.hpp</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1><IMG height="86" alt="C++ Boost" src="../../boost.png" width="277" align="middle" border="0">Pointer
|
||||
cast functions</h1>
|
||||
<p>The pointer cast functions (<code>boost::static_pointer_cast</code> <code>boost::dynamic_pointer_cast</code>
|
||||
<code>boost::reinterpret_pointer_cast</code> <code>boost::const_pointer_cast</code>)
|
||||
provide a way to write generic pointer castings for raw pointers. The functions
|
||||
are defined in <CITE><A href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</A>.</CITE></p>
|
||||
<P>There is test/example code in <CITE><A href="test/pointer_cast_test.cpp">pointer_cast_test.cpp</A></CITE>.</p>
|
||||
<h2><a name="rationale">Rationale</a></h2>
|
||||
<P>Boost smart pointers usually overload those functions to provide a mechanism to
|
||||
emulate pointers casts. For example, <code>boost::shared_ptr<...></code> implements
|
||||
a static pointer cast this way:</P>
|
||||
<pre>
|
||||
template<class T, class U>
|
||||
shared_ptr<T> static_pointer_cast(shared_ptr<U> const &r);
|
||||
</pre>
|
||||
<P>Pointer cast functions from <CITE><A href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</A></CITE>
|
||||
are overloads of <code>boost::static_pointer_cast</code>, <code>boost::dynamic_pointer_cast</code>,
|
||||
<code>boost::reinterpret_pointer_cast</code> and <code>boost::const_pointer_cast</code>
|
||||
for raw pointers. This way when developing pointer type independent classes,
|
||||
for example, memory managers or shared memory compatible classes, the same code
|
||||
can be used for raw and smart pointers.</p>
|
||||
<H2><A name="synopsis">Synopsis</A></H2>
|
||||
<BLOCKQUOTE>
|
||||
<PRE>
|
||||
namespace boost {
|
||||
|
||||
template<class T, class U>
|
||||
inline T* static_pointer_cast(U *ptr)
|
||||
{ return static_cast<T*>(ptr); }
|
||||
|
||||
template<class T, class U>
|
||||
inline T* dynamic_pointer_cast(U *ptr)
|
||||
{ return dynamic_cast<T*>(ptr); }
|
||||
|
||||
template<class T, class U>
|
||||
inline T* const_pointer_cast(U *ptr)
|
||||
{ return const_cast<T*>(ptr); }
|
||||
|
||||
template<class T, class U>
|
||||
inline T* reinterpret_pointer_cast(U *ptr)
|
||||
{ return reinterpret_cast<T*>(ptr); }
|
||||
|
||||
} // namespace boost
|
||||
</PRE>
|
||||
</BLOCKQUOTE>
|
||||
<P>As you can see from the above synopsis, the pointer cast functions are just
|
||||
wrappers around standard C++ cast operators.</P>
|
||||
<H2><A name="example">Example</A></H2>
|
||||
<BLOCKQUOTE>
|
||||
<PRE>
|
||||
#include <boost/pointer_cast.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
class base
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~base()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class derived: public base
|
||||
{
|
||||
};
|
||||
|
||||
template <class BasePtr>
|
||||
void check_if_it_is_derived(const BasePtr &ptr)
|
||||
{
|
||||
assert(boost::dynamic_pointer_cast<derived>(ptr) != 0);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
<I>// Create a raw and a shared_ptr</I>
|
||||
|
||||
base *ptr = new derived;
|
||||
boost::shared_ptr<base> sptr(new derived);
|
||||
|
||||
<I>// Check that base pointer points actually to derived class</I>
|
||||
|
||||
check_if_it_is_derived(ptr);
|
||||
check_if_it_is_derived(sptr);
|
||||
|
||||
// <EM>Ok!</EM>
|
||||
|
||||
delete ptr;
|
||||
return 0;
|
||||
}</PRE>
|
||||
</BLOCKQUOTE>
|
||||
<P>The example demonstrates how the generic pointer casts help us create pointer
|
||||
independent code.</P>
|
||||
<hr>
|
||||
<p>Revised: $Date$</p>
|
||||
<p>Copyright 2005 Ion Gazta<74>aga. Use, modification, and distribution are subject to
|
||||
the Boost Software License, Version 1.0. (See accompanying file <A href="../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</A> or a copy at <<A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>>.)</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,108 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>pointer_to_other.hpp</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">Header
|
||||
<a href="../../boost/pointer_to_other.hpp">boost/pointer_to_other.hpp</a></h1>
|
||||
<p>
|
||||
The pointer to other utility provides a way, given a source pointer type,
|
||||
to obtain a pointer of the same type to another pointee type. The utility is
|
||||
defined in <cite><a href="../../boost/pointer_to_other.hpp">boost/pointer_to_other.hpp</a>.</cite></p>
|
||||
<p>There is test/example code in <cite><a href="test/pointer_to_other_test.cpp">pointer_to_other_test.cpp</a></cite>.</p>
|
||||
<h2><a name="contents">Contents</a></h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#rationale">Rationale</a>
|
||||
<li>
|
||||
<a href="#synopsis">Synopsis</a>
|
||||
<li>
|
||||
<a href="#example">Example</a></li>
|
||||
</ul>
|
||||
<h2><a name="rationale">Rationale</a></h2>
|
||||
<p>When building pointer independent classes, like memory managers, allocators, or
|
||||
containers, there is often a need to define pointers generically, so that if a
|
||||
template parameter represents a pointer (for example, a raw or smart pointer to
|
||||
an int), we can define another pointer of the same type to another pointee (a
|
||||
raw or smart pointer to a float.)</p>
|
||||
<pre>template <class IntPtr>
|
||||
class FloatPointerHolder
|
||||
{
|
||||
<em>// Let's define a pointer to a float</em>
|
||||
typedef typename boost::pointer_to_other
|
||||
<IntPtr, float>::type float_ptr_t;
|
||||
float_ptr_t float_ptr;
|
||||
};</pre>
|
||||
<h2><a name="synopsis">Synopsis</a></h2>
|
||||
<pre>
|
||||
namespace boost {
|
||||
|
||||
template<class T, class U>
|
||||
struct pointer_to_other;
|
||||
|
||||
template<class T, class U, template <class> class Sp>
|
||||
struct pointer_to_other< Sp<T>, U >
|
||||
{
|
||||
typedef Sp<U> type;
|
||||
};
|
||||
|
||||
template<class T, class T2, class U,
|
||||
template <class, class> class Sp>
|
||||
struct pointer_to_other< Sp<T, T2>, U >
|
||||
{
|
||||
typedef Sp<U, T2> type;
|
||||
};
|
||||
|
||||
template<class T, class T2, class T3, class U,
|
||||
template <class, class, class> class Sp>
|
||||
struct pointer_to_other< Sp<T, T2, T3>, U >
|
||||
{
|
||||
typedef Sp<U, T2, T3> type;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
struct pointer_to_other< T*, U >
|
||||
{
|
||||
typedef U* type;
|
||||
};
|
||||
|
||||
} <em>// namespace boost</em></pre>
|
||||
<p>If these definitions are not correct for a specific smart pointer, we can define
|
||||
a specialization of pointer_to_other.</p>
|
||||
<h2><a name="example">Example</a></h2>
|
||||
<pre><em>// Let's define a memory allocator that can
|
||||
// work with raw and smart pointers</em>
|
||||
|
||||
#include <boost/pointer_to_other.hpp>
|
||||
|
||||
template <class VoidPtr>
|
||||
class memory_allocator
|
||||
{<em>
|
||||
// Predefine a memory_block </em>
|
||||
struct block;<em>
|
||||
|
||||
// Define a pointer to a memory_block from a void pointer
|
||||
// If VoidPtr is void *, block_ptr_t is block*
|
||||
// If VoidPtr is smart_ptr<void>, block_ptr_t is smart_ptr<block></em>
|
||||
typedef typename boost::pointer_to_other
|
||||
<VoidPtr, block>::type block_ptr_t;
|
||||
|
||||
struct block
|
||||
{
|
||||
std::size_t size;
|
||||
block_ptr_t next_block;
|
||||
};
|
||||
|
||||
block_ptr_t free_blocks;
|
||||
};</pre>
|
||||
<p>As we can see, using pointer_to_other we can create pointer independent code.</p>
|
||||
<hr>
|
||||
<p>Last revised: $Date$</p>
|
||||
<p><small>Copyright 2005, 2006 Ion Gazta<74>aga and Peter Dimov. Use, modification,
|
||||
and distribution are subject to the Boost Software License, Version 1.0.<br>
|
||||
(See accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a
|
||||
copy at < <a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>>.)</small></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -5,8 +5,8 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body bgcolor="#ffffff" text="#000000">
|
||||
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
|
||||
border="0"></A>scoped_array class template</h1>
|
||||
<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
|
||||
@@ -14,9 +14,10 @@
|
||||
<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>,
|
||||
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
|
||||
@@ -47,8 +48,6 @@
|
||||
T & <a href="#operator[]">operator[]</a>(std::ptrdiff_t i) 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>(scoped_array & b); // never throws
|
||||
};
|
||||
|
||||
@@ -91,10 +90,6 @@
|
||||
<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="conversions">conversions</a></h3>
|
||||
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
|
||||
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent
|
||||
to <code>get() != 0</code>.</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
|
||||
@@ -106,12 +101,11 @@
|
||||
<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>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-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.</p>
|
||||
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>
|
||||
</html>
|
||||
@@ -5,8 +5,8 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body bgcolor="#ffffff" text="#000000">
|
||||
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
|
||||
border="0"></A>scoped_ptr class template</h1>
|
||||
<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>,
|
||||
@@ -48,8 +48,6 @@
|
||||
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>(scoped_ptr & b); // never throws
|
||||
};
|
||||
|
||||
@@ -92,10 +90,6 @@
|
||||
<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="conversions">conversions</a></h3>
|
||||
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
|
||||
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent
|
||||
to <code>get() != 0</code>.</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
|
||||
@@ -156,8 +150,8 @@ Buckle my shoe</pre>
|
||||
<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>,
|
||||
<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>
|
||||
@@ -171,10 +165,10 @@ Buckle my shoe</pre>
|
||||
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 -->
|
||||
<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-2005 Peter Dimov. Permission to copy, use, modify, sell and
|
||||
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>
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body bgcolor="#ffffff" text="#000000">
|
||||
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
|
||||
border="0"></A>shared_array class template</h1>
|
||||
<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>
|
||||
@@ -53,8 +53,6 @@
|
||||
bool <a href="#unique">unique</a>() const; // never throws
|
||||
long <a href="#use_count">use_count</a>() const; // never throws
|
||||
|
||||
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
|
||||
|
||||
void <a href="#swap">swap</a>(shared_array<T> & b); // never throws
|
||||
};
|
||||
|
||||
@@ -141,10 +139,6 @@
|
||||
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="conversions">conversions</a></h3>
|
||||
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
|
||||
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent
|
||||
to <code>get() != 0</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
|
||||
@@ -178,9 +172,9 @@ template<class T>
|
||||
<!--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-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.</p>
|
||||
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>
|
||||
|
||||
131
shared_ptr.htm
131
shared_ptr.htm
@@ -5,8 +5,8 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgColor="#ffffff">
|
||||
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle"
|
||||
border="0"></A>shared_ptr class template</h1>
|
||||
<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>
|
||||
@@ -20,7 +20,7 @@
|
||||
<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
|
||||
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>
|
||||
@@ -47,13 +47,6 @@
|
||||
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>
|
||||
@@ -106,7 +99,6 @@ void bad()
|
||||
<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);
|
||||
template<class Y, class D, class A> <A href="#allocator_constructor" >shared_ptr</A>(Y * p, D d, A a);
|
||||
<A href="#destructor" >~shared_ptr</A>(); // never throws
|
||||
|
||||
<A href="#constructors" >shared_ptr</A>(shared_ptr const & r); // never throws
|
||||
@@ -121,7 +113,6 @@ void bad()
|
||||
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);
|
||||
template<class Y, class D, class A> void <A href="#reset" >reset</A>(Y * p, D d, A a);
|
||||
|
||||
T & <A href="#indirection" >operator*</A>() const; // never throws
|
||||
T * <A href="#indirection" >operator-></A>() const; // never throws
|
||||
@@ -163,6 +154,15 @@ void bad()
|
||||
template<class D, class T>
|
||||
D * <A href="#get_deleter">get_deleter</A>(shared_ptr<T> const & p);
|
||||
}</pre>
|
||||
<P><EM>[It might be convenient to relax the requirements on <STRONG>shared_ptr</STRONG>'s
|
||||
signature, allowing an additional, defaulted, template parameter; the parameter
|
||||
can encode the threading model, for example. This would help in detecting
|
||||
possible ODR violations.</EM></P>
|
||||
<P><EM>On the other hand, using <STRONG>shared_ptr</STRONG> as an argument to a
|
||||
template template parameter requires an exact signature match. </EM><EM>Metaprogramming
|
||||
experts tend to deemphasize template template parameters as they are too
|
||||
inflexible, but the alternative is typically an std::allocator::rebind-type
|
||||
"hack".]</EM></P>
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
@@ -172,13 +172,24 @@ void bad()
|
||||
<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>Effects:</b> Constructs an <EM>empty</EM> <b>shared_ptr</b>. <EM>Empty</EM> <STRONG>
|
||||
shared_ptr</STRONG> objects have an unspecified <A href="#use_count">use_count</A>.</p>
|
||||
<p><b>Postconditions:</b> <code>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>
|
||||
allocate memory.</EM></P>
|
||||
<P><EM>There are two possible implementations, one stores 0 as a pointer to the
|
||||
reference count, the other uses a single statically allocated count for all
|
||||
default-constructed <STRONG>shared_ptr</STRONG>s. The second option is
|
||||
difficult to achieve in the current header-only reference implementation due to
|
||||
thread safety issues and initialization order, but it should not be precluded
|
||||
by the specification. That's why the use_count() has been left unspecified.</EM></P>
|
||||
<P><EM>A future release may enable <STRONG>shared_ptr</STRONG> construction from a
|
||||
literal zero, for consistency with built-in pointers. It is not clear yet
|
||||
whether this constructor should be left implicit, enabling <STRONG>0</STRONG> to
|
||||
be used as a shorthand for <STRONG>shared_ptr<T>().</STRONG>]</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>
|
||||
@@ -187,8 +198,8 @@ void bad()
|
||||
</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>Throws:</b> <b>std::bad_alloc</b> 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
|
||||
@@ -205,23 +216,18 @@ void bad()
|
||||
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>
|
||||
<a name="allocator_constructor"></a>
|
||||
<pre>template<class Y, class D> shared_ptr(Y * p, D d);
|
||||
template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);</pre>
|
||||
<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. <STRONG>
|
||||
A</STRONG> must be an <EM>Allocator</EM>, as described in section 20.1.5 (<STRONG>Allocator
|
||||
requirements</STRONG>) of the C++ Standard.
|
||||
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>. The second constructor allocates
|
||||
memory using a copy of <STRONG>a</STRONG>.</p>
|
||||
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>Throws:</b> <b>std::bad_alloc</b> 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>
|
||||
@@ -239,10 +245,17 @@ template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);</pre>
|
||||
<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">
|
||||
<P><EM>Pass by reference is problematic since (1) pass by value conveniently changes
|
||||
functions (function references) to function pointers (this has to be performed
|
||||
manually otherwise and some compilers may not be able to do it) and (2) const
|
||||
references don't currently (per the standard) bind to functions. This can be
|
||||
solved (I think) but it requires an overload set that breaks on many compilers
|
||||
due to 14.5.5.2 problems (and of course it will break on compilers that don't
|
||||
do partial ordering at all.)</EM></P>
|
||||
<P><EM>The main problem with pass by reference, though, lies in its interaction with
|
||||
rvalues. A const reference may still cause a copy, and will require a const
|
||||
operator(). A non-const reference won't bind to an rvalue at all. A good
|
||||
solution to this problem is the rvalue reference proposed in <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>
|
||||
@@ -255,8 +268,9 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r); // never
|
||||
</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>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>
|
||||
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
|
||||
@@ -266,8 +280,8 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r); // never
|
||||
<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>Throws:</b> <b>std::bad_alloc</b> 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>
|
||||
@@ -311,6 +325,12 @@ q = p;
|
||||
</pre>
|
||||
<p>both assignments may be no-ops.</p>
|
||||
</BLOCKQUOTE>
|
||||
<P><EM>[Some experts consider the note to be redundant, as it appears to essentially
|
||||
mirror the "as if" rule. However, experience suggests that when C++ code is
|
||||
used to describe effects, it is often misinterpreted as required
|
||||
implementation. In addition, it is not entirely clear whether the "as if" rule
|
||||
actually applies here, so it's better to be explicit about the possible
|
||||
optimizations.]</EM></P>
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
<pre>void reset(); // never throws</pre>
|
||||
<BLOCKQUOTE>
|
||||
@@ -324,10 +344,6 @@ q = p;
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p, d).swap(*this)</code>.</P>
|
||||
</BLOCKQUOTE>
|
||||
<pre>template<class Y, class D, class A> void reset(Y * p, D d, A a);</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p, d, a).swap(*this)</code>.</P>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="indirection">indirection</a></h3>
|
||||
<pre>T & operator*() const; // never throws</pre>
|
||||
<blockquote>
|
||||
@@ -411,7 +427,7 @@ q = p;
|
||||
<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>
|
||||
are equivalent if and only if they <EM>share ownership</EM>.</LI></UL>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> Allows <STRONG>shared_ptr</STRONG> objects to be used as keys in
|
||||
associative containers.</P>
|
||||
@@ -586,32 +602,11 @@ 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>
|
||||
<p><STRONG>shared_ptr</STRONG> uses <A href="../config/config.htm">Boost.Config</A>
|
||||
to detect whether the implementation supports threads. If your program is
|
||||
single-threaded, but your platform is autodetected by <STRONG>Boost.Config</STRONG>
|
||||
as supporting multiple threads, <STRONG>#define BOOST_DISABLE_THREADS</STRONG> to
|
||||
eliminate the thread safety overhead.</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
|
||||
@@ -632,7 +627,7 @@ p3.reset(new int(2)); // undefined, multiple writes
|
||||
day a highly configurable smart pointer may be invented that is also very easy
|
||||
to use and very hard to misuse. Until then, <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">
|
||||
based smart pointers should read <A href="http://cseng.aw.com/book/0,,0201704315,00.html">
|
||||
Modern C++ Design</A> by Andrei Alexandrescu.)<BR>
|
||||
</P>
|
||||
<P><B>Q.</B> I am not convinced. Default parameters can be used where appropriate
|
||||
@@ -696,7 +691,7 @@ int * p = a.release();
|
||||
<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
|
||||
Copyright 2002, 2003 Peter Dimov. Permission to copy, use, modify, sell and
|
||||
distribute this document is granted provided this copyright notice appears in
|
||||
all copies. This document is provided "as is" without express or implied
|
||||
warranty, and with no claim as to its suitability for any purpose.</small></p>
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body bgcolor="#ffffff" text="#000000">
|
||||
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
|
||||
border="0"></A>Smart Pointers</h1>
|
||||
<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>
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgColor="#ffffff">
|
||||
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle"
|
||||
border="0"></A>Smart Pointer Programming Techniques</h1>
|
||||
<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>
|
||||
@@ -272,9 +272,6 @@ shared_ptr<X> createX()
|
||||
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
|
||||
@@ -519,9 +516,6 @@ public:
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<p>Note that you no longer need to manually initialize the <code>weak_ptr</code> member
|
||||
in <code><A href="enable_shared_from_this.html">enable_shared_from_this</A></code>.
|
||||
Constructing a <code>shared_ptr</code> to <code>impl</code> takes care of that.</p>
|
||||
<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>
|
||||
@@ -758,8 +752,9 @@ public:
|
||||
all weak pointers will automatically expire.</p>
|
||||
<hr>
|
||||
<p>$Date$</p>
|
||||
<p><small>Copyright <20> 2003 Peter Dimov. Distributed under the Boost Software License, Version
|
||||
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></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>
|
||||
|
||||
41
test/Jamfile
Normal file
41
test/Jamfile
Normal file
@@ -0,0 +1,41 @@
|
||||
# Boost.SmartPtr Library test Jamfile
|
||||
#
|
||||
# Copyright (c) 2003 Peter Dimov
|
||||
# Copyright (c) 2003 Dave Abrahams
|
||||
#
|
||||
# Permission to copy, use, modify, sell and distribute this software
|
||||
# is granted provided this copyright notice appears in all copies.
|
||||
# This software is provided "as is" without express or implied
|
||||
# warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
subproject libs/smart_ptr/test ;
|
||||
|
||||
# bring in rules for testing
|
||||
import testing ;
|
||||
|
||||
# Make tests run by default.
|
||||
DEPENDS all : smart_ptr ;
|
||||
|
||||
{
|
||||
test-suite "smart_ptr"
|
||||
: [ run smart_ptr_test.cpp ]
|
||||
[ run shared_ptr_basic_test.cpp : : : <gcc><*><cxxflags>-Wno-non-virtual-dtor ]
|
||||
[ run shared_ptr_test.cpp : : : <gcc><*><cxxflags>-Wno-non-virtual-dtor ]
|
||||
[ run weak_ptr_test.cpp ]
|
||||
[ run shared_from_this_test.cpp : : : <gcc><*><cxxflags>-Wno-non-virtual-dtor ]
|
||||
[ run get_deleter_test.cpp ]
|
||||
[ run intrusive_ptr_test.cpp ]
|
||||
[ run intrusive_ptr_test.cpp ]
|
||||
[ compile-fail shared_ptr_assign_fail.cpp ]
|
||||
;
|
||||
|
||||
# this one is too slow to run unless explicitly requested, and ALL
|
||||
# tests are run by default when this file is subincluded from
|
||||
# boost/status, so it's guarded from that case. It will only be
|
||||
# built from this directory when the targets "test" (all tests) or
|
||||
# "shared_ptr_alloc_test" are requested.
|
||||
if [ in-invocation-subdir ]
|
||||
{
|
||||
run shared_ptr_alloc_test.cpp ;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
# Boost.SmartPtr Library test Jamfile
|
||||
#
|
||||
# Copyright (c) 2003-2005 Peter Dimov
|
||||
# Copyright (c) 2003 Peter Dimov
|
||||
# Copyright (c) 2003 Dave Abrahams
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See
|
||||
# accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
# 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 ;
|
||||
@@ -19,13 +20,17 @@ import testing ;
|
||||
[ 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 ]
|
||||
[ run shared_ptr_alloc2_test.cpp ]
|
||||
[ run pointer_cast_test.cpp ]
|
||||
[ compile pointer_to_other_test.cpp ]
|
||||
[ run auto_ptr_rv_test.cpp ]
|
||||
;
|
||||
|
||||
# this one is too slow to run unless explicitly requested, and ALL
|
||||
# tests are run by default when this file is subincluded from
|
||||
# boost/status, so it's guarded from that case. It will only be
|
||||
# built from this directory when the targets "test" (all tests) or
|
||||
# "shared_ptr_alloc_test" are requested.
|
||||
#!!!
|
||||
#if [ in-invocation-subdir ]
|
||||
#{
|
||||
# run shared_ptr_alloc_test.cpp ;
|
||||
#}
|
||||
}
|
||||
|
||||
@@ -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,111 +0,0 @@
|
||||
//
|
||||
// auto_ptr_rv_test.cpp
|
||||
//
|
||||
// Copyright (c) 2006 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <memory>
|
||||
|
||||
struct X
|
||||
{
|
||||
static long instances;
|
||||
|
||||
X()
|
||||
{
|
||||
++instances;
|
||||
}
|
||||
|
||||
~X()
|
||||
{
|
||||
--instances;
|
||||
}
|
||||
|
||||
static std::auto_ptr<X> create()
|
||||
{
|
||||
return std::auto_ptr<X>( new X );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
X( X const & );
|
||||
X & operator=( X const & );
|
||||
};
|
||||
|
||||
long X::instances = 0;
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
|
||||
{
|
||||
boost::shared_ptr<X> p( X::create() );
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
|
||||
p = X::create();
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
|
||||
p.reset();
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
|
||||
p = X::create();
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
}
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
|
||||
{
|
||||
boost::shared_ptr<X const> p( X::create() );
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
|
||||
p = X::create();
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
|
||||
p.reset();
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
|
||||
p = X::create();
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
}
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
|
||||
{
|
||||
boost::shared_ptr<void> p( X::create() );
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
|
||||
p = X::create();
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
|
||||
p.reset();
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
|
||||
p = X::create();
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
}
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
|
||||
{
|
||||
boost::shared_ptr<void const> p( X::create() );
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
|
||||
p = X::create();
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
|
||||
p.reset();
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
|
||||
p = X::create();
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
}
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
//
|
||||
// intrusive_ptr_test.cpp
|
||||
//
|
||||
// Copyright (c) 2002-2005 Peter Dimov
|
||||
// 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
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
#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>
|
||||
@@ -42,7 +41,7 @@ class base
|
||||
{
|
||||
private:
|
||||
|
||||
boost::detail::atomic_count use_count_;
|
||||
long use_count_;
|
||||
|
||||
base(base const &);
|
||||
base & operator=(base const &);
|
||||
|
||||
@@ -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,126 +0,0 @@
|
||||
//
|
||||
// pointer_cast_test.cpp - a test for boost/pointer_cast.hpp
|
||||
//
|
||||
// Copyright (c) 2005 Ion Gazta<74>aga
|
||||
// Copyright (c) 2005 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include <boost/pointer_cast.hpp>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/get_pointer.hpp>
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Let's create these inheritance relationship:
|
||||
//
|
||||
// base base2
|
||||
// | |
|
||||
// derived
|
||||
// |
|
||||
// derived_derived
|
||||
//
|
||||
|
||||
class base
|
||||
{
|
||||
public:
|
||||
virtual ~base(){}
|
||||
int filler [5];
|
||||
};
|
||||
|
||||
class base2
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~base2(){}
|
||||
int filler [5];
|
||||
};
|
||||
|
||||
class derived
|
||||
: public base, public base2
|
||||
{
|
||||
int filler [5];
|
||||
};
|
||||
|
||||
class derived_derived
|
||||
: public derived
|
||||
{
|
||||
int filler [5];
|
||||
};
|
||||
|
||||
// And now some simple check functions
|
||||
|
||||
template <class BasePtr>
|
||||
bool check_dynamic_pointer_cast(const BasePtr &ptr)
|
||||
{
|
||||
//Check that dynamic_pointer_cast versus dynamic_cast
|
||||
return
|
||||
//Correct cast with dynamic_pointer_cast
|
||||
boost::get_pointer(boost::dynamic_pointer_cast<derived>(ptr)) ==
|
||||
//Correct cast with dynamic_cast
|
||||
dynamic_cast<derived*>(boost::get_pointer(ptr))
|
||||
&&
|
||||
//Incorrect cast with dynamic_pointer_cast
|
||||
boost::get_pointer(boost::dynamic_pointer_cast<derived_derived>(ptr)) ==
|
||||
//Incorrect cast with dynamic_cast
|
||||
dynamic_cast<derived_derived*>(boost::get_pointer(ptr));
|
||||
}
|
||||
|
||||
template <class BasePtr>
|
||||
bool check_static_pointer_cast(const BasePtr &ptr)
|
||||
{
|
||||
return
|
||||
//Cast base -> derived -> base2 using static_pointer_cast
|
||||
boost::get_pointer(
|
||||
boost::static_pointer_cast<base2>(
|
||||
boost::static_pointer_cast<derived>(ptr))) ==
|
||||
//Now the same with static_cast
|
||||
static_cast<base2*>(static_cast<derived*>(boost::get_pointer(ptr)));
|
||||
}
|
||||
|
||||
template <class BasePtr>
|
||||
bool check_const_pointer_cast(const BasePtr &ptr)
|
||||
{
|
||||
return
|
||||
//Unconst and const again using const_pointer_cast
|
||||
boost::get_pointer(
|
||||
boost::const_pointer_cast<const base>
|
||||
(boost::const_pointer_cast<base>(ptr))) ==
|
||||
//Now the same with const_cast
|
||||
const_cast<const base*>(const_cast<base*>(boost::get_pointer(ptr)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
// Try casts with shared_ptr
|
||||
|
||||
boost::shared_ptr<base> ptr(new derived);
|
||||
|
||||
BOOST_TEST( check_dynamic_pointer_cast( ptr ) );
|
||||
BOOST_TEST( check_static_pointer_cast( ptr ) );
|
||||
BOOST_TEST( check_const_pointer_cast( ptr ) );
|
||||
}
|
||||
|
||||
{
|
||||
// Try casts with raw pointer
|
||||
|
||||
boost::scoped_ptr<base> ptr(new derived);
|
||||
|
||||
BOOST_TEST( check_dynamic_pointer_cast( ptr.get() ) );
|
||||
BOOST_TEST( check_static_pointer_cast( ptr.get() ) );
|
||||
BOOST_TEST( check_const_pointer_cast( ptr.get() ) );
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
//
|
||||
// pointer_to_other_test.cpp - a test for boost/pointer_to_other.hpp
|
||||
//
|
||||
// Copyright (c) 2005 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include <boost/pointer_to_other.hpp>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/shared_array.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/scoped_array.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
template<class T, class U> void assert_same_type( T** pt = 0, U** pu = 0 )
|
||||
{
|
||||
pt = pu;
|
||||
}
|
||||
|
||||
struct X;
|
||||
struct Y;
|
||||
|
||||
int main()
|
||||
{
|
||||
// shared_ptr
|
||||
|
||||
assert_same_type< boost::pointer_to_other< boost::shared_ptr<X>, Y >::type, boost::shared_ptr<Y> >();
|
||||
assert_same_type< boost::pointer_to_other< boost::shared_ptr<X>, void >::type, boost::shared_ptr<void> >();
|
||||
assert_same_type< boost::pointer_to_other< boost::shared_ptr<void>, Y >::type, boost::shared_ptr<Y> >();
|
||||
|
||||
// shared_array
|
||||
|
||||
assert_same_type< boost::pointer_to_other< boost::shared_array<X>, Y >::type, boost::shared_array<Y> >();
|
||||
assert_same_type< boost::pointer_to_other< boost::shared_array<X>, void >::type, boost::shared_array<void> >();
|
||||
assert_same_type< boost::pointer_to_other< boost::shared_array<void>, Y >::type, boost::shared_array<Y> >();
|
||||
|
||||
// scoped_ptr
|
||||
|
||||
assert_same_type< boost::pointer_to_other< boost::scoped_ptr<X>, Y >::type, boost::scoped_ptr<Y> >();
|
||||
assert_same_type< boost::pointer_to_other< boost::scoped_ptr<X>, void >::type, boost::scoped_ptr<void> >();
|
||||
assert_same_type< boost::pointer_to_other< boost::scoped_ptr<void>, Y >::type, boost::scoped_ptr<Y> >();
|
||||
|
||||
// scoped_array
|
||||
|
||||
assert_same_type< boost::pointer_to_other< boost::scoped_array<X>, Y >::type, boost::scoped_array<Y> >();
|
||||
assert_same_type< boost::pointer_to_other< boost::scoped_array<X>, void >::type, boost::scoped_array<void> >();
|
||||
assert_same_type< boost::pointer_to_other< boost::scoped_array<void>, Y >::type, boost::scoped_array<Y> >();
|
||||
|
||||
// intrusive_ptr
|
||||
|
||||
assert_same_type< boost::pointer_to_other< boost::intrusive_ptr<X>, Y >::type, boost::intrusive_ptr<Y> >();
|
||||
assert_same_type< boost::pointer_to_other< boost::intrusive_ptr<X>, void >::type, boost::intrusive_ptr<void> >();
|
||||
assert_same_type< boost::pointer_to_other< boost::intrusive_ptr<void>, Y >::type, boost::intrusive_ptr<Y> >();
|
||||
|
||||
// auto_ptr
|
||||
|
||||
assert_same_type< boost::pointer_to_other< std::auto_ptr<X>, Y >::type, std::auto_ptr<Y> >();
|
||||
assert_same_type< boost::pointer_to_other< std::auto_ptr<X>, void >::type, std::auto_ptr<void> >();
|
||||
assert_same_type< boost::pointer_to_other< std::auto_ptr<void>, Y >::type, std::auto_ptr<Y> >();
|
||||
|
||||
// raw pointer
|
||||
|
||||
assert_same_type< boost::pointer_to_other< X *, Y >::type, Y * >();
|
||||
assert_same_type< boost::pointer_to_other< X *, void >::type, void * >();
|
||||
assert_same_type< boost::pointer_to_other< void *, Y >::type, Y * >();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// shared_ptr_alloc2_test.cpp
|
||||
//
|
||||
// Copyright (c) 2005 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <memory>
|
||||
#include <cstddef>
|
||||
|
||||
// test_allocator
|
||||
|
||||
struct test_allocator_base
|
||||
{
|
||||
int id_;
|
||||
|
||||
static int last_global_id_;
|
||||
static int count_;
|
||||
|
||||
explicit test_allocator_base( int id ): id_( id )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
int test_allocator_base::last_global_id_ = 0;
|
||||
int test_allocator_base::count_ = 0;
|
||||
|
||||
template<class T> class test_allocator: public test_allocator_base
|
||||
{
|
||||
public:
|
||||
|
||||
typedef T * pointer;
|
||||
typedef T const * const_pointer;
|
||||
typedef T & reference;
|
||||
typedef T const & const_reference;
|
||||
typedef T value_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
private:
|
||||
|
||||
static T * last_pointer_;
|
||||
static std::size_t last_n_;
|
||||
static int last_id_;
|
||||
|
||||
public:
|
||||
|
||||
template<class U> struct rebind
|
||||
{
|
||||
typedef test_allocator<U> other;
|
||||
};
|
||||
|
||||
pointer address( reference r ) const
|
||||
{
|
||||
return &r;
|
||||
}
|
||||
|
||||
const_pointer address( const_reference s ) const
|
||||
{
|
||||
return &s;
|
||||
}
|
||||
|
||||
explicit test_allocator( int id = 0 ): test_allocator_base( id )
|
||||
{
|
||||
}
|
||||
|
||||
template<class U> test_allocator( test_allocator<U> const & r ): test_allocator_base( r )
|
||||
{
|
||||
}
|
||||
|
||||
template<class U> test_allocator & operator=( test_allocator<U> const & r )
|
||||
{
|
||||
test_allocator_base::operator=( r );
|
||||
return *this;
|
||||
}
|
||||
|
||||
void deallocate( pointer p, size_type n )
|
||||
{
|
||||
BOOST_TEST( p == last_pointer_ );
|
||||
BOOST_TEST( n == last_n_ );
|
||||
BOOST_TEST( id_ == last_id_ );
|
||||
|
||||
--count_;
|
||||
|
||||
::operator delete( p );
|
||||
}
|
||||
|
||||
pointer allocate( size_type n, void const * )
|
||||
{
|
||||
T * p = static_cast< T* >( ::operator new( n * sizeof( T ) ) );
|
||||
|
||||
last_pointer_ = p;
|
||||
last_n_ = n;
|
||||
last_id_ = id_;
|
||||
|
||||
last_global_id_ = id_;
|
||||
++count_;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void construct( pointer p, T const & t )
|
||||
{
|
||||
new( p ) T( t );
|
||||
}
|
||||
|
||||
void destroy( pointer p )
|
||||
{
|
||||
p->~T();
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return size_type( -1 ) / sizeof( T );
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> T * test_allocator<T>::last_pointer_ = 0;
|
||||
template<class T> std::size_t test_allocator<T>::last_n_ = 0;
|
||||
template<class T> int test_allocator<T>::last_id_ = 0;
|
||||
|
||||
template<class T, class U> inline bool operator==( test_allocator<T> const & a1, test_allocator<U> const & a2 )
|
||||
{
|
||||
return a1.id_ == a2.id_;
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator!=( test_allocator<T> const & a1, test_allocator<U> const & a2 )
|
||||
{
|
||||
return a1.id_ != a2.id_;
|
||||
}
|
||||
|
||||
template<> class test_allocator<void>: public test_allocator_base
|
||||
{
|
||||
public:
|
||||
|
||||
typedef void * pointer;
|
||||
typedef void const * const_pointer;
|
||||
typedef void value_type;
|
||||
|
||||
template<class U> struct rebind
|
||||
{
|
||||
typedef test_allocator<U> other;
|
||||
};
|
||||
|
||||
explicit test_allocator( int id = 0 ): test_allocator_base( id )
|
||||
{
|
||||
}
|
||||
|
||||
template<class U> test_allocator( test_allocator<U> const & r ): test_allocator_base( r )
|
||||
{
|
||||
}
|
||||
|
||||
template<class U> test_allocator & operator=( test_allocator<U> const & r )
|
||||
{
|
||||
test_allocator_base::operator=( r );
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
struct X
|
||||
{
|
||||
static int instances;
|
||||
|
||||
X()
|
||||
{
|
||||
++instances;
|
||||
}
|
||||
|
||||
~X()
|
||||
{
|
||||
--instances;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
X( X const & );
|
||||
X & operator=( X const & );
|
||||
};
|
||||
|
||||
int X::instances = 0;
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
|
||||
boost::shared_ptr<void> pv( new X, boost::checked_deleter<X>(), std::allocator<X>() );
|
||||
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
|
||||
pv.reset( new X, boost::checked_deleter<X>(), test_allocator<float>( 42 ) );
|
||||
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
|
||||
BOOST_TEST( test_allocator_base::last_global_id_ == 42 );
|
||||
BOOST_TEST( test_allocator_base::count_ > 0 );
|
||||
|
||||
pv.reset();
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
BOOST_TEST( test_allocator_base::count_ == 0 );
|
||||
|
||||
pv.reset( new X, boost::checked_deleter<X>(), test_allocator<void>( 43 ) );
|
||||
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
BOOST_TEST( test_allocator_base::last_global_id_ == 43 );
|
||||
|
||||
pv.reset( new X, boost::checked_deleter<X>(), std::allocator<void>() );
|
||||
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
|
||||
pv.reset();
|
||||
|
||||
BOOST_TEST( X::instances == 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;
|
||||
}
|
||||
@@ -143,11 +143,19 @@ void test(boost::shared_ptr<int> const & pi)
|
||||
|
||||
int const m = 16; // threads
|
||||
|
||||
#if defined(BOOST_LWM_USE_CRITICAL_SECTION)
|
||||
char const * implementation = "critical section";
|
||||
#elif defined(BOOST_LWM_USE_PTHREADS)
|
||||
char const * implementation = "pthread_mutex";
|
||||
#else
|
||||
char const * implementation = "spinlock";
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace std; // printf, clock_t, clock
|
||||
|
||||
printf("%s: %d threads, %d iterations: ", title, m, n);
|
||||
printf("%s: %s, %d threads, %d iterations: ", title, implementation, m, n);
|
||||
|
||||
boost::shared_ptr<int> pi(new int(42));
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
//
|
||||
// weak_ptr_test.cpp
|
||||
//
|
||||
// Copyright (c) 2002-2005 Peter Dimov
|
||||
// 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
|
||||
@@ -500,7 +500,7 @@ void test()
|
||||
namespace n_assignment
|
||||
{
|
||||
|
||||
template<class T> void copy_assignment(boost::shared_ptr<T> & sp)
|
||||
template<class T> void copy_assignment(boost::shared_ptr<T> sp)
|
||||
{
|
||||
BOOST_TEST(sp.unique());
|
||||
|
||||
@@ -611,7 +611,7 @@ void conversion_assignment()
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, class U> void shared_ptr_assignment(boost::shared_ptr<U> & sp, T * = 0)
|
||||
template<class T, class U> void shared_ptr_assignment(boost::shared_ptr<U> sp, T * = 0)
|
||||
{
|
||||
BOOST_TEST(sp.unique());
|
||||
|
||||
@@ -644,62 +644,18 @@ template<class T, class U> void shared_ptr_assignment(boost::shared_ptr<U> & sp,
|
||||
|
||||
void test()
|
||||
{
|
||||
{
|
||||
boost::shared_ptr<int> p( new int );
|
||||
copy_assignment( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<X> p( new X );
|
||||
copy_assignment( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<void> p( new int );
|
||||
copy_assignment( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<incomplete> p = create_incomplete();
|
||||
copy_assignment( p );
|
||||
}
|
||||
|
||||
copy_assignment(boost::shared_ptr<int>(new int));
|
||||
copy_assignment(boost::shared_ptr<X>(new X));
|
||||
copy_assignment(boost::shared_ptr<void>(new int));
|
||||
copy_assignment(create_incomplete());
|
||||
conversion_assignment();
|
||||
|
||||
{
|
||||
boost::shared_ptr<int> p( new int );
|
||||
shared_ptr_assignment<int>( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<int> p( new int );
|
||||
shared_ptr_assignment<void>( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<X> p( new X );
|
||||
shared_ptr_assignment<X>( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<X> p( new X );
|
||||
shared_ptr_assignment<void>( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<void> p( new int );
|
||||
shared_ptr_assignment<void>( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<incomplete> p = create_incomplete();
|
||||
shared_ptr_assignment<incomplete>( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<incomplete> p = create_incomplete();
|
||||
shared_ptr_assignment<void>( p );
|
||||
}
|
||||
shared_ptr_assignment<int>(boost::shared_ptr<int>(new int));
|
||||
shared_ptr_assignment<void>(boost::shared_ptr<int>(new int));
|
||||
shared_ptr_assignment<X>(boost::shared_ptr<X>(new X));
|
||||
shared_ptr_assignment<void>(boost::shared_ptr<X>(new X));
|
||||
shared_ptr_assignment<void>(boost::shared_ptr<void>(new int));
|
||||
shared_ptr_assignment<incomplete>(create_incomplete());
|
||||
shared_ptr_assignment<void>(create_incomplete());
|
||||
}
|
||||
|
||||
} // namespace n_assignment
|
||||
@@ -707,7 +663,7 @@ void test()
|
||||
namespace n_reset
|
||||
{
|
||||
|
||||
template<class T, class U> void test2( boost::shared_ptr<U> & sp, T * = 0 )
|
||||
template<class T, class U> void test2(boost::shared_ptr<U> sp, T * = 0)
|
||||
{
|
||||
BOOST_TEST(sp.unique());
|
||||
|
||||
@@ -741,40 +697,13 @@ template<class T, class U> void test2( boost::shared_ptr<U> & sp, T * = 0 )
|
||||
|
||||
void test()
|
||||
{
|
||||
{
|
||||
boost::shared_ptr<int> p( new int );
|
||||
test2<int>( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<int> p( new int );
|
||||
test2<void>( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<X> p( new X );
|
||||
test2<X>( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<X> p( new X );
|
||||
test2<void>( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<void> p( new int );
|
||||
test2<void>( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<incomplete> p = create_incomplete();
|
||||
test2<incomplete>( p );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<incomplete> p = create_incomplete();
|
||||
test2<void>( p );
|
||||
}
|
||||
test2<int>(boost::shared_ptr<int>(new int));
|
||||
test2<void>(boost::shared_ptr<int>(new int));
|
||||
test2<X>(boost::shared_ptr<X>(new X));
|
||||
test2<void>(boost::shared_ptr<X>(new X));
|
||||
test2<void>(boost::shared_ptr<void>(new int));
|
||||
test2<incomplete>(create_incomplete());
|
||||
test2<void>(create_incomplete());
|
||||
}
|
||||
|
||||
} // namespace n_reset
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
13
weak_ptr.htm
13
weak_ptr.htm
@@ -5,8 +5,8 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgColor="#ffffff">
|
||||
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle"
|
||||
border="0"></A>weak_ptr class template</h1>
|
||||
<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>
|
||||
@@ -145,8 +145,9 @@ template<class Y> weak_ptr & operator=(shared_ptr<Y> const &
|
||||
<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>Returns:</b> if <STRONG>*this</STRONG> is <EM>empty</EM>, an unspecified
|
||||
nonnegative value; otherwise, the number of <b>shared_ptr</b> objects that <EM>share
|
||||
ownership</EM> with <STRONG>*this</STRONG>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> <code>use_count()</code> is not necessarily efficient. Use only
|
||||
for debugging and testing purposes, not for production code.</P>
|
||||
@@ -188,7 +189,7 @@ template<class Y> weak_ptr & operator=(shared_ptr<Y> const &
|
||||
<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>
|
||||
are equivalent if and only if they <EM>share ownership</EM>.</LI></UL>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> Allows <STRONG>weak_ptr</STRONG> objects to be used as keys in
|
||||
associative containers.</P>
|
||||
@@ -235,7 +236,7 @@ public:
|
||||
<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
|
||||
Copyright 2002, 2003 Peter Dimov. Permission to copy, use, modify, sell and
|
||||
distribute this document is granted provided this copyright notice appears in
|
||||
all copies. This document is provided "as is" without express or implied
|
||||
warranty, and with no claim as to its suitability for any purpose.</small></p>
|
||||
|
||||
Reference in New Issue
Block a user