intrusive_ptr.hpp added (still experimental)

[SVN r13526]
This commit is contained in:
Peter Dimov
2002-04-19 19:34:16 +00:00
parent 9b800d4f84
commit fbc9028313
3 changed files with 226 additions and 4 deletions

View File

@ -41,9 +41,6 @@ public:
}
};
namespace detail
{
class counted_base
{
public:
@ -77,7 +74,7 @@ public:
#ifdef BOOST_HAS_THREADS
lightweight_mutex::scoped_lock lock(mtx_);
#endif
if(use_count_ == 0) throw use_count_is_zero();
if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero();
++use_count_;
++weak_count_;
}
@ -161,6 +158,19 @@ private:
void (*self_deleter_) (counted_base *);
};
inline void intrusive_ptr_add_ref(counted_base * p)
{
if(p != 0) p->add_ref();
}
inline void intrusive_ptr_release(counted_base * p)
{
if(p != 0) p->release();
}
namespace detail
{
template<class P, class D> class counted_base_impl: public counted_base
{
private:
@ -202,6 +212,11 @@ public:
{
}
explicit shared_count(counted_base * pi): pi_(pi) // never throws
{
pi_->add_ref();
}
template<class P, class D> shared_count(P p, D d): pi_(0)
{
try

View File

@ -0,0 +1,201 @@
#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);
// (note: p may be 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)
{
intrusive_ptr_add_ref(p_);
}
~intrusive_ptr()
{
intrusive_ptr_release(p_);
}
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
template<class U> intrusive_ptr(intrusive_ptr<U> const & rhs): p_(rhs.get())
{
intrusive_ptr_add_ref(p_);
}
#endif
intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_)
{
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

View File

@ -68,6 +68,7 @@ template<> struct shared_ptr_traits<void>
//
template<typename T> class weak_ptr;
template<typename T> class intrusive_ptr;
template<typename T> class shared_ptr
{
@ -110,6 +111,11 @@ public:
{
}
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)
{