//+----------------------------------------------------------------------------+ //| Description: Magic Set Editor - Program to make Magic (tm) cards | //| Copyright: (C) Twan van Laarhoven and the other MSE developers | //| License: GNU General Public License 2 or later (see file COPYING) | //+----------------------------------------------------------------------------+ #pragma once /** @file util/smart_ptr.hpp * * @brief Smart pointers and related utility functions */ // ----------------------------------------------------------------------------- : Includes #include using std::shared_ptr; using std::unique_ptr; using std::static_pointer_cast; using std::dynamic_pointer_cast; using std::make_shared; using std::make_unique; #ifndef USE_INTRUSIVE_PTR #define USE_INTRUSIVE_PTR 1 #endif // ----------------------------------------------------------------------------- : Intrusive pointers #if USE_INTRUSIVE_PTR #include #include using boost::intrusive_ptr; /// Base class for types that can be pointed to template class IntrusivePtrBase { public: IntrusivePtrBase() {} // don't copy or assign ref count IntrusivePtrBase(IntrusivePtrBase const&) {} void operator = (IntrusivePtrBase const&) {} protected: inline void destroy() const { delete static_cast(this); } private: mutable std::atomic ref_count = 0; template friend void intrusive_ptr_add_ref(const IntrusivePtrBase* ptr); template friend void intrusive_ptr_release(const IntrusivePtrBase* ptr); }; template void intrusive_ptr_add_ref(const IntrusivePtrBase* ptr) { ++(ptr->ref_count); } template void intrusive_ptr_release(const IntrusivePtrBase* ptr) { if (--(ptr->ref_count) == 0) { static_cast(ptr)->destroy(); } } template class IntrusiveFromThis { public: inline intrusive_ptr intrusive_from_this() noexcept { return intrusive_ptr(static_cast(this)); } }; /// Allocate an object of type T and store it in a new intrusive_ptr, similar to std::make_shared template inline intrusive_ptr make_intrusive(Args&&... args) { return intrusive_ptr(new T(std::forward(args)...)); } // ----------------------------------------------------------------------------- : Shared pointers #else template using intrusive_ptr = shared_ptr; /// Base class for types that can be pointed to template class IntrusivePtrBase {}; template class IntrusiveFromThis : public std::enable_shared_from_this { public: inline intrusive_ptr intrusive_from_this() { return this->shared_from_this(); } }; /// Allocate an object of type T and store it in a new intrusive_ptr, similar to std::make_shared template inline intrusive_ptr make_intrusive(Args&&... args) { return std::make_shared(std::forward(args)...); } #endif // ----------------------------------------------------------------------------- : Declaring /// Declares the type TypeP as a intrusive_ptr #define DECLARE_POINTER_TYPE(Type) \ class Type; \ typedef intrusive_ptr Type##P /// Declares the type TypeP as a shared_ptr #define DECLARE_SHARED_POINTER_TYPE(Type) \ class Type; \ typedef shared_ptr Type##P // ----------------------------------------------------------------------------- : Utility /// IntrusivePtrBase with a virtual destructor class IntrusivePtrVirtualBase : public IntrusivePtrBase { public: virtual ~IntrusivePtrVirtualBase() {} }; class IntrusivePtrBaseWithDelete : public IntrusivePtrBase { public: virtual ~IntrusivePtrBaseWithDelete() {} protected: /// Delete this object virtual void destroy() const { delete this; } template friend void intrusive_ptr_release(const IntrusivePtrBase* ptr); }; /// Pointer to 'anything' typedef intrusive_ptr VoidP;