forked from boostorg/smart_ptr
weak_ptr made thread safe, shared->weak conversions, lightweight_mutex added.
[SVN r12786]
This commit is contained in:
49
include/boost/detail/lightweight_mutex.hpp
Normal file
49
include/boost/detail/lightweight_mutex.hpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#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.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
|
#ifndef BOOST_HAS_THREADS
|
||||||
|
# include <boost/detail/lwm_nop.hpp>
|
||||||
|
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||||
|
# include <boost/detail/lwm_win32.hpp>
|
||||||
|
//#elif defined(linux) || defined(__linux) || defined(__linux__)
|
||||||
|
//# include <boost/detail/lwm_linux.hpp>
|
||||||
|
#elif defined(BOOST_HAS_PTHREADS)
|
||||||
|
# include <boost/detail/lwm_pthreads.hpp>
|
||||||
|
#else
|
||||||
|
# include <boost/detail/lwm_nop.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
|
57
include/boost/detail/lwm_nop.hpp
Normal file
57
include/boost/detail/lwm_nop.hpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#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
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
lightweight_mutex(lightweight_mutex const &);
|
||||||
|
lightweight_mutex & operator=(lightweight_mutex const &);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
lightweight_mutex()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
class scoped_lock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
scoped_lock(scoped_lock const &);
|
||||||
|
scoped_lock & operator=(scoped_lock const &);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit scoped_lock(lightweight_mutex &)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // #ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED
|
78
include/boost/detail/lwm_pthreads.hpp
Normal file
78
include/boost/detail/lwm_pthreads.hpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#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
|
84
include/boost/detail/lwm_win32.hpp
Normal file
84
include/boost/detail/lwm_win32.hpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#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.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace boost
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
// Avoid #including <windows.h>
|
||||||
|
|
||||||
|
namespace win32
|
||||||
|
{
|
||||||
|
extern "C" __declspec(dllimport) long __stdcall InterlockedExchange(long volatile *, long);
|
||||||
|
extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long);
|
||||||
|
}
|
||||||
|
|
||||||
|
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( win32::InterlockedExchange(&m_.l_, 1) ) win32::Sleep(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_lock()
|
||||||
|
{
|
||||||
|
win32::InterlockedExchange(&m_.l_, 0);
|
||||||
|
|
||||||
|
// Note: adding a win32::Sleep(0) here will make
|
||||||
|
// the mutex more fair and will increase the overall
|
||||||
|
// performance of the application 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
|
@ -23,9 +23,10 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/checked_delete.hpp>
|
#include <boost/checked_delete.hpp>
|
||||||
#include <boost/detail/atomic_count.hpp>
|
#include <boost/detail/lightweight_mutex.hpp>
|
||||||
|
|
||||||
#include <functional> // for std::less
|
#include <functional> // for std::less
|
||||||
|
#include <exception> // for std::exception
|
||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
@ -33,11 +34,19 @@ namespace boost
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
class counted_base
|
class bad_weak_to_shared_cast: public std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef atomic_count count_type;
|
virtual char const * what() const throw()
|
||||||
|
{
|
||||||
|
return "bad_weak_to_shared_cast";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class counted_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
// pre: initial_use_count <= initial_weak_count
|
// pre: initial_use_count <= initial_weak_count
|
||||||
|
|
||||||
@ -63,20 +72,31 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_ref() // nothrow
|
void add_ref()
|
||||||
{
|
{
|
||||||
|
lightweight_mutex::scoped_lock lock(mtx_);
|
||||||
|
if(use_count_ == 0) throw bad_weak_to_shared_cast();
|
||||||
++use_count_;
|
++use_count_;
|
||||||
++weak_count_;
|
++weak_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void release() // nothrow
|
void release() // nothrow
|
||||||
{
|
{
|
||||||
if(--use_count_ == 0)
|
long new_use_count;
|
||||||
|
long new_weak_count;
|
||||||
|
|
||||||
|
{
|
||||||
|
lightweight_mutex::scoped_lock lock(mtx_);
|
||||||
|
new_use_count = --use_count_;
|
||||||
|
new_weak_count = --weak_count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(new_use_count == 0)
|
||||||
{
|
{
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(--weak_count_ == 0)
|
if(new_weak_count == 0)
|
||||||
{
|
{
|
||||||
// not a direct 'delete this', because the inlined
|
// not a direct 'delete this', because the inlined
|
||||||
// release() may use a different heap manager
|
// release() may use a different heap manager
|
||||||
@ -86,12 +106,20 @@ public:
|
|||||||
|
|
||||||
void weak_add_ref() // nothrow
|
void weak_add_ref() // nothrow
|
||||||
{
|
{
|
||||||
|
lightweight_mutex::scoped_lock lock(mtx_);
|
||||||
++weak_count_;
|
++weak_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void weak_release() // nothrow
|
void weak_release() // nothrow
|
||||||
{
|
{
|
||||||
if(--weak_count_ == 0)
|
long new_weak_count;
|
||||||
|
|
||||||
|
{
|
||||||
|
lightweight_mutex::scoped_lock lock(mtx_);
|
||||||
|
new_weak_count = --weak_count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(new_weak_count == 0)
|
||||||
{
|
{
|
||||||
self_deleter_(this);
|
self_deleter_(this);
|
||||||
}
|
}
|
||||||
@ -99,6 +127,7 @@ public:
|
|||||||
|
|
||||||
long use_count() const // nothrow
|
long use_count() const // nothrow
|
||||||
{
|
{
|
||||||
|
lightweight_mutex::scoped_lock lock(mtx_);
|
||||||
return use_count_;
|
return use_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,9 +143,9 @@ private:
|
|||||||
|
|
||||||
// inv: use_count_ <= weak_count_
|
// inv: use_count_ <= weak_count_
|
||||||
|
|
||||||
count_type use_count_;
|
long use_count_;
|
||||||
count_type weak_count_;
|
long weak_count_;
|
||||||
|
mutable lightweight_mutex mtx_;
|
||||||
void (*self_deleter_) (counted_base *);
|
void (*self_deleter_) (counted_base *);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -191,6 +220,8 @@ public:
|
|||||||
pi_->add_ref();
|
pi_->add_ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit shared_count(weak_count const & r); // throws bad_weak_to_shared_cast when r.use_count() == 0
|
||||||
|
|
||||||
shared_count & operator= (shared_count const & r) // nothrow
|
shared_count & operator= (shared_count const & r) // nothrow
|
||||||
{
|
{
|
||||||
counted_base * tmp = r.pi_;
|
counted_base * tmp = r.pi_;
|
||||||
@ -235,6 +266,8 @@ private:
|
|||||||
|
|
||||||
counted_base * pi_;
|
counted_base * pi_;
|
||||||
|
|
||||||
|
friend class shared_count;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
weak_count(): pi_(new counted_base(0, 1)) // can throw
|
weak_count(): pi_(new counted_base(0, 1)) // can throw
|
||||||
@ -299,6 +332,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
|
||||||
|
{
|
||||||
|
pi_->add_ref();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
@ -97,6 +97,10 @@ public:
|
|||||||
|
|
||||||
// generated copy constructor, assignment, destructor are fine
|
// generated copy constructor, assignment, destructor are fine
|
||||||
|
|
||||||
|
explicit shared_ptr(weak_ptr<T> const & r): px(r.px), pn(r.pn) // may throw
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Y>
|
template<typename Y>
|
||||||
shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
|
shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
|
||||||
{
|
{
|
||||||
@ -191,6 +195,20 @@ public:
|
|||||||
return pn.use_count();
|
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
|
void swap(shared_ptr<T> & other) // never throws
|
||||||
{
|
{
|
||||||
std::swap(px, other.px);
|
std::swap(px, other.px);
|
||||||
|
@ -30,6 +30,7 @@ private:
|
|||||||
|
|
||||||
// Borland 5.5.1 specific workarounds
|
// Borland 5.5.1 specific workarounds
|
||||||
typedef weak_ptr<T> this_type;
|
typedef weak_ptr<T> this_type;
|
||||||
|
typedef shared_ptr<T> shared_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -95,23 +96,32 @@ public:
|
|||||||
this_type().swap(*this);
|
this_type().swap(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
T * get() const // never throws
|
shared_type get() const // never throws
|
||||||
{
|
{
|
||||||
return use_count() == 0? 0: px;
|
// optimization: avoid throw overhead
|
||||||
|
if(use_count() == 0)
|
||||||
|
{
|
||||||
|
return shared_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return shared_type(*this);
|
||||||
|
}
|
||||||
|
catch(boost::detail::bad_weak_to_shared_cast const &)
|
||||||
|
{
|
||||||
|
return shared_type();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typename detail::shared_ptr_traits<T>::reference operator* () const // never throws
|
// operator* has been removed; it's unsafe.
|
||||||
{
|
|
||||||
element_type * p = get();
|
|
||||||
BOOST_ASSERT(p != 0);
|
|
||||||
return *p;
|
|
||||||
}
|
|
||||||
|
|
||||||
T * operator-> () const // never throws
|
// operator-> retained for convenience, since it's safe
|
||||||
|
// in its current form.
|
||||||
|
|
||||||
|
shared_type operator-> () const // may throw
|
||||||
{
|
{
|
||||||
element_type * p = get();
|
return shared_type(*this);
|
||||||
BOOST_ASSERT(p != 0);
|
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long use_count() const // never throws
|
long use_count() const // never throws
|
||||||
@ -119,7 +129,21 @@ public:
|
|||||||
return pn.use_count();
|
return pn.use_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(weak_ptr<T> & other) // never throws
|
// implicit conversion to "bool"
|
||||||
|
|
||||||
|
typedef long (this_type::*bool_type)() const;
|
||||||
|
|
||||||
|
operator bool_type() const // never throws
|
||||||
|
{
|
||||||
|
return use_count() == 0? 0: &this_type::use_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator! () const // never throws
|
||||||
|
{
|
||||||
|
return use_count() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(this_type & other) // never throws
|
||||||
{
|
{
|
||||||
std::swap(px, other.px);
|
std::swap(px, other.px);
|
||||||
pn.swap(other.pn);
|
pn.swap(other.pn);
|
||||||
@ -138,6 +162,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
template<typename Y> friend class weak_ptr;
|
template<typename Y> friend class weak_ptr;
|
||||||
|
template<typename Y> friend class shared_ptr;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -198,13 +223,6 @@ template<typename T, typename U> weak_ptr<T> shared_polymorphic_downcast(weak_pt
|
|||||||
return shared_static_cast<T>(r);
|
return shared_static_cast<T>(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get_pointer() enables boost::mem_fn to recognize weak_ptr
|
|
||||||
|
|
||||||
template<class T> inline T * get_pointer(weak_ptr<T> const & p)
|
|
||||||
{
|
|
||||||
return p.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
#ifdef BOOST_MSVC
|
#ifdef BOOST_MSVC
|
||||||
|
@ -96,18 +96,28 @@ void release_object(int * p)
|
|||||||
std::cout << "release_object()\n";
|
std::cout << "release_object()\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T> void test_is_X(T const & p)
|
template<class T> void test_is_X(boost::shared_ptr<T> const & p)
|
||||||
{
|
{
|
||||||
BOOST_TEST(p->id() == 1);
|
BOOST_TEST(p->id() == 1);
|
||||||
BOOST_TEST((*p).id() == 1);
|
BOOST_TEST((*p).id() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T> void test_is_Y(T const & p)
|
template<class T> void test_is_X(boost::weak_ptr<T> const & p)
|
||||||
|
{
|
||||||
|
BOOST_TEST(p->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);
|
||||||
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->id() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
template<class T> void test_eq(T const & a, T const & b)
|
template<class T> void test_eq(T const & a, T const & b)
|
||||||
{
|
{
|
||||||
BOOST_TEST(a == b);
|
BOOST_TEST(a == b);
|
||||||
@ -136,6 +146,30 @@ 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_zero(boost::weak_ptr<T> const & p)
|
||||||
|
{
|
||||||
|
BOOST_TEST(!p);
|
||||||
|
test_is_zero(p.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> void test_is_nonzero(boost::shared_ptr<T> const & p)
|
||||||
|
{
|
||||||
|
BOOST_TEST(p);
|
||||||
|
BOOST_TEST(p.get() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> void test_is_nonzero(boost::weak_ptr<T> const & p)
|
||||||
|
{
|
||||||
|
BOOST_TEST(p);
|
||||||
|
test_is_nonzero(p.get());
|
||||||
|
}
|
||||||
|
|
||||||
int test_main(int, char * [])
|
int test_main(int, char * [])
|
||||||
{
|
{
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
@ -144,6 +178,8 @@ int test_main(int, char * [])
|
|||||||
shared_ptr<X> p(new Y);
|
shared_ptr<X> p(new Y);
|
||||||
shared_ptr<X> p2(new X);
|
shared_ptr<X> p2(new X);
|
||||||
|
|
||||||
|
test_is_nonzero(p);
|
||||||
|
test_is_nonzero(p2);
|
||||||
test_is_Y(p);
|
test_is_Y(p);
|
||||||
test_is_X(p2);
|
test_is_X(p2);
|
||||||
test_ne(p, p2);
|
test_ne(p, p2);
|
||||||
@ -156,6 +192,9 @@ int test_main(int, char * [])
|
|||||||
shared_ptr<Y> p3 = shared_dynamic_cast<Y>(p);
|
shared_ptr<Y> p3 = shared_dynamic_cast<Y>(p);
|
||||||
shared_ptr<Y> p4 = shared_dynamic_cast<Y>(p2);
|
shared_ptr<Y> p4 = shared_dynamic_cast<Y>(p2);
|
||||||
|
|
||||||
|
test_is_nonzero(p3);
|
||||||
|
test_is_zero(p4);
|
||||||
|
|
||||||
BOOST_TEST(p.use_count() == 2);
|
BOOST_TEST(p.use_count() == 2);
|
||||||
BOOST_TEST(p2.use_count() == 1);
|
BOOST_TEST(p2.use_count() == 1);
|
||||||
BOOST_TEST(p3.use_count() == 2);
|
BOOST_TEST(p3.use_count() == 2);
|
||||||
@ -167,6 +206,7 @@ int test_main(int, char * [])
|
|||||||
|
|
||||||
shared_ptr<void> p5(p);
|
shared_ptr<void> p5(p);
|
||||||
|
|
||||||
|
test_is_nonzero(p5);
|
||||||
test_eq2(p, p5);
|
test_eq2(p, p5);
|
||||||
|
|
||||||
std::cout << "--\n";
|
std::cout << "--\n";
|
||||||
@ -176,6 +216,11 @@ int test_main(int, char * [])
|
|||||||
p3.reset();
|
p3.reset();
|
||||||
p4.reset();
|
p4.reset();
|
||||||
|
|
||||||
|
test_is_zero(p);
|
||||||
|
test_is_zero(p2);
|
||||||
|
test_is_zero(p3);
|
||||||
|
test_is_zero(p4);
|
||||||
|
|
||||||
std::cout << "--\n";
|
std::cout << "--\n";
|
||||||
|
|
||||||
BOOST_TEST(p5.use_count() == 1);
|
BOOST_TEST(p5.use_count() == 1);
|
||||||
@ -183,25 +228,24 @@ int test_main(int, char * [])
|
|||||||
weak_ptr<X> wp1;
|
weak_ptr<X> wp1;
|
||||||
|
|
||||||
BOOST_TEST(wp1.use_count() == 0);
|
BOOST_TEST(wp1.use_count() == 0);
|
||||||
BOOST_TEST(wp1.get() == 0);
|
test_is_zero(wp1);
|
||||||
|
|
||||||
weak_ptr<X> wp2 = shared_static_cast<X>(p5);
|
weak_ptr<X> wp2 = shared_static_cast<X>(p5);
|
||||||
|
|
||||||
BOOST_TEST(wp2.use_count() == 1);
|
BOOST_TEST(wp2.use_count() == 1);
|
||||||
BOOST_TEST(wp2.get() != 0);
|
test_is_nonzero(wp2);
|
||||||
|
|
||||||
test_is_Y(wp2);
|
test_is_Y(wp2);
|
||||||
test_ne(wp1, wp2);
|
test_ne(wp1, wp2);
|
||||||
|
|
||||||
weak_ptr<Y> wp3 = shared_dynamic_cast<Y>(wp2);
|
weak_ptr<Y> wp3 = shared_dynamic_cast<Y>(wp2);
|
||||||
|
|
||||||
BOOST_TEST(wp3.use_count() == 1);
|
BOOST_TEST(wp3.use_count() == 1);
|
||||||
BOOST_TEST(wp3.get() != 0);
|
test_is_nonzero(wp3);
|
||||||
|
|
||||||
test_eq2(wp2, wp3);
|
test_eq2(wp2, wp3);
|
||||||
|
|
||||||
weak_ptr<X> wp4(wp3);
|
weak_ptr<X> wp4(wp3);
|
||||||
|
|
||||||
|
test_is_nonzero(wp4);
|
||||||
test_eq(wp2, wp4);
|
test_eq(wp2, wp4);
|
||||||
|
|
||||||
wp1 = p2;
|
wp1 = p2;
|
||||||
@ -210,8 +254,7 @@ int test_main(int, char * [])
|
|||||||
wp1 = wp2;
|
wp1 = wp2;
|
||||||
|
|
||||||
BOOST_TEST(wp1.use_count() == 1);
|
BOOST_TEST(wp1.use_count() == 1);
|
||||||
BOOST_TEST(wp1.get() != 0);
|
test_is_nonzero(wp1);
|
||||||
|
|
||||||
test_eq(wp1, wp2);
|
test_eq(wp1, wp2);
|
||||||
|
|
||||||
weak_ptr<X> wp5;
|
weak_ptr<X> wp5;
|
||||||
@ -220,15 +263,16 @@ int test_main(int, char * [])
|
|||||||
bool b2 = wp5 < wp1;
|
bool b2 = wp5 < wp1;
|
||||||
|
|
||||||
p5.reset();
|
p5.reset();
|
||||||
|
test_is_zero(wp5);
|
||||||
|
|
||||||
BOOST_TEST(wp1.use_count() == 0);
|
BOOST_TEST(wp1.use_count() == 0);
|
||||||
BOOST_TEST(wp1.get() == 0);
|
test_is_zero(wp1);
|
||||||
|
|
||||||
BOOST_TEST(wp2.use_count() == 0);
|
BOOST_TEST(wp2.use_count() == 0);
|
||||||
BOOST_TEST(wp2.get() == 0);
|
test_is_zero(wp2);
|
||||||
|
|
||||||
BOOST_TEST(wp3.use_count() == 0);
|
BOOST_TEST(wp3.use_count() == 0);
|
||||||
BOOST_TEST(wp3.get() == 0);
|
test_is_zero(wp3);
|
||||||
|
|
||||||
// Test operator< stability for std::set< weak_ptr<> >
|
// Test operator< stability for std::set< weak_ptr<> >
|
||||||
// Thanks to Joe Gottman for pointing this out
|
// Thanks to Joe Gottman for pointing this out
|
||||||
|
Reference in New Issue
Block a user