Compare commits

...

83 Commits

Author SHA1 Message Date
nobody
9fa591db1f This commit was manufactured by cvs2svn to create tag
'Version_1_29_0'.

[SVN r15904]
2002-10-11 15:17:55 +00:00
Peter Dimov
71a0c0ee97 Fixes, notes.
[SVN r15487]
2002-09-23 13:32:54 +00:00
nobody
4990c9c83e This commit was manufactured by cvs2svn to create branch 'RC_1_29_0'.
[SVN r15460]
2002-09-19 20:49:39 +00:00
Peter Dimov
9dcbc46225 Minor fix
[SVN r15437]
2002-09-18 13:00:38 +00:00
Peter Dimov
024f918b86 More documentation fixes reflecting Dave Abrahams' comments
[SVN r15411]
2002-09-17 13:59:17 +00:00
Peter Dimov
0f05f41306 Documentation fixes (reflecting Dave Abrahams' comments)
[SVN r15382]
2002-09-16 15:26:52 +00:00
Peter Dimov
4ea6decc7d scoped_ptr::reset changed to copy+swap (problem reported by Thomas Witt)
[SVN r15239]
2002-09-09 17:44:33 +00:00
Peter Dimov
f79b8cb7ae Tabs removed.
[SVN r15175]
2002-09-06 12:50:02 +00:00
Peter Dimov
275cb77378 Fixed broken links.
[SVN r15123]
2002-08-31 13:04:52 +00:00
Peter Dimov
b916445dd8 weak_ptr documentation updates; get() declared deprecated.
[SVN r15111]
2002-08-29 15:18:04 +00:00
Douglas Gregor
c02fee7013 *_ptr.hpp:
- Revert addition of is_pointerlike_helper

weak_ptr.hpp:
  - Revert addition of get_pointer


[SVN r15108]
2002-08-29 13:49:05 +00:00
Douglas Gregor
e77889679f intrusive_ptr.hpp:
scoped_ptr.hpp:
  - include <boost/type_traits/ice.hpp>


[SVN r15104]
2002-08-27 13:33:22 +00:00
Douglas Gregor
b9dceb2340 *_ptr.hpp:
- Added detail::is_pointerlike_helper function templates for Signals

weak_ptr.hpp:
  - Added get_pointer function template for weak_ptr


[SVN r15099]
2002-08-26 15:27:23 +00:00
John Maddock
e84eb3f1ba Added #pragma's to fix codeguard errors.
[SVN r14984]
2002-08-20 11:08:11 +00:00
Peter Dimov
92999be436 Corrected the shared_ptr(auto_ptr<Y> &) postcondition (reported by Maciej Sobczak)
[SVN r14953]
2002-08-19 16:23:07 +00:00
Peter Dimov
bd4f575567 HPUX 10.20 patch (problem reported by Tom Matelich)
[SVN r14943]
2002-08-17 13:33:41 +00:00
Peter Dimov
09016db3c3 Note added to shared_ptr(Y*, D).
[SVN r14942]
2002-08-17 13:05:25 +00:00
Peter Dimov
c2ee5172b0 Switched to <boost/detail/lightweight_test.hpp> for testing.
[SVN r14932]
2002-08-16 16:41:16 +00:00
Peter Dimov
8436c4d271 #pragma option -pc around use_count_is_zero added for Borland 5.5.1, to enable compilation with -ps set.
[SVN r14927]
2002-08-16 15:55:19 +00:00
Peter Dimov
a09c2e556f BOOST_NO_EXCEPTIONS support added.
[SVN r14835]
2002-08-14 12:27:22 +00:00
Peter Dimov
e650c7ff16 Changed BOOST_TEST(p) to BOOST_TEST(p? true: false) to make sure the right thing is being tested.
[SVN r14834]
2002-08-14 11:59:13 +00:00
Peter Dimov
c06b4206f2 #include <iostream> added.
[SVN r14813]
2002-08-13 15:58:12 +00:00
Peter Dimov
89435a6287 get_pointer added.
[SVN r14628]
2002-07-27 16:02:26 +00:00
Peter Dimov
5328674c2d Minor scoped_* fix (px -> ptr) (Thanks to Bertolt Mildner)
[SVN r14619]
2002-07-26 14:18:21 +00:00
Peter Dimov
927fe73093 Changed #ifdefs so that member templates aren't disabled by an empty config.hpp.
[SVN r14589]
2002-07-24 15:36:25 +00:00
Peter Dimov
053aa108e3 Tabs. Grrr.
[SVN r14588]
2002-07-24 14:14:17 +00:00
Peter Dimov
b5e5c35696 Minor updates.
[SVN r14580]
2002-07-24 10:20:30 +00:00
Peter Dimov
77ad156c52 Design notes updated.
[SVN r14575]
2002-07-23 19:12:40 +00:00
Peter Dimov
018c401e47 Best practices section, thread safety section, design notes added.
[SVN r14572]
2002-07-23 15:19:22 +00:00
Peter Dimov
f586d3f83e shared_ptr<void const> support added.
[SVN r14570]
2002-07-23 12:33:11 +00:00
Peter Dimov
3f0ebd4c71 'shared_from_this' added.
[SVN r14561]
2002-07-22 16:36:52 +00:00
Peter Dimov
33077bda71 Win64 patch (Tim Fenders)
[SVN r14537]
2002-07-19 20:06:35 +00:00
Peter Dimov
547888d507 Consistent 'bool' conversions; scoped_ptr(auto_ptr); get_pointer(scoped_ptr) added.
[SVN r14496]
2002-07-17 15:15:39 +00:00
Peter Dimov
af6fe18c9d Minor fixes.
[SVN r14464]
2002-07-15 12:52:29 +00:00
Peter Dimov
dca9628be3 Disabled some Borland warnings (David B. Held)
[SVN r14368]
2002-07-09 12:06:46 +00:00
Peter Dimov
d84fa738ef Sleep(0) changed to Sleep(1) to (hopefully) avoid livelocks.
[SVN r14226]
2002-06-22 15:55:01 +00:00
Peter Dimov
a322dc54dc Platform-specific spinlocks disabled by default unless BOOST_LWM_USE_SPINLOCK is defined.
[SVN r14213]
2002-06-20 15:16:03 +00:00
Peter Dimov
951c2b7e83 counted_base is now smaller
[SVN r14212]
2002-06-20 14:56:10 +00:00
Peter Dimov
23f68a5657 Added libstdc++ v3 specific lightweight_mutex and atomic_count (contributed by Lars Gullik Bjønnes)
[SVN r13999]
2002-05-21 16:48:20 +00:00
Peter Dimov
ecb0b4478b Typo fixed.
[SVN r13770]
2002-05-09 11:16:29 +00:00
Peter Dimov
70255d46bb Documented templated pointer constructors, revised the intro a bit.
[SVN r13665]
2002-05-04 14:27:21 +00:00
Peter Dimov
4653c3673b shared_ptr now autodetects counted_bases; minor test updates; intrusive_ptr no longer calls addref/release for NULL pointers.
[SVN r13602]
2002-05-01 11:22:22 +00:00
Peter Dimov
11eacab70e Made shared_ptr::share_ptr(Y * p) a member template.
[SVN r13551]
2002-04-23 14:56:42 +00:00
Peter Dimov
110c0021e2 counted_base default constructor added
[SVN r13542]
2002-04-22 18:01:19 +00:00
Peter Dimov
4c5e355a0b Bugfixes.
[SVN r13541]
2002-04-22 09:37:08 +00:00
Peter Dimov
fbc9028313 intrusive_ptr.hpp added (still experimental)
[SVN r13526]
2002-04-19 19:34:16 +00:00
Peter Dimov
9b800d4f84 Added more mem_fn, shared_ptr tests.
[SVN r13432]
2002-04-10 16:04:53 +00:00
Peter Dimov
513752eee5 Worked around an MSVC 6 bug (Markus Schoepflin)
[SVN r13430]
2002-04-10 14:12:12 +00:00
Beman Dawes
9eb1ba7e9f test_main args must be *[] not ** for new rev of test tools
[SVN r13381]
2002-04-06 21:44:37 +00:00
Peter Dimov
fb5b1a20d2 Small modifications.
[SVN r13212]
2002-03-15 22:03:56 +00:00
Peter Dimov
b89945d36a Added winapi.hpp and a CRITICAL_SECTION lightweight_mutex variant.
[SVN r13211]
2002-03-15 22:00:10 +00:00
Peter Dimov
220f35a0f1 Casts removed as unsafe, added intro paragraph about make_shared.
[SVN r13180]
2002-03-12 14:39:22 +00:00
Peter Dimov
72f83165e0 Removed casts as unsafe.
[SVN r13179]
2002-03-12 14:02:38 +00:00
Peter Dimov
c17f8c36c1 weak_ptr::expired() added; weak_ptr documentation updated.
[SVN r13141]
2002-03-08 16:56:16 +00:00
Peter Dimov
8e604a9da9 Disabled the linux-specific versions since using kernel headers is problematic. #define BOOST_USE_ASM_ATOMIC_H to get them back.
[SVN r12995]
2002-03-01 16:17:08 +00:00
Darin Adler
3e0233a26c Minor text updates in history section.
[SVN r12956]
2002-02-27 17:03:30 +00:00
Peter Dimov
aa98e2b37e Added lwm_irix.hpp (contributed by Dan Gohman)
[SVN r12955]
2002-02-27 16:35:15 +00:00
Peter Dimov
7b53c0040c More output.
[SVN r12852]
2002-02-18 12:39:32 +00:00
Peter Dimov
e6605637f8 BOOST_LWM_WIN32_USE_CRITICAL_SECTION option.
[SVN r12842]
2002-02-16 18:45:20 +00:00
Peter Dimov
6dfe0896e3 Untabified.
[SVN r12838]
2002-02-16 16:14:16 +00:00
Peter Dimov
9f295cbb48 Threaded test added.
[SVN r12837]
2002-02-16 16:09:08 +00:00
Peter Dimov
76c19e6111 Enabled lwm_linux.hpp in lightweight_mutex.hpp.
[SVN r12834]
2002-02-16 15:00:55 +00:00
Peter Dimov
6e6a2a013a Added lwm_linux.hpp
[SVN r12833]
2002-02-16 14:34:34 +00:00
Peter Dimov
2482e00224 Modified scoped_* to use checked_delete; HP aCC doesn't like the inline assertions.
[SVN r12832]
2002-02-16 13:23:01 +00:00
Peter Dimov
7981b647c3 lwm_nop fixed to not emit warnings on g++; locking code #ifdef'ed since compilers sometimes have trouble removing it.
[SVN r12822]
2002-02-15 18:07:42 +00:00
Peter Dimov
875bab352c Added a timing test for the single/multi threaded perf ratio (~2:1)
[SVN r12821]
2002-02-15 18:06:17 +00:00
Peter Dimov
862dc0001f Documented the bool conversion.
[SVN r12817]
2002-02-15 14:46:53 +00:00
Peter Dimov
adc3ec3851 Fixes.
[SVN r12816]
2002-02-15 14:19:30 +00:00
Peter Dimov
5a6cd1cf3e Added a default constructor to shared_count and shared_ptr for incomplete types (void).
[SVN r12815]
2002-02-15 13:31:58 +00:00
Douglas Gregor
5e2f514140 Added forward declaration of 'weak_count' class, which is referenced in
shared_count; the friend declaration does not suffice to forward-declare the
name.


[SVN r12813]
2002-02-14 23:08:30 +00:00
Peter Dimov
309e6dd82e Revised to match the style of the C++ standard.
[SVN r12806]
2002-02-14 17:12:07 +00:00
Peter Dimov
6c5d296722 Modified weak_ptr to reflect list comments.
[SVN r12793]
2002-02-13 13:16:15 +00:00
Peter Dimov
b1a1ab99aa Bug fixes.
[SVN r12787]
2002-02-12 20:38:31 +00:00
Peter Dimov
1b69c14f45 weak_ptr made thread safe, shared->weak conversions, lightweight_mutex added.
[SVN r12786]
2002-02-12 16:55:25 +00:00
Darin Adler
cd8dea78e6 Don't reinclude, since everything we need to include is already taken
care of by <boost/shared_ptr.hpp>.


[SVN r12776]
2002-02-09 17:18:38 +00:00
Peter Dimov
d77b35f333 Fix the g++ 2.9x operator!= ambiguity.
[SVN r12772]
2002-02-09 15:45:29 +00:00
Peter Dimov
6f7b927641 weak_ptr::operator< is now stable, shared_ptr_test has much better coverage.
[SVN r12769]
2002-02-09 12:34:05 +00:00
Darin Adler
d2e20cf56c Remove obsolete paragraph
[SVN r12767]
2002-02-09 02:54:00 +00:00
Darin Adler
a6126b1370 Fixed some broken internal links.
[SVN r12766]
2002-02-09 01:18:00 +00:00
Peter Dimov
87f0accb23 Minor fixes.
[SVN r12763]
2002-02-08 20:45:04 +00:00
Darin Adler
7add76dae8 Always say "private noncopyable" to avoid warnings.
[SVN r12762]
2002-02-08 20:08:15 +00:00
Peter Dimov
2a2f10fddd Borland 5.5.1 fix
[SVN r12761]
2002-02-08 18:40:49 +00:00
Darin Adler
0dd3285d56 New casts for smart pointers.
[SVN r12743]
2002-02-06 19:42:04 +00:00
36 changed files with 3523 additions and 1518 deletions

View File

@@ -72,6 +72,8 @@
// are called driven by smart_ptr interface... // are called driven by smart_ptr interface...
// //
// Note: atomic_count_linux.hpp has been disabled by default; see the
// comments inside for more info.
#include <boost/config.hpp> #include <boost/config.hpp>
@@ -89,18 +91,17 @@ typedef long atomic_count;
} }
#elif defined(BOOST_USE_ASM_ATOMIC_H)
# include <boost/detail/atomic_count_linux.hpp>
#elif defined(BOOST_AC_USE_PTHREADS)
# include <boost/detail/atomic_count_pthreads.hpp>
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
# include <boost/detail/atomic_count_win32.hpp>
#include <boost/detail/atomic_count_win32.hpp> #elif defined(__GLIBCPP__)
# include <boost/detail/atomic_count_gcc.hpp>
#elif defined(linux) || defined(__linux) || defined(__linux__)
#include <boost/detail/atomic_count_linux.hpp>
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
# define BOOST_AC_USE_PTHREADS
#include <boost/detail/atomic_count_pthreads.hpp> # include <boost/detail/atomic_count_pthreads.hpp>
#else #else
// #warning Unrecognized platform, detail::atomic_count will not be thread safe // #warning Unrecognized platform, detail::atomic_count will not be thread safe

View File

@@ -0,0 +1,61 @@
#ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED
#define BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED
//
// boost/detail/atomic_count_gcc.hpp
//
// atomic_count for GNU libstdc++ v3
//
// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2002 Lars Gullik Bj<42>nnes <larsbj@lyx.org>
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <bits/atomicity.h>
namespace boost
{
namespace detail
{
class atomic_count
{
public:
explicit atomic_count(long v) : value_(v) {}
void operator++()
{
__atomic_add(&value_, 1);
}
long operator--()
{
return !__exchange_and_add(&value_, -1);
}
operator long() const
{
return __exchange_and_add(&value_, 0);
}
private:
atomic_count(atomic_count const &);
atomic_count & operator=(atomic_count const &);
_Atomic_word value_;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED

View File

@@ -13,7 +13,13 @@
// //
// //
// On Linux, atomic.h is usually located in /usr/include/asm // 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> #include <asm/atomic.h>

View File

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

View File

@@ -16,20 +16,14 @@
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
#include <boost/detail/winapi.hpp>
namespace boost namespace boost
{ {
namespace detail namespace detail
{ {
// Avoid #including <windows.h>
namespace win32
{
extern "C" __declspec(dllimport) long __stdcall InterlockedIncrement(long volatile *);
extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement(long volatile *);
}
class atomic_count class atomic_count
{ {
public: public:
@@ -40,12 +34,12 @@ public:
long operator++() long operator++()
{ {
return win32::InterlockedIncrement(&value_); return winapi::InterlockedIncrement(&value_);
} }
long operator--() long operator--()
{ {
return win32::InterlockedDecrement(&value_); return winapi::InterlockedDecrement(&value_);
} }
operator long() const operator long() const

View File

@@ -0,0 +1,88 @@
#ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
#define BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/detail/lightweight_mutex.hpp - lightweight mutex
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// typedef <unspecified> boost::detail::lightweight_mutex;
//
// boost::detail::lightweight_mutex meets a subset of the Mutex concept
// requirements: http://www.boost.org/libs/thread/doc/mutex_concept.html#Mutex
//
// * Used by the smart pointer library
// * Performance oriented
// * Header-only implementation
// * Small memory footprint
// * Not a general purpose mutex, use boost::mutex, CRITICAL_SECTION or
// pthread_mutex instead.
// * Never spin in a tight lock/do-something/unlock loop, since
// lightweight_mutex does not guarantee fairness.
// * Never keep a lightweight_mutex locked for long periods.
//
// The current implementation can use a pthread_mutex, a CRITICAL_SECTION,
// or a platform-specific spinlock.
//
// You can force a particular implementation by defining BOOST_LWM_USE_PTHREADS,
// BOOST_LWM_USE_CRITICAL_SECTION, or BOOST_LWM_USE_SPINLOCK.
//
// If neither macro has been defined, the default is to use a spinlock on Win32,
// and a pthread_mutex otherwise.
//
// Note that a spinlock is not a general synchronization primitive. In particular,
// it is not guaranteed to be a memory barrier, and it is possible to "livelock"
// if a lower-priority thread has acquired the spinlock but a higher-priority
// thread is spinning trying to acquire the same lock.
//
// For these reasons, spinlocks have been disabled by default except on Windows,
// where a spinlock can be several orders of magnitude faster than a CRITICAL_SECTION.
// Note: lwm_linux.hpp has been disabled by default; see the comments
// inside for more info.
#include <boost/config.hpp>
// Note to implementors: if you write a platform-specific spinlock
// for a platform that supports pthreads, be sure to test its performance
// against the pthreads-based version using shared_ptr_timing_test.cpp and
// shared_ptr_mt_test.cpp. Custom versions are usually not worth the trouble
// _unless_ the performance gains are substantial.
//
// Be sure to compare against a "real" pthreads library;
// shared_ptr_timing_test.cpp will compile succesfully with a stub do-nothing
// pthreads library, since it doesn't create any threads.
#ifndef BOOST_HAS_THREADS
# include <boost/detail/lwm_nop.hpp>
#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(WIN32) || defined(_WIN32) || defined(__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
# include <boost/detail/lwm_nop.hpp>
#endif
#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED

View File

@@ -0,0 +1,78 @@
#ifndef BOOST_DETAIL_LWM_GCC_HPP_INCLUDED
#define BOOST_DETAIL_LWM_GCC_HPP_INCLUDED
//
// boost/detail/lwm_gcc.hpp
//
// lightweight_mutex for GNU libstdc++ v3
//
// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2002 Lars Gullik Bj<42>nnes <larsbj@lyx.org>
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <bits/atomicity.h>
#include <sched.h>
namespace boost
{
namespace detail
{
class lightweight_mutex
{
private:
_Atomic_word a_;
lightweight_mutex(lightweight_mutex const &);
lightweight_mutex & operator=(lightweight_mutex const &);
public:
lightweight_mutex(): a_(1)
{
}
class scoped_lock;
friend class scoped_lock;
class scoped_lock
{
private:
lightweight_mutex & m_;
scoped_lock(scoped_lock const &);
scoped_lock & operator=(scoped_lock const &);
public:
explicit scoped_lock(lightweight_mutex & m): m_(m)
{
while( !__exchange_and_add(&m_.a_, -1) )
{
__atomic_add(&m_.a_, 1);
sched_yield();
}
}
~scoped_lock()
{
__atomic_add(&m_.a_, 1);
}
};
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_LWM_GCC_HPP_INCLUDED

View File

@@ -0,0 +1,78 @@
#ifndef BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED
#define BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/detail/lwm_irix.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2002 Dan Gohman
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <sgidefs.h>
#include <mutex.h>
#include <sched.h>
namespace boost
{
namespace detail
{
class lightweight_mutex
{
private:
__uint32_t l_;
lightweight_mutex(lightweight_mutex const &);
lightweight_mutex & operator=(lightweight_mutex const &);
public:
lightweight_mutex(): l_(0)
{
}
class scoped_lock;
friend class scoped_lock;
class scoped_lock
{
private:
lightweight_mutex & m_;
scoped_lock(scoped_lock const &);
scoped_lock & operator=(scoped_lock const &);
public:
explicit scoped_lock(lightweight_mutex & m): m_(m)
{
while( test_and_set32(&m_.l_, 1) )
{
sched_yield();
}
}
~scoped_lock()
{
m_.l_ = 0;
}
};
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED

View File

@@ -0,0 +1,89 @@
#ifndef BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED
#define BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/detail/lwm_linux.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//
// This implementation uses <asm/atomic.h>. This is a kernel header;
// using kernel headers in a user program may cause a number of problems,
// and not all flavors of Linux provide the atomic instructions.
//
// This file is only provided because the performance of this implementation
// is about 3.5 times higher than the pthreads version. Use at your own risk
// (by defining BOOST_USE_ASM_ATOMIC_H.)
//
#include <asm/atomic.h>
#include <sched.h>
namespace boost
{
namespace detail
{
class lightweight_mutex
{
private:
atomic_t a_;
lightweight_mutex(lightweight_mutex const &);
lightweight_mutex & operator=(lightweight_mutex const &);
public:
lightweight_mutex()
{
atomic_t a = ATOMIC_INIT(1);
a_ = a;
}
class scoped_lock;
friend class scoped_lock;
class scoped_lock
{
private:
lightweight_mutex & m_;
scoped_lock(scoped_lock const &);
scoped_lock & operator=(scoped_lock const &);
public:
explicit scoped_lock(lightweight_mutex & m): m_(m)
{
while( !atomic_dec_and_test(&m_.a_) )
{
atomic_inc(&m_.a_);
sched_yield();
}
}
~scoped_lock()
{
atomic_inc(&m_.a_);
}
};
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED

View File

@@ -0,0 +1,36 @@
#ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED
#define BOOST_DETAIL_LWM_NOP_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/detail/lwm_nop.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
namespace boost
{
namespace detail
{
class lightweight_mutex
{
public:
typedef lightweight_mutex scoped_lock;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED

View File

@@ -0,0 +1,85 @@
#ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED
#define BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/detail/lwm_pthreads.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <pthread.h>
namespace boost
{
namespace detail
{
class lightweight_mutex
{
private:
pthread_mutex_t m_;
lightweight_mutex(lightweight_mutex const &);
lightweight_mutex & operator=(lightweight_mutex const &);
public:
lightweight_mutex()
{
// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
#if defined(__hpux) && defined(_DECTHREADS_)
pthread_mutex_init(&m_, pthread_mutexattr_default);
#else
pthread_mutex_init(&m_, 0);
#endif
}
~lightweight_mutex()
{
pthread_mutex_destroy(&m_);
}
class scoped_lock;
friend class scoped_lock;
class scoped_lock
{
private:
pthread_mutex_t & m_;
scoped_lock(scoped_lock const &);
scoped_lock & operator=(scoped_lock const &);
public:
scoped_lock(lightweight_mutex & m): m_(m.m_)
{
pthread_mutex_lock(&m_);
}
~scoped_lock()
{
pthread_mutex_unlock(&m_);
}
};
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED

View File

@@ -0,0 +1,94 @@
#ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED
#define BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/detail/lwm_win32.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/detail/winapi.hpp>
#ifdef __BORLANDC__
# pragma warn -8027 // Functions containing while are not expanded inline
#endif
namespace boost
{
namespace detail
{
class lightweight_mutex
{
private:
long l_;
lightweight_mutex(lightweight_mutex const &);
lightweight_mutex & operator=(lightweight_mutex const &);
public:
lightweight_mutex(): l_(0)
{
}
class scoped_lock;
friend class scoped_lock;
class scoped_lock
{
private:
lightweight_mutex & m_;
scoped_lock(scoped_lock const &);
scoped_lock & operator=(scoped_lock const &);
public:
explicit scoped_lock(lightweight_mutex & m): m_(m)
{
while( winapi::InterlockedExchange(&m_.l_, 1) )
{
// Note: changed to Sleep(1) from Sleep(0).
// According to MSDN, Sleep(0) will never yield
// to a lower-priority thread, whereas Sleep(1)
// will. Performance seems not to be affected.
winapi::Sleep(1);
}
}
~scoped_lock()
{
winapi::InterlockedExchange(&m_.l_, 0);
// Note: adding a yield here will make
// the spinlock more fair and will increase the overall
// performance of some applications substantially in
// high contention situations, but will penalize the
// low contention / single thread case up to 5x
}
};
};
} // namespace detail
} // namespace boost
#ifdef __BORLANDC__
# pragma warn .8027 // Functions containing while are not expanded inline
#endif
#endif // #ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED

View File

@@ -0,0 +1,78 @@
#ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
#define BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/detail/lwm_win32_cs.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/detail/winapi.hpp>
namespace boost
{
namespace detail
{
class lightweight_mutex
{
private:
winapi::critical_section cs_;
lightweight_mutex(lightweight_mutex const &);
lightweight_mutex & operator=(lightweight_mutex const &);
public:
lightweight_mutex()
{
winapi::InitializeCriticalSection(&cs_);
}
~lightweight_mutex()
{
winapi::DeleteCriticalSection(&cs_);
}
class scoped_lock;
friend class scoped_lock;
class scoped_lock
{
private:
lightweight_mutex & m_;
scoped_lock(scoped_lock const &);
scoped_lock & operator=(scoped_lock const &);
public:
explicit scoped_lock(lightweight_mutex & m): m_(m)
{
winapi::EnterCriticalSection(&m_.cs_);
}
~scoped_lock()
{
winapi::LeaveCriticalSection(&m_.cs_);
}
};
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED

View File

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

View File

@@ -23,24 +23,63 @@
#endif #endif
#include <boost/checked_delete.hpp> #include <boost/checked_delete.hpp>
#include <boost/detail/atomic_count.hpp> #include <boost/throw_exception.hpp>
#include <boost/detail/lightweight_mutex.hpp>
#include <functional> // for std::less
#include <exception> // for std::exception
#include <new> // for std::bad_alloc
#ifdef __BORLANDC__
# pragma warn -8026 // Functions with excep. spec. are not expanded inline
# pragma warn -8027 // Functions containing try are not expanded inline
#endif
namespace boost namespace boost
{ {
namespace detail // The standard library that comes with Borland C++ 5.5.1
{ // defines std::exception and its members as having C calling
// convention (-pc). When the definition of use_count_is_zero
// is compiled with -ps, the compiler issues an error.
// Hence, the temporary #pragma option -pc below. The version
// check is deliberately conservative.
class counted_base #if defined(__BORLANDC__) && __BORLANDC__ == 0x551
# pragma option push -pc
#endif
class use_count_is_zero: public std::exception
{ {
public: public:
typedef atomic_count count_type; virtual char const * what() const throw()
{
return "boost::use_count_is_zero";
}
};
#if defined(__BORLANDC__) && __BORLANDC__ == 0x551
# pragma option pop
#endif
class counted_base
{
private:
typedef detail::lightweight_mutex mutex_type;
public:
counted_base():
use_count_(0), weak_count_(0)
{
}
// pre: initial_use_count <= initial_weak_count // pre: initial_use_count <= initial_weak_count
explicit counted_base(long initial_use_count, long initial_weak_count): explicit counted_base(long initial_use_count, long initial_weak_count):
use_count_(initial_use_count), weak_count_(initial_weak_count), self_deleter_(&self_delete) use_count_(initial_use_count), weak_count_(initial_weak_count)
{ {
} }
@@ -61,42 +100,77 @@ public:
{ {
} }
void add_ref() // nothrow // destruct() is called when weak_count_ drops to zero.
virtual void destruct() // nothrow
{ {
delete this;
}
void add_ref()
{
#ifdef BOOST_HAS_THREADS
mutex_type::scoped_lock lock(mtx_);
#endif
if(use_count_ == 0 && weak_count_ != 0) boost::throw_exception(boost::use_count_is_zero());
++use_count_; ++use_count_;
++weak_count_; ++weak_count_;
} }
void release() // nothrow void release() // nothrow
{ {
if(--use_count_ == 0) long new_use_count;
long new_weak_count;
{
#ifdef BOOST_HAS_THREADS
mutex_type::scoped_lock lock(mtx_);
#endif
new_use_count = --use_count_;
new_weak_count = --weak_count_;
}
if(new_use_count == 0)
{ {
dispose(); dispose();
} }
if(--weak_count_ == 0) if(new_weak_count == 0)
{ {
// not a direct 'delete this', because the inlined destruct();
// release() may use a different heap manager
self_deleter_(this);
} }
} }
void weak_add_ref() // nothrow void weak_add_ref() // nothrow
{ {
#ifdef BOOST_HAS_THREADS
mutex_type::scoped_lock lock(mtx_);
#endif
++weak_count_; ++weak_count_;
} }
void weak_release() // nothrow void weak_release() // nothrow
{ {
if(--weak_count_ == 0) long new_weak_count;
{ {
self_deleter_(this); #ifdef 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 long use_count() const // nothrow
{ {
#ifdef BOOST_HAS_THREADS
mutex_type::scoped_lock lock(mtx_);
#endif
return use_count_; return use_count_;
} }
@@ -105,19 +179,36 @@ private:
counted_base(counted_base const &); counted_base(counted_base const &);
counted_base & operator= (counted_base const &); counted_base & operator= (counted_base const &);
static void self_delete(counted_base * p)
{
delete p;
}
// inv: use_count_ <= weak_count_ // inv: use_count_ <= weak_count_
count_type use_count_; long use_count_;
count_type weak_count_; long weak_count_;
void (*self_deleter_) (counted_base *); #ifdef BOOST_HAS_THREADS
mutable mutex_type mtx_;
#endif
}; };
inline void intrusive_ptr_add_ref(counted_base * p)
{
p->add_ref();
}
inline void intrusive_ptr_release(counted_base * p)
{
p->release();
}
namespace detail
{
//
// Borland's Codeguard trips up over the -Vx- option here:
//
#ifdef __CODEGUARD__
#pragma option push -Vx-
#endif
template<class P, class D> class counted_base_impl: public counted_base template<class P, class D> class counted_base_impl: public counted_base
{ {
private: private:
@@ -143,6 +234,7 @@ public:
} }
}; };
class weak_count;
class shared_count class shared_count
{ {
@@ -152,10 +244,23 @@ private:
friend class weak_count; friend class weak_count;
template<class P, class D> shared_count(P, D, counted_base const *);
public: public:
template<class P, class D> shared_count(P p, D d): pi_(0) shared_count(): pi_(new counted_base(1, 1))
{ {
}
explicit shared_count(counted_base * pi): pi_(pi) // never throws
{
pi_->add_ref();
}
template<class P, class D> shared_count(P p, D d, void const * = 0): pi_(0)
{
#ifndef BOOST_NO_EXCEPTIONS
try try
{ {
pi_ = new counted_base_impl<P, D>(p, d, 1, 1); pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
@@ -165,6 +270,23 @@ public:
d(p); // delete p d(p); // delete p
throw; throw;
} }
#else
pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
if(pi_ == 0)
{
d(p); // delete p
boost::throw_exception(std::bad_alloc());
}
#endif
}
template<class P, class D> shared_count(P, D, counted_base * pi): pi_(pi)
{
pi_->add_ref();
} }
#ifndef BOOST_NO_AUTO_PTR #ifndef BOOST_NO_AUTO_PTR
@@ -189,6 +311,8 @@ public:
pi_->add_ref(); pi_->add_ref();
} }
explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0
shared_count & operator= (shared_count const & r) // nothrow shared_count & operator= (shared_count const & r) // nothrow
{ {
counted_base * tmp = r.pi_; counted_base * tmp = r.pi_;
@@ -215,14 +339,31 @@ public:
{ {
return pi_->use_count() == 1; return pi_->use_count() == 1;
} }
friend inline bool operator==(shared_count const & a, shared_count const & b)
{
return a.pi_ == b.pi_;
}
friend inline bool operator<(shared_count const & a, shared_count const & b)
{
return std::less<counted_base *>()(a.pi_, b.pi_);
}
}; };
#ifdef __CODEGUARD__
#pragma option pop
#endif
class weak_count class weak_count
{ {
private: private:
counted_base * pi_; counted_base * pi_;
friend class shared_count;
public: public:
weak_count(): pi_(new counted_base(0, 1)) // can throw weak_count(): pi_(new counted_base(0, 1)) // can throw
@@ -275,10 +416,30 @@ public:
{ {
return pi_->use_count(); return pi_->use_count();
} }
friend inline bool operator==(weak_count const & a, weak_count const & b)
{
return a.pi_ == b.pi_;
}
friend inline bool operator<(weak_count const & a, weak_count const & b)
{
return std::less<counted_base *>()(a.pi_, b.pi_);
}
}; };
inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
{
pi_->add_ref();
}
} // namespace detail } // namespace detail
} // namespace boost } // namespace boost
#ifdef __BORLANDC__
# pragma warn .8027 // Functions containing try are not expanded inline
# pragma warn .8026 // Functions with excep. spec. are not expanded inline
#endif
#endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED

View File

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

View File

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

View File

@@ -0,0 +1,202 @@
#ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED
#define BOOST_INTRUSIVE_PTR_HPP_INCLUDED
//
// intrusive_ptr.hpp
//
// Copyright (c) 2001, 2002 Peter Dimov
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation.
//
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
# pragma warning(push)
# pragma warning(disable:4284) // odd return type for operator->
#endif
#include <functional> // std::less
namespace boost
{
//
// intrusive_ptr
//
// A smart pointer that uses intrusive reference counting.
//
// Relies on unqualified calls to
//
// void intrusive_ptr_add_ref(T * p);
// void intrusive_ptr_release(T * p);
//
// (p != 0)
//
// The object is responsible for destroying itself.
//
template<class T> class intrusive_ptr
{
private:
typedef intrusive_ptr this_type;
public:
intrusive_ptr(): p_(0)
{
}
intrusive_ptr(T * p): p_(p)
{
if(p_ != 0) intrusive_ptr_add_ref(p_);
}
~intrusive_ptr()
{
if(p_ != 0) intrusive_ptr_release(p_);
}
#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
template<class U> intrusive_ptr(intrusive_ptr<U> const & rhs): p_(rhs.get())
{
if(p_ != 0) intrusive_ptr_add_ref(p_);
}
#endif
intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_)
{
if(p_ != 0) intrusive_ptr_add_ref(p_);
}
#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
template<class U> intrusive_ptr & operator=(intrusive_ptr<U> const & rhs)
{
this_type(rhs).swap(*this);
return *this;
}
#endif
intrusive_ptr & operator=(intrusive_ptr const & rhs)
{
this_type(rhs).swap(*this);
return *this;
}
intrusive_ptr & operator=(T * rhs)
{
this_type(rhs).swap(*this);
return *this;
}
void swap(intrusive_ptr & rhs)
{
T * tmp = p_;
p_ = rhs.p_;
rhs.p_ = tmp;
}
T * get() const
{
return p_;
}
T & operator*() const
{
return *p_;
}
T * operator->() const
{
return p_;
}
bool empty() const
{
return p_ == 0;
}
typedef bool (intrusive_ptr::*bool_type) () const;
operator bool_type () const
{
return p_ == 0? 0: &intrusive_ptr::empty;
}
private:
T * p_;
};
template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)
{
lhs.swap(rhs);
}
template<class T, class U> intrusive_ptr<T> shared_dynamic_cast(intrusive_ptr<U> const & p)
{
return dynamic_cast<T *>(p.get());
}
template<class T, class U> intrusive_ptr<T> shared_static_cast(intrusive_ptr<U> const & p)
{
return static_cast<T *>(p.get());
}
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
{
return a.get() == b.get();
}
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
{
return a.get() != b.get();
}
template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
{
return std::less<T *>(a.get(), b.get());
}
template<class T> inline bool operator==(intrusive_ptr<T> const & a, T * b)
{
return a.get() == b;
}
template<class T> inline bool operator!=(intrusive_ptr<T> const & a, T * b)
{
return a.get() != b;
}
template<class T> inline bool operator==(T * a, intrusive_ptr<T> const & b)
{
return a == b.get();
}
template<class T> inline bool operator!=(T * a, intrusive_ptr<T> const & b)
{
return a != b.get();
}
// mem_fn support
template<class T> T * get_pointer(intrusive_ptr<T> const & p)
{
return p.get();
}
} // namespace boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif // #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED

View File

@@ -13,6 +13,7 @@
// //
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/config.hpp> // in case ptrdiff_t not in std #include <boost/config.hpp> // in case ptrdiff_t not in std
#include <cstddef> // for std::ptrdiff_t #include <cstddef> // for std::ptrdiff_t
@@ -32,6 +33,8 @@ private:
scoped_array(scoped_array const &); scoped_array(scoped_array const &);
scoped_array & operator=(scoped_array const &); scoped_array & operator=(scoped_array const &);
typedef scoped_array<T> this_type;
public: public:
typedef T element_type; typedef T element_type;
@@ -42,17 +45,14 @@ public:
~scoped_array() // never throws ~scoped_array() // never throws
{ {
typedef char type_must_be_complete[sizeof(T)]; checked_array_delete(ptr);
delete [] ptr;
} }
void reset(T * p = 0) // never throws void reset(T * p = 0) // never throws
{ {
typedef char type_must_be_complete[sizeof(T)];
if (ptr != p) if (ptr != p)
{ {
delete [] ptr; checked_array_delete(ptr);
ptr = p; ptr = p;
} }
} }
@@ -69,6 +69,20 @@ public:
return ptr; return ptr;
} }
// implicit conversion to "bool"
typedef T * (this_type::*unspecified_bool_type)() const;
operator unspecified_bool_type() const // never throws
{
return ptr == 0? 0: &this_type::get;
}
bool operator! () const // never throws
{
return ptr == 0;
}
void swap(scoped_array & b) // never throws void swap(scoped_array & b) // never throws
{ {
T * tmp = b.ptr; T * tmp = b.ptr;

View File

@@ -13,6 +13,11 @@
// //
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#ifndef BOOST_NO_AUTO_PTR
# include <memory> // for std::auto_ptr
#endif
namespace boost namespace boost
{ {
@@ -26,11 +31,13 @@ template<typename T> class scoped_ptr // noncopyable
{ {
private: private:
T* ptr; T * ptr;
scoped_ptr(scoped_ptr const &); scoped_ptr(scoped_ptr const &);
scoped_ptr & operator=(scoped_ptr const &); scoped_ptr & operator=(scoped_ptr const &);
typedef scoped_ptr<T> this_type;
public: public:
typedef T element_type; typedef T element_type;
@@ -39,20 +46,24 @@ public:
{ {
} }
#ifndef BOOST_NO_AUTO_PTR
explicit scoped_ptr(std::auto_ptr<T> p): ptr(p.release()) // never throws
{
}
#endif
~scoped_ptr() // never throws ~scoped_ptr() // never throws
{ {
typedef char type_must_be_complete[sizeof(T)]; checked_delete(ptr);
delete ptr;
} }
void reset(T * p = 0) // never throws void reset(T * p = 0) // never throws
{ {
typedef char type_must_be_complete[sizeof(T)]; if(ptr != p)
if (ptr != p)
{ {
delete ptr; this_type(p).swap(*this);
ptr = p;
} }
} }
@@ -73,6 +84,20 @@ public:
return ptr; return ptr;
} }
// implicit conversion to "bool"
typedef T * (this_type::*unspecified_bool_type)() const;
operator unspecified_bool_type() const // never throws
{
return ptr == 0? 0: &this_type::get;
}
bool operator! () const // never throws
{
return ptr == 0;
}
void swap(scoped_ptr & b) // never throws void swap(scoped_ptr & b) // never throws
{ {
T * tmp = b.ptr; T * tmp = b.ptr;
@@ -86,6 +111,13 @@ template<typename T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) // n
a.swap(b); a.swap(b);
} }
// get_pointer(p) is a generic way to say p.get()
template<typename T> inline T * get_pointer(scoped_ptr<T> const & p)
{
return p.get();
}
} // namespace boost } // namespace boost
#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED #endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED

View File

@@ -17,7 +17,7 @@
#include <boost/config.hpp> // for broken compiler workarounds #include <boost/config.hpp> // for broken compiler workarounds
#ifndef BOOST_MSVC6_MEMBER_TEMPLATES #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
#include <boost/detail/shared_array_nmt.hpp> #include <boost/detail/shared_array_nmt.hpp>
#else #else
@@ -92,6 +92,20 @@ public:
return px; return px;
} }
// implicit conversion to "bool"
typedef T * (this_type::*unspecified_bool_type)() const;
operator unspecified_bool_type() const // never throws
{
return px == 0? 0: &this_type::get;
}
bool operator! () const // never throws
{
return px == 0;
}
bool unique() const // never throws bool unique() const // never throws
{ {
return pn.unique(); return pn.unique();
@@ -137,6 +151,6 @@ template<typename T> void swap(shared_array<T> & a, shared_array<T> & b) // neve
} // namespace boost } // namespace boost
#endif // #ifndef BOOST_MSVC6_MEMBER_TEMPLATES #endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
#endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED #endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED

View File

@@ -17,18 +17,19 @@
#include <boost/config.hpp> // for broken compiler workarounds #include <boost/config.hpp> // for broken compiler workarounds
#ifndef BOOST_MSVC6_MEMBER_TEMPLATES #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
#include <boost/detail/shared_ptr_nmt.hpp> #include <boost/detail/shared_ptr_nmt.hpp>
#else #else
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/checked_delete.hpp> #include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/detail/shared_count.hpp> #include <boost/detail/shared_count.hpp>
#include <memory> // for std::auto_ptr #include <memory> // for std::auto_ptr
#include <algorithm> // for std::swap #include <algorithm> // for std::swap
#include <functional> // for std::less #include <functional> // for std::less
#include <typeinfo> // for std::bad_cast
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
# pragma warning(push) # pragma warning(push)
@@ -43,6 +44,7 @@ namespace detail
struct static_cast_tag {}; struct static_cast_tag {};
struct dynamic_cast_tag {}; struct dynamic_cast_tag {};
struct polymorphic_cast_tag {};
template<typename T> struct shared_ptr_traits template<typename T> struct shared_ptr_traits
{ {
@@ -54,6 +56,15 @@ template<> struct shared_ptr_traits<void>
typedef void reference; typedef void reference;
}; };
#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
template<> struct shared_ptr_traits<void const>
{
typedef void reference;
};
#endif
} // namespace detail } // namespace detail
@@ -66,20 +77,27 @@ template<> struct shared_ptr_traits<void>
// //
template<typename T> class weak_ptr; template<typename T> class weak_ptr;
template<typename T> class intrusive_ptr;
template<typename T> class shared_ptr template<typename T> class shared_ptr
{ {
private: private:
// Borland 5.5.1 specific workarounds // Borland 5.5.1 specific workarounds
typedef checked_deleter<T> deleter; // typedef checked_deleter<T> deleter;
typedef shared_ptr<T> this_type; typedef shared_ptr<T> this_type;
public: public:
typedef T element_type; typedef T element_type;
typedef T value_type;
explicit shared_ptr(T * p = 0): px(p), pn(p, deleter()) shared_ptr(): px(0), pn()
{
}
template<typename Y>
explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter<Y>(), p) // Y must be complete
{ {
} }
@@ -89,17 +107,27 @@ public:
// shared_ptr will release p by calling d(p) // shared_ptr will release p by calling d(p)
// //
template<typename D> shared_ptr(T * p, D d): px(p), pn(p, d) template<typename Y, typename D> shared_ptr(Y * p, D d): px(p), pn(p, d)
{ {
} }
// generated copy constructor, assignment, destructor are fine // generated copy constructor, assignment, destructor are fine
template<typename Y>
explicit shared_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // may throw
{
}
template<typename Y> template<typename Y>
shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
{ {
} }
template<typename Y>
shared_ptr(intrusive_ptr<Y> const & r): px(r.get()), pn(r.get()) // never throws
{
}
template<typename Y> template<typename Y>
shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn) shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
{ {
@@ -110,7 +138,16 @@ public:
{ {
if (px == 0) // need to allocate new counter -- the cast failed if (px == 0) // need to allocate new counter -- the cast failed
{ {
pn = detail::shared_count(static_cast<element_type *>(0), deleter()); pn = detail::shared_count();
}
}
template<typename Y>
shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
{
if (px == 0)
{
boost::throw_exception(std::bad_cast());
} }
} }
@@ -123,6 +160,8 @@ public:
#endif #endif
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
template<typename Y> template<typename Y>
shared_ptr & operator=(shared_ptr<Y> const & r) // never throws shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
{ {
@@ -131,6 +170,8 @@ public:
return *this; return *this;
} }
#endif
#ifndef BOOST_NO_AUTO_PTR #ifndef BOOST_NO_AUTO_PTR
template<typename Y> template<typename Y>
@@ -142,13 +183,18 @@ public:
#endif #endif
void reset(T * p = 0) void reset()
{ {
BOOST_ASSERT(p == 0 || p != px); this_type().swap(*this);
}
template<typename Y> void reset(Y * p) // Y must be complete
{
BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
this_type(p).swap(*this); this_type(p).swap(*this);
} }
template<typename D> void reset(T * p, D d) template<typename Y, typename D> void reset(Y * p, D d)
{ {
this_type(p, d).swap(*this); this_type(p, d).swap(*this);
} }
@@ -170,6 +216,20 @@ public:
return px; return px;
} }
// implicit conversion to "bool"
typedef T * (this_type::*unspecified_bool_type)() const;
operator unspecified_bool_type() const // never throws
{
return px == 0? 0: &this_type::get;
}
bool operator! () const // never throws
{
return px == 0;
}
bool unique() const // never throws bool unique() const // never throws
{ {
return pn.unique(); return pn.unique();
@@ -214,12 +274,23 @@ template<typename T, typename U> inline bool operator!=(shared_ptr<T> const & a,
return a.get() != b.get(); return a.get() != b.get();
} }
#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
// Resolve the ambiguity between our op!= and the one in rel_ops
template<typename T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
{
return a.get() != b.get();
}
#endif
template<typename T> inline bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b) template<typename T> inline bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b)
{ {
return std::less<T*>()(a.get(), b.get()); return std::less<T*>()(a.get(), b.get());
} }
template<typename T> void swap(shared_ptr<T> & a, shared_ptr<T> & b) template<typename T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
{ {
a.swap(b); a.swap(b);
} }
@@ -234,6 +305,17 @@ template<typename T, typename U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U>
return shared_ptr<T>(r, detail::dynamic_cast_tag()); return shared_ptr<T>(r, detail::dynamic_cast_tag());
} }
template<typename T, typename U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
{
return shared_ptr<T>(r, detail::polymorphic_cast_tag());
}
template<typename T, typename U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
{
BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
return shared_static_cast<T>(r);
}
// get_pointer() enables boost::mem_fn to recognize shared_ptr // get_pointer() enables boost::mem_fn to recognize shared_ptr
template<typename T> inline T * get_pointer(shared_ptr<T> const & p) template<typename T> inline T * get_pointer(shared_ptr<T> const & p)
@@ -241,12 +323,34 @@ template<typename T> inline T * get_pointer(shared_ptr<T> const & p)
return p.get(); return p.get();
} }
// shared_from_this() creates a shared_ptr from a raw pointer (usually 'this')
namespace detail
{
inline void sp_assert_counted_base(boost::counted_base const *)
{
}
template<class T> inline T * sp_remove_const(T const * p)
{
return const_cast<T *>(p);
}
} // namespace detail
template<class T> shared_ptr<T> shared_from_this(T * p)
{
detail::sp_assert_counted_base(p);
return shared_ptr<T>(detail::sp_remove_const(p));
}
} // namespace boost } // namespace boost
#ifdef BOOST_MSVC #ifdef BOOST_MSVC
# pragma warning(pop) # pragma warning(pop)
#endif #endif
#endif // #ifndef BOOST_MSVC6_MEMBER_TEMPLATES #endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED #endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED

View File

@@ -16,14 +16,6 @@
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/config.hpp> // for broken compiler workarounds
#include <boost/assert.hpp>
#include <boost/detail/shared_count.hpp>
#include <algorithm> // for std::swap
#include <functional> // for std::less
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
# pragma warning(push) # pragma warning(push)
# pragma warning(disable:4284) // odd return type for operator-> # pragma warning(disable:4284) // odd return type for operator->
@@ -59,19 +51,7 @@ public:
{ {
} }
template<typename Y> #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
weak_ptr(weak_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
{
}
template<typename Y>
weak_ptr(weak_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
{
if (px == 0) // need to allocate new counter -- the cast failed
{
pn = detail::weak_count();
}
}
template<typename Y> template<typename Y>
weak_ptr & operator=(weak_ptr<Y> const & r) // never throws weak_ptr & operator=(weak_ptr<Y> const & r) // never throws
@@ -89,28 +69,16 @@ public:
return *this; return *this;
} }
#endif
void reset() void reset()
{ {
this_type().swap(*this); this_type().swap(*this);
} }
T * get() const // never throws T * get() const // never throws; deprecated, removal pending, don't use
{ {
return use_count() == 0? 0: px; return pn.use_count() == 0? 0: px;
}
typename detail::shared_ptr_traits<T>::reference operator* () const // never throws
{
T * p = get();
BOOST_ASSERT(p != 0);
return *p;
}
T * operator-> () const // never throws
{
T * p = get();
BOOST_ASSERT(p != 0);
return p;
} }
long use_count() const // never throws long use_count() const // never throws
@@ -118,12 +86,22 @@ public:
return pn.use_count(); return pn.use_count();
} }
void swap(weak_ptr<T> & other) // never throws bool expired() const // never throws
{
return pn.use_count() == 0;
}
void swap(this_type & other) // never throws
{ {
std::swap(px, other.px); std::swap(px, other.px);
pn.swap(other.pn); pn.swap(other.pn);
} }
bool less(this_type const & rhs) const // implementation detail, never throws
{
return pn < rhs.pn;
}
// Tasteless as this may seem, making all members public allows member templates // Tasteless as this may seem, making all members public allows member templates
// to work in the absence of member template friends. (Matthew Langston) // to work in the absence of member template friends. (Matthew Langston)
@@ -132,6 +110,7 @@ public:
private: private:
template<typename Y> friend class weak_ptr; template<typename Y> friend class weak_ptr;
template<typename Y> friend class shared_ptr;
#endif #endif
@@ -150,9 +129,20 @@ template<class T, class U> inline bool operator!=(weak_ptr<T> const & a, weak_pt
return a.get() != b.get(); return a.get() != b.get();
} }
#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
// Resolve the ambiguity between our op!= and the one in rel_ops
template<typename T> inline bool operator!=(weak_ptr<T> const & a, weak_ptr<T> const & b)
{
return a.get() != b.get();
}
#endif
template<class T> inline bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b) template<class T> inline bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b)
{ {
return std::less<T*>()(a.get(), b.get()); return a.less(b);
} }
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
@@ -160,22 +150,27 @@ template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
a.swap(b); a.swap(b);
} }
template<class T, class U> weak_ptr<T> shared_static_cast(weak_ptr<U> const & r) template<class T> shared_ptr<T> make_shared(weak_ptr<T> const & r) // never throws
{ {
return weak_ptr<T>(r, detail::static_cast_tag()); // optimization: avoid throw overhead
if(r.use_count() == 0)
{
return shared_ptr<T>();
}
try
{
return shared_ptr<T>(r);
}
catch(use_count_is_zero const &)
{
return shared_ptr<T>();
}
} }
template<class T, class U> weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r) // Note: there is no get_pointer overload for weak_ptr.
{ // This is intentional. Even get() will disappear in a
return weak_ptr<T>(r, detail::dynamic_cast_tag()); // future release; these accessors are too error-prone.
}
// get_pointer() enables boost::mem_fn to recognize weak_ptr
template<class T> inline T * get_pointer(weak_ptr<T> const & p)
{
return p.get();
}
} // namespace boost } // namespace boost

View File

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

View File

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

View File

@@ -9,7 +9,7 @@
// is complete where it counts - in the inplementation translation unit where // is complete where it counts - in the inplementation translation unit where
// destruction is actually instantiated. // destruction is actually instantiated.
class example : boost::noncopyable class example : private boost::noncopyable
{ {
public: public:
example(); example();

View File

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

View File

@@ -1,356 +1,678 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head>
<title>shared_ptr</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body text="#000000" bgColor="#ffffff">
<h1><IMG height="86" alt="c++boost.gif (8819 bytes)" src="../../c++boost.gif" width="277" align="middle">shared_ptr
class template</h1>
<p><A href="#Introduction">Introduction</A><br>
<a href="#BestPractices">Best Practices</a><br>
<A href="#Synopsis">Synopsis</A><br>
<A href="#Members">Members</A><br>
<A href="#functions">Free Functions</A><br>
<A href="#example">Example</A><br>
<A href="#Handle/Body">Handle/Body Idiom</A><br>
<a href="#ThreadSafety">Thread Safety</a><br>
<A href="#FAQ">Frequently Asked Questions</A><br>
<A href="smarttests.htm">Smart Pointer Timings</A></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <b>shared_ptr</b> class template stores a pointer to a dynamically allocated
object, typically with a C++ <EM>new-expression</EM> . The object pointed to is
guaranteed to be deleted when the last <b>shared_ptr</b> pointing to it is
destroyed or reset. See the <A href="#example">example</A>.</p>
<p>Every <b>shared_ptr</b> meets the <b>CopyConstructible</b> and <b>Assignable</b>
requirements of the C++ Standard Library, and so can be used in standard
library containers. Comparison operators are supplied so that <b>shared_ptr</b>
works with the standard library's associative containers.</p>
<p>Normally, a <b>shared_ptr</b> cannot correctly hold a pointer to a dynamically
allocated array. See <A href="shared_array.htm"><b>shared_array</b></A> for
that usage.</p>
<p>Because the implementation uses reference counting, cycles of <b>shared_ptr</b> instances
will not be reclaimed. For example, if <b>main()</b> holds a <b>shared_ptr</b> to
<b>A</b>, which directly or indirectly holds a <b>shared_ptr</b> back to <b>A</b>,
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_ptr</b> will
leave <b>A</b> dangling with a use count of 1. Use <A href="weak_ptr.htm">weak_ptr</A>
to "break cycles."</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <STRONG>shared_ptr</STRONG> and most of its member functions place no
requirements on <STRONG>T</STRONG>; it is allowed to be an incomplete type, or <STRONG>
void</STRONG>. Member functions that do place additional requirements (<A href="#constructors">constructors</A>,
<A href="#reset">reset</A>) are explicitly documented below.</p>
<P><STRONG>shared_ptr&lt;T&gt;</STRONG> can be implicitly converted to <STRONG>shared_ptr&lt;U&gt;</STRONG>
whenever <STRONG>T*</STRONG> can be implicitly converted to <STRONG>U*</STRONG>.
In particular, <STRONG>shared_ptr&lt;T&gt;</STRONG> is implicitly convertible
to <STRONG>shared_ptr&lt;T const&gt;</STRONG>, to <STRONG>shared_ptr&lt;U&gt;</STRONG>
where <STRONG>U</STRONG> is an accessible base of <STRONG>T</STRONG>, and to <STRONG>
shared_ptr&lt;void&gt;</STRONG>.</P>
<h2><a name="BestPractices">Best Practices</a></h2>
<P>A simple guideline that nearly eliminates the possibility of memory leaks
is: always use a named smart pointer variable to hold the result of <STRONG>new. </STRONG>
Every occurence of the <STRONG>new</STRONG> keyword in the code should have the
form:</P>
<PRE>shared_ptr&lt;T&gt; p(new Y);</PRE>
<P>It is, of course, acceptable to use another smart pointer in place of <STRONG>shared_ptr</STRONG>
above; having <STRONG>T</STRONG> and <STRONG>Y</STRONG> be the same type, or
passing arguments to <STRONG>Y</STRONG>'s constructor is also OK.</P>
<P>If you observe this guideline, it naturally follows that you will have no
explicit <STRONG>delete</STRONG>s; <STRONG>try/catch</STRONG> constructs will
be rare.</P>
<P>Avoid using unnamed <STRONG>shared_ptr</STRONG> temporaries to save typing; to
see why this is dangerous, consider this example:</P>
<PRE>
void f(shared_ptr&lt;int&gt;, int);
int g();
<head> void ok()
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> {
<title>shared_ptr</title> shared_ptr&lt;int&gt; p(new int(2));
</head> f(p, g());
}
<body bgcolor="#FFFFFF" text="#000000"> void bad()
{
f(shared_ptr&lt;int&gt;(new int(2)), g());
}
</PRE>
<P>The function <STRONG>ok</STRONG> follows the guideline to the letter, whereas <STRONG>
bad</STRONG> constructs the temporary <STRONG>shared_ptr</STRONG> in place,
admitting the possibility of a memory leak. Since function arguments are
evaluated in unspecified order, it is possible for <STRONG>new int(2)</STRONG> to
be evaluated first, <STRONG>g()</STRONG> second, and we may never get to the <STRONG>
shared_ptr </STRONG>constructor if <STRONG>g</STRONG> throws an exception.
See <A href="http://www.gotw.ca/gotw/056.htm">Herb Sutter's treatment</A> of
the issue for more information.</P>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost {
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">shared_ptr class template</h1> class use_count_is_zero: public std::exception;
<p><a href="#Introduction">Introduction</a><br> template&lt;typename T&gt; class <A href="weak_ptr.htm" >weak_ptr</A>;
<a href="#Synopsis">Synopsis</a><br>
<a href="#Members">Members</a><br>
<a href="#functions">Free Functions</a><br>
<a href="#example">Example</a><br>
<a href="#Handle/Body">Handle/Body Idiom</a><br>
<a href="#FAQ">Frequently Asked Questions</a><br>
<a href="smarttests.htm">Smart Pointer Timings</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <b>shared_ptr</b> class template stores a pointer to a dynamically allocated
object. (Dynamically allocated objects are allocated with the C++ <b>new</b>
expression.) The object pointed to is guaranteed to be deleted when
the last <b>shared_ptr</b> pointing to it is destroyed or reset.
See the <a href="#example">example</a>.</p>
<p>Every <b>shared_ptr</b> meets the <b>CopyConstructible</b>
and <b>Assignable</b> requirements of the C++ Standard Library, and so
can be used in standard library containers. Comparison operators
are supplied so that <b>shared_ptr</b> works with
the standard library's associative containers.</p>
<p>Normally, a <b>shared_ptr</b> cannot correctly hold a pointer to a
dynamically allocated array. See <a href="shared_array.htm"><b>shared_array</b></a>
for that usage.</p>
<p>Because the implementation uses reference counting, <b>shared_ptr</b> will not work
correctly with cyclic data structures. For example, if <b>main()</b> holds a <b>shared_ptr</b>
to <b>A</b>, which directly or indirectly holds a <b>shared_ptr</b> back to <b>A</b>,
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_ptr</b>
will leave <b>A</b> dangling with a use count of 1.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object
pointed to. <b>T</b> must meet the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.
<b>T</b> may be <b>void</b>, but in that case, either an explicit delete
function must be passed in, or the pointed-to object must have a trivial destructor.</p>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost {
template&lt;typename T&gt; class shared_ptr { template&lt;typename T&gt; class shared_ptr {
public: public:
typedef T <a href="#element_type">element_type</a>;
explicit <a href="#constructors">shared_ptr</a>(T * p = 0); typedef T <A href="#element_type" >element_type</A>;
template&lt;typename D&gt; <a href="#constructors">shared_ptr</a>(T * p, D d);
<a href="#destructor">~shared_ptr</a>(); // never throws
<a href="#constructors">shared_ptr</a>(shared_ptr const &amp; r); // never throws <A href="#constructors">shared_ptr</A>();
template&lt;typename Y&gt; <a href="#constructors">shared_ptr</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws template&lt;typename Y&gt; explicit <A href="#constructors" >shared_ptr</A>(Y * p);
template&lt;typename Y&gt; <a href="#constructors">shared_ptr</a>(std::auto_ptr&lt;Y&gt; &amp; r); template&lt;typename Y, typename D&gt; <A href="#constructors" >shared_ptr</A>(Y * p, D d);
<A href="#destructor">~shared_ptr</A>(); // never throws
shared_ptr &amp; <a href="#assignment">operator=</a>(shared_ptr const &amp; r); // never throws <A href="#constructors">shared_ptr</A>(shared_ptr const &amp; r); // never throws
template&lt;typename Y&gt; shared_ptr &amp; <a href="#assignment">operator=</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws template&lt;typename Y&gt; <A href="#constructors">shared_ptr</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;typename Y&gt; shared_ptr &amp; <a href="#assignment">operator=</a>(std::auto_ptr&lt;Y&gt; &amp; r); template&lt;typename Y&gt; explicit <A href="#constructors">shared_ptr</A>(<A href="weak_ptr.htm" >weak_ptr</A>&lt;Y&gt; const &amp; r);
template&lt;typename Y&gt; explicit <A href="#constructors" >shared_ptr</A>(std::auto_ptr&lt;Y&gt; &amp; r);
void <a href="#reset">reset</a>(T * p = 0); // never throws shared_ptr &amp; <A href="#assignment" >operator=</A>(shared_ptr const &amp; r); // never throws
template&lt;typename D&gt; void <a href="#reset">reset</a>(T * p, D d); // never throws template&lt;typename Y&gt; shared_ptr &amp; <A href="#assignment" >operator=</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;typename Y&gt; shared_ptr &amp; <A href="#assignment" >operator=</A>(std::auto_ptr&lt;Y&gt; &amp; r);
T &amp; <a href="#indirection">operator*</a>() const; // never throws void <A href="#reset" >reset</A>();
T * <a href="#indirection">operator-&gt;</a>() const; // never throws template&lt;typename Y&gt; void <A href="#reset" >reset</A>(Y * p);
T * <a href="#get">get</a>() const; // never throws template&lt;typename Y, typename D&gt; void <A href="#reset" >reset</A>(Y * p, D d);
bool <a href="#unique">unique</a>() const; // never throws T &amp; <A href="#indirection" >operator*</A>() const; // never throws
long <a href="#use_count">use_count</a>() const; // never throws T * <A href="#indirection" >operator-&gt;</A>() const; // never throws
T * <A href="#get" >get</A>() const; // never throws
void <a href="#swap">swap</a>(shared_ptr&lt;T&gt; &amp; b); // never throws 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_ptr &amp; b); // never throws
}; };
template&lt;typename T, typename U&gt; template&lt;typename T, typename U&gt;
bool <a href="#operator==">operator==</a>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws bool <A href="#comparison" >operator==</A>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;typename T, typename U&gt; template&lt;typename T, typename U&gt;
bool <a href="#operator!=">operator!=</a>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws bool <A href="#comparison" >operator!=</A>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;typename T, typename U&gt; template&lt;typename T&gt;
bool <a href="#operator&lt;">operator&lt;</a>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws bool <A href="#comparison" >operator&lt;</A>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;T&gt; const &amp; b); // never throws
template&lt;typename T&gt; void <a href="#free-swap">swap</a>(shared_ptr&lt;T&gt; &amp; a, shared_ptr&lt;T&gt; &amp; b); // never throws template&lt;typename T&gt; void <A href="#free-swap" >swap</A>(shared_ptr&lt;T&gt; &amp; a, shared_ptr&lt;T&gt; &amp; b); // never throws
template&lt;typename T&gt; T * <A href="#get_pointer" >get_pointer</A>(shared_ptr&lt;T&gt; const &amp; p); // never throws
template&lt;typename T, typename U&gt; template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt <a href="#shared_static_cast">shared_static_cast</a>(shared_ptr&lt;U&gt; const &amp; r); // never throws shared_ptr&lt;T&gt; <A href="#shared_static_cast" >shared_static_cast</A>(shared_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;typename T, typename U&gt; template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(shared_ptr&lt;U&gt; const &amp; r); shared_ptr&lt;T&gt; <A href="#shared_dynamic_cast" >shared_dynamic_cast</A>(shared_ptr&lt;U&gt; const &amp; r);
template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; <A href="#shared_polymorphic_cast" >shared_polymorphic_cast</A>(shared_ptr&lt;U&gt; const &amp; r);
template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; <A href="#shared_polymorphic_downcast" >shared_polymorphic_downcast</A>(shared_ptr&lt;U&gt; const &amp; r); // never throws
}</pre> }</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>
<blockquote>
<p>Provides the type of the template parameter T.</p>
</blockquote>
<h3><a name="constructors">constructors</a></h3>
<pre>shared_ptr();</pre>
<blockquote>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>.</p>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> is 1; the stored
pointer is 0.</p>
<p><b>Throws:</b> <b>std::bad_alloc</b>.</p>
<p><b>Exception safety:</b> If an exception is thrown, the constructor has no
effect.</p>
</blockquote>
<P><EM>[The poscondition of use_count() == 1 is too strong. Having the nothrow
guarantee is important, since <STRONG>reset()</STRONG> is specified in terms of
the default constructor, but the current specification requires that a count be
allocated. Therefore, this postcondition will be dropped in a future release.
The use count of a default-constructed <STRONG>shared_ptr</STRONG>, including
all copies created from it, will probably be left unspecified.</EM></P>
<P><EM>There are two possible nothrow implementations, one stores 0 as a pointer to the
reference count, the other uses a single statically allocated count for all
default-constructed <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.</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&lt;T&gt;().</STRONG>]</EM></P>
<pre>template&lt;typename Y&gt; explicit shared_ptr(Y * p);</pre>
<blockquote>
<p><b>Requirements:</b> <b>p</b> must be convertible to <b>T *</b>. <STRONG>Y</STRONG>
must be a complete type. The expression <code>delete p</code> must be
well-formed, must not invoke undefined behavior, and must not throw exceptions.
</p>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b>.</p>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> is 1.</p>
<p><b>Throws:</b> <b>std::bad_alloc</b>.</p>
<p><b>Exception safety:</b> If an exception is thrown, <code>delete p</code> is
called.</p>
<P><STRONG>Notes:</STRONG> <B>p</B> must be a pointer to an object that was
allocated via a C++ <B>new</B> expression or be 0. The postcondition that <A href="#use_count">
use count</A> is 1 holds even if <b>p</b> is 0; invoking <STRONG>delete</STRONG>
on a pointer that has a value of 0 is harmless.</P>
</blockquote>
<P><EM>[This constructor has been changed to a template in order to remember the actual
pointer type passed. The destructor will call <STRONG>delete</STRONG> with the
same pointer, complete with its original type, even when <STRONG>T</STRONG> does
not have a virtual destructor, or is <STRONG>void</STRONG>.</EM></P>
<P><EM>In the current implementation, if <STRONG>p</STRONG> is convertible to <STRONG>counted_base
*</STRONG>, <STRONG>shared_ptr</STRONG> will use the embedded reference
count supplied by <STRONG>counted_base</STRONG>. This is an (experimental)
attempt to provide a way for <STRONG>shared_ptr</STRONG> to be constructed from
a raw pointer such as <STRONG>this</STRONG>. A free function <STRONG>shared_from_this(q)</STRONG>
performs the conversion when <STRONG>q</STRONG> is convertible to <STRONG>counted_base
const *</STRONG>.</EM></P>
<P><EM>The optional intrusive counting employed by the current implementation allows <STRONG>
shared_ptr</STRONG> to interoperate with <STRONG>intrusive_ptr</STRONG>, an
experimental generic intrusive-counted smart pointer.</EM></P>
<P><EM> Another possible implementation is to use a global pointer-to-count map instead
of intrusive counting. <STRONG>shared_from_this</STRONG> would no longer be
O(1), which is a concern for some users, although I do not expect any
performance problems, since the operation is rare. Maintaining a global
map is difficult; it needs to be initialized before any <STRONG>shared_ptr</STRONG>
instances are constructed, and the initialization needs to be thread safe.
In addition, under the Windows dynamic library model, it is possible for
several maps to exist.</EM></P>
<P><EM> It is not yet clear which implementation should be used, or whether the
specification should allow both; nevertheless, the ability to make a <STRONG>shared_ptr</STRONG>
from <STRONG>this</STRONG> is considered essential by experienced smart
pointer users.</EM><EM>]</EM></P>
<pre>template&lt;typename Y, typename D&gt; shared_ptr(Y * p, D d);</pre>
<blockquote>
<p><b>Requirements:</b> <B>p</B> must be convertible to <B>T *</B>. <STRONG>D</STRONG>
must be <STRONG>CopyConstructible</STRONG>. The copy constructor and destructor
of <b>D</b> must not throw. The expression <code>d(p)</code> must be
well-formed, must not invoke undefined behavior, and must not throw exceptions.
</p>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b> and <b>d</b>.</p>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> is 1.</p>
<p><b>Throws:</b> <b>std::bad_alloc</b>.</p>
<p><b>Exception safety:</b> If an exception is thrown, <code>d(p)</code> is called.</p>
<p><b>Notes:</b> When the the time comes to delete the object pointed to by <b>p</b>,
the stored copy of <STRONG>d</STRONG> is invoked with the stored copy of <STRONG>p</STRONG>
as an argument.</p>
</blockquote>
<P><EM>[Custom deallocators allow a factory function returning a <STRONG>shared_ptr</STRONG>
to insulate the user from its memory allocation strategy. Since the deallocator
is not part of the type, changing the allocation strategy does not break source
or binary compatibility, and does not require a client recompilation. For
example, a "no-op" deallocator is useful when returning a <STRONG>shared_ptr</STRONG>
to a statically allocated object.</EM></P>
<P><EM>The support for custom deallocators does not impose significant overhead. Other <STRONG>
shared_ptr</STRONG> features still require a deallocator to be kept.</EM></P>
<P><EM>The requirement that the copy constructor of <b>D</b> does not throw comes from
the pass by value. If the copy constructor throws, the pointer is leaked.
Removing the requirement requires a pass by (const) reference. The problems are
that (1) pass by value conveniently changes functions (function references) to
function pointers (this has to be performed manually otherwise and some
compilers may not be able to do it) and (2) const references don't currently
(per the standard) bind to functions. This can be solved (I think) but it
requires an overload set that breaks on many compilers due to 14.5.5.2 problems
(and of course it will break on compilers that don't do partial ordering at
all.)</EM></P>
<P><EM>The requrement will be removed when the aforementioned issues are
resolved.]</EM></P>
<pre>shared_ptr(shared_ptr const &amp; r); // never throws
template&lt;typename Y&gt; shared_ptr(shared_ptr&lt;Y&gt; const &amp; r); // never throws</pre>
<blockquote>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, as if by storing a copy of the
pointer stored in <STRONG>r</STRONG>.</p>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> for all copies is
increased by one.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<P><EM>[The postcondition will be relaxed when a default-constructed <STRONG>shared_ptr</STRONG>
is being copied.]</EM></P>
<pre>template&lt;typename Y&gt; explicit shared_ptr(<A href="weak_ptr.htm">weak_ptr</A>&lt;Y&gt; const &amp; r);</pre>
<blockquote>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, as if by storing a copy of the
pointer stored in <STRONG>r</STRONG>.</p>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> for all copies is
increased by one.</p>
<p><b>Throws:</b> <b>use_count_is_zero</b> when <code>r.use_count() == 0</code>.</p>
<p><b>Exception safety:</b> If an exception is thrown, the constructor has no
effect.</p>
</blockquote>
<P><EM>[This constructor is an optional part of the specification; it depends on the
existence of <STRONG>weak_ptr</STRONG>. It is true that <STRONG>weak_ptr</STRONG>
support imposes overhead on every <STRONG>shared_ptr</STRONG> user, regardless
of whether weak pointers are used.</EM></P>
<P><EM>On the other hand, cyclic references are a serious problem with all reference
counted designs. Not providing a solution within the library is unacceptable;
if users are forced to reinvent the weak pointer wheel, there is substantial
probability that they will get it wrong, as designing a safe <STRONG>weak_ptr</STRONG>
interface is non-trivial.</EM></P>
<P><EM>My opinion is that the added functionality is worth the cost. <STRONG>weak_ptr</STRONG>
is provided in the reference implementation as a proof of concept.]</EM></P>
<pre>template&lt;typename Y&gt; shared_ptr(std::auto_ptr&lt;Y&gt; &amp; r);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Constructs a <B>shared_ptr</B>, as if by storing a copy of <STRONG>r.release()</STRONG>.</P>
<P><B>Postconditions:</B> <A href="#use_count">use count</A> is 1.</P>
<P><B>Throws:</B> <B>std::bad_alloc</B>.</P>
<P><B>Exception safety:</B> If an exception is thrown, the constructor has no
effect.</P>
</BLOCKQUOTE>
<P><EM>[This constructor takes a the source <STRONG>auto_ptr</STRONG> by reference and
not by value, and cannot accept <STRONG>auto_ptr</STRONG> temporaries. This is
by design, as the constructor offers the strong guarantee.]</EM></P>
<h3><a name="destructor">destructor</a></h3>
<pre>~shared_ptr(); // never throws</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> If <STRONG>*this</STRONG> is the sole owner (<code>use_count() == 1</code>),
destroys the object pointed to by the stored pointer.</P>
<P><B>Postconditions:</B> <A href="#use_count">use count</A> for all remaining
copies is decreased by one.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<H3><a name="assignment">assignment</a></H3>
<pre>shared_ptr &amp; operator=(shared_ptr const &amp; r); // never throws
template&lt;typename Y&gt; shared_ptr &amp; operator=(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;typename Y&gt; shared_ptr &amp; operator=(std::auto_ptr&lt;Y&gt; &amp; r);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr(r).swap(*this)</code>.</P>
<P><B>Notes:</B> The use count updates caused by the temporary object construction
and destruction are not considered observable side effects, and the
implementation is free to meet the effects (and the implied guarantees) via
different means, without creating a temporary. In particular, in the example:</P>
<pre>
shared_ptr&lt;int&gt; p(new int);
shared_ptr&lt;void&gt; q(p);
p = p;
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" rile. However, experience suggests that when C++ code is
used to describe effects, it is often misinterpreted as required
implementation. In addition, it is not entirely clear whether the "as if" rule
actually applies here, so it's better to be explicit about the possible
optimizations.]</EM></P>
<h3><a name="reset">reset</a></h3>
<pre>void reset();</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr().swap(*this)</code>.</P>
</BLOCKQUOTE>
<P><EM>[<STRONG>reset()</STRONG> will offer the nothrow guarantee in a future
implementation.]</EM></P>
<pre>template&lt;typename Y&gt; void reset(Y * p);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p).swap(*this)</code>.</P>
</BLOCKQUOTE>
<pre>template&lt;typename Y, typename D&gt; void reset(Y * p, D d);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p, d).swap(*this)</code>.</P>
</BLOCKQUOTE>
<h3><a name="indirection">indirection</a></h3>
<pre>T &amp; operator*() const; // never throws</pre>
<blockquote>
<p><b>Requirements:</b> The stored pointer must not be 0.</p>
<p><b>Returns:</b> a reference to the object pointed to by the stored pointer.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>T * operator-&gt;() const; // never throws</pre>
<blockquote>
<p><b>Requirements:</b> The stored pointer must not be 0.</p>
<p><b>Returns:</b> the stored pointer.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> the stored pointer.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h3><a name="unique">unique</a></h3>
<pre>bool unique() const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>use_count() == 1</code>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <code>unique()</code> may be faster than <code>use_count()</code>.
If you are using <code>unique()</code> to implement copy on write, do not rely
on a specific value when the stored pointer is zero.</P>
</blockquote>
<P><EM>[In a future release, <STRONG>unique()</STRONG> will return an unspecified value
for a default-constructed <STRONG>shared_ptr.</STRONG>]</EM></P>
<h3><a name="use_count">use_count</a></h3>
<pre>long use_count() const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> the number of <b>shared_ptr</b> objects sharing ownership of the
stored pointer.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <code>use_count()</code> is not necessarily efficient. Use only
for debugging and testing purposes, not for production code.</P>
</blockquote>
<h3><a name="conversions">conversions</a></h3>
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> an unspecified value that, when used in boolean contexts,
is equivalent to <code>get() != 0</code>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> This conversion operator allows <b>shared_ptr</b> objects to be
used in boolean contexts, like <code>if (p &amp;&amp; p-&gt;valid()) {}</code>.
The actual target type is typically a pointer to a member function, avoiding
many of the implicit conversion pitfalls.</P>
</blockquote>
<P><EM>[The conversion to bool is not merely syntactic sugar. It allows <STRONG>shared_ptr</STRONG>s
to be declared in conditions when using <STRONG>shared_dynamic_cast </STRONG>or <STRONG>
make_shared</STRONG>.]</EM></P>
<h3><a name="swap">swap</a></h3>
<pre>void swap(shared_ptr &amp; b); // never throws</pre>
<blockquote>
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h2><a name="functions">Free Functions</a></h2>
<h3><a name="comparison">comparison</a></h3>
<pre>template&lt;typename T, typename U&gt;
bool operator==(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;typename T, typename U&gt;
bool operator!=(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a.get() != b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;typename T&gt;
bool operator&lt;(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;T&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> an unspecified value such that <b>operator&lt;</b> is a
strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
of the C++ standard.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> Allows <STRONG>shared_ptr</STRONG> objects to be used as keys in
associative containers.</P>
</blockquote>
<P><EM>[<STRONG>Operator&lt;</STRONG> has been preferred over a <STRONG>std::less </STRONG>
specialization for consistency and legality reasons, as <STRONG>std::less</STRONG>
is required to return the results of <STRONG>operator&lt;</STRONG>, and many
standard algorithms use <STRONG>operator&lt;</STRONG> instead of <STRONG>std::less</STRONG>
for comparisons when a predicate is not supplied. Composite objects, like <STRONG>std::pair</STRONG>,
also implement their <STRONG>operator&lt;</STRONG> in terms of their contained
subobjects' <STRONG>operator&lt;</STRONG>.</EM></P>
<P><EM>The rest of the comparison operators are omitted by design.]</EM></P>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;typename T&gt;
void swap(shared_ptr&lt;T&gt; &amp; a, shared_ptr&lt;T&gt; &amp; b); // never throws</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
generic programming.</P>
</BLOCKQUOTE>
<P><EM>[<STRONG>swap</STRONG> is defined in the same namespace as <STRONG>shared_ptr</STRONG>
as this is currently the only legal way to supply a <STRONG>swap</STRONG> function
that has a chance to be used by the standard library.]</EM></P>
<h3><a name="get_pointer">get_pointer</a></h3>
<pre>template&lt;typename T&gt;
T * get_pointer(shared_ptr&lt;T&gt; const &amp; p); // never throws</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> <code>p.get()</code>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> Provided as an aid to generic programming. Used by <A href="../bind/mem_fn.html">
mem_fn</A>.</P>
</BLOCKQUOTE>
<h3><a name="shared_static_cast">shared_static_cast</a></h3>
<pre>template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; shared_static_cast(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE>
<P><STRONG>Requires:</STRONG> The expression <code>static_cast&lt;T*&gt;(r.get())</code>
must be well-formed.</P>
<P><B>Returns:</B> A <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy
of <code>static_cast&lt;T*&gt;(r.get())</code> and shares ownership with <b>r</b>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> the seemingly equivalent expression</P>
<p><code>shared_ptr&lt;T&gt;(static_cast&lt;T*&gt;(r.get()))</code></p>
<p>will eventually result in undefined behavior, attempting to delete the same
object twice.</p>
</BLOCKQUOTE>
<h3><a name="shared_dynamic_cast">shared_dynamic_cast</a></h3>
<pre>template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; shared_dynamic_cast(shared_ptr&lt;U&gt; const &amp; r);</pre>
<BLOCKQUOTE>
<P><STRONG>Requires:</STRONG> The expression <CODE>dynamic_cast&lt;T*&gt;(r.get())</CODE>
must be well-formed and its behavior defined.</P>
<P><B>Returns:</B></P>
<UL>
<LI>
When <CODE>dynamic_cast&lt;T*&gt;(r.get())</CODE> returns a nonzero value, a <STRONG>
shared_ptr&lt;T&gt;</STRONG> object that stores a copy of it and shares
ownership with <STRONG>r</STRONG>;
<LI>
Otherwise, a default-constructed <STRONG>shared_ptr&lt;T&gt;</STRONG> object.</LI></UL>
<P><B>Throws:</B> <STRONG>std::bad_alloc</STRONG>.</P>
<P><B>Exception safety:</B> If an exception is thrown, the function has no effect.</P>
<P><B>Notes:</B> the seemingly equivalent expression</P>
<P><CODE>shared_ptr&lt;T&gt;(dynamic_cast&lt;T*&gt;(r.get()))</CODE></P>
<P>will eventually result in undefined behavior, attempting to delete the same
object twice.</P>
</BLOCKQUOTE>
<h3><a name="shared_polymorphic_cast">shared_polymorphic_cast</a></h3>
<pre>template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; shared_polymorphic_cast(shared_ptr&lt;U&gt; const &amp; r);</pre>
<BLOCKQUOTE>
<p><STRONG>Requires:</STRONG> The expression <CODE><A href="../conversion/cast.htm#Polymorphic_cast">
polymorphic_cast</A>&lt;T*&gt;(r.get())</CODE> must be well-formed and
its behavior defined.</p>
<P><B>Returns:</B> A <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy
of <CODE><A href="../conversion/cast.htm#Polymorphic_cast">polymorphic_cast</A>&lt;T*&gt;(r.get())</CODE>
and shares ownership with <B>r</B>.</P>
<P><B>Throws:</B> <STRONG>std::bad_cast</STRONG> when the pointer cannot be
converted.</P>
<P><B>Exception safety:</B> If an exception is thrown, the function has no effect.</P>
</BLOCKQUOTE>
<h3><a name="shared_polymorphic_downcast">shared_polymorphic_downcast</a></h3>
<pre>template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; shared_polymorphic_downcast(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE>
<p><STRONG>Requires:</STRONG> The expression <CODE><A href="../conversion/cast.htm#Polymorphic_cast">
polymorphic_downcast</A>&lt;T*&gt;(r.get())</CODE> must be well-formed
and its behavior defined.</p>
<P><B>Returns:</B> A <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy
of <CODE><A href="../conversion/cast.htm#Polymorphic_cast">polymorphic_downcast</A>&lt;T*&gt;(r.get())</CODE>
and shares ownership with <B>r</B>.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<h2><a name="example">Example</a></h2>
<p>See <A href="shared_ptr_example.cpp">shared_ptr_example.cpp</A> for a complete
example program. The program builds a <b>std::vector</b> and <b>std::set</b> of <b>shared_ptr</b>
objects.</p>
<p>Note that after the containers have been populated, some of the <b>shared_ptr</b>
objects will have a use count of 1 rather than a use count of 2, since the set
is a <b>std::set</b> rather than a <b>std::multiset</b>, and thus does not
contain duplicate entries. Furthermore, the use count may be even higher at
various times while <b>push_back</b> and <b>insert</b> container operations are
performed. More complicated yet, the container operations may throw exceptions
under a variety of circumstances. Getting the memory management and exception
handling in this example right without a smart pointer would be a nightmare.</p>
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
<p>One common usage of <b>shared_ptr</b> is to implement a handle/body (also called
pimpl) idiom which avoids exposing the body (implementation) in the header
file.</p>
<p>The <A href="shared_ptr_example2_test.cpp">shared_ptr_example2_test.cpp</A> sample
program includes a header file, <A href="shared_ptr_example2.hpp">shared_ptr_example2.hpp</A>,
which uses a <b>shared_ptr&lt;&gt;</b> to an incomplete type to hide the
implementation. The instantiation of member functions which require a complete
type occurs in the <A href="shared_ptr_example2.cpp">shared_ptr_example2.cpp</A>
implementation file. Note that there is no need for an explicit destructor.
Unlike ~scoped_ptr, ~shared_ptr does not require that <b>T</b> be a complete
type.</p>
<h2><a name="ThreadSafety">Thread Safety</a></h2>
<p><STRONG>shared_ptr</STRONG> objects offer the same level of thread safety as
built-in types. A <STRONG>shared_ptr</STRONG> instance can be "read"
(accessed using only const operations) simultaneously by multiple threads.
Different <STRONG>shared_ptr</STRONG> instances can be "written to" (accessed
using mutable operations such as <STRONG>operator= </STRONG>or <STRONG>reset</STRONG>)
simultaneosly by multiple threads (even when these instances are copies, and
share the same reference count underneath.)</p>
<P>Any other simultaneous accesses result in undefined behavior.</P>
<P>Examples:</P>
<pre>
shared_ptr&lt;int&gt; p(new int(42));
<h2><a name="Members">Members</a></h2> //--- Example 1 ---
<h3><a name="element_type">element_type</a></h3> // thread A
<pre>typedef T element_type;</pre> shared_ptr&lt;int&gt; p2(p); // reads p
<p>Provides the type of the stored pointer.</p>
<h3><a name="constructors">constructors</a></h3> // thread B
shared_ptr&lt;int&gt; p3(p); // OK, multiple reads are safe
<pre>explicit shared_ptr(T * p = 0);</pre> //--- Example 2 ---
<p>Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b>, which
must be a pointer to an object that was allocated via a C++ <b>new</b> expression or be 0.
Afterwards, the <a href="#use_count">use count</a> is 1 (even if p == 0; see <a href="#destructor">~shared_ptr</a>).
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
If an exception is thrown, <b>delete p</b> is called.</p>
<pre>template&lt;typename D&gt; shared_ptr(T * p, D d);</pre> // thread A
<p>Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b> and of <b>d</b>.
Afterwards, the <a href="#use_count">use count</a> is 1.
<b>D</b>'s copy constructor and destructor must not throw.
When the the time comes to delete the object pointed to by <b>p</b>, the object
<b>d</b> is used in the statement <b>d(p)</b>. Invoking the object <b>d</b> with
parameter <b>p</b> in this way must not throw.
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
If an exception is thrown, <b>d(p)</b> is called.</p>
<pre>shared_ptr(shared_ptr const &amp; r); // never throws p.reset(new int(1912)); // writes p
template&lt;typename Y&gt; shared_ptr(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;typename Y&gt; shared_ptr(std::auto_ptr&lt;Y&gt; &amp; r);</pre>
<p>Constructs a <b>shared_ptr</b>, as if by storing a copy of the
pointer stored in <b>r</b>. Afterwards, the <a href="#use_count">use count</a>
for all copies is 1 more than the initial use count, or 1
in the <b>auto_ptr</b> case. In the <b>auto_ptr</b> case, <b>r.release()</b>
is called.
The only exception which may be thrown is <b>std::bad_alloc</b>,
which may be thrown during construction from <b>auto_ptr</b>.
If an exception is thrown, the constructor has no effect.</p>
<h3><a name="destructor">destructor</a></h3> // thread B
p2.reset(); // OK, writes p2
<pre>~shared_ptr(); // never throws</pre> //--- Example 3 ---
<p>Decrements the <a href="#use_count">use count</a>. Then, if the use count is 0,
deletes the object pointed to by the stored pointer.
Note that <b>delete</b> on a pointer with a value of 0 is harmless.
<b>T</b> need not be a complete type.
The guarantee that this does not throw exceptions depends on the requirement that the
deleted object's destructor does not throw exceptions.
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h3><a name="operator=">assignment</a></h3> // thread A
p = p3; // reads p3, writes p
<pre>shared_ptr &amp; <a href="#assignment">operator=</a>(shared_ptr const &amp; r); // never throws // thread B
template&lt;typename Y&gt; shared_ptr &amp; <a href="#assignment">operator=</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws p3.reset(); // writes p3; undefined, simultaneous read/write
template&lt;typename Y&gt; shared_ptr &amp; <a href="#assignment">operator=</a>(std::auto_ptr&lt;Y&gt; &amp; r);</pre>
<p>Constructs a new <b>shared_ptr</b> as described <a href="#constructors">above</a>,
then replaces this <b>shared_ptr</b> with the new one, destroying the replaced object.
The only exception which may be thrown is <b>std::bad_alloc</b>,
which may be thrown during assignment from <b>auto_ptr</b>.
If an exception is thrown, the assignment has no effect.</p>
<h3><a name="reset">reset</a></h3> //--- Example 4 ---
<pre>void reset(T * p = 0);</pre> // thread A
<p>Constructs a new <b>shared_ptr</b> as described <a href="#constructors">above</a>, p3 = p2; // reads p2, writes p3
then replaces this <b>shared_ptr</b> with the new one, destroying the replaced object.
The only exception which may be thrown is <b>std::bad_alloc</b>. If
an exception is thrown, <b>delete p</b> is called.</p>
<pre>template&lt;typename D&gt; void reset(T * p, D d);</pre> // thread B
<p>Constructs a new <b>shared_ptr</b> as described <a href="#constructors">above</a>, // p2 goes out of scope: undefined, the destructor is considered a "write access"
then replaces this <b>shared_ptr</b> with the new one, destroying the replaced object.
<b>D</b>'s copy constructor must not throw.
The only exception which may be thrown is <b>std::bad_alloc</b>. If
an exception is thrown, <b>d(p)</b> is called.</p>
<h3><a name="indirection">indirection</a></h3> //--- Example 5 ---
<pre>T &amp; operator*() const; // never throws</pre>
<p>Returns a reference to the object pointed to by the stored pointer.
Behavior is undefined if the stored pointer is 0.</p>
<pre>T * operator-&gt;() const; // never throws</pre>
<p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
<h3><a name="get">get</a></h3> // thread A
<pre>T * get() const; // never throws</pre> p3.reset(new int(1));
<p>Returns the stored pointer.
<b>T</b> need not be a complete type.
See the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h3><a name="unique">unique</a></h3> // thread B
<pre>bool unique() const; // never throws</pre> p3.reset(new int(2)); // undefined, multiple writes
<p>Returns true if no other <b>shared_ptr</b> is sharing ownership of </pre>
the stored pointer, false otherwise. <p><STRONG>shared_ptr</STRONG> uses <A href="../config/config.htm">Boost.Config</A>
<b>T</b> need not be a complete type. to detect whether the implementation supports threads. If your program is
See the smart pointer single-threaded, but your platform is autodetected by <STRONG>Boost.Config</STRONG>
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> as supporting multiple threads, <STRONG>#define BOOST_DISABLE_THREADS</STRONG> to
eliminate the thread safety overhead.</p>
<h3><a name="use_count">use_count</a></h3> <h2><a name="FAQ">Frequently Asked Questions</a></h2>
<pre>long use_count() const; // never throws</pre> <P><B>Q.</B> There are several variations of shared pointers, with different
<p>Returns the number of <b>shared_ptr</b> objects sharing ownership of the tradeoffs; why does the smart pointer library supply only a single
stored pointer. implementation? It would be useful to be able to experiment with each type so
<b>T</b> need not be a complete type. as to find the most suitable for the job at hand?<BR>
See the smart pointer <b>A.</b> An important goal of <STRONG>shared_ptr</STRONG> is to provide a
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> standard shared-ownership pointer. Having a single pointer type is important
<p>Because <b>use_count</b> is not necessarily efficient to implement for for stable library interfaces, since different shared pointers typically cannot
implementations of <b>shared_ptr</b> that do not use an explicit reference interoperate, i.e. a reference counted pointer (used by library A) cannot share
count, it might be removed from some future version. Thus it should ownership with a linked pointer (used by library B.)</P>
be used for debugging purposes only, and not production code.</p> <P><B>Q.</B> Why doesn't <B>shared_ptr</B> have template parameters supplying
traits or policies to allow extensive user customization?<BR>
<h3><a name="swap">swap</a></h3> <B>A.</B> Parameterization discourages users. The <B>shared_ptr</B> template is
<pre>void swap(shared_ptr &amp; b); // never throws</pre> carefully crafted to meet common needs without extensive parameterization. Some
<p>Exchanges the contents of the two smart pointers. day a highly configurable smart pointer may be invented that is also very easy
<b>T</b> need not be a complete type. to use and very hard to misuse. Until then, <B>shared_ptr</B> is the smart
See the smart pointer pointer of choice for a wide range of applications. (Those interested in policy
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> based smart pointers should read <A href="http://cseng.aw.com/book/0,,0201704315,00.html">
Modern C++ Design</A> by Andrei Alexandrescu.)</P>
<h2><a name="functions">Free Functions</a></h2> <P><B>Q.</B> I am not convinced. Default parameters can be used where appropriate
to hide the complexity. Again, why not policies?<BR>
<h3><a name="comparison">comparison</a></h3> <B>A.</B> Template parameters affect the type. See the answer to the first
<pre>template&lt;typename T, typename U&gt; question above.</P>
bool <a href="#operator==">operator==</a>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws <p><b>Q.</b> Why doesn't <b>shared_ptr</b> use a linked list implementation?<br>
template&lt;typename T, typename U&gt; <b>A.</b> A linked list implementation does not offer enough advantages to
bool <a href="#operator!=">operator!=</a>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws offset the added cost of an extra pointer. See <A href="smarttests.htm">timings</A>
template&lt;typename T, typename U&gt; page. In addition, it is expensive to make a linked list implementation thread
bool <a href="#operator&lt;">operator&lt;</a>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws</pre> safe.</p>
<p>Compares the stored pointers of the two smart pointers. <p><b>Q.</b> Why doesn't <b>shared_ptr</b> (or any of the other Boost smart
<b>T</b> need not be a complete type. pointers) supply an automatic conversion to <b>T*</b>?<br>
See the smart pointer <b>A.</b> Automatic conversion is believed to be too error prone.</p>
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> <p><b>Q.</b> Why does <b>shared_ptr</b> supply use_count()?<br>
<p>The <b>operator&lt;</b> overload is provided to define an ordering so that <b>shared_ptr</b> <b>A.</b> As an aid to writing test cases and debugging displays. One of the
objects can be used in associative containers such as <b>std::map</b>. progenitors had use_count(), and it was useful in tracking down bugs in a
The implementation uses <b>std::less&lt;T *&gt;</b> to perform the complex project that turned out to have cyclic-dependencies.</p>
comparison. This ensures that the comparison is handled correctly, since the <p><b>Q.</b> Why doesn't <b>shared_ptr</b> specify complexity requirements?<br>
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] <b>A.</b> Because complexity requirements limit implementors and complicate the
paragraph 2) but <b>std::less&lt;&gt;</b> on pointers is well-defined (20.3.3 [lib.comparisons] specification without apparent benefit to <b>shared_ptr</b> users. For example,
paragraph 8).</p> error-checking implementations might become non-conforming if they had to meet
stringent complexity requirements.</p>
<h3><a name="free-swap">swap</a></h3> <p><b>Q.</b> Why doesn't <b>shared_ptr</b> provide a release() function?<br>
<pre>template&lt;typename T&gt; <b>A.</b> <b>shared_ptr</b> cannot give away ownership unless it's unique()
void swap(shared_ptr&lt;T&gt; &amp; a, shared_ptr&lt;T&gt; &amp; b) // never throws</pre> because the other copy will still destroy the object.</p>
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>. <p>Consider:</p>
Provided as an aid to generic programming.</p> <blockquote><pre>shared_ptr&lt;int&gt; a(new int);
<h3><a name="shared_static_cast">shared_static_cast</a></h3>
<pre>template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt <a href="#shared_static_cast">shared_static_cast</a>(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<p>Perform a <b>static_cast</b> on the stored pointer, returning another <b>shared_ptr</b>.
The resulting smart pointer will share its use count with the original pointer.</p>
<p>Note that the seemingly equivalent expression</p>
<blockquote><code>shared_ptr&lt;T&gt;(static_cast&lt;T*&gt;(r.get()))</code></blockquote>
<p>will eventually result in undefined behavior, attempting to delete the same object twice.</p>
<h3><a name="shared_dynamic_cast">shared_dynamic_cast</a></h3>
<pre>template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(shared_ptr&lt;U&gt; const &amp; r);</pre>
<p>Perform a <b>dynamic_cast</b> on the stored pointer, returning another <b>shared_ptr</b>.
The resulting smart pointer will share its use count with the original pointer unless the result of the
cast is 0. The only exception which may be thrown is <b>std::bad_alloc</b>, which may be thrown during the
construction of the new <b>shared_ptr</b> if the result of the cast is 0. If an exception is thrown, the
cast has no effect.</p>
<p>Note that the seemingly equivalent expression</p>
<blockquote><code>shared_ptr&lt;T&gt;(dynamic_cast&lt;T*&gt;(r.get()))</code></blockquote>
<p>will eventually result in undefined behavior, attempting to delete the same object twice.</p>
<h2><a name="example">Example</a></h2>
<p>See <a href="shared_ptr_example.cpp">shared_ptr_example.cpp</a> for a complete example program.
The program builds a <b>std::vector</b> and <b>std::set</b> of <b>shared_ptr</b> objects.</p>
<p>Note that after the containers have been populated, some of the <b>shared_ptr</b> objects
will have a use count of 1 rather than a use count of 2, since the set is a <b>std::set</b>
rather than a <b>std::multiset</b>, and thus does not contain duplicate entries.
Furthermore, the use count may be even higher
at various times while <b>push_back</b> and <b>insert</b> container operations are performed.
More complicated yet, the container operations may throw exceptions under a
variety of circumstances. Getting the memory management and exception handling in this
example right without a smart pointer would be a nightmare.</p>
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
<p>One common usage of <b>shared_ptr</b> is to implement a handle/body (also
called pimpl) idiom which avoids exposing the body (implementation) in the header
file.</p>
<p>The <a href="shared_ptr_example2_test.cpp">shared_ptr_example2_test.cpp</a>
sample program includes a header file, <a href="shared_ptr_example2.hpp">shared_ptr_example2.hpp</a>,
which uses a <b>shared_ptr&lt;&gt;</b> to an incomplete type to hide the
implementation. The
instantiation of member functions which require a complete type occurs in the
<a href="shared_ptr_example2.cpp">shared_ptr_example2.cpp</a>
implementation file.
Note that there is no need for an explicit destructor.
Unlike ~scoped_ptr, ~shared_ptr does not require that <b>T</b> be a complete type.</p>
<h2><a name="FAQ">Frequently Asked Questions</a></h2>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> have template parameters supplying
traits or policies to allow extensive user customization?<br>
<b>A.</b> Parameterization discourages users. The <b>shared_ptr</b> template is
carefully crafted to meet common needs without extensive parameterization.
Some day a highly configurable smart pointer may be invented that is also very
easy to use and very hard to misuse. Until then, <b>shared_ptr</b> is the
smart pointer of choice for a wide range of applications. (Those
interested in policy based smart pointers should read
<a href="http://cseng.aw.com/book/0,,0201704315,00.html">Modern C++ Design</a> by Andrei Alexandrescu.)</p>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> use a linked list implementation?<br>
<b>A.</b> A linked list implementation does not offer enough advantages to
offset the added cost of an extra pointer. See <a href="smarttests.htm">timings</a>
page.</p>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> (or any of the other Boost smart pointers)
supply an automatic conversion to <b>T*</b>?<br>
<b>A.</b> Automatic conversion is believed to be too error prone.</p>
<p><b>Q.</b> Why does <b>shared_ptr</b> supply use_count()?<br>
<b>A.</b> As an aid to writing test cases and debugging displays. One of the
progenitors had use_count(), and it was useful in tracking down bugs in a
complex project that turned out to have cyclic-dependencies.</p>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> specify complexity requirements?<br>
<b>A.</b> Because complexity requirements limit implementors and complicate the
specification without apparent benefit to <b>shared_ptr</b> users.
For example, error-checking implementations might become non-conforming if they
had to meet stringent complexity requirements.</p>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> provide a release() function?<br>
<b>A.</b> <b>shared_ptr</b> cannot give away ownership unless it's unique()
because the other copy will still destroy the object.</p>
<p>Consider:</p>
<blockquote><pre>shared_ptr&lt;int&gt; a(new int);
shared_ptr&lt;int&gt; b(a); // a.use_count() == b.use_count() == 2 shared_ptr&lt;int&gt; b(a); // a.use_count() == b.use_count() == 2
int * p = a.release(); int * p = a.release();
// Who owns p now? b will still call delete on it in its destructor.</pre></blockquote> // Who owns p now? b will still call delete on it in its destructor.</pre>
</blockquote>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> provide (your pet feature here)?<br> <p><b>Q.</b> Why doesn't <b>shared_ptr</b> provide (your pet feature here)?<br>
<b>A.</b> Because (your pet feature here) would mandate a reference counted <b>A.</b> Because (your pet feature here) would mandate a reference counted
implementation or a linked list implementation, or some other specific implementation. implementation or a linked list implementation, or some other specific
This is not the intent.</p> implementation. This is not the intent.</p>
<hr>
<hr> <p>Revised $Date$</p>
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->1 February 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p> Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears in
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. all copies. This document is provided "as is" without express or implied
Permission to copy, use, modify, sell and distribute this document is granted warranty, and with no claim as to its suitability for any purpose.</p>
provided this copyright notice appears in all copies. </body>
This document is provided &quot;as is&quot; without express or implied warranty,
and with no claim as to its suitability for any purpose.</p>
</body>
</html> </html>

View File

@@ -0,0 +1,31 @@
#if defined(_MSC_VER) && !defined(__ICL)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#endif
//
// shared_ptr_assign_fail.cpp - a negative test for shared_ptr assignment
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/shared_ptr.hpp>
bool boost_error(char const *, char const *, char const *, long)
{
return true;
}
int main()
{
boost::shared_ptr<int> p;
p = new int(42); // assignment must fail
return 0;
}

178
shared_ptr_mt_test.cpp Normal file
View File

@@ -0,0 +1,178 @@
#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#endif
//
// shared_ptr_mt_test.cpp - tests shared_ptr with multiple threads
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <vector>
#include <memory>
#include <stdexcept>
#include <cstdio>
#include <ctime>
// 'portable' thread framework
class abstract_thread
{
public:
virtual ~abstract_thread() {}
virtual void run() = 0;
};
#if !defined(BOOST_HAS_PTHREADS) && defined(BOOST_HAS_WINTHREADS)
char const * title = "Using Windows threads";
#include <windows.h>
#include <process.h>
typedef HANDLE pthread_t;
unsigned __stdcall common_thread_routine(void * pv)
{
abstract_thread * pt = static_cast<abstract_thread *>(pv);
pt->run();
delete pt;
return 0;
}
int pthread_create(pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg)
{
HANDLE h = (HANDLE)_beginthreadex(0, 0, start_routine, arg, 0, 0);
if(h != 0)
{
*thread = h;
return 0;
}
else
{
return 1; // return errno;
}
}
int pthread_join(pthread_t thread, void ** /*value_ptr*/)
{
::WaitForSingleObject(thread, INFINITE);
::CloseHandle(thread);
return 0;
}
#else
char const * title = "Using POSIX threads";
#include <pthread.h>
extern "C" void * common_thread_routine(void * pv)
{
abstract_thread * pt = static_cast<abstract_thread *>(pv);
pt->run();
delete pt;
return 0;
}
#endif
//
template<class F> class thread: public abstract_thread
{
public:
explicit thread(F f): f_(f)
{
}
void run()
{
f_();
}
private:
F f_;
};
template<class F> pthread_t createThread(F f)
{
std::auto_ptr<abstract_thread> p(new thread<F>(f));
pthread_t r;
if(pthread_create(&r, 0, common_thread_routine, p.get()) == 0)
{
p.release();
return r;
}
throw std::runtime_error("createThread failed.");
}
//
int const n = 1024 * 1024;
void test(boost::shared_ptr<int> const & pi)
{
std::vector< boost::shared_ptr<int> > v;
for(int i = 0; i < n; ++i)
{
v.push_back(pi);
}
}
int const m = 16; // threads
#if defined(BOOST_LWM_USE_CRITICAL_SECTION)
char const * implementation = "critical section";
#elif defined(BOOST_LWM_USE_PTHREADS)
char const * implementation = "pthread_mutex";
#else
char const * implementation = "spinlock";
#endif
int main()
{
std::printf("%s: %s, %d threads, %d iterations: ", title, implementation, m, n);
boost::shared_ptr<int> pi(new int(42));
std::clock_t t = std::clock();
pthread_t a[m];
for(int i = 0; i < m; ++i)
{
a[i] = createThread( boost::bind(test, pi) );
}
for(int i = 0; i < m; ++i)
{
pthread_join(a[i], 0);
}
t = std::clock() - t;
std::printf("\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC);
return 0;
}

View File

@@ -1,4 +1,4 @@
#if defined(_MSC_VER) && !defined(__ICL) #if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__)
#pragma warning(disable: 4786) // identifier truncated in debug info #pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined #pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion #pragma warning(disable: 4711) // function selected for automatic inline expansion
@@ -8,7 +8,7 @@
// //
// shared_ptr_test.cpp - a test for shared_ptr.hpp and weak_ptr.hpp // shared_ptr_test.cpp - a test for shared_ptr.hpp and weak_ptr.hpp
// //
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd. // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
@@ -16,12 +16,13 @@
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
#define BOOST_INCLUDE_MAIN #include <boost/detail/lightweight_test.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp> #include <boost/weak_ptr.hpp>
#include <iostream>
bool boost_error(char const *, char const *, char const *, long) bool boost_error(char const *, char const *, char const *, long)
{ {
return true; return true;
@@ -40,12 +41,17 @@ struct X
std::cout << "X(" << this << ")::X()\n"; std::cout << "X(" << this << ")::X()\n";
} }
virtual ~X() ~X() // virtual destructor deliberately omitted
{ {
--cnt; --cnt;
std::cout << "X(" << this << ")::~X()\n"; std::cout << "X(" << this << ")::~X()\n";
} }
virtual int id() const
{
return 1;
}
private: private:
X(X const &); X(X const &);
@@ -66,6 +72,11 @@ struct Y: public X
std::cout << "Y(" << this << ")::~Y()\n"; std::cout << "Y(" << this << ")::~Y()\n";
} }
virtual int id() const
{
return 2;
}
private: private:
Y(Y const &); Y(Y const &);
@@ -86,7 +97,106 @@ void release_object(int * p)
std::cout << "release_object()\n"; std::cout << "release_object()\n";
} }
int test_main(int, char * []) class Z: public virtual boost::counted_base
{
public:
Z()
{
++cnt;
std::cout << "Z(" << this << ")::Z()\n";
}
~Z()
{
--cnt;
std::cout << "Z(" << this << ")::~Z()\n";
}
boost::shared_ptr<Z> shared_this()
{
return boost::shared_from_this(this);
}
boost::shared_ptr<Z const> shared_this() const
{
return boost::shared_from_this(this);
}
private:
Z(Z const &);
Z & operator= (Z const &);
};
template<class T> void test_is_X(boost::shared_ptr<T> const & p)
{
BOOST_TEST(p->id() == 1);
BOOST_TEST((*p).id() == 1);
}
template<class T> void test_is_X(boost::weak_ptr<T> const & p)
{
BOOST_TEST(p.get() != 0);
BOOST_TEST(p.get()->id() == 1);
}
template<class T> void test_is_Y(boost::shared_ptr<T> const & p)
{
BOOST_TEST(p->id() == 2);
BOOST_TEST((*p).id() == 2);
}
template<class T> void test_is_Y(boost::weak_ptr<T> const & p)
{
BOOST_TEST(p.get() != 0);
BOOST_TEST(p.get()->id() == 2);
}
template<class T> void test_eq(T const & a, T const & b)
{
BOOST_TEST(a == b);
BOOST_TEST(!(a != b));
BOOST_TEST(!(a < b));
BOOST_TEST(!(b < a));
}
template<class T> void test_ne(T const & a, T const & b)
{
BOOST_TEST(!(a == b));
BOOST_TEST(a != b);
BOOST_TEST(a < b || b < a);
BOOST_TEST(!(a < b && b < a));
}
template<class T, class U> void test_eq2(T const & a, U const & b)
{
BOOST_TEST(a == b);
BOOST_TEST(!(a != b));
}
template<class T, class U> void test_ne2(T const & a, U const & b)
{
BOOST_TEST(!(a == b));
BOOST_TEST(a != b);
}
template<class T> void test_is_zero(boost::shared_ptr<T> const & p)
{
BOOST_TEST(!p);
BOOST_TEST(p.get() == 0);
}
template<class T> void test_is_nonzero(boost::shared_ptr<T> const & p)
{
// p? true: false is used to test p in a boolean context.
// BOOST_TEST(p) is not guaranteed to test the conversion,
// as the macro might test !!p instead.
BOOST_TEST(p? true: false);
BOOST_TEST(p.get() != 0);
}
int main()
{ {
using namespace boost; using namespace boost;
@@ -94,16 +204,37 @@ int test_main(int, char * [])
shared_ptr<X> p(new Y); shared_ptr<X> p(new Y);
shared_ptr<X> p2(new X); shared_ptr<X> p2(new X);
test_is_nonzero(p);
test_is_nonzero(p2);
test_is_Y(p);
test_is_X(p2);
test_ne(p, p2);
{
shared_ptr<X> q(p);
test_eq(p, q);
}
shared_ptr<Y> p3 = shared_dynamic_cast<Y>(p); shared_ptr<Y> p3 = shared_dynamic_cast<Y>(p);
shared_ptr<Y> p4 = shared_dynamic_cast<Y>(p2); shared_ptr<Y> p4 = shared_dynamic_cast<Y>(p2);
test_is_nonzero(p3);
test_is_zero(p4);
BOOST_TEST(p.use_count() == 2); BOOST_TEST(p.use_count() == 2);
BOOST_TEST(p2.use_count() == 1); BOOST_TEST(p2.use_count() == 1);
BOOST_TEST(p3.use_count() == 2); BOOST_TEST(p3.use_count() == 2);
BOOST_TEST(p4.use_count() == 1); BOOST_TEST(p4.use_count() == 1);
test_is_Y(p3);
test_eq2(p, p3);
test_ne2(p2, p4);
shared_ptr<void> p5(p); shared_ptr<void> p5(p);
test_is_nonzero(p5);
test_eq2(p, p5);
std::cout << "--\n"; std::cout << "--\n";
p.reset(); p.reset();
@@ -111,6 +242,11 @@ int test_main(int, char * [])
p3.reset(); p3.reset();
p4.reset(); p4.reset();
test_is_zero(p);
test_is_zero(p2);
test_is_zero(p3);
test_is_zero(p4);
std::cout << "--\n"; std::cout << "--\n";
BOOST_TEST(p5.use_count() == 1); BOOST_TEST(p5.use_count() == 1);
@@ -120,27 +256,70 @@ int test_main(int, char * [])
BOOST_TEST(wp1.use_count() == 0); BOOST_TEST(wp1.use_count() == 0);
BOOST_TEST(wp1.get() == 0); BOOST_TEST(wp1.get() == 0);
try
{
shared_ptr<X> sp1(wp1);
BOOST_ERROR("shared_ptr<X> sp1(wp1) failed to throw");
}
catch(boost::use_count_is_zero const &)
{
}
test_is_zero(boost::make_shared(wp1));
weak_ptr<X> wp2 = shared_static_cast<X>(p5); weak_ptr<X> wp2 = shared_static_cast<X>(p5);
BOOST_TEST(wp2.use_count() == 1); BOOST_TEST(wp2.use_count() == 1);
BOOST_TEST(wp2.get() != 0); BOOST_TEST(wp2.get() != 0);
test_is_Y(wp2);
test_ne(wp1, wp2);
weak_ptr<Y> wp3 = shared_dynamic_cast<Y>(wp2); // Scoped to not affect the subsequent use_count() tests.
{
shared_ptr<X> sp2(wp2);
test_is_nonzero(boost::make_shared(wp2));
}
weak_ptr<Y> wp3 = shared_dynamic_cast<Y>(boost::make_shared(wp2));
BOOST_TEST(wp3.use_count() == 1); BOOST_TEST(wp3.use_count() == 1);
BOOST_TEST(wp3.get() != 0); BOOST_TEST(wp3.get() != 0);
BOOST_TEST(wp2 == wp3); test_eq2(wp2, wp3);
weak_ptr<X> wp4(wp3); weak_ptr<X> wp4(wp3);
BOOST_TEST(wp4.use_count() == 1);
BOOST_TEST(wp4.get() != 0);
test_eq(wp2, wp4);
wp1 = p2; wp1 = p2;
BOOST_TEST(wp1.get() == 0);
// Note the following test. Construction succeeds,
// but make_shared() returns a null shared_ptr with
// use_count() == 2.
shared_ptr<X> sp1(wp1);
test_is_zero(boost::make_shared(wp1));
BOOST_TEST(p2.use_count() == 2);
BOOST_TEST(sp1.use_count() == 2);
BOOST_TEST(wp1.use_count() == 2);
//
wp1 = p4; wp1 = p4;
wp1 = wp3; wp1 = wp3;
wp1 = wp2; wp1 = wp2;
BOOST_TEST(wp1.use_count() == 1); BOOST_TEST(wp1.use_count() == 1);
BOOST_TEST(wp1.get() != 0); BOOST_TEST(wp1.get() != 0);
BOOST_TEST(wp1 == wp2); test_eq(wp1, wp2);
weak_ptr<X> wp5;
bool b1 = wp1 < wp5;
bool b2 = wp5 < wp1;
p5.reset(); p5.reset();
@@ -153,10 +332,41 @@ int test_main(int, char * [])
BOOST_TEST(wp3.use_count() == 0); BOOST_TEST(wp3.use_count() == 0);
BOOST_TEST(wp3.get() == 0); BOOST_TEST(wp3.get() == 0);
shared_ptr<int> p6(get_object(), release_object); // Test operator< stability for std::set< weak_ptr<> >
// Thanks to Joe Gottman for pointing this out
BOOST_TEST(b1 == (wp1 < wp5));
BOOST_TEST(b2 == (wp5 < wp1));
{
// note that both get_object and release_object deal with int*
shared_ptr<void> p6(get_object(), release_object);
}
{
// test intrusive counting
boost::shared_ptr<void> pv(new Z);
boost::shared_ptr<Z> pz = boost::shared_static_cast<Z>(pv);
BOOST_TEST(pz.use_count() == pz->use_count());
// test shared_from_this
boost::shared_ptr<Z> pz2 = pz->shared_this();
Z const & z = *pz2;
boost::shared_ptr<Z const> pz3 = z.shared_this();
BOOST_TEST(pz.use_count() == pz->use_count());
BOOST_TEST(pz2.use_count() == pz2->use_count());
BOOST_TEST(pz3.use_count() == pz3->use_count());
BOOST_TEST(pz.use_count() == pz2.use_count());
BOOST_TEST(pz.use_count() == pz3.use_count());
}
} }
BOOST_TEST(cnt == 0); BOOST_TEST(cnt == 0);
return 0; return boost::report_errors();
} }

View File

@@ -0,0 +1,41 @@
#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#endif
//
// shared_ptr_timing_test.cpp - use to evaluate the impact of thread safety
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <vector>
#include <ctime>
int const n = 8 * 1024 * 1024;
int main()
{
std::vector< boost::shared_ptr<int> > v;
boost::shared_ptr<int> pi(new int);
std::clock_t t = std::clock();
for(int i = 0; i < n; ++i)
{
v.push_back(pi);
}
t = std::clock() - t;
std::cout << static_cast<double>(t) / CLOCKS_PER_SEC << '\n';
}

View File

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

View File

@@ -18,8 +18,7 @@
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp> #include <boost/shared_array.hpp>
#define BOOST_INCLUDE_MAIN #include <boost/detail/lightweight_test.hpp>
#include <boost/test/test_tools.hpp>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
@@ -84,12 +83,11 @@ Incomplete * check_incomplete( shared_ptr<Incomplete>& incomplete,
cout << incomplete.use_count() << ' ' << incomplete.unique() << '\n'; cout << incomplete.use_count() << ' ' << incomplete.unique() << '\n';
return incomplete.get(); return incomplete.get();
} }
// main --------------------------------------------------------------------//
// This isn't a very systematic test; it just hits some of the basics. // This isn't a very systematic test; it just hits some of the basics.
int test_main( int, char ** ) { void test()
{
BOOST_TEST( UDT_use_count == 0 ); // reality check BOOST_TEST( UDT_use_count == 0 ); // reality check
// test scoped_ptr with a built-in type // test scoped_ptr with a built-in type
@@ -289,7 +287,10 @@ int test_main( int, char ** ) {
cout << "OK\n"; cout << "OK\n";
new char[12345]; // deliberate memory leak to verify leaks detected new char[12345]; // deliberate memory leak to verify leaks detected
}
return 0; int main()
} // main {
test();
return boost::report_errors();
}

View File

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

View File

@@ -1,42 +1,72 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head>
<title>weak_ptr</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#ffffff" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">weak_ptr
class template</h1>
<p>The <b>weak_ptr</b> class template stores a&nbsp;"weak reference"&nbsp;to an
object that's already managed by a <b>shared_ptr</b>. To access the object, a <STRONG>
weak_ptr</STRONG> can be converted to a <STRONG>shared_ptr</STRONG> using <A href="shared_ptr.htm#constructors">
the <STRONG>shared_ptr</STRONG> constructor</A> or the function <STRONG><A href="#make_shared">
make_shared</A></STRONG>. When the last <b>shared_ptr</b> to the object
goes away and the object is deleted,&nbsp;the attempt to obtain a <STRONG>shared_ptr</STRONG>
&nbsp;from the <b>weak_ptr</b> instances that refer to the deleted object will
fail: the constructor will throw an exception of type <STRONG>boost::use_count_is_zero</STRONG>,
and <STRONG>make_shared</STRONG> will return a default constructed (null) <STRONG>shared_ptr</STRONG>.</p>
<p>Every <b>weak_ptr</b> meets the <b>CopyConstructible</b> and <b>Assignable</b> requirements
of the C++ Standard Library, and so can be used in standard library containers.
Comparison operators are supplied so that <b>weak_ptr</b> works with the
standard library's associative containers.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">
common requirements</a>.</p>
<P>Compared to&nbsp;<STRONG>shared_ptr</STRONG>, <STRONG>weak_ptr</STRONG> provides
a very limited subset of operations since accessing its stored pointer is
often&nbsp;dangerous in multithreaded&nbsp;programs, and sometimes unsafe even
within a single thread&nbsp;(that is, it may invoke undefined behavior.)
Consider, for example, this innocent piece of code:</P>
<pre>
shared_ptr&lt;int&gt; p(new int(5));
weak_ptr&lt;int&gt; q(p);
<head> // some time later
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>weak_ptr</title>
</head>
<body bgcolor="#FFFFFF" text="#000000"> if(int * r = q.get())
{
// use *r
}
</pre>
<P>Imagine that after the <STRONG>if</STRONG>, but immediately before <STRONG>r</STRONG>
is used, another thread executes the statement <code>p.reset()</code>. Now <STRONG>r</STRONG>
is a dangling pointer.</P>
<P>The solution to this problem is to create a temporary <STRONG>shared_ptr</STRONG>
from <STRONG>q</STRONG>:</P>
<pre>
shared_ptr&lt;int&gt; p(new int(5));
weak_ptr&lt;int&gt; q(p);
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">weak_ptr class template</h1> // some time later
<p>The <b>weak_ptr</b> class template stores a pointer to an if(shared_ptr&lt;int&gt; r = <a href="#make_shared">make_shared</a>(q))
object that's already managed by a <b>shared_ptr</b>. When the {
object last <b>shared_ptr</b> to the object goes away and the object // use *r
is deleted, all <b>weak_ptr</b> objects have their stored pointers }
set to 0.</p> </pre>
<p>Now <STRONG>r</STRONG> holds a reference to the object that was pointed by <STRONG>q</STRONG>.
<p>Every <b>weak_ptr</b> meets the <b>CopyConstructible</b> Even if <code>p.reset()</code> is executed in another thread, the object will
and <b>Assignable</b> requirements of the C++ Standard Library, and so stay alive until <STRONG>r</STRONG> goes out of scope (or is reset.)</p>
can be used in standard library containers. Comparison operators <h2><a name="Synopsis">Synopsis</a></h2>
are supplied so that <b>weak_ptr</b> works with <pre>namespace boost {
the standard library's associative containers.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object
pointed to. <b>T</b> must meet the smart pointer
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost {
template&lt;typename T&gt; class weak_ptr { template&lt;typename T&gt; class weak_ptr {
public: public:
typedef T <a href="#element_type">element_type</a>; typedef T <a href="#element_type">element_type</a>;
explicit <a href="#constructors">weak_ptr</a>(); <a href="#constructors">weak_ptr</a>();
template&lt;typename Y&gt; <a href="#constructors">weak_ptr</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws template&lt;typename Y&gt; <a href="#constructors">weak_ptr</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
<a href="#destructor">~weak_ptr</a>(); // never throws <a href="#destructor">~weak_ptr</a>(); // never throws
@@ -47,174 +77,182 @@ pointed to. <b>T</b> must meet the smart pointer
template&lt;typename Y&gt; weak_ptr &amp; <a href="#assignment">operator=</a>(weak_ptr&lt;Y&gt; const &amp; r); // never throws template&lt;typename Y&gt; weak_ptr &amp; <a href="#assignment">operator=</a>(weak_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;typename Y&gt; weak_ptr &amp; <a href="#assignment">operator=</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws template&lt;typename Y&gt; weak_ptr &amp; <a href="#assignment">operator=</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
void <a href="#reset">reset</a>(); // never throws void <a href="#reset">reset</a>();
T * <a href="#get">get</a>() const; // never throws; deprecated, will disappear
T &amp; <a href="#indirection">operator*</a>() const; // never throws
T * <a href="#indirection">operator-&gt;</a>() const; // never throws
T * <a href="#get">get</a>() const; // never throws
long <a href="#use_count">use_count</a>() const; // never throws long <a href="#use_count">use_count</a>() const; // never throws
bool <a href="#expired">expired</a>() const; // never throws
void <a href="#swap">swap</a>(weak_ptr&lt;T&gt; &amp; b); // never throws void <a href="#swap">swap</a>(weak_ptr&lt;T&gt; &amp; b); // never throws
}; };
template&lt;typename T, typename U&gt; template&lt;typename T, typename U&gt;
bool <a href="#operator==">operator==</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws bool <a href="#comparison">operator==</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;typename T, typename U&gt; template&lt;typename T, typename U&gt;
bool <a href="#operator!=">operator!=</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws bool <a href="#comparison">operator!=</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;typename T, typename U&gt; template&lt;typename T&gt;
bool <a href="#operator&lt;">operator&lt;</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws bool <a href="#comparison">operator&lt;</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;T&gt; const &amp; b); // never throws
template&lt;typename T&gt; void <a href="#free-swap">swap</a>(weak_ptr&lt;T&gt; &amp; a, weak_ptr&lt;T&gt; &amp; b); // never throws template&lt;typename T&gt; void <a href="#free-swap">swap</a>(weak_ptr&lt;T&gt; &amp; a, weak_ptr&lt;T&gt; &amp; b); // never throws
template&lt;typename T, typename U&gt; template&lt;typename T&gt;
weak_ptr&lt;T&gt <a href="#shared_static_cast">shared_static_cast</a>(weak_ptr&lt;U&gt; const &amp; r); // never throws shared_ptr&lt;T&gt; <a href="#make_shared">make_shared</a>(weak_ptr&lt;T&gt; const &amp; r); // never throws
template&lt;typename T, typename U&gt;
weak_ptr&lt;T&gt <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(weak_ptr&lt;U&gt; const &amp; r);
}</pre> }
</pre>
<h2><a name="Members">Members</a></h2> <h2><a name="Members">Members</a></h2>
<h3><a name="element_type">element_type</a></h3>
<h3><a name="element_type">element_type</a></h3> <pre>typedef T element_type;</pre>
<pre>typedef T element_type;</pre> <blockquote>
<p>Provides the type of the stored pointer.</p> <p>Provides the type of the template parameter T.</p>
</blockquote>
<h3><a name="constructors">constructors</a></h3> <h3><a name="constructors">constructors</a></h3>
<pre> weak_ptr();</pre>
<pre>explicit weak_ptr();</pre> <blockquote>
<p>Constructs a <b>weak_ptr</b>, with 0 as its stored pointer. <p><b>Effects:</b> Constructs a <b>weak_ptr</b>.</p>
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>. <p><b>Postconditions:</b> <A href="#use_count">use count</A> is 0; the stored
If an exception is thrown, the constructor has no effect.</p> pointer is 0.</p>
<p><b>Throws:</b> <b>std::bad_alloc</b>.</p>
<pre>template&lt;typename Y&gt; weak_ptr</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws</pre> <p><b>Exception safety:</b> If an exception is thrown, the constructor has no
<p>Constructs a <b>weak_ptr</b>, as if by storing a copy of the pointer stored in <b>r</b>. effect.</p>
Afterwards, the <a href="#use_count">use count</a> for all copies is unchanged. <P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
When the last <b>shared_ptr</b> is destroyed, the use count and stored pointer become 0.</p> common requirements</A>.</P>
</blockquote>
<pre>weak_ptr(weak_ptr const &amp; r); // never throws <pre>template&lt;typename Y&gt; weak_ptr</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws</pre>
<blockquote>
<p><b>Effects:</b> Constructs a <b>weak_ptr</b>, as if by storing a copy of the
pointer stored in <b>r</b>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> The <a href="#use_count">use count</a> for all copies is
unchanged. When the last <b>shared_ptr</b> is destroyed, the use count and
stored pointer become 0.</P>
</blockquote>
<pre>weak_ptr(weak_ptr const &amp; r); // never throws
template&lt;typename Y&gt; weak_ptr(weak_ptr&lt;Y&gt; const &amp; r); // never throws</pre> template&lt;typename Y&gt; weak_ptr(weak_ptr&lt;Y&gt; const &amp; r); // never throws</pre>
<p>Constructs a <b>weak_ptr</b>, as if by storing a copy of the <blockquote>
pointer stored in <b>r</b>.</p> <p><b>Effects:</b> Constructs a <b>weak_ptr</b>, as if by storing a copy of the
pointer stored in <b>r</b>.</p>
<h3><a name="destructor">destructor</a></h3> <p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> The <a href="#use_count">use count</a> for all copies is
<pre>~weak_ptr(); // never throws</pre> unchanged.</P>
<p>Destroys this <b>weak_ptr</b> but has no effect on the object its stored pointer points to. </blockquote>
<b>T</b> need not be a complete type. <h3><a name="destructor">destructor</a></h3>
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> <pre>~weak_ptr(); // never throws</pre>
<BLOCKQUOTE>
<h3><a name="operator=">assignment</a></h3> <P><B>Effects:</B> Destroys this <b>weak_ptr</b> but has no effect on the object
its stored pointer points to.</P>
<pre>weak_ptr &amp; <a href="#assignment">operator=</a>(weak_ptr const &amp; r); // never throws <P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
common requirements</A>.</P>
</BLOCKQUOTE>
<h3><a name="assignment">assignment</a></h3>
<pre>weak_ptr &amp; <a href="#assignment">operator=</a>(weak_ptr const &amp; r); // never throws
template&lt;typename Y&gt; weak_ptr &amp; <a href="#assignment">operator=</a>(weak_ptr&lt;Y&gt; const &amp; r); // never throws template&lt;typename Y&gt; weak_ptr &amp; <a href="#assignment">operator=</a>(weak_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;typename Y&gt; weak_ptr &amp; <a href="#assignment">operator=</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws</pre> template&lt;typename Y&gt; weak_ptr &amp; <a href="#assignment">operator=</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws</pre>
<p>Constructs a new <b>weak_ptr</b> as described <a href="#constructors">above</a>, <BLOCKQUOTE>
then replaces this <b>weak_ptr</b> with the new one, destroying the replaced object.</p> <P><B>Effects:</B> Equivalent to <code>weak_ptr(r).swap(*this)</code>.</P>
<P><B>Throws:</B> nothing.</P>
<h3><a name="reset">reset</a></h3> <P><B>Notes:</B> The implementation is free to meet the effects (and the implied
guarantees) via different means, without creating a temporary.</P>
<pre>void reset();</pre> </BLOCKQUOTE>
<p>Constructs a new <b>weak_ptr</b> as described <a href="#constructors">above</a>, <h3><a name="reset">reset</a></h3>
then replaces this <b>weak_ptr</b> with the new one, destroying the replaced object. <pre>void reset();</pre>
The only exception which may be thrown is <b>std::bad_alloc</b>. If <BLOCKQUOTE>
an exception is thrown, the <b>reset</b> has no effect.</p> <P><B>Effects:</B> Equivalent to <code>weak_ptr().swap(*this)</code>.</P>
</BLOCKQUOTE>
<h3><a name="indirection">indirection</a></h3> <h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<pre>T &amp; operator*() const; // never throws</pre> <blockquote>
<p>Returns a reference to the object pointed to by the stored pointer. <p><b>Returns:</b> the stored pointer (0 if all <b>shared_ptr</b> objects for that
Behavior is undefined if the stored pointer is 0. pointer are destroyed.)</p>
Note that the stored pointer becomes 0 if all <b>shared_ptr</b> objects for that <p><b>Throws:</b> nothing.</p>
pointer are destroyed.</p> <P><B>Notes:</B> Using <b>get</b> in multithreaded code is dangerous. After the
function returns, the pointed-to object may be destroyed by a different thread,
<pre>T * operator-&gt;() const; // never throws</pre> since the <b>weak_ptr</b> doesn't affect its <b>use_count</b>.</P>
<p>Returns the stored pointer. </blockquote>
Behavior is undefined if the stored pointer is 0. <P><EM>[<b>get</b> is&nbsp;very error-prone. Even single-threaded code may experience
Note that the stored pointer becomes 0 if all <b>shared_ptr</b> objects for that problems, as the returned pointer may be invalidated at any time, for example,
pointer are destroyed.</p> indirectly by a member function of the pointee.</EM></P>
<P><EM><STRONG>get</STRONG>&nbsp;is deprecated, and it will disappear in a future
<h3><a name="get">get</a></h3> release. Do not use it.]</EM></P>
<pre>T * get() const; // never throws</pre> <h3><a name="use_count">use_count</a></h3>
<p>Returns the stored pointer. <pre>long use_count() const; // never throws</pre>
Note that the stored pointer becomes 0 if all <b>shared_ptr</b> objects for that <blockquote>
pointer are destroyed. <p><b>Returns:</b> the number of <b>shared_ptr</b> objects sharing ownership of the
<b>T</b> need not be a complete type. stored pointer.</p>
See the smart pointer <p><b>Throws:</b> nothing.</p>
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> <P><B>Notes:</B> <code>use_count()</code> is not necessarily efficient. Use only
for debugging and testing purposes, not for production code. <B>T</B> need not
<h3><a name="use_count">use_count</a></h3> be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
<pre>long use_count() const; // never throws</pre> common requirements</A>.</P>
<p>Returns the number of <b>shared_ptr</b> objects sharing ownership of the </blockquote>
stored pointer. <h3><a name="expired">expired</a></h3>
<b>T</b> need not be a complete type. <pre>bool expired() const; // never throws</pre>
See the smart pointer <blockquote>
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> <p><b>Returns:</b> <code>use_count() == 0</code>.</p>
<p>Because <b>use_count</b> is not necessarily efficient to implement for <p><b>Throws:</b> nothing.</p>
implementations of <b>weak_ptr</b> that do not use an explicit reference <P><B>Notes:</B> <code>expired()</code> may be faster than <code>use_count()</code>.
count, it might be removed from some future version. Thus it should <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
be used for debugging purposes only, and <b>get</b> should be used for common requirements</A>.</P>
production code.</p> </blockquote>
<h3><a name="swap">swap</a></h3>
<h3><a name="swap">swap</a></h3> <pre>void swap(weak_ptr &amp; b); // never throws</pre>
<pre>void swap(weak_ptr &amp; b); // never throws</pre> <blockquote>
<p>Exchanges the contents of the two smart pointers. <p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
<b>T</b> need not be a complete type. <p><b>Throws:</b> nothing.</p>
See the smart pointer <P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> common requirements</A>.</P>
</blockquote>
<h2><a name="functions">Free Functions</a></h2> <h2><a name="functions">Free Functions</a></h2>
<h3><a name="comparison">comparison</a></h3>
<h3><a name="comparison">comparison</a></h3> <pre>template&lt;typename T, typename U&gt;
<pre>template&lt;typename T, typename U&gt; bool operator==(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws
bool <a href="#operator==">operator==</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;typename T, typename U&gt; template&lt;typename T, typename U&gt;
bool <a href="#operator!=">operator!=</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws bool operator!=(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws</pre>
template&lt;typename T, typename U&gt; <blockquote>
bool <a href="#operator&lt;">operator&lt;</a>(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b); // never throws</pre> <p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
<p>Compares the stored pointers of the two smart pointers. <p><b>Throws:</b> nothing.</p>
<b>T</b> need not be a complete type. <P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
See the smart pointer common requirements</A>.</P>
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> </blockquote>
<p>The <b>operator&lt;</b> overload is provided to define an ordering so that <b>weak_ptr</b> <pre>template&lt;typename T&gt;
objects can be used in associative containers such as <b>std::map</b>. bool operator&lt;(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;T&gt; const &amp; b); // never throws</pre>
The implementation uses <b>std::less&lt;T *&gt;</b> to perform the <blockquote>
comparison. This ensures that the comparison is handled correctly, since the <p><b>Returns:</b> an implementation-defined value such that <b>operator&lt;</b> is
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] a strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
paragraph 2) but <b>std::less&lt;&gt;</b> on pointers is well-defined (20.3.3 [lib.comparisons] of the C++ standard.</p>
paragraph 8).</p> <p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> Allows <STRONG>weak_ptr</STRONG> objects to be used as keys in
<h3><a name="free-swap">swap</a></h3> associative containers. <B>T</B> need not be a complete type. See the smart
<pre>template&lt;typename T&gt; pointer <A href="smart_ptr.htm#Common requirements">common requirements</A>.</P>
</blockquote>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;typename T&gt;
void swap(weak_ptr&lt;T&gt; &amp; a, weak_ptr&lt;T&gt; &amp; b) // never throws</pre> void swap(weak_ptr&lt;T&gt; &amp; a, weak_ptr&lt;T&gt; &amp; b) // never throws</pre>
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>. <BLOCKQUOTE>
Provided as an aid to generic programming.</p> <P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
<P><B>Throws:</B> nothing.</P>
<h3><a name="shared_static_cast">shared_static_cast</a></h3> <P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
<pre>template&lt;typename T, typename U&gt; generic programming.</P>
weak_ptr&lt;T&gt <a href="#shared_static_cast">shared_static_cast</a>(weak_ptr&lt;U&gt; const &amp; r); // never throws</pre> </BLOCKQUOTE>
<p>Perform a <b>static_cast</b> on the stored pointer, returning another <b>weak_ptr</b>. <h3><a name="make_shared">make_shared</a></h3>
The resulting smart pointer will share its use count with the original pointer.</p> <pre>template&lt;typename T&gt;
shared_ptr&lt;T&gt; make_shared(weak_ptr&lt;T&gt; &amp; const r) // never throws</pre>
<h3><a name="shared_dynamic_cast">shared_dynamic_cast</a></h3> <BLOCKQUOTE>
<pre>template&lt;typename T, typename U&gt; <P><B>Returns:</B> <code>r.expired()? shared_ptr&lt;T&gt;(): shared_ptr&lt;T&gt;(r)</code>.</P>
weak_ptr&lt;T&gt <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(weak_ptr&lt;U&gt; const &amp; r);</pre> <P><B>Throws:</B> nothing.</P>
<p>Perform a <b>dynamic_cast</b> on the stored pointer, returning another <b>weak_ptr</b>. </BLOCKQUOTE>
The resulting smart pointer will share its use count with the original pointer unless the result of the <P><EM>[The current implementation of <STRONG>make_shared</STRONG> can&nbsp;propagate
cast is 0. The only exception which may be thrown is <b>std::bad_alloc</b>, which may be thrown during the an exception&nbsp;thrown by the <STRONG>shared_ptr</STRONG> default
construction of the new <b>weak_ptr</b> if the result of the cast is 0. If an exception is thrown, the constructor, so it doesn't meet the stated requirements</EM><EM>. In a future
cast has no effect.</p> release, this default constructor will not throw.]</EM></P>
<hr>
<hr> <p>Revised 29 August 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->1 February 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p> Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears in
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. all copies. This document is provided "as is" without express or implied
Permission to copy, use, modify, sell and distribute this document is granted warranty, and with no claim as to its suitability for any purpose.</p>
provided this copyright notice appears in all copies. </A>
This document is provided &quot;as is&quot; without express or implied warranty, </body>
and with no claim as to its suitability for any purpose.</p>
</body>
</html> </html>