.. _program_listing_file_src_common_intrusive_ptr.h: Program Listing for File intrusive_ptr.h ======================================== |exhale_lsh| :ref:`Return to documentation for file ` (``src/common/intrusive_ptr.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #pragma once #include #include #include "common/logging.h" // Smart pointer class for small objects with reference counting but no thread-safety. // Inspired by boost::intrusive_ptr. // Compared to std::shared_ptr this is small and cheap to construct and destroy. // Does not hold the counter, the pointed to class `T` needs to add // ENABLE_INTRUSIVE_PTR(T) into the body of the class (private section). This adds // the reference counters and count manipulation functions to the class. #define ENABLE_INTRUSIVE_PTR(type) \ size_t references_{0}; \ \ inline friend void intrusivePtrAddRef(type* x) { \ if(x != 0) \ ++x->references_; \ } \ \ inline friend void intrusivePtrRelease(type* x) { \ if(x != 0 && --x->references_ == 0) { \ delete x; \ x = 0; \ } \ } \ \ inline friend size_t references(type* x) { \ return x->references_; \ } \ template class IntrusivePtr { private: typedef IntrusivePtr this_type; public: typedef T element_type; IntrusivePtr() : ptr_(0) {}; IntrusivePtr(T* p) : ptr_(p) { if(ptr_ != 0) intrusivePtrAddRef(ptr_); } template IntrusivePtr(const IntrusivePtr& rhs) : ptr_(rhs.get()) { if(ptr_ != 0) intrusivePtrAddRef(ptr_); } IntrusivePtr(const IntrusivePtr& rhs) : ptr_(rhs.ptr_) { if(ptr_ != 0) intrusivePtrAddRef(ptr_); } ~IntrusivePtr() { if(ptr_ != 0) intrusivePtrRelease(ptr_); } IntrusivePtr(IntrusivePtr&& rhs) : ptr_(rhs.ptr_) { rhs.ptr_ = 0; } inline size_t useCount() { return references(ptr_); } inline IntrusivePtr& operator=(IntrusivePtr&& rhs) { this_type(static_cast(rhs)).swap(*this); return *this; } inline IntrusivePtr& operator=(const IntrusivePtr& rhs) { this_type(rhs).swap(*this); return *this; } template inline IntrusivePtr& operator=(const IntrusivePtr& rhs) { this_type(rhs).swap(*this); return *this; } inline void reset() { this_type().swap(*this); } inline void reset(T* rhs) { this_type(rhs).swap(*this); } inline T* get() const { return ptr_; } inline T* detach() { T* ret = ptr_; ptr_ = 0; return ret; } inline T& operator*() const { //ABORT_IF(ptr_ == 0, "Null pointer in IntrusivePtr"); return *ptr_; } inline T* operator->() const { //ABORT_IF(ptr_ == 0, "Null pointer in IntrusivePtr"); return ptr_; } inline explicit operator bool() const { return ptr_ != 0; } inline bool operator!() const { return ptr_ == 0; } inline void swap(IntrusivePtr& rhs) { T* tmp = ptr_; ptr_ = rhs.ptr_; rhs.ptr_ = tmp; } private: T* ptr_; }; template inline bool operator==(const IntrusivePtr& a, const IntrusivePtr& b) { return a.get() == b.get(); } template inline bool operator!=(const IntrusivePtr& a, const IntrusivePtr& b) { return a.get() != b.get(); } template inline bool operator==(const IntrusivePtr& a, std::nullptr_t) { return a.get() == 0; } template inline bool operator!=(const IntrusivePtr& a, std::nullptr_t) { return a.get() != 0; } template inline bool operator==(const IntrusivePtr& a, T* b) { return a.get() == b; } template inline bool operator!=(const IntrusivePtr& a, T* b) { return a.get() != b; } template inline bool operator==(T* a, const IntrusivePtr& b) { return a == b.get(); } template inline bool operator!=(T* a, const IntrusivePtr& b) { return a != b.get(); } template inline bool operator<(const IntrusivePtr& a, const IntrusivePtr& b) { return std::less()(a.get(), b.get()); } template inline void swap(IntrusivePtr & a, IntrusivePtr & b) { a.swap(b); } template std::basic_ostream& operator<<(std::basic_ostream& os, const IntrusivePtr& p) { os << p.get(); return os; } // compatibility functions to make std::*_pointer_cast work, also for automatic hashing namespace std { template T* get_pointer(const IntrusivePtr& p) { return p.get(); } template IntrusivePtr static_pointer_cast(const IntrusivePtr& p) { return static_cast(p.get()); } template IntrusivePtr const_pointer_cast(const IntrusivePtr& p) { return const_cast(p.get()); } template IntrusivePtr dynamic_pointer_cast(const IntrusivePtr& p) { return dynamic_cast(p.get()); } // IntrusivePtr can be used as hash map key template struct hash> { size_t operator()(const IntrusivePtr& x) const { std::hash hasher; return hasher((size_t)x.get()); } }; }