From fbc902831395559dadc40cd3b1f549a75dfe3a79 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 19 Apr 2002 19:34:16 +0000 Subject: [PATCH] intrusive_ptr.hpp added (still experimental) [SVN r13526] --- include/boost/detail/shared_count.hpp | 23 ++- include/boost/intrusive_ptr.hpp | 201 ++++++++++++++++++++++++++ include/boost/shared_ptr.hpp | 6 + 3 files changed, 226 insertions(+), 4 deletions(-) create mode 100644 include/boost/intrusive_ptr.hpp diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index 9dfed4f..22a1e09 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -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 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 shared_count(P p, D d): pi_(0) { try diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp new file mode 100644 index 0000000..1d5349a --- /dev/null +++ b/include/boost/intrusive_ptr.hpp @@ -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 // 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 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 intrusive_ptr(intrusive_ptr 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 intrusive_ptr & operator=(intrusive_ptr 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 void swap(intrusive_ptr & lhs, intrusive_ptr & rhs) +{ + lhs.swap(rhs); +} + +template intrusive_ptr shared_dynamic_cast(intrusive_ptr const & p) +{ + return dynamic_cast(p.get()); +} + +template intrusive_ptr shared_static_cast(intrusive_ptr const & p) +{ + return static_cast(p.get()); +} + +template inline bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return std::less(a.get(), b.get()); +} + +template inline bool operator==(intrusive_ptr const & a, T * b) +{ + return a.get() == b; +} + +template inline bool operator!=(intrusive_ptr const & a, T * b) +{ + return a.get() != b; +} + +template inline bool operator==(T * a, intrusive_ptr const & b) +{ + return a == b.get(); +} + +template inline bool operator!=(T * a, intrusive_ptr const & b) +{ + return a != b.get(); +} + +// mem_fn support + +template T * get_pointer(intrusive_ptr const & p) +{ + return p.get(); +} + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index ad013d3..6cb187d 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -68,6 +68,7 @@ template<> struct shared_ptr_traits // template class weak_ptr; +template class intrusive_ptr; template class shared_ptr { @@ -110,6 +111,11 @@ public: { } + template + shared_ptr(intrusive_ptr const & r): px(r.get()), pn(r.get()) // never throws + { + } + template shared_ptr(shared_ptr const & r, detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) {