diff options
Diffstat (limited to 'include/llvm/ADT/IntrusiveRefCntPtr.h')
-rw-r--r-- | include/llvm/ADT/IntrusiveRefCntPtr.h | 83 |
1 files changed, 62 insertions, 21 deletions
diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index b8b88619957e..f9df3781257e 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -23,6 +23,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" +#include <atomic> #include <memory> namespace llvm { @@ -88,6 +89,31 @@ namespace llvm { static void retain(T *obj) { obj->Retain(); } static void release(T *obj) { obj->Release(); } }; + +/// \brief A thread-safe version of \c llvm::RefCountedBase. +/// +/// A generic base class for objects that wish to have their lifetimes managed +/// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to +/// obtain such functionality, and are typically handled with +/// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the +/// management of reference counts. +template <class Derived> +class ThreadSafeRefCountedBase { + mutable std::atomic<int> RefCount; + +protected: + ThreadSafeRefCountedBase() : RefCount(0) {} + +public: + void Retain() const { ++RefCount; } + + void Release() const { + int NewRefCount = --RefCount; + assert(NewRefCount >= 0 && "Reference count was already zero."); + if (NewRefCount == 0) + delete static_cast<const Derived*>(this); + } +}; //===----------------------------------------------------------------------===// /// IntrusiveRefCntPtr - A template class that implements a "smart pointer" @@ -109,11 +135,11 @@ namespace llvm { template <typename T> class IntrusiveRefCntPtr { T* Obj; - typedef IntrusiveRefCntPtr this_type; + public: typedef T element_type; - explicit IntrusiveRefCntPtr() : Obj(0) {} + explicit IntrusiveRefCntPtr() : Obj(nullptr) {} IntrusiveRefCntPtr(T* obj) : Obj(obj) { retain(); @@ -123,20 +149,18 @@ namespace llvm { retain(); } -#if LLVM_HAS_RVALUE_REFERENCES IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) { - S.Obj = 0; + S.Obj = nullptr; } template <class X> - IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.getPtr()) { + IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.get()) { S.Obj = 0; } -#endif template <class X> IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S) - : Obj(S.getPtr()) { + : Obj(S.get()) { retain(); } @@ -151,12 +175,9 @@ namespace llvm { T* operator->() const { return Obj; } - T* getPtr() const { return Obj; } + T* get() const { return Obj; } - typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const; - operator unspecified_bool_type() const { - return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr; - } + LLVM_EXPLICIT operator bool() const { return Obj; } void swap(IntrusiveRefCntPtr& other) { T* tmp = other.Obj; @@ -166,7 +187,7 @@ namespace llvm { void reset() { release(); - Obj = 0; + Obj = nullptr; } void resetWithoutRelease() { @@ -182,42 +203,62 @@ namespace llvm { inline bool operator==(const IntrusiveRefCntPtr<T>& A, const IntrusiveRefCntPtr<U>& B) { - return A.getPtr() == B.getPtr(); + return A.get() == B.get(); } template<class T, class U> inline bool operator!=(const IntrusiveRefCntPtr<T>& A, const IntrusiveRefCntPtr<U>& B) { - return A.getPtr() != B.getPtr(); + return A.get() != B.get(); } template<class T, class U> inline bool operator==(const IntrusiveRefCntPtr<T>& A, U* B) { - return A.getPtr() == B; + return A.get() == B; } template<class T, class U> inline bool operator!=(const IntrusiveRefCntPtr<T>& A, U* B) { - return A.getPtr() != B; + return A.get() != B; } template<class T, class U> inline bool operator==(T* A, const IntrusiveRefCntPtr<U>& B) { - return A == B.getPtr(); + return A == B.get(); } template<class T, class U> inline bool operator!=(T* A, const IntrusiveRefCntPtr<U>& B) { - return A != B.getPtr(); + return A != B.get(); + } + + template <class T> + bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { + return !B; + } + + template <class T> + bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { + return B == A; + } + + template <class T> + bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { + return !(A == B); + } + + template <class T> + bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { + return !(A == B); } //===----------------------------------------------------------------------===// @@ -227,14 +268,14 @@ namespace llvm { template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > { typedef T* SimpleType; static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) { - return Val.getPtr(); + return Val.get(); } }; template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > { typedef /*const*/ T* SimpleType; static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { - return Val.getPtr(); + return Val.get(); } }; |