From aaade9dd829ad565b5b5a6b524ad8baade0da613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carsten=20Gr=C3=A4ser?= <graeser@dune-project.org> Date: Tue, 26 Jan 2010 23:36:48 +0000 Subject: [PATCH] Fix bug in get() method and implement the missing constructor and reset() taking a deleter. This solves the issue with bcrsmatrix.hh in fs#727. Please merge to release. [[Imported from SVN: r5871]] --- dune/common/shared_ptr.hh | 93 +++++++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 13 deletions(-) diff --git a/dune/common/shared_ptr.hh b/dune/common/shared_ptr.hh index 2435dcc65..2abcb3056 100644 --- a/dune/common/shared_ptr.hh +++ b/dune/common/shared_ptr.hh @@ -65,6 +65,20 @@ namespace Dune */ inline shared_ptr(T * pointer); + /** + * @brief Constructs a new smart pointer from a preallocated Object. + * + * \tparam Deleter This class must by copyconstructable, the copy constructor must not throw an exception + * and it must implement void operator() (T*) const + * + * \param deleter A copy of this deleter is stored + * + * note: the object must be allocated on the heap and after handing the pointer to + * shared_ptr the ownership of the pointer is also handed to the shared_ptr. + */ + template<class Deleter> + inline shared_ptr(T * pointer, Deleter deleter); + /** * @brief Copy constructor. * @param pointer The object to copy. @@ -93,9 +107,12 @@ namespace Dune /** \brief Access to the raw pointer, if you really want it */ element_type* get() const { - return rep_->rep_; + return rep_==0 ? 0 : rep_->rep_; } + /** \brief Swap content of this shared_ptr and another */ + inline void swap(shared_ptr& other); + /** \brief Decrease the reference count by one and free the memory if the reference count has reached 0 */ @@ -104,6 +121,10 @@ namespace Dune /** \brief Detach shared pointer and set it anew for the given pointer */ inline void reset(T* pointer); + //** \brief Same as shared_ptr(pointer,deleter).swap(*this) + template<class Deleter> + inline void reset(T* pointer, Deleter deleter); + /** \brief The number of shared_ptrs pointing to the object we point to */ int use_count() const; @@ -116,16 +137,44 @@ namespace Dune int count_; /** @brief The representative. */ element_type * rep_; - /** @brief Default Constructor. */ - PointerRep() : count_(1), rep_(new element_type) {} /** @brief Constructor from existing Pointer. */ PointerRep(element_type * p) : count_(1), rep_(p) {} /** @brief Destructor, deletes element_type* rep_. */ - ~PointerRep() { delete rep_; } - } *rep_; + virtual ~PointerRep() {}; + }; + + /** @brief Adds call to deleter to PointerRep. */ + template<class Deleter> + class PointerRepImpl : + public PointerRep + { + friend class shared_ptr<element_type>; + + /** @brief Constructor from existing Pointer with custom deleter. */ + PointerRepImpl(element_type * p, const Deleter& deleter) : + PointerRep(p), + deleter_(deleter) + {} + + /** @brief Destructor, deletes element_type* rep_ using deleter. */ + ~PointerRepImpl() + { deleter_(this->rep_); } + + // store a copy of the deleter + Deleter deleter_; + }; + + /** \brief A default deleter that just calls delete */ + struct DefaultDeleter + { + void operator() (element_type* p) const + { delete p; } + }; + + + PointerRep *rep_; // Needed for the implicit conversion to "bool" - private: typedef T* shared_ptr::PointerRep::*__unspecified_bool_type; public: @@ -141,7 +190,14 @@ namespace Dune template<class T> inline shared_ptr<T>::shared_ptr(T * p) { - rep_ = new PointerRep(p); + rep_ = new PointerRepImpl<DefaultDeleter>(p, DefaultDeleter()); + } + + template<class T> + template<class Deleter> + inline shared_ptr<T>::shared_ptr(T * p, Deleter deleter) + { + rep_ = new PointerRepImpl<Deleter>(p, deleter); } template<class T> @@ -204,20 +260,31 @@ namespace Dune return rep_->count_; } + template<class T> + inline void shared_ptr<T>::swap(shared_ptr<T>& other) + { + PointerRep* dummy = rep_; + rep_ = other.rep_; + other.rep_ = dummy; + } + template<class T> inline void shared_ptr<T>::reset() { - if(rep_!=0 && --(rep_->count_)==0) { - delete rep_; - rep_=0; - } + shared_ptr<T>().swap(*this); } template<class T> inline void shared_ptr<T>::reset(T* pointer) { - reset(); - rep_ = new PointerRep(pointer); + shared_ptr<T>(pointer).swap(*this); + } + + template<class T> + template<class Deleter> + inline void shared_ptr<T>::reset(T* pointer, Deleter deleter) + { + shared_ptr<T>(pointer, deleter).swap(*this); } /** @} */ -- GitLab