diff options
author | Murray Cumming <murrayc@murrayc.com> | 2016-12-07 11:48:15 +0100 |
---|---|---|
committer | Murray Cumming <murrayc@murrayc.com> | 2016-12-07 11:50:56 +0100 |
commit | b7e86f5410e8924a6482096c0049b1e635eef5b7 (patch) | |
tree | fbf8349601c49d6e05177df5de2384cf73a0af7c | |
parent | 3bf93d7303811b98b76270c9faf6706a43053b63 (diff) |
RefPtr: Make this an alias for shared_ptr<> instead.
Specifying a Deleter in make_refptr_for_instance().
-rw-r--r-- | cairomm/refptr.h | 433 |
1 files changed, 13 insertions, 420 deletions
diff --git a/cairomm/refptr.h b/cairomm/refptr.h index 7faae4b..664fb59 100644 --- a/cairomm/refptr.h +++ b/cairomm/refptr.h @@ -2,6 +2,8 @@ #ifndef _cairo_REFPTR_H #define _cairo_REFPTR_H +#include <memory> + /* $Id: refptr.h,v 1.6 2006-09-27 18:38:57 murrayc Exp $ */ /* Copyright 2005 The cairomm Development Team @@ -27,7 +29,15 @@ namespace Cairo { -//TODO: Use std::shared_ptr<> instead when we can break ABI. +template <class T_CppObject> +void RefPtrDeleter(T_CppObject* object) +{ + if (!object) + return; + + object->unreference(); +} + /** RefPtr<> is a reference-counting shared smartpointer. * * Reference counting means that a shared reference count is incremented each @@ -41,430 +51,13 @@ namespace Cairo * and unreference() cairo objects. */ template <class T_CppObject> -class RefPtr -{ -public: - // Let the cast constructors and assignement operators access private data. - template <typename T_CastFrom> - friend class RefPtr; - - /** Default constructor - * - * Afterwards it will be null and use of -> will cause a segmentation fault. - */ - inline RefPtr() noexcept; - - /// Destructor - decrements reference count. - inline ~RefPtr() noexcept; - - /** For use only in the internal implementation of cairomm, gtkmm, etc. - * - * This takes ownership of @a pCppObject, so it will be deleted when the - * last RefPtr is deleted, for instance when it goes out of scope. - * - * This assumes that @a pCppObject already has a starting reference for its underlying cairo object, - * so that destruction of @a @pCppObject will cause a corresponding unreference of its underlying - * cairo object. For instance, a cairo_*_create() function usually provides a starting reference, - * but a cairo_*_get_*() function requires the caller to manually reference the returned object. - * In this case, you should call reference() on @a pCppObject before passing it to this constructor. - */ - explicit inline RefPtr(T_CppObject* pCppObject) noexcept; - - /// For use only in the internal implementation of sharedptr. - explicit inline RefPtr(T_CppObject* pCppObject, int* refcount) noexcept; - - /** Move constructor - */ - inline RefPtr(RefPtr&& src) noexcept; - - /** Move constructor (from different, but castable type). - */ - template <class T_CastFrom> - inline RefPtr(RefPtr<T_CastFrom>&& src) noexcept; - - /** Copy constructor - * - * This increments the shared reference count. - */ - inline RefPtr(const RefPtr<T_CppObject>& src) noexcept; - - /** Copy constructor (from different, but castable type). - * - * Increments the reference count. - */ - template <class T_CastFrom> - inline RefPtr(const RefPtr<T_CastFrom>& src) noexcept; - - /** Swap the contents of two RefPtr<>. - * This method swaps the internal pointers to T_CppObject. This can be - * done safely without involving a reference/unreference cycle and is - * therefore highly efficient. - */ - inline void swap(RefPtr<T_CppObject>& other) noexcept; - - /// Copy from another RefPtr: - inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CppObject>& src) noexcept; - - /** Copy from different, but castable type). - * - * Increments the reference count. - */ - template <class T_CastFrom> - inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CastFrom>& src) noexcept; - - /// Move assignment operator: - inline RefPtr& operator=(RefPtr&& src) noexcept; - - /// Move assignment operator (from different, but castable type): - template <class T_CastFrom> - inline RefPtr& operator=(RefPtr<T_CastFrom>&& src) noexcept; - - /// Tests whether the RefPtr<> point to the same underlying instance. - inline bool operator==(const RefPtr<T_CppObject>& src) const noexcept; - - /// See operator==(). - inline bool operator!=(const RefPtr<T_CppObject>& src) const noexcept; - - /** Dereferencing. - * - * Use the methods of the underlying instance like so: - * <code>refptr->memberfun()</code>. - */ - inline T_CppObject* operator->() const noexcept; - - /** Test whether the RefPtr<> points to any underlying instance. - * - * Mimics usage of ordinary pointers: - * @code - * if (ptr) - * do_something(); - * @endcode - */ - inline explicit operator bool() const noexcept; - - /// Set underlying instance to 0, decrementing reference count of existing instance appropriately. - inline void clear() noexcept; - - - /** Dynamic cast to derived class. - * - * The RefPtr can't be cast with the usual notation so instead you can use - * @code - * ptr_derived = RefPtr<Derived>::cast_dynamic(ptr_base); - * @endcode - */ - template <class T_CastFrom> - static inline RefPtr<T_CppObject> cast_dynamic(const RefPtr<T_CastFrom>& src) noexcept; - - /** Static cast to derived class. - * - * Like the dynamic cast; the notation is - * @code - * ptr_derived = RefPtr<Derived>::cast_static(ptr_base); - * @endcode - */ - template <class T_CastFrom> - static inline RefPtr<T_CppObject> cast_static(const RefPtr<T_CastFrom>& src) noexcept; - - /** Cast to non-const. - * - * The RefPtr can't be cast with the usual notation so instead you can use - * @code - * ptr_unconst = RefPtr<UnConstType>::cast_const(ptr_const); - * @endcode - */ - template <class T_CastFrom> - static inline RefPtr<T_CppObject> cast_const(const RefPtr<T_CastFrom>& src) noexcept; - - -#ifndef DOXYGEN_IGNORE_THIS - - // Warning: This is for internal use only. Do not manually modify the - // reference count with this pointer. - inline int* refcount_() const noexcept { return pCppRefcount_; } - -#endif // DOXYGEN_IGNORE_THIS - -private: - void unref() noexcept; - - T_CppObject* pCppObject_; - mutable int* pCppRefcount_; -}; - - -#ifndef DOXYGEN_IGNORE_THIS - -// RefPtr<>::operator->() comes first here since it's used by other methods. -// If it would come after them it wouldn't be inlined. - -template <class T_CppObject> inline -T_CppObject* RefPtr<T_CppObject>::operator->() const noexcept -{ - return pCppObject_; -} - -template <class T_CppObject> inline -RefPtr<T_CppObject>::RefPtr() noexcept -: - pCppObject_(nullptr), - pCppRefcount_(nullptr) -{} - -template <class T_CppObject> inline -RefPtr<T_CppObject>::~RefPtr() noexcept -{ - unref(); -} - -template <class T_CppObject> inline -void RefPtr<T_CppObject>::unref() noexcept -{ - if(pCppRefcount_) - { - --(*pCppRefcount_); - - if(*pCppRefcount_ == 0) - { - if(pCppObject_) - { - delete pCppObject_; - pCppObject_ = nullptr; - } - - delete pCppRefcount_; - pCppRefcount_ = nullptr; - } - } -} - - -template <class T_CppObject> inline -RefPtr<T_CppObject>::RefPtr(T_CppObject* pCppObject) noexcept -: - pCppObject_(pCppObject), - pCppRefcount_(nullptr) -{ - if(pCppObject) - { - pCppRefcount_ = new int; - *pCppRefcount_ = 1; //This will be decremented in the destructor. - } -} - -//Used by cast_*() implementations: -template <class T_CppObject> inline -RefPtr<T_CppObject>::RefPtr(T_CppObject* pCppObject, int* refcount) noexcept -: - pCppObject_(pCppObject), - pCppRefcount_(refcount) -{ - if(pCppObject_ && pCppRefcount_) - ++(*pCppRefcount_); -} - -template <class T_CppObject> inline -RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CppObject>& src) noexcept -: - pCppObject_ (src.pCppObject_), - pCppRefcount_(src.pCppRefcount_) -{ - if(pCppObject_ && pCppRefcount_) - ++(*pCppRefcount_); -} - -template <class T_CppObject> inline -RefPtr<T_CppObject>::RefPtr(RefPtr&& src) noexcept -: - pCppObject_ (src.pCppObject_), - pCppRefcount_ (src.pCppRefcount_) -{ - src.pCppObject_ = nullptr; - src.pCppRefcount_ = nullptr; -} - -template <class T_CppObject> - template <class T_CastFrom> -inline -RefPtr<T_CppObject>::RefPtr(RefPtr<T_CastFrom>&& src) noexcept -: - pCppObject_ (src.pCppObject_), - pCppRefcount_ (src.pCppRefcount_) -{ - src.pCppObject_ = nullptr; - src.pCppRefcount_ = nullptr; -} - -// The templated ctor allows copy construction from any object that's -// castable. Thus, it does downcasts: -// base_ref = derived_ref -template <class T_CppObject> - template <class T_CastFrom> -inline -RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CastFrom>& src) noexcept -: - // Without the friend delaration, - // a different RefPtr<> will not allow us access to pCppObject_. We need - // to add a get_underlying() for this, but that would encourage incorrect - // use, so we use the less well-known operator->() accessor: - pCppObject_ (src.operator->()), - pCppRefcount_(src.refcount_()) -{ - if(pCppObject_ && pCppRefcount_) - ++(*pCppRefcount_); -} - -template <class T_CppObject> inline -void RefPtr<T_CppObject>::swap(RefPtr<T_CppObject>& other) noexcept -{ - T_CppObject *const temp = pCppObject_; - int* temp_count = pCppRefcount_; - - pCppObject_ = other.pCppObject_; - pCppRefcount_ = other.pCppRefcount_; - - other.pCppObject_ = temp; - other.pCppRefcount_ = temp_count; -} - -template <class T_CppObject> inline -RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CppObject>& src) noexcept -{ - // In case you haven't seen the swap() technique to implement copy - // assignment before, here's what it does: - // - // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby - // increasing the reference count of the source object. - // - // 2) Swap the internal object pointers of *this and the temporary - // RefPtr<>. After this step, *this already contains the new pointer, - // and the old pointer is now managed by temp. - // - // 3) The destructor of temp is executed, thereby unreferencing the - // old object pointer. - // - // This technique is described in Herb Sutter's "Exceptional C++", and - // has a number of advantages over conventional approaches: - // - // - Code reuse by calling the copy ctor. - // - Strong exception safety for free. - // - Self assignment is handled implicitely. - // - Simplicity. - // - It just works and is hard to get wrong; i.e. you can use it without - // even thinking about it to implement copy assignment whereever the - // object data is managed indirectly via a pointer, which is very common. - - RefPtr<T_CppObject> temp (src); - this->swap(temp); - return *this; -} - -template <class T_CppObject> inline -RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(RefPtr&& src) noexcept -{ - RefPtr<T_CppObject> temp (std::move(src)); - this->swap(temp); - src.pCppObject_ = nullptr; - src.pCppRefcount_ = nullptr; - - return *this; -} - -template <class T_CppObject> - template <class T_CastFrom> -inline -RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(RefPtr<T_CastFrom>&& src) noexcept -{ - RefPtr<T_CppObject> temp (std::move(src)); - this->swap(temp); - src.pCppObject_ = nullptr; - src.pCppRefcount_ = nullptr; - - return *this; -} - -template <class T_CppObject> - template <class T_CastFrom> -inline -RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src) noexcept -{ - RefPtr<T_CppObject> temp (src); - this->swap(temp); - return *this; -} - -template <class T_CppObject> inline -bool RefPtr<T_CppObject>::operator==(const RefPtr<T_CppObject>& src) const noexcept -{ - return (pCppObject_ == src.pCppObject_); -} - -template <class T_CppObject> inline -bool RefPtr<T_CppObject>::operator!=(const RefPtr<T_CppObject>& src) const noexcept -{ - return (pCppObject_ != src.pCppObject_); -} - -template <class T_CppObject> inline -RefPtr<T_CppObject>::operator bool() const noexcept -{ - return (pCppObject_ != nullptr); -} - -template <class T_CppObject> inline -void RefPtr<T_CppObject>::clear() noexcept -{ - RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this - this->swap(temp); -} - -template <class T_CppObject> - template <class T_CastFrom> -inline -RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src) noexcept -{ - T_CppObject *const pCppObject = dynamic_cast<T_CppObject*>(src.operator->()); - - if(pCppObject) //Check whether dynamic_cast<> succeeded so we don't pass a null object with a used refcount: - return RefPtr<T_CppObject>(pCppObject, src.refcount_()); - else - return RefPtr<T_CppObject>(); -} - -template <class T_CppObject> - template <class T_CastFrom> -inline -RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src) noexcept -{ - T_CppObject *const pCppObject = static_cast<T_CppObject*>(src.operator->()); - - return RefPtr<T_CppObject>(pCppObject, src.refcount_()); -} - -template <class T_CppObject> - template <class T_CastFrom> -inline -RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_const(const RefPtr<T_CastFrom>& src) noexcept -{ - T_CppObject *const pCppObject = const_cast<T_CppObject*>(src.operator->()); - - return RefPtr<T_CppObject>(pCppObject, src.refcount_()); -} - -#endif /* DOXYGEN_IGNORE_THIS */ - -/** @relates Glib::RefPtr */ -template <class T_CppObject> inline -void swap(RefPtr<T_CppObject>& lhs, RefPtr<T_CppObject>& rhs) noexcept -{ - lhs.swap(rhs); -} +using RefPtr = std::shared_ptr<T_CppObject>; template <class T_CppObject> RefPtr<T_CppObject> make_refptr_for_instance(T_CppObject* object) { - return RefPtr<T_CppObject>(object); + return RefPtr<T_CppObject>(object, &RefPtrDeleter<T_CppObject>); } } // namespace Cairo |