diff --git a/dune/common/shared_ptr.hh b/dune/common/shared_ptr.hh index 58fe766b94b56aa87f14b374284a72535d9db8e7..22ead5b4633f30bec0f6b8666542bd7119821f51 100644 --- a/dune/common/shared_ptr.hh +++ b/dune/common/shared_ptr.hh @@ -33,6 +33,26 @@ namespace Dune * * @{ */ + + /** @brief The object we reference. */ + class SharedCount + { + template<class T1> + friend class shared_ptr; + protected: + /** @brief The number of references. */ + int count_; + /** @brief Constructor from existing Pointer. */ + SharedCount() : count_(1) {} + /** @brief Copy constructor with type conversion. */ + template<class T1> + SharedCount(const SharedCount& rep) + : count_(rep.count_) {} + + /** @brief Destructor, deletes element_type* rep_. */ + virtual ~SharedCount() {}; + + }; /** * @brief A reference counting smart pointer. * @@ -58,6 +78,8 @@ namespace Dune */ inline shared_ptr(); + inline shared_ptr(nullptr_t null); + /** * @brief Constructs a new smart pointer from a preallocated Object. * @@ -69,6 +91,7 @@ namespace Dune template<class T1> inline shared_ptr(T1 * pointer); + /** * @brief Constructs a new smart pointer from a preallocated Object. * @@ -91,6 +114,12 @@ namespace Dune template<class T1> inline shared_ptr(const shared_ptr<T1>& pointer); + /** + * @brief Copy constructor. + * @param pointer The object to copy. + */ + inline shared_ptr(const shared_ptr& pointer); + /** * @brief Destructor. */ @@ -114,7 +143,12 @@ namespace Dune /** \brief Access to the raw pointer, if you really want it */ element_type* get() const { - return rep_==0 ? 0 : rep_->rep_; + return rep_; + } + + /** \brief Checks if shared_ptr manages an object, i.e. whether get() != 0. */ + operator bool() const { + return count_->count_ != 0 && rep_ != nullptr; } /** \brief Swap content of this shared_ptr and another */ @@ -137,56 +171,30 @@ namespace Dune int use_count() const; private: - /** @brief The object we reference. */ - class PointerRep - { - template<class T1> - friend class shared_ptr; - protected: - /** @brief The number of references. */ - int count_; - /** @brief The representative. */ - element_type * rep_; - /** @brief Constructor from existing Pointer. */ - template<class T1> - PointerRep(T1 * p) : count_(1), rep_(p) {} - /** @brief Copy constructor with type conversion. */ - template<class T1> - PointerRep(const typename shared_ptr<T1>::PointerRep& rep) - : count_(rep.count_), rep_(rep.rep_) {} - - template<class T1> - operator typename shared_ptr<T1>::PointerRep() - { - return shared_ptr<T1>::PointerRep(*this); - } - /** @brief Destructor, deletes element_type* rep_. */ - virtual ~PointerRep() {}; - }; - - /** @brief Adds call to deleter to PointerRep. */ + /** @brief Adds call to deleter to SharedCount. */ template<class Deleter> - class PointerRepImpl : - public PointerRep + class SharedCountImpl : + public SharedCount { template<class T1> friend class shared_ptr; /** @brief Constructor from existing Pointer with custom deleter. */ - PointerRepImpl(element_type * p, const Deleter& deleter) : - PointerRep(p), + SharedCountImpl(T* elem,const Deleter& deleter) : + SharedCount(), + rep_(elem), deleter_(deleter) {} /** @brief Copy constructor with type conversion. */ - template<class T1> - PointerRepImpl(const typename shared_ptr<T1>::PointerRepImpl& rep) - : PointerRep(rep), deleter_(rep.deleter_) {} + SharedCountImpl(const SharedCountImpl& rep) + : SharedCount(rep), deleter_(rep.deleter_) {} /** @brief Destructor, deletes element_type* rep_ using deleter. */ - ~PointerRepImpl() - { deleter_(this->rep_); } + ~SharedCountImpl() + { deleter_(rep_); } // store a copy of the deleter Deleter deleter_; + T* rep_; }; /** \brief A default deleter that just calls delete */ @@ -197,16 +205,17 @@ namespace Dune }; - PointerRep *rep_; + SharedCount *count_; + T *rep_; // Needed for the implicit conversion to "bool" - typedef T* shared_ptr::PointerRep::*__unspecified_bool_type; + typedef T* SharedCount::*__unspecified_bool_type; public: /** \brief Implicit conversion to "bool" */ operator __unspecified_bool_type() const // never throws { - return rep_ == 0 ? 0 : &shared_ptr::PointerRep::rep_; + return rep_ == 0 ? 0 : &shared_ptr::SharedCount::rep_; } @@ -216,91 +225,115 @@ namespace Dune template<class T1> inline shared_ptr<T>::shared_ptr(T1 * p) { - rep_ = new PointerRepImpl<DefaultDeleter>(p, DefaultDeleter()); + rep_ = p; + count_ = new SharedCountImpl<DefaultDeleter>(p, DefaultDeleter()); + } + + template<class T> + inline shared_ptr<T>::shared_ptr(nullptr_t n) + { + rep_ = n; + count_ = new SharedCountImpl<DefaultDeleter>(rep_, DefaultDeleter()); + count_->count_=0; } template<class T> template<class T1, class Deleter> inline shared_ptr<T>::shared_ptr(T1 * p, Deleter deleter) { - rep_ = new PointerRepImpl<Deleter>(p, deleter); + rep_ = p; + count_ = new SharedCountImpl<Deleter>(p, deleter); } template<class T> inline shared_ptr<T>::shared_ptr() { rep_ = nullptr; + count_ = new SharedCountImpl<DefaultDeleter>(rep_, DefaultDeleter()); + count_->count_=0; } template<class T> template<class T1> - inline shared_ptr<T>::shared_ptr(const shared_ptr<T1>& other) : rep_() + inline shared_ptr<T>::shared_ptr(const shared_ptr<T1>& other) + : rep_(other.rep_), count_(other.count_) { - rep_->count_=other.rep_->count_; - rep_->rep_=other.rep_->rep_; if (rep_) - ++(rep_->count_); + ++(count_->count_); + } + + template<class T> + inline shared_ptr<T>::shared_ptr(const shared_ptr& other) + : rep_(other.rep_), count_(other.count_) + { + if (rep_) + ++(count_->count_); } template<class T> template<class T1> inline shared_ptr<T>& shared_ptr<T>::operator=(const shared_ptr<T1>& other) { - if (other.rep_) - (other.rep_->count_)++; + if (other.count_) + (other.count_->count_)++; - if(rep_!=0 && --(rep_->count_)<=0) - delete rep_; + if(rep_!=0 && --(count_->count_)<=0) { + delete count_; + } rep_ = other.rep_; + count_ = other.count_; return *this; } template<class T> inline shared_ptr<T>::~shared_ptr() { - if(rep_!=0 && --(rep_->count_)==0) { - delete rep_; - rep_=0; + if(rep_!=nullptr && --(count_->count_)==0) { + delete count_; + rep_=nullptr; } } template<class T> inline T& shared_ptr<T>::operator*() { - return *(rep_->rep_); + return *(rep_); } template<class T> inline T *shared_ptr<T>::operator->() { - return rep_->rep_; + return rep_; } template<class T> inline const T& shared_ptr<T>::operator*() const { - return *(rep_->rep_); + return *(rep_); } template<class T> inline const T *shared_ptr<T>::operator->() const { - return rep_->rep_; + return rep_; } template<class T> inline int shared_ptr<T>::use_count() const { - return rep_->count_; + return count_->count_; } template<class T> inline void shared_ptr<T>::swap(shared_ptr<T>& other) { - PointerRep* dummy = rep_; + SharedCount* dummy = count_; + count_=other.count_; + other.count_ = dummy; + T* tdummy=rep_; rep_ = other.rep_; - other.rep_ = dummy; + other.rep_ = tdummy; } template<class T> diff --git a/dune/common/test/shared_ptrtest.cc b/dune/common/test/shared_ptrtest.cc index daddbe57d67c0a18f9c259f6e8eb91e9eb8d9f18..cd3f787fd0ca4eb84a653d58758202460702ae1b 100644 --- a/dune/common/test/shared_ptrtest.cc +++ b/dune/common/test/shared_ptrtest.cc @@ -65,6 +65,23 @@ int main(){ // test conversion in make_shared shared_ptr<A> a=test_make_shared(); + { + shared_ptr<B> b(new B); + a=b; + + if(b.use_count()!=2) { + std::cout << "Reference count is wrong! "<<__LINE__<<":"<< + __FILE__<<std::endl; + ret=1; + } + + if(a.use_count()!=2) { + std::cout << "Reference count is wrong! "<<__LINE__<<":"<< + __FILE__<<std::endl; + ret=1; + } + + } // print the type of the shared_ptr, so we know whether we are // checking dune's shared_ptr or some std one std::cout << "=== checking shared_ptr type: " << className(foo)