mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-11-02 16:51:59 +01:00
Compare commits
2 Commits
boost-1.28
...
boost-1.27
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e982a20e93 | ||
|
|
d1f2ed19d3 |
@@ -72,8 +72,6 @@
|
||||
// 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>
|
||||
|
||||
@@ -91,15 +89,18 @@ typedef long atomic_count;
|
||||
|
||||
}
|
||||
|
||||
#elif defined(BOOST_USE_ASM_ATOMIC_H)
|
||||
# include <boost/detail/atomic_count_linux.hpp>
|
||||
#elif defined(BOOST_AC_USE_PTHREADS)
|
||||
# include <boost/detail/atomic_count_pthreads.hpp>
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||
# include <boost/detail/atomic_count_win32.hpp>
|
||||
|
||||
#include <boost/detail/atomic_count_win32.hpp>
|
||||
|
||||
#elif defined(linux) || defined(__linux) || defined(__linux__)
|
||||
|
||||
#include <boost/detail/atomic_count_linux.hpp>
|
||||
|
||||
#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
|
||||
|
||||
// #warning Unrecognized platform, detail::atomic_count will not be thread safe
|
||||
|
||||
@@ -13,13 +13,7 @@
|
||||
//
|
||||
|
||||
//
|
||||
// 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.)
|
||||
// On Linux, atomic.h is usually located in /usr/include/asm
|
||||
//
|
||||
|
||||
#include <asm/atomic.h>
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
// inefficiencies. Example: a class with two atomic_count members
|
||||
// can get away with a single mutex.
|
||||
//
|
||||
// Users can detect this situation by checking BOOST_AC_USE_PTHREADS.
|
||||
// Define a macro so that users can detect the situation and optimize.
|
||||
//
|
||||
|
||||
#define BOOST_ATOMIC_COUNT_USES_PTHREADS
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
|
||||
@@ -16,14 +16,20 @@
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
|
||||
#include <boost/detail/winapi.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
@@ -34,12 +40,12 @@ public:
|
||||
|
||||
long operator++()
|
||||
{
|
||||
return winapi::InterlockedIncrement(&value_);
|
||||
return win32::InterlockedIncrement(&value_);
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
return winapi::InterlockedDecrement(&value_);
|
||||
return win32::InterlockedDecrement(&value_);
|
||||
}
|
||||
|
||||
operator long() const
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
#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 <implementation-defined> boost::detail::lightweight_mutex;
|
||||
//
|
||||
// boost::detail::lightweight_mutex meets the Mutex concept requirements
|
||||
// See 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.
|
||||
//
|
||||
|
||||
// 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 lightweight_mutex
|
||||
// for a platform that supports pthreads, be sure to test its performance
|
||||
// against the pthreads-based version using smart_ptr_timing_test.cpp and
|
||||
// smart_ptr_mt_test.cpp. Custom versions are usually not worth the trouble
|
||||
// _unless_ the performance gains are substantial.
|
||||
//
|
||||
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# include <boost/detail/lwm_nop.hpp>
|
||||
#elif defined(BOOST_USE_ASM_ATOMIC_H)
|
||||
# include <boost/detail/lwm_linux.hpp>
|
||||
#elif defined(BOOST_LWM_USE_CRITICAL_SECTION)
|
||||
# include <boost/detail/lwm_win32_cs.hpp>
|
||||
#elif defined(BOOST_LWM_USE_PTHREADS)
|
||||
# include <boost/detail/lwm_pthreads.hpp>
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||
# include <boost/detail/lwm_win32.hpp>
|
||||
#elif defined(__sgi)
|
||||
# include <boost/detail/lwm_irix.hpp>
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
# define BOOST_LWM_USE_PTHREADS
|
||||
# include <boost/detail/lwm_pthreads.hpp>
|
||||
#else
|
||||
# include <boost/detail/lwm_nop.hpp>
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
|
||||
@@ -1,78 +0,0 @@
|
||||
#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
|
||||
@@ -1,89 +0,0 @@
|
||||
#ifndef BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED
|
||||
|
||||
#if _MSC_VER >= 1020
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/lwm_linux.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
|
||||
//
|
||||
// This implementation uses <asm/atomic.h>. This is a kernel header;
|
||||
// using kernel headers in a user program may cause a number of problems,
|
||||
// and not all flavors of Linux provide the atomic instructions.
|
||||
//
|
||||
// This file is only provided because the performance of this implementation
|
||||
// is about 3.5 times higher than the pthreads version. Use at your own risk
|
||||
// (by defining BOOST_USE_ASM_ATOMIC_H.)
|
||||
//
|
||||
|
||||
#include <asm/atomic.h>
|
||||
#include <sched.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class lightweight_mutex
|
||||
{
|
||||
private:
|
||||
|
||||
atomic_t a_;
|
||||
|
||||
lightweight_mutex(lightweight_mutex const &);
|
||||
lightweight_mutex & operator=(lightweight_mutex const &);
|
||||
|
||||
public:
|
||||
|
||||
lightweight_mutex()
|
||||
{
|
||||
atomic_t a = ATOMIC_INIT(1);
|
||||
a_ = a;
|
||||
}
|
||||
|
||||
class scoped_lock;
|
||||
friend class scoped_lock;
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
private:
|
||||
|
||||
lightweight_mutex & m_;
|
||||
|
||||
scoped_lock(scoped_lock const &);
|
||||
scoped_lock & operator=(scoped_lock const &);
|
||||
|
||||
public:
|
||||
|
||||
explicit scoped_lock(lightweight_mutex & m): m_(m)
|
||||
{
|
||||
while( !atomic_dec_and_test(&m_.a_) )
|
||||
{
|
||||
atomic_inc(&m_.a_);
|
||||
sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
atomic_inc(&m_.a_);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED
|
||||
@@ -1,36 +0,0 @@
|
||||
#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
|
||||
@@ -1,78 +0,0 @@
|
||||
#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()
|
||||
{
|
||||
pthread_mutex_init(&m_, 0);
|
||||
}
|
||||
|
||||
~lightweight_mutex()
|
||||
{
|
||||
pthread_mutex_destroy(&m_);
|
||||
}
|
||||
|
||||
class scoped_lock;
|
||||
friend class scoped_lock;
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
private:
|
||||
|
||||
pthread_mutex_t & m_;
|
||||
|
||||
scoped_lock(scoped_lock const &);
|
||||
scoped_lock & operator=(scoped_lock const &);
|
||||
|
||||
public:
|
||||
|
||||
scoped_lock(lightweight_mutex & m): m_(m.m_)
|
||||
{
|
||||
pthread_mutex_lock(&m_);
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
pthread_mutex_unlock(&m_);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED
|
||||
@@ -1,81 +0,0 @@
|
||||
#ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED
|
||||
|
||||
#if _MSC_VER >= 1020
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/lwm_win32.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
|
||||
#include <boost/detail/winapi.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class lightweight_mutex
|
||||
{
|
||||
private:
|
||||
|
||||
long l_;
|
||||
|
||||
lightweight_mutex(lightweight_mutex const &);
|
||||
lightweight_mutex & operator=(lightweight_mutex const &);
|
||||
|
||||
public:
|
||||
|
||||
lightweight_mutex(): l_(0)
|
||||
{
|
||||
}
|
||||
|
||||
class scoped_lock;
|
||||
friend class scoped_lock;
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
private:
|
||||
|
||||
lightweight_mutex & m_;
|
||||
|
||||
scoped_lock(scoped_lock const &);
|
||||
scoped_lock & operator=(scoped_lock const &);
|
||||
|
||||
public:
|
||||
|
||||
explicit scoped_lock(lightweight_mutex & m): m_(m)
|
||||
{
|
||||
while( winapi::InterlockedExchange(&m_.l_, 1) )
|
||||
{
|
||||
winapi::Sleep(0);
|
||||
}
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
winapi::InterlockedExchange(&m_.l_, 0);
|
||||
|
||||
// Note: adding a Sleep(0) here will make
|
||||
// the mutex more fair and will increase the overall
|
||||
// performance of some applications substantially in
|
||||
// high contention situations, but will penalize the
|
||||
// low contention / single thread case up to 5x
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED
|
||||
@@ -1,78 +0,0 @@
|
||||
#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
|
||||
@@ -23,36 +23,19 @@
|
||||
#endif
|
||||
|
||||
#include <boost/checked_delete.hpp>
|
||||
#include <boost/detail/lightweight_mutex.hpp>
|
||||
|
||||
#include <functional> // for std::less
|
||||
#include <exception> // for std::exception
|
||||
#include <boost/detail/atomic_count.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
class use_count_is_zero: public std::exception
|
||||
namespace detail
|
||||
{
|
||||
public:
|
||||
|
||||
virtual char const * what() const throw()
|
||||
{
|
||||
return "use_count_is_zero";
|
||||
}
|
||||
};
|
||||
|
||||
class counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
typedef detail::lightweight_mutex mutex_type;
|
||||
|
||||
public:
|
||||
|
||||
counted_base():
|
||||
use_count_(0), weak_count_(0), self_deleter_(&self_delete)
|
||||
{
|
||||
}
|
||||
typedef atomic_count count_type;
|
||||
|
||||
// pre: initial_use_count <= initial_weak_count
|
||||
|
||||
@@ -78,35 +61,20 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void add_ref()
|
||||
void add_ref() // nothrow
|
||||
{
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
mutex_type::scoped_lock lock(mtx_);
|
||||
#endif
|
||||
if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero();
|
||||
++use_count_;
|
||||
++weak_count_;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
long new_use_count;
|
||||
long new_weak_count;
|
||||
|
||||
{
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
mutex_type::scoped_lock lock(mtx_);
|
||||
#endif
|
||||
new_use_count = --use_count_;
|
||||
new_weak_count = --weak_count_;
|
||||
}
|
||||
|
||||
if(new_use_count == 0)
|
||||
if(--use_count_ == 0)
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
|
||||
if(new_weak_count == 0)
|
||||
if(--weak_count_ == 0)
|
||||
{
|
||||
// not a direct 'delete this', because the inlined
|
||||
// release() may use a different heap manager
|
||||
@@ -116,24 +84,12 @@ public:
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
mutex_type::scoped_lock lock(mtx_);
|
||||
#endif
|
||||
++weak_count_;
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
long new_weak_count;
|
||||
|
||||
{
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
mutex_type::scoped_lock lock(mtx_);
|
||||
#endif
|
||||
new_weak_count = --weak_count_;
|
||||
}
|
||||
|
||||
if(new_weak_count == 0)
|
||||
if(--weak_count_ == 0)
|
||||
{
|
||||
self_deleter_(this);
|
||||
}
|
||||
@@ -141,9 +97,6 @@ public:
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
mutex_type::scoped_lock lock(mtx_);
|
||||
#endif
|
||||
return use_count_;
|
||||
}
|
||||
|
||||
@@ -159,27 +112,12 @@ private:
|
||||
|
||||
// inv: use_count_ <= weak_count_
|
||||
|
||||
long use_count_;
|
||||
long weak_count_;
|
||||
#ifdef BOOST_HAS_THREADS
|
||||
mutable mutex_type mtx_;
|
||||
#endif
|
||||
count_type use_count_;
|
||||
count_type weak_count_;
|
||||
|
||||
void (*self_deleter_) (counted_base *);
|
||||
};
|
||||
|
||||
inline void intrusive_ptr_add_ref(counted_base * p)
|
||||
{
|
||||
p->add_ref();
|
||||
}
|
||||
|
||||
inline void intrusive_ptr_release(counted_base * p)
|
||||
{
|
||||
p->release();
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class P, class D> class counted_base_impl: public counted_base
|
||||
{
|
||||
private:
|
||||
@@ -205,7 +143,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class weak_count;
|
||||
|
||||
class shared_count
|
||||
{
|
||||
@@ -215,20 +152,9 @@ private:
|
||||
|
||||
friend class weak_count;
|
||||
|
||||
template<class P, class D> shared_count(P, D, counted_base const *);
|
||||
|
||||
public:
|
||||
|
||||
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)
|
||||
template<class P, class D> shared_count(P p, D d): pi_(0)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -241,11 +167,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template<class P, class D> shared_count(P, D, counted_base * pi): pi_(pi)
|
||||
{
|
||||
pi_->add_ref();
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
|
||||
// auto_ptr<Y> is special cased to provide the strong guarantee
|
||||
@@ -268,8 +189,6 @@ public:
|
||||
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
|
||||
{
|
||||
counted_base * tmp = r.pi_;
|
||||
@@ -296,16 +215,6 @@ public:
|
||||
{
|
||||
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_);
|
||||
}
|
||||
};
|
||||
|
||||
class weak_count
|
||||
@@ -314,8 +223,6 @@ private:
|
||||
|
||||
counted_base * pi_;
|
||||
|
||||
friend class shared_count;
|
||||
|
||||
public:
|
||||
|
||||
weak_count(): pi_(new counted_base(0, 1)) // can throw
|
||||
@@ -368,23 +275,8 @@ public:
|
||||
{
|
||||
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 boost
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
#ifndef BOOST_DETAIL_WINAPI_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_WINAPI_HPP_INCLUDED
|
||||
|
||||
#if _MSC_VER >= 1020
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/winapi.hpp - a lightweight version of <windows.h>
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
namespace winapi
|
||||
{
|
||||
|
||||
typedef long long_type;
|
||||
typedef unsigned long dword_type;
|
||||
typedef void * handle_type;
|
||||
|
||||
#if defined(_WIN64)
|
||||
|
||||
typedef __int64 int_ptr_type;
|
||||
typedef unsigned __int64 uint_ptr_type;
|
||||
typedef __int64 long_ptr_type;
|
||||
typedef unsigned __int64 ulong_ptr_type;
|
||||
|
||||
#else
|
||||
|
||||
typedef int int_ptr_type;
|
||||
typedef unsigned int uint_ptr_type;
|
||||
typedef long long_ptr_type;
|
||||
typedef unsigned long ulong_ptr_type;
|
||||
|
||||
#endif
|
||||
|
||||
struct critical_section
|
||||
{
|
||||
struct critical_section_debug * DebugInfo;
|
||||
long_type LockCount;
|
||||
long_type RecursionCount;
|
||||
handle_type OwningThread;
|
||||
handle_type LockSemaphore;
|
||||
ulong_ptr_type SpinCount;
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllimport) long_type __stdcall InterlockedIncrement(long_type volatile *);
|
||||
extern "C" __declspec(dllimport) long_type __stdcall InterlockedDecrement(long_type volatile *);
|
||||
extern "C" __declspec(dllimport) long_type __stdcall InterlockedExchange(long_type volatile *, long_type);
|
||||
|
||||
extern "C" __declspec(dllimport) void __stdcall Sleep(dword_type);
|
||||
|
||||
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *);
|
||||
extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(critical_section *);
|
||||
extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(critical_section *);
|
||||
extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(critical_section *);
|
||||
|
||||
} // namespace winapi
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_WINAPI_HPP_INCLUDED
|
||||
@@ -1,202 +0,0 @@
|
||||
#ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED
|
||||
#define BOOST_INTRUSIVE_PTR_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// intrusive_ptr.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation.
|
||||
//
|
||||
|
||||
#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_);
|
||||
}
|
||||
|
||||
#ifdef 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_);
|
||||
}
|
||||
|
||||
#ifdef 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
|
||||
@@ -13,7 +13,6 @@
|
||||
//
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/checked_delete.hpp>
|
||||
#include <boost/config.hpp> // in case ptrdiff_t not in std
|
||||
#include <cstddef> // for std::ptrdiff_t
|
||||
|
||||
@@ -43,14 +42,17 @@ public:
|
||||
|
||||
~scoped_array() // never throws
|
||||
{
|
||||
checked_array_delete(ptr);
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
delete [] ptr;
|
||||
}
|
||||
|
||||
void reset(T * p = 0) // never throws
|
||||
{
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
|
||||
if (ptr != p)
|
||||
{
|
||||
checked_array_delete(ptr);
|
||||
delete [] ptr;
|
||||
ptr = p;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
//
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/checked_delete.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -42,14 +41,17 @@ public:
|
||||
|
||||
~scoped_ptr() // never throws
|
||||
{
|
||||
checked_delete(ptr);
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
void reset(T * p = 0) // never throws
|
||||
{
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
|
||||
if (ptr != p)
|
||||
{
|
||||
checked_delete(ptr);
|
||||
delete ptr;
|
||||
ptr = p;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <memory> // for std::auto_ptr
|
||||
#include <algorithm> // for std::swap
|
||||
#include <functional> // for std::less
|
||||
#include <typeinfo> // for std::bad_cast
|
||||
|
||||
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
|
||||
# pragma warning(push)
|
||||
@@ -44,7 +43,6 @@ namespace detail
|
||||
|
||||
struct static_cast_tag {};
|
||||
struct dynamic_cast_tag {};
|
||||
struct polymorphic_cast_tag {};
|
||||
|
||||
template<typename T> struct shared_ptr_traits
|
||||
{
|
||||
@@ -68,26 +66,20 @@ template<> struct shared_ptr_traits<void>
|
||||
//
|
||||
|
||||
template<typename T> class weak_ptr;
|
||||
template<typename T> class intrusive_ptr;
|
||||
|
||||
template<typename T> class shared_ptr
|
||||
{
|
||||
private:
|
||||
|
||||
// Borland 5.5.1 specific workarounds
|
||||
// typedef checked_deleter<T> deleter;
|
||||
typedef checked_deleter<T> deleter;
|
||||
typedef shared_ptr<T> this_type;
|
||||
|
||||
public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
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
|
||||
explicit shared_ptr(T * p = 0): px(p), pn(p, deleter())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -97,27 +89,17 @@ public:
|
||||
// shared_ptr will release p by calling d(p)
|
||||
//
|
||||
|
||||
template<typename Y, typename D> shared_ptr(Y * p, D d): px(p), pn(p, d)
|
||||
template<typename D> shared_ptr(T * p, D d): px(p), pn(p, d)
|
||||
{
|
||||
}
|
||||
|
||||
// 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>
|
||||
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>
|
||||
shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
|
||||
{
|
||||
@@ -128,16 +110,7 @@ public:
|
||||
{
|
||||
if (px == 0) // need to allocate new counter -- the cast failed
|
||||
{
|
||||
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)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
pn = detail::shared_count(static_cast<element_type *>(0), deleter());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,9 +121,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
|
||||
#endif
|
||||
|
||||
template<typename Y>
|
||||
shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
|
||||
@@ -160,8 +131,6 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
|
||||
template<typename Y>
|
||||
@@ -173,18 +142,13 @@ public:
|
||||
|
||||
#endif
|
||||
|
||||
void reset()
|
||||
void reset(T * p = 0)
|
||||
{
|
||||
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
|
||||
BOOST_ASSERT(p == 0 || p != px);
|
||||
this_type(p).swap(*this);
|
||||
}
|
||||
|
||||
template<typename Y, typename D> void reset(Y * p, D d)
|
||||
template<typename D> void reset(T * p, D d)
|
||||
{
|
||||
this_type(p, d).swap(*this);
|
||||
}
|
||||
@@ -216,20 +180,6 @@ public:
|
||||
return pn.use_count();
|
||||
}
|
||||
|
||||
// implicit conversion to "bool"
|
||||
|
||||
typedef long (this_type::*bool_type)() const;
|
||||
|
||||
operator bool_type() const // never throws
|
||||
{
|
||||
return px == 0? 0: &this_type::use_count;
|
||||
}
|
||||
|
||||
bool operator! () const // never throws
|
||||
{
|
||||
return px == 0;
|
||||
}
|
||||
|
||||
void swap(shared_ptr<T> & other) // never throws
|
||||
{
|
||||
std::swap(px, other.px);
|
||||
@@ -264,23 +214,12 @@ template<typename T, typename U> inline bool operator!=(shared_ptr<T> const & a,
|
||||
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)
|
||||
{
|
||||
return std::less<T*>()(a.get(), b.get());
|
||||
}
|
||||
|
||||
template<typename T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
|
||||
template<typename T> void swap(shared_ptr<T> & a, shared_ptr<T> & b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
@@ -295,17 +234,6 @@ template<typename T, typename U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U>
|
||||
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
|
||||
|
||||
template<typename T> inline T * get_pointer(shared_ptr<T> const & p)
|
||||
|
||||
@@ -16,10 +16,18 @@
|
||||
|
||||
#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
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4284) // odd return type for operator->
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -51,7 +59,19 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
|
||||
template<typename Y>
|
||||
weak_ptr(weak_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Y>
|
||||
weak_ptr(weak_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
|
||||
{
|
||||
if (px == 0) // need to allocate new counter -- the cast failed
|
||||
{
|
||||
pn = detail::weak_count();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Y>
|
||||
weak_ptr & operator=(weak_ptr<Y> const & r) // never throws
|
||||
@@ -69,39 +89,41 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void reset()
|
||||
{
|
||||
this_type().swap(*this);
|
||||
}
|
||||
|
||||
T * get() const // never throws; unsafe in multithreaded programs!
|
||||
T * get() const // never throws
|
||||
{
|
||||
return pn.use_count() == 0? 0: px;
|
||||
return 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
|
||||
{
|
||||
return pn.use_count();
|
||||
}
|
||||
|
||||
bool expired() const // never throws
|
||||
{
|
||||
return pn.use_count() == 0;
|
||||
}
|
||||
|
||||
void swap(this_type & other) // never throws
|
||||
void swap(weak_ptr<T> & other) // never throws
|
||||
{
|
||||
std::swap(px, other.px);
|
||||
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
|
||||
// to work in the absence of member template friends. (Matthew Langston)
|
||||
|
||||
@@ -110,7 +132,6 @@ public:
|
||||
private:
|
||||
|
||||
template<typename Y> friend class weak_ptr;
|
||||
template<typename Y> friend class shared_ptr;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -129,20 +150,9 @@ template<class T, class U> inline bool operator!=(weak_ptr<T> const & a, weak_pt
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
|
||||
|
||||
// Resolve the ambiguity between our op!= and the one in rel_ops
|
||||
|
||||
template<typename T> inline bool operator!=(weak_ptr<T> const & a, weak_ptr<T> const & b)
|
||||
{
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<class T> inline bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b)
|
||||
{
|
||||
return a.less(b);
|
||||
return std::less<T*>()(a.get(), b.get());
|
||||
}
|
||||
|
||||
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
|
||||
@@ -150,22 +160,21 @@ template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template<class T> shared_ptr<T> make_shared(weak_ptr<T> const & r) // never throws
|
||||
template<class T, class U> weak_ptr<T> shared_static_cast(weak_ptr<U> const & r)
|
||||
{
|
||||
// optimization: avoid throw overhead
|
||||
if(r.use_count() == 0)
|
||||
{
|
||||
return shared_ptr<T>();
|
||||
}
|
||||
return weak_ptr<T>(r, detail::static_cast_tag());
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return weak_ptr<T>(r, detail::dynamic_cast_tag());
|
||||
}
|
||||
|
||||
// get_pointer() enables boost::mem_fn to recognize weak_ptr
|
||||
|
||||
template<class T> inline T * get_pointer(weak_ptr<T> const & p)
|
||||
{
|
||||
return p.get();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// is complete where it counts - in the inplementation translation unit where
|
||||
// destruction is actually instantiated.
|
||||
|
||||
class example : private boost::noncopyable
|
||||
class example : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
example();
|
||||
|
||||
@@ -23,7 +23,7 @@ are supplied so that <b>shared_array</b> works with
|
||||
the standard library's associative containers.</p>
|
||||
|
||||
<p>Normally, a <b>shared_array</b> cannot correctly hold a pointer to a
|
||||
single dynamically allocated object. See <a href="shared_ptr.htm"><b>shared_ptr</b></a>
|
||||
dynamically allocated array. See <a href="shared_ptr.htm"><b>shared_ptr</b></a>
|
||||
for that usage.</p>
|
||||
|
||||
<p>Because the implementation uses reference counting, <b>shared_array</b> will not work
|
||||
@@ -54,10 +54,10 @@ pointed to. <b>T</b> must meet the smart pointer
|
||||
|
||||
<a href="#constructors">shared_array</a>(shared_array const & r); // never throws
|
||||
|
||||
shared_array & <a href="#assignment">operator=</a>(shared_array const & r); // never throws
|
||||
shared_array & <a href="#assignment">operator=</a>(shared_array const & r); // never throws
|
||||
|
||||
void <a href="#reset">reset</a>(T * p = 0);
|
||||
template<typename D> void <a href="#reset">reset</a>(T * p, D d);
|
||||
void <a href="#reset">reset</a>(T * p = 0); // never throws
|
||||
template<typename D> void <a href="#reset">reset</a>(T * p, D d); // never throws
|
||||
|
||||
T & <a href="#indexing">operator[]</a>(std::ptrdiff_t i) const() const; // never throws
|
||||
T * <a href="#get">get</a>() const; // never throws
|
||||
@@ -69,11 +69,11 @@ pointed to. <b>T</b> must meet the smart pointer
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool <a href="#comparison">operator==</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
bool <a href="#operator==">operator==</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
template<typename T>
|
||||
bool <a href="#comparison">operator!=</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
bool <a href="#operator!=">operator!=</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
template<typename T>
|
||||
bool <a href="#comparison">operator<</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
bool <a href="#operator<">operator<</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
|
||||
template<typename T> void <a href="#free-swap">swap</a>(shared_array<T> & a, shared_array<T> & b); // never throws
|
||||
|
||||
@@ -186,11 +186,11 @@ See the smart pointer
|
||||
|
||||
<h3><a name="comparison">comparison</a></h3>
|
||||
<pre>template<typename T>
|
||||
bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
bool <a href="#operator==">operator==</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
template<typename T>
|
||||
bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
bool <a href="#operator!=">operator!=</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
template<typename T>
|
||||
bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws</pre>
|
||||
bool <a href="#operator<">operator<</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws</pre>
|
||||
<p>Compares the stored pointers of the two smart pointers.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
@@ -211,7 +211,7 @@ Provided as an aid to generic programming.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->8 February 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
|
||||
<p>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
|
||||
|
||||
750
shared_ptr.htm
750
shared_ptr.htm
@@ -1,456 +1,356 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>shared_ptr</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgColor="#ffffff">
|
||||
<h1><IMG height="86" alt="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="#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. Use <A href="weak_ptr.htm">weak_ptr</A>
|
||||
to "break cycles."</p>
|
||||
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
|
||||
to. <STRONG>shared_ptr</STRONG> and most of its member functions place no
|
||||
requirements on <STRONG>T</STRONG>; it is allowed to be an incomplete type, or <STRONG>
|
||||
void</STRONG>. Member functions that do place additional requirements (<A href="#constructors">constructors</A>,
|
||||
<A href="#reset">reset</A>) are explicitly documented below.</p>
|
||||
<P><STRONG>shared_ptr<T></STRONG> can be implicitly converted to <STRONG>shared_ptr<U></STRONG>
|
||||
whenever <STRONG>T*</STRONG> can be implicitly converted to <STRONG>U*</STRONG>.
|
||||
In particular, <STRONG>shared_ptr<T></STRONG> is implicitly convertible
|
||||
to <STRONG>shared_ptr<T const></STRONG>, to <STRONG>shared_ptr<U></STRONG>
|
||||
where <STRONG>U</STRONG> is an accessible base of <STRONG>T</STRONG>, and to <STRONG>
|
||||
shared_ptr<void></STRONG>.</P>
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
<pre>namespace boost {
|
||||
|
||||
class use_count_is_zero: public std::exception;
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>shared_ptr</title>
|
||||
</head>
|
||||
|
||||
template<typename T> class <A href="weak_ptr.htm" >weak_ptr</A>;
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">shared_ptr class template</h1>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#functions">Free Functions</a><br>
|
||||
<a href="#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<typename T> class shared_ptr {
|
||||
|
||||
public:
|
||||
typedef T <a href="#element_type">element_type</a>;
|
||||
|
||||
typedef T <A href="#element_type" >element_type</A>;
|
||||
explicit <a href="#constructors">shared_ptr</a>(T * p = 0);
|
||||
template<typename D> <a href="#constructors">shared_ptr</a>(T * p, D d);
|
||||
<a href="#destructor">~shared_ptr</a>(); // never throws
|
||||
|
||||
<A href="#constructors" >shared_ptr</A> ();
|
||||
template<typename Y> explicit <A href="#constructors" >shared_ptr</A> (Y * p);
|
||||
template<typename Y, typename D> <A href="#constructors" >shared_ptr</A>(Y * p, D d);
|
||||
<A href="#destructor" >~shared_ptr</A>(); // never throws
|
||||
<a href="#constructors">shared_ptr</a>(shared_ptr const & r); // never throws
|
||||
template<typename Y> <a href="#constructors">shared_ptr</a>(shared_ptr<Y> const & r); // never throws
|
||||
template<typename Y> <a href="#constructors">shared_ptr</a>(std::auto_ptr<Y> & r);
|
||||
|
||||
<A href="#constructors" >shared_ptr</A>(shared_ptr const & r); // never throws
|
||||
template<typename Y> <A href="#constructors" >shared_ptr</A>(shared_ptr<Y> const & r); // never throws
|
||||
explicit <A href="#constructors" >shared_ptr</A>(<A href="weak_ptr.htm" >weak_ptr</A> const & r);
|
||||
template<typename Y> <A href="#constructors" >shared_ptr</A>(std::auto_ptr<Y> & r);
|
||||
shared_ptr & <a href="#assignment">operator=</a>(shared_ptr const & r); // never throws
|
||||
template<typename Y> shared_ptr & <a href="#assignment">operator=</a>(shared_ptr<Y> const & r); // never throws
|
||||
template<typename Y> shared_ptr & <a href="#assignment">operator=</a>(std::auto_ptr<Y> & r);
|
||||
|
||||
shared_ptr & <A href="#assignment" >operator=</A>(shared_ptr const & r); // never throws
|
||||
template<typename Y> shared_ptr & <A href="#assignment" >operator=</A>(shared_ptr<Y> const & r); // never throws
|
||||
template<typename Y> shared_ptr & <A href="#assignment" >operator=</A>(std::auto_ptr<Y> & r);
|
||||
void <a href="#reset">reset</a>(T * p = 0); // never throws
|
||||
template<typename D> void <a href="#reset">reset</a>(T * p, D d); // never throws
|
||||
|
||||
void <A href="#reset" >reset</A> ();
|
||||
template<typename Y> void <A href="#reset" >reset</A> (Y * p);
|
||||
template<typename Y> template<typename D> void <A href="#reset" >reset</A>(Y * p, D d);
|
||||
T & <a href="#indirection">operator*</a>() const; // never throws
|
||||
T * <a href="#indirection">operator-></a>() const; // never throws
|
||||
T * <a href="#get">get</a>() const; // never throws
|
||||
|
||||
T & <A href="#indirection" >operator*</A>() const; // never throws
|
||||
T * <A href="#indirection" >operator-></A>() const; // never throws
|
||||
T * <A href="#get" >get</A>() const; // never throws
|
||||
bool <a href="#unique">unique</a>() const; // never throws
|
||||
long <a href="#use_count">use_count</a>() const; // 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>implementation-defined-type</i></a> () const; // never throws
|
||||
|
||||
void <A href="#swap" >swap</A>(shared_ptr<T> & b); // never throws
|
||||
void <a href="#swap">swap</a>(shared_ptr<T> & b); // never throws
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
bool <A href="#comparison" >operator==</A>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
bool <a href="#operator==">operator==</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <A href="#comparison" >operator!=</A>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
template<typename T>
|
||||
bool <A href="#comparison" >operator<</A>(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws
|
||||
bool <a href="#operator!=">operator!=</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator<">operator<</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
|
||||
template<typename T> void <A href="#free-swap" >swap</A>(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
|
||||
template<typename T> void <a href="#free-swap">swap</a>(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
|
||||
|
||||
template<typename T, typename U>
|
||||
shared_ptr<T> <A href="#shared_static_cast" >shared_static_cast</A>(shared_ptr<U> const & r); // never throws
|
||||
shared_ptr<T> <a href="#shared_static_cast">shared_static_cast</a>(shared_ptr<U> const & r); // never throws
|
||||
template<typename T, typename U>
|
||||
shared_ptr<T> <A href="#shared_dynamic_cast" >shared_dynamic_cast</A>(shared_ptr<U> const & r);
|
||||
template<typename T, typename U>
|
||||
shared_ptr<T> <A href="#shared_polymorphic_cast" >shared_polymorphic_cast</A>(shared_ptr<U> const & r);
|
||||
template<typename T, typename U>
|
||||
shared_ptr<T> <A href="#shared_polymorphic_downcast" >shared_polymorphic_downcast</A>(shared_ptr<U> const & r); // never throws
|
||||
shared_ptr<T> <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(shared_ptr<U> const & r);
|
||||
|
||||
}</pre>
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<blockquote>
|
||||
<p>Provides the type of the template parameter T.</p>
|
||||
</blockquote>
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
<pre>shared_ptr();</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>
|
||||
<pre>template<typename Y> explicit shared_ptr(Y * p);</pre>
|
||||
<blockquote>
|
||||
<p><b>Requirements:</b> <b>p</b> must be convertible to <b>T *</b>. <STRONG>Y</STRONG>
|
||||
must be a complete type. The expression <code>delete p</code> must be
|
||||
well-formed, must not invoke undefined behavior, and must not throw exceptions.
|
||||
</p>
|
||||
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, 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>
|
||||
<pre>template<typename Y, typename D> shared_ptr(Y * p, D d);</pre>
|
||||
<blockquote>
|
||||
<p><b>Requirements:</b> <B>p</B> must be convertible to <B>T *</B>. The copy
|
||||
constructor and destructor of <b>D</b> must not throw. The expression <code>d(p)</code>
|
||||
must be well-formed, must not invoke undefined behavior, and must not throw
|
||||
exceptions.
|
||||
</p>
|
||||
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, 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>,
|
||||
<code>d(p)</code> is invoked.</p>
|
||||
</blockquote>
|
||||
<pre>shared_ptr(shared_ptr const & r); // never throws
|
||||
template<typename Y> shared_ptr(shared_ptr<Y> const & 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>
|
||||
<pre>explicit shared_ptr(<A href="weak_ptr.htm" >weak_ptr</A> const & 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>
|
||||
<pre>template<typename Y> shared_ptr(std::auto_ptr<Y> & r);</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Constructs a <B>shared_ptr</B>, as if by storing a copy of <STRONG>r.release()</STRONG>.</P>
|
||||
<P><B>Postconditions:</B> <A href="#use_count">use count</A> for all copies is
|
||||
increased by one.</P>
|
||||
<P><B>Throws:</B> <B>std::bad_alloc</B>.</P>
|
||||
<P><B>Exception safety:</B> If an exception is thrown, the constructor has no
|
||||
effect.</P>
|
||||
</BLOCKQUOTE>
|
||||
<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 & operator=(shared_ptr const & r); // never throws
|
||||
template<typename Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
|
||||
template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r);</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Equivalent to <code>shared_ptr(r).swap(*this)</code>.</P>
|
||||
<P><B>Notes:</B> The implementation is free to meet the effects (and the implied
|
||||
guarantees) via different means, without creating a temporary. In particular,
|
||||
in the example:</P>
|
||||
<pre>
|
||||
shared_ptr<int> p(new int);
|
||||
shared_ptr<void> q(p);
|
||||
p = p;
|
||||
q = p;
|
||||
</pre>
|
||||
<p>both assignments may be no-ops.</p>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
<pre>void reset();</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Equivalent to <code>shared_ptr().swap(*this)</code>.</P>
|
||||
</BLOCKQUOTE>
|
||||
<pre>template<typename Y> void reset(Y * p);</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p).swap(*this)</code>.</P>
|
||||
</BLOCKQUOTE>
|
||||
<pre>template<typename Y, typename D> void reset(Y * p, D d);</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p, d).swap(*this)</code>.</P>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="indirection">indirection</a></h3>
|
||||
<pre>T & operator*() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requirements:</b> The stored pointer must not be 0.</p>
|
||||
<p><b>Returns:</b> a reference to the object pointed to by the stored pointer.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>T * operator->() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requirements:</b> The stored pointer must not be 0.</p>
|
||||
<p><b>Returns:</b> the stored pointer.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3><a name="get">get</a></h3>
|
||||
<pre>T * get() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> the stored pointer.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3><a name="unique">unique</a></h3>
|
||||
<pre>bool unique() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>use_count() == 1</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> <code>unique()</code> may be faster than <code>use_count()</code>.</P>
|
||||
</blockquote>
|
||||
<h3><a name="use_count">use_count</a></h3>
|
||||
<pre>long use_count() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> the number of <b>shared_ptr</b> objects sharing ownership of the
|
||||
stored pointer.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> <code>use_count()</code> is not necessarily efficient. Use only
|
||||
for debugging and testing purposes, not for production code.</P>
|
||||
</blockquote>
|
||||
<h3><a name="conversions">conversions</a></h3>
|
||||
<pre>operator <i>implementation-defined-type</i> () const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> an implementation defined value that, when used in boolean
|
||||
contexts, is equivalent to <code>get() != 0</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> This conversion operator allows <b>shared_ptr</b> objects to be
|
||||
used in boolean contexts, like <code>if (p && p->valid()) {}</code>.
|
||||
The actual target type is typically a pointer to a member function, avloiding
|
||||
many of the implicit conversion pitfalls.</P>
|
||||
</blockquote>
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(shared_ptr & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
<h3><a name="comparison">comparison</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>template<typename T, typename U>
|
||||
bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>a.get() != b.get()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>template<typename T>
|
||||
bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> an implementation-defined value such that <b>operator<</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>
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<typename T>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<p>Provides the type of the stored pointer.</p>
|
||||
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
|
||||
<pre>explicit shared_ptr(T * p = 0);</pre>
|
||||
<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<typename D> shared_ptr(T * p, D d);</pre>
|
||||
<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 & r); // never throws
|
||||
template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws
|
||||
template<typename Y> shared_ptr(std::auto_ptr<Y> & 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>
|
||||
|
||||
<pre>~shared_ptr(); // never throws</pre>
|
||||
<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>
|
||||
|
||||
<pre>shared_ptr & <a href="#assignment">operator=</a>(shared_ptr const & r); // never throws
|
||||
template<typename Y> shared_ptr & <a href="#assignment">operator=</a>(shared_ptr<Y> const & r); // never throws
|
||||
template<typename Y> shared_ptr & <a href="#assignment">operator=</a>(std::auto_ptr<Y> & 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>
|
||||
|
||||
<pre>void reset(T * p = 0);</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>. If
|
||||
an exception is thrown, <b>delete p</b> is called.</p>
|
||||
|
||||
<pre>template<typename D> void reset(T * p, D d);</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.
|
||||
<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>
|
||||
<pre>T & operator*() const; // never throws</pre>
|
||||
<p>Returns a reference to the object pointed to by the stored pointer.
|
||||
Behavior is undefined if the stored pointer is 0.</p>
|
||||
<pre>T * operator->() const; // never throws</pre>
|
||||
<p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
|
||||
|
||||
<h3><a name="get">get</a></h3>
|
||||
<pre>T * get() const; // never throws</pre>
|
||||
<p>Returns the stored pointer.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="unique">unique</a></h3>
|
||||
<pre>bool unique() const; // never throws</pre>
|
||||
<p>Returns true if no other <b>shared_ptr</b> is sharing ownership of
|
||||
the stored pointer, false otherwise.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="use_count">use_count</a></h3>
|
||||
<pre>long use_count() const; // never throws</pre>
|
||||
<p>Returns the number of <b>shared_ptr</b> objects sharing ownership of the
|
||||
stored pointer.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
<p>Because <b>use_count</b> is not necessarily efficient to implement for
|
||||
implementations of <b>shared_ptr</b> that do not use an explicit reference
|
||||
count, it might be removed from some future version. Thus it should
|
||||
be used for debugging purposes only, and not production code.</p>
|
||||
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(shared_ptr & b); // never throws</pre>
|
||||
<p>Exchanges the contents of the two smart pointers.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
|
||||
<h3><a name="comparison">comparison</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
bool <a href="#operator==">operator==</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator!=">operator!=</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator<">operator<</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre>
|
||||
<p>Compares the stored pointers of the two smart pointers.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
<p>The <b>operator<</b> overload is provided to define an ordering so that <b>shared_ptr</b>
|
||||
objects can be used in associative containers such as <b>std::map</b>.
|
||||
The implementation uses <b>std::less<T *></b> to perform the
|
||||
comparison. This ensures that the comparison is handled correctly, since the
|
||||
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel]
|
||||
paragraph 2) but <b>std::less<></b> on pointers is well-defined (20.3.3 [lib.comparisons]
|
||||
paragraph 8).</p>
|
||||
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<typename T>
|
||||
void swap(shared_ptr<T> & a, shared_ptr<T> & b) // never throws</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
|
||||
<P><B>Throws:</B> nothing.</P>
|
||||
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
|
||||
generic programming.</P>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="shared_static_cast">shared_static_cast</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><STRONG>Requires:</STRONG> The expression <code>static_cast<T*>(r.get())</code>
|
||||
must be well-formed.</P>
|
||||
<P><B>Returns:</B> A <STRONG>shared_ptr<T></STRONG> object that stores a copy
|
||||
of <code>static_cast<T*>(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<T>(static_cast<T*>(r.get()))</code></p>
|
||||
<p>will eventually result in undefined behavior, attempting to delete the same
|
||||
object twice.</p>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="shared_dynamic_cast">shared_dynamic_cast</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r);</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><STRONG>Requires:</STRONG> The expression <CODE>dynamic_cast<T*>(r.get())</CODE>
|
||||
must be well-formed and its behavior defined.</P>
|
||||
<P><B>Returns:</B></P>
|
||||
<UL>
|
||||
<LI>
|
||||
When <CODE>dynamic_cast<T*>(r.get())</CODE> returns a nonzero value, a <STRONG>
|
||||
shared_ptr<T></STRONG> object that stores a copy of it and shares
|
||||
ownership with <STRONG>r</STRONG>;
|
||||
<LI>
|
||||
Otherwise, a default-constructed <STRONG>shared_ptr<T></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<T>(dynamic_cast<T*>(r.get()))</CODE></P>
|
||||
<P>will eventually result in undefined behavior, attempting to delete the same
|
||||
object twice.</P>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="shared_polymorphic_cast">shared_polymorphic_cast</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r);</pre>
|
||||
<BLOCKQUOTE>
|
||||
<p><STRONG>Requires:</STRONG> The expression <CODE><A href="../conversion/cast.htm#Polymorphic_cast">
|
||||
polymorphic_cast</A><T*>(r.get())</CODE> must be well-formed and
|
||||
its behavior defined.</p>
|
||||
<P><B>Returns:</B> A <STRONG>shared_ptr<T></STRONG> object that stores a copy
|
||||
of <CODE><A href="../conversion/cast.htm#Polymorphic_cast">polymorphic_cast</A><T*>(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<typename T, typename U>
|
||||
shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws</pre>
|
||||
<BLOCKQUOTE>
|
||||
<p><STRONG>Requires:</STRONG> The expression <CODE><A href="../conversion/cast.htm#Polymorphic_cast">
|
||||
polymorphic_downcast</A><T*>(r.get())</CODE> must be well-formed
|
||||
and its behavior defined.</p>
|
||||
<P><B>Returns:</B> A <STRONG>shared_ptr<T></STRONG> object that stores a copy
|
||||
of <CODE><A href="../conversion/cast.htm#Polymorphic_cast">polymorphic_downcast</A><T*>(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<></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> There are several variations of shared pointers, with different
|
||||
tradeoffs; why does the smart pointer library supply only a single
|
||||
implementation? It would be useful to be able to experiment with each type so
|
||||
as to find the most suitable for the job at hand?<BR>
|
||||
<b>A.</b> An important goal of <STRONG>shared_ptr</STRONG> is to provide a
|
||||
standard shared-ownership pointer. Having a single pointer type is important
|
||||
for stable library interfaces, since different shared pointers typically cannot
|
||||
interoperate, i.e. a reference counted pointer (used by library A) cannot share
|
||||
ownership with a linked pointer (used by library B.)</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>
|
||||
<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> I am not convinced. Default parameters can be used where appropriate to
|
||||
hide the complexity. Again, why not policies?<BR>
|
||||
<B>A.</B> Template parameters affect the type. See the answer to the first
|
||||
question above.</P>
|
||||
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> use a linked list implementation?<br>
|
||||
<b>A.</b> A linked list implementation does not offer enough advantages to
|
||||
offset the added cost of an extra pointer. See <A href="smarttests.htm">timings</A>
|
||||
page. In addition, it is expensive to make a linked list implementation thread
|
||||
safe.</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<int> a(new int);
|
||||
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
|
||||
Provided as an aid to generic programming.</p>
|
||||
|
||||
<h3><a name="shared_static_cast">shared_static_cast</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
shared_ptr<T> <a href="#shared_static_cast">shared_static_cast</a>(shared_ptr<U> const & 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<T>(static_cast<T*>(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<typename T, typename U>
|
||||
shared_ptr<T> <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(shared_ptr<U> const & 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<T>(dynamic_cast<T*>(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<></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<int> a(new int);
|
||||
shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
|
||||
|
||||
int * p = a.release();
|
||||
|
||||
// Who owns p now? b will still call delete on it in its destructor.</pre>
|
||||
</blockquote>
|
||||
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> provide (your pet feature here)?<br>
|
||||
<b>A.</b> Because (your pet feature here) would mandate a reference counted
|
||||
implementation or a linked list implementation, or some other specific
|
||||
implementation. This is not the intent.</p>
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->
|
||||
04 May 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
|
||||
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||
Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and
|
||||
distribute this document is granted provided this copyright notice appears in
|
||||
all copies. This document is provided "as is" without express or implied
|
||||
warranty, and with no claim as to its suitability for any purpose.</p>
|
||||
</body>
|
||||
// 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>
|
||||
<b>A.</b> Because (your pet feature here) would mandate a reference counted
|
||||
implementation or a linked list implementation, or some other specific implementation.
|
||||
This is not the intent.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->1 February 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
|
||||
|
||||
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||
Permission to copy, use, modify, sell and distribute this document is granted
|
||||
provided this copyright notice appears in all copies.
|
||||
This document is provided "as is" without express or implied warranty,
|
||||
and with no claim as to its suitability for any purpose.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
#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>
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include <boost/test/test_tools.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 test_main( int, char ** )
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__)
|
||||
#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
|
||||
@@ -8,7 +8,7 @@
|
||||
//
|
||||
// shared_ptr_test.cpp - a test for shared_ptr.hpp and weak_ptr.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
@@ -40,17 +40,12 @@ struct X
|
||||
std::cout << "X(" << this << ")::X()\n";
|
||||
}
|
||||
|
||||
~X() // virtual destructor deliberately omitted
|
||||
virtual ~X()
|
||||
{
|
||||
--cnt;
|
||||
std::cout << "X(" << this << ")::~X()\n";
|
||||
}
|
||||
|
||||
virtual int id() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
X(X const &);
|
||||
@@ -71,11 +66,6 @@ struct Y: public X
|
||||
std::cout << "Y(" << this << ")::~Y()\n";
|
||||
}
|
||||
|
||||
virtual int id() const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Y(Y const &);
|
||||
@@ -96,92 +86,6 @@ void release_object(int * p)
|
||||
std::cout << "release_object()\n";
|
||||
}
|
||||
|
||||
class Z: public virtual boost::counted_base
|
||||
{
|
||||
public:
|
||||
|
||||
Z()
|
||||
{
|
||||
++cnt;
|
||||
std::cout << "Z(" << this << ")::Z()\n";
|
||||
}
|
||||
|
||||
~Z()
|
||||
{
|
||||
--cnt;
|
||||
std::cout << "Z(" << this << ")::~Z()\n";
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Z(Z const &);
|
||||
Z & operator= (Z const &);
|
||||
};
|
||||
|
||||
template<class T> void test_is_X(boost::shared_ptr<T> const & p)
|
||||
{
|
||||
BOOST_TEST(p->id() == 1);
|
||||
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)
|
||||
{
|
||||
BOOST_TEST(p);
|
||||
BOOST_TEST(p.get() != 0);
|
||||
}
|
||||
|
||||
int test_main(int, char * [])
|
||||
{
|
||||
using namespace boost;
|
||||
@@ -190,37 +94,16 @@ int test_main(int, char * [])
|
||||
shared_ptr<X> p(new Y);
|
||||
shared_ptr<X> p2(new X);
|
||||
|
||||
test_is_nonzero(p);
|
||||
test_is_nonzero(p2);
|
||||
test_is_Y(p);
|
||||
test_is_X(p2);
|
||||
test_ne(p, p2);
|
||||
|
||||
{
|
||||
shared_ptr<X> q(p);
|
||||
test_eq(p, q);
|
||||
}
|
||||
|
||||
shared_ptr<Y> p3 = shared_dynamic_cast<Y>(p);
|
||||
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(p2.use_count() == 1);
|
||||
BOOST_TEST(p3.use_count() == 2);
|
||||
BOOST_TEST(p4.use_count() == 1);
|
||||
|
||||
test_is_Y(p3);
|
||||
test_eq2(p, p3);
|
||||
test_ne2(p2, p4);
|
||||
|
||||
shared_ptr<void> p5(p);
|
||||
|
||||
test_is_nonzero(p5);
|
||||
test_eq2(p, p5);
|
||||
|
||||
std::cout << "--\n";
|
||||
|
||||
p.reset();
|
||||
@@ -228,11 +111,6 @@ int test_main(int, char * [])
|
||||
p3.reset();
|
||||
p4.reset();
|
||||
|
||||
test_is_zero(p);
|
||||
test_is_zero(p2);
|
||||
test_is_zero(p3);
|
||||
test_is_zero(p4);
|
||||
|
||||
std::cout << "--\n";
|
||||
|
||||
BOOST_TEST(p5.use_count() == 1);
|
||||
@@ -242,70 +120,27 @@ int test_main(int, char * [])
|
||||
BOOST_TEST(wp1.use_count() == 0);
|
||||
BOOST_TEST(wp1.get() == 0);
|
||||
|
||||
try
|
||||
{
|
||||
shared_ptr<X> sp1(wp1);
|
||||
BOOST_ERROR("shared_ptr<X> sp1(wp1) failed to throw");
|
||||
}
|
||||
catch(boost::use_count_is_zero const &)
|
||||
{
|
||||
}
|
||||
|
||||
test_is_zero(boost::make_shared(wp1));
|
||||
|
||||
weak_ptr<X> wp2 = shared_static_cast<X>(p5);
|
||||
|
||||
BOOST_TEST(wp2.use_count() == 1);
|
||||
BOOST_TEST(wp2.get() != 0);
|
||||
test_is_Y(wp2);
|
||||
test_ne(wp1, 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));
|
||||
weak_ptr<Y> wp3 = shared_dynamic_cast<Y>(wp2);
|
||||
|
||||
BOOST_TEST(wp3.use_count() == 1);
|
||||
BOOST_TEST(wp3.get() != 0);
|
||||
test_eq2(wp2, wp3);
|
||||
BOOST_TEST(wp2 == wp3);
|
||||
|
||||
weak_ptr<X> wp4(wp3);
|
||||
|
||||
BOOST_TEST(wp4.use_count() == 1);
|
||||
BOOST_TEST(wp4.get() != 0);
|
||||
test_eq(wp2, wp4);
|
||||
|
||||
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 = wp3;
|
||||
wp1 = wp2;
|
||||
|
||||
BOOST_TEST(wp1.use_count() == 1);
|
||||
BOOST_TEST(wp1.get() != 0);
|
||||
test_eq(wp1, wp2);
|
||||
|
||||
weak_ptr<X> wp5;
|
||||
|
||||
bool b1 = wp1 < wp5;
|
||||
bool b2 = wp5 < wp1;
|
||||
BOOST_TEST(wp1 == wp2);
|
||||
|
||||
p5.reset();
|
||||
|
||||
@@ -318,23 +153,7 @@ int test_main(int, char * [])
|
||||
BOOST_TEST(wp3.use_count() == 0);
|
||||
BOOST_TEST(wp3.get() == 0);
|
||||
|
||||
// Test operator< stability for std::set< weak_ptr<> >
|
||||
// Thanks to Joe Gottman for pointing this out
|
||||
|
||||
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());
|
||||
}
|
||||
shared_ptr<int> p6(get_object(), release_object);
|
||||
}
|
||||
|
||||
BOOST_TEST(cnt == 0);
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
#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';
|
||||
}
|
||||
@@ -138,13 +138,15 @@ destruction. Refinement evolved in discussions including Dave Abrahams,
|
||||
Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus,
|
||||
Shankar Sai, and others.</p>
|
||||
|
||||
<p>November 1999. Darin Adler provided <b>operator ==</b>, <b>operator !=</b>, and <b>std::swap</b>
|
||||
and <b>std::less</b> specializations for shared types.</p>
|
||||
<p>November 1999. Darin Adler provided operator ==, operator !=, and std::swap
|
||||
and std::less specializations for shared types.</p>
|
||||
|
||||
<p>September 1999. Luis Coelho provided <b>shared_ptr::swap</b> and <b>shared_array::swap</b></p>
|
||||
<p>September 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap</p>
|
||||
|
||||
<p>May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams
|
||||
made a number of suggestions resulting in numerous improvements.</p>
|
||||
made a number of suggestions resulting in numerous improvements. See the
|
||||
revision history in <a href="../../boost/smart_ptr.hpp"><b>smart_ptr.hpp</b></a>
|
||||
for the specific changes made as a result of their constructive criticism.</p>
|
||||
|
||||
<p>October 1998. In 1994 Greg Colvin proposed to the C++ Standards Committee
|
||||
classes named <b>auto_ptr</b> and <b>counted_ptr</b> which
|
||||
@@ -189,6 +191,8 @@ preferred, and that was also experimented with.</p>
|
||||
discourage users", and in the end we choose to supply only the direct
|
||||
implementation.</p>
|
||||
|
||||
<p>See the Revision History section of the header for further contributors.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan
|
||||
|
||||
@@ -88,7 +88,7 @@ Incomplete * check_incomplete( shared_ptr<Incomplete>& incomplete,
|
||||
|
||||
// This isn't a very systematic test; it just hits some of the basics.
|
||||
|
||||
int test_main( int, char *[] ) {
|
||||
int test_main( int, char ** ) {
|
||||
|
||||
BOOST_TEST( UDT_use_count == 0 ); // reality check
|
||||
|
||||
|
||||
383
weak_ptr.htm
383
weak_ptr.htm
@@ -1,66 +1,42 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>weak_ptr</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body 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 pointer to an object that's already
|
||||
managed by a <b>shared_ptr</b>. When the object last <b>shared_ptr</b> to the
|
||||
object goes away and the object is deleted, all <b>weak_ptr</b> objects have
|
||||
their stored pointers set to 0.</p>
|
||||
<p>Every <b>weak_ptr</b> meets the <b>CopyConstructible</b> and <b>Assignable</b> requirements
|
||||
of the C++ Standard Library, and so can be used in standard library containers.
|
||||
Comparison operators are supplied so that <b>weak_ptr</b> works with the
|
||||
standard library's associative containers.</p>
|
||||
<p>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 <STRONG>shared_ptr</STRONG>, <STRONG>weak_ptr</STRONG> provides
|
||||
a very limited subset of operations since accessing its stored pointer is
|
||||
unsafe in multithreaded programs (that is, it may invoke undefined
|
||||
behavior.) Consider, for example, this innocent piece of code:</P>
|
||||
<pre>
|
||||
shared_ptr<int> p(new int(5));
|
||||
weak_ptr<int> q(p);
|
||||
|
||||
// some time later
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>weak_ptr</title>
|
||||
</head>
|
||||
|
||||
if(int * r = q.get())
|
||||
{
|
||||
// use *r
|
||||
}
|
||||
</pre>
|
||||
<P>Imagine that after the <STRONG>if</STRONG>, but immediately before <STRONG>r</STRONG>
|
||||
is used, another thread executes the statement <code>p.reset()</code>. Now <STRONG>r</STRONG>
|
||||
is a dangling pointer.</P>
|
||||
<P>The solution to this problem is to create a temporary <STRONG>shared_ptr</STRONG>
|
||||
from <STRONG>q</STRONG>:</P>
|
||||
<pre>
|
||||
shared_ptr<int> p(new int(5));
|
||||
weak_ptr<int> q(p);
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
// some time later
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">weak_ptr class template</h1>
|
||||
|
||||
if(shared_ptr<int> r = <a href="#make_shared">make_shared</a>(q))
|
||||
{
|
||||
// use *r
|
||||
}
|
||||
</pre>
|
||||
<p>Now <STRONG>r</STRONG> holds a reference to the object that was pointed by <STRONG>q</STRONG>.
|
||||
Even if <code>p.reset()</code> is executed in another thread, the object will
|
||||
stay alive until <STRONG>r</STRONG> goes out of scope (or is reset.)</p>
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
<pre>namespace boost {
|
||||
<p>The <b>weak_ptr</b> class template stores a pointer to an
|
||||
object that's already managed by a <b>shared_ptr</b>. When the
|
||||
object last <b>shared_ptr</b> to the object goes away and the object
|
||||
is deleted, all <b>weak_ptr</b> objects have their stored pointers
|
||||
set to 0.</p>
|
||||
|
||||
<p>Every <b>weak_ptr</b> meets the <b>CopyConstructible</b>
|
||||
and <b>Assignable</b> requirements of the C++ Standard Library, and so
|
||||
can be used in standard library containers. Comparison operators
|
||||
are supplied so that <b>weak_ptr</b> works with
|
||||
the standard library's associative containers.</p>
|
||||
|
||||
<p>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<typename T> class weak_ptr {
|
||||
|
||||
public:
|
||||
typedef T <a href="#element_type">element_type</a>;
|
||||
|
||||
<a href="#constructors">weak_ptr</a>();
|
||||
explicit <a href="#constructors">weak_ptr</a>();
|
||||
template<typename Y> <a href="#constructors">weak_ptr</a>(shared_ptr<Y> const & r); // never throws
|
||||
<a href="#destructor">~weak_ptr</a>(); // never throws
|
||||
|
||||
@@ -71,173 +47,174 @@ if(shared_ptr<int> r = <a href="#make_shared">make_shared</a>(q))
|
||||
template<typename Y> weak_ptr & <a href="#assignment">operator=</a>(weak_ptr<Y> const & r); // never throws
|
||||
template<typename Y> weak_ptr & <a href="#assignment">operator=</a>(shared_ptr<Y> const & r); // never throws
|
||||
|
||||
void <a href="#reset">reset</a>();
|
||||
T * <a href="#get">get</a>() const; // never throws; unsafe in multithreaded code!
|
||||
void <a href="#reset">reset</a>(); // never throws
|
||||
|
||||
T & <a href="#indirection">operator*</a>() const; // never throws
|
||||
T * <a href="#indirection">operator-></a>() const; // never throws
|
||||
T * <a href="#get">get</a>() const; // never throws
|
||||
|
||||
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<T> & b); // never throws
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
bool <a href="#comparison">operator==</a>(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
|
||||
bool <a href="#operator==">operator==</a>(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#comparison">operator!=</a>(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
|
||||
template<typename T>
|
||||
bool <a href="#comparison">operator<</a>(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws
|
||||
bool <a href="#operator!=">operator!=</a>(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator<">operator<</a>(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
|
||||
|
||||
template<typename T> void <a href="#free-swap">swap</a>(weak_ptr<T> & a, weak_ptr<T> & b); // never throws
|
||||
|
||||
template<typename T>
|
||||
shared_ptr<T> <a href="#make_shared">make_shared</a>(weak_ptr<T> const & r); // never throws
|
||||
template<typename T, typename U>
|
||||
weak_ptr<T> <a href="#shared_static_cast">shared_static_cast</a>(weak_ptr<U> const & r); // never throws
|
||||
template<typename T, typename U>
|
||||
weak_ptr<T> <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(weak_ptr<U> const & r);
|
||||
|
||||
}
|
||||
</pre>
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<blockquote>
|
||||
<p>Provides the type of the template parameter T.</p>
|
||||
</blockquote>
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
<pre>explicit weak_ptr();</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Constructs a <b>weak_ptr</b>.</p>
|
||||
<p><b>Postconditions:</b> <A href="#use_count">use count</A> is 0; the stored
|
||||
pointer is 0.</p>
|
||||
<p><b>Throws:</b> <b>std::bad_alloc</b>.</p>
|
||||
<p><b>Exception safety:</b> If an exception is thrown, the constructor has no
|
||||
effect.</p>
|
||||
<P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
|
||||
common requirements</A>.</P>
|
||||
</blockquote>
|
||||
<pre>template<typename Y> weak_ptr</A>(shared_ptr<Y> const & 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 & r); // never throws
|
||||
}</pre>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<p>Provides the type of the stored pointer.</p>
|
||||
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
|
||||
<pre>explicit weak_ptr();</pre>
|
||||
<p>Constructs a <b>weak_ptr</b>, with 0 as its stored pointer.
|
||||
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
|
||||
If an exception is thrown, the constructor has no effect.</p>
|
||||
|
||||
<pre>template<typename Y> weak_ptr</a>(shared_ptr<Y> const & r); // never throws</pre>
|
||||
<p>Constructs a <b>weak_ptr</b>, as if by storing a copy of the pointer stored in <b>r</b>.
|
||||
Afterwards, the <a href="#use_count">use count</a> for all copies is unchanged.
|
||||
When the last <b>shared_ptr</b> is destroyed, the use count and stored pointer become 0.</p>
|
||||
|
||||
<pre>weak_ptr(weak_ptr const & r); // never throws
|
||||
template<typename Y> weak_ptr(weak_ptr<Y> const & r); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Constructs a <b>weak_ptr</b>, as if by storing a copy of the
|
||||
pointer stored in <b>r</b>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> The <a href="#use_count">use count</a> for all copies is
|
||||
unchanged.</P>
|
||||
</blockquote>
|
||||
<h3><a name="destructor">destructor</a></h3>
|
||||
<pre>~weak_ptr(); // never throws</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Destroys this <b>weak_ptr</b> but has no effect on the object
|
||||
its stored pointer points to.</P>
|
||||
<P><B>Throws:</B> nothing.</P>
|
||||
<P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
|
||||
common requirements</A>.</P>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="assignment">assignment</a></h3>
|
||||
<pre>weak_ptr & <a href="#assignment">operator=</a>(weak_ptr const & r); // never throws
|
||||
<p>Constructs a <b>weak_ptr</b>, as if by storing a copy of the
|
||||
pointer stored in <b>r</b>.</p>
|
||||
|
||||
<h3><a name="destructor">destructor</a></h3>
|
||||
|
||||
<pre>~weak_ptr(); // never throws</pre>
|
||||
<p>Destroys this <b>weak_ptr</b> but has no effect on the object its stored pointer points to.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="operator=">assignment</a></h3>
|
||||
|
||||
<pre>weak_ptr & <a href="#assignment">operator=</a>(weak_ptr const & r); // never throws
|
||||
template<typename Y> weak_ptr & <a href="#assignment">operator=</a>(weak_ptr<Y> const & r); // never throws
|
||||
template<typename Y> weak_ptr & <a href="#assignment">operator=</a>(shared_ptr<Y> const & r); // never throws</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Equivalent to <code>weak_ptr(r).swap(*this)</code>.</P>
|
||||
<P><B>Throws:</B> nothing.</P>
|
||||
<P><B>Notes:</B> The implementation is free to meet the effects (and the implied
|
||||
guarantees) via different means, without creating a temporary.</P>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
<pre>void reset();</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Equivalent to <code>weak_ptr().swap(*this)</code>.</P>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="get">get</a></h3>
|
||||
<pre>T * get() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> the stored pointer (0 if all <b>shared_ptr</b> objects for that
|
||||
pointer are destroyed.)</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> Using <b>get</b> in multithreaded code is dangerous. After the
|
||||
function returns, the pointed-to object may be destroyed by a different thread,
|
||||
since the <b>weak_ptr</b> doesn't affect its <b>use_count</b>.</P>
|
||||
</blockquote>
|
||||
<h3><a name="use_count">use_count</a></h3>
|
||||
<pre>long use_count() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> the number of <b>shared_ptr</b> objects sharing ownership of the
|
||||
stored pointer.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> <code>use_count()</code> is not necessarily efficient. Use only
|
||||
for debugging and testing purposes, not for production code. <B>T</B> need not
|
||||
be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
|
||||
common requirements</A>.</P>
|
||||
</blockquote>
|
||||
<h3><a name="expired">expired</a></h3>
|
||||
<pre>bool expired() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>use_count() == 0</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> <code>expired()</code> may be faster than <code>use_count()</code>.
|
||||
<B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
|
||||
common requirements</A>.</P>
|
||||
</blockquote>
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(weak_ptr & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
|
||||
common requirements</A>.</P>
|
||||
</blockquote>
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
<h3><a name="comparison">comparison</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
|
||||
<p>Constructs a new <b>weak_ptr</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>weak_ptr</b> with the new one, destroying the replaced object.</p>
|
||||
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
|
||||
<pre>void reset();</pre>
|
||||
<p>Constructs a new <b>weak_ptr</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>weak_ptr</b> with the new one, destroying the replaced object.
|
||||
The only exception which may be thrown is <b>std::bad_alloc</b>. If
|
||||
an exception is thrown, the <b>reset</b> has no effect.</p>
|
||||
|
||||
<h3><a name="indirection">indirection</a></h3>
|
||||
|
||||
<pre>T & operator*() const; // never throws</pre>
|
||||
<p>Returns a reference to the object pointed to by the stored pointer.
|
||||
Behavior is undefined if the stored pointer is 0.
|
||||
Note that the stored pointer becomes 0 if all <b>shared_ptr</b> objects for that
|
||||
pointer are destroyed.</p>
|
||||
|
||||
<pre>T * operator->() const; // never throws</pre>
|
||||
<p>Returns the stored pointer.
|
||||
Behavior is undefined if the stored pointer is 0.
|
||||
Note that the stored pointer becomes 0 if all <b>shared_ptr</b> objects for that
|
||||
pointer are destroyed.</p>
|
||||
|
||||
<h3><a name="get">get</a></h3>
|
||||
<pre>T * get() const; // never throws</pre>
|
||||
<p>Returns the stored pointer.
|
||||
Note that the stored pointer becomes 0 if all <b>shared_ptr</b> objects for that
|
||||
pointer are destroyed.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="use_count">use_count</a></h3>
|
||||
<pre>long use_count() const; // never throws</pre>
|
||||
<p>Returns the number of <b>shared_ptr</b> objects sharing ownership of the
|
||||
stored pointer.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
<p>Because <b>use_count</b> is not necessarily efficient to implement for
|
||||
implementations of <b>weak_ptr</b> that do not use an explicit reference
|
||||
count, it might be removed from some future version. Thus it should
|
||||
be used for debugging purposes only, and <b>get</b> should be used for
|
||||
production code.</p>
|
||||
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(weak_ptr & 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<typename T, typename U>
|
||||
bool <a href="#operator==">operator==</a>(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
|
||||
common requirements</A>.</P>
|
||||
</blockquote>
|
||||
<pre>template<typename T>
|
||||
bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> an implementation-defined value such that <b>operator<</b> is
|
||||
a strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
|
||||
of the C++ standard.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> Allows <STRONG>weak_ptr</STRONG> objects to be used as keys in
|
||||
associative containers. <B>T</B> need not be a complete type. See the smart
|
||||
pointer <A href="smart_ptr.htm#Common requirements">common requirements</A>.</P>
|
||||
</blockquote>
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<typename T>
|
||||
bool <a href="#operator!=">operator!=</a>(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator<">operator<</a>(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws</pre>
|
||||
<p>Compares the stored pointers of the two smart pointers.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
<p>The <b>operator<</b> overload is provided to define an ordering so that <b>weak_ptr</b>
|
||||
objects can be used in associative containers such as <b>std::map</b>.
|
||||
The implementation uses <b>std::less<T *></b> to perform the
|
||||
comparison. This ensures that the comparison is handled correctly, since the
|
||||
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel]
|
||||
paragraph 2) but <b>std::less<></b> on pointers is well-defined (20.3.3 [lib.comparisons]
|
||||
paragraph 8).</p>
|
||||
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<typename T>
|
||||
void swap(weak_ptr<T> & a, weak_ptr<T> & b) // never throws</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
|
||||
<P><B>Throws:</B> nothing.</P>
|
||||
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
|
||||
generic programming.</P>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="make_shared">make_shared</a></h3>
|
||||
<pre>template<typename T>
|
||||
shared_ptr<T> make_shared(weak_ptr<T> & const r) // never throws</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Returns:</B> <code>r.expired()? shared_ptr<T>(): shared_ptr<T>(r)</code>.</P>
|
||||
<P><B>Throws:</B> nothing.</P>
|
||||
</BLOCKQUOTE>
|
||||
<hr>
|
||||
<p>Revised 12 March 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
|
||||
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||
Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and
|
||||
distribute this document is granted provided this copyright notice appears in
|
||||
all copies. This document is provided "as is" without express or implied
|
||||
warranty, and with no claim as to its suitability for any purpose.</p>
|
||||
</A>
|
||||
</body>
|
||||
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
|
||||
Provided as an aid to generic programming.</p>
|
||||
|
||||
<h3><a name="shared_static_cast">shared_static_cast</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
weak_ptr<T> <a href="#shared_static_cast">shared_static_cast</a>(weak_ptr<U> const & r); // never throws</pre>
|
||||
<p>Perform a <b>static_cast</b> on the stored pointer, returning another <b>weak_ptr</b>.
|
||||
The resulting smart pointer will share its use count with the original pointer.</p>
|
||||
|
||||
<h3><a name="shared_dynamic_cast">shared_dynamic_cast</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
weak_ptr<T> <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(weak_ptr<U> const & r);</pre>
|
||||
<p>Perform a <b>dynamic_cast</b> on the stored pointer, returning another <b>weak_ptr</b>.
|
||||
The resulting smart pointer will share its use count with the original pointer unless the result of the
|
||||
cast is 0. The only exception which may be thrown is <b>std::bad_alloc</b>, which may be thrown during the
|
||||
construction of the new <b>weak_ptr</b> if the result of the cast is 0. If an exception is thrown, the
|
||||
cast has no effect.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->1 February 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
|
||||
|
||||
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||
Permission to copy, use, modify, sell and distribute this document is granted
|
||||
provided this copyright notice appears in all copies.
|
||||
This document is provided "as is" without express or implied warranty,
|
||||
and with no claim as to its suitability for any purpose.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user