LLVM API Documentation
00001 //== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- C++ -*-==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines IntrusiveRefCntPtr, a template class that 00011 // implements a "smart" pointer for objects that maintain their own 00012 // internal reference count, and RefCountedBase/RefCountedBaseVPTR, two 00013 // generic base classes for objects that wish to have their lifetimes 00014 // managed using reference counting. 00015 // 00016 // IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added 00017 // LLVM-style casting. 00018 // 00019 //===----------------------------------------------------------------------===// 00020 00021 #ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H 00022 #define LLVM_ADT_INTRUSIVEREFCNTPTR_H 00023 00024 #include "llvm/Support/Casting.h" 00025 #include "llvm/Support/Compiler.h" 00026 #include <atomic> 00027 #include <memory> 00028 00029 namespace llvm { 00030 00031 template <class T> 00032 class IntrusiveRefCntPtr; 00033 00034 //===----------------------------------------------------------------------===// 00035 /// RefCountedBase - A generic base class for objects that wish to 00036 /// have their lifetimes managed using reference counts. Classes 00037 /// subclass RefCountedBase to obtain such functionality, and are 00038 /// typically handled with IntrusiveRefCntPtr "smart pointers" (see below) 00039 /// which automatically handle the management of reference counts. 00040 /// Objects that subclass RefCountedBase should not be allocated on 00041 /// the stack, as invoking "delete" (which is called when the 00042 /// reference count hits 0) on such objects is an error. 00043 //===----------------------------------------------------------------------===// 00044 template <class Derived> 00045 class RefCountedBase { 00046 mutable unsigned ref_cnt; 00047 00048 public: 00049 RefCountedBase() : ref_cnt(0) {} 00050 RefCountedBase(const RefCountedBase &) : ref_cnt(0) {} 00051 00052 void Retain() const { ++ref_cnt; } 00053 void Release() const { 00054 assert (ref_cnt > 0 && "Reference count is already zero."); 00055 if (--ref_cnt == 0) delete static_cast<const Derived*>(this); 00056 } 00057 }; 00058 00059 //===----------------------------------------------------------------------===// 00060 /// RefCountedBaseVPTR - A class that has the same function as 00061 /// RefCountedBase, but with a virtual destructor. Should be used 00062 /// instead of RefCountedBase for classes that already have virtual 00063 /// methods to enforce dynamic allocation via 'new'. Classes that 00064 /// inherit from RefCountedBaseVPTR can't be allocated on stack - 00065 /// attempting to do this will produce a compile error. 00066 //===----------------------------------------------------------------------===// 00067 class RefCountedBaseVPTR { 00068 mutable unsigned ref_cnt; 00069 virtual void anchor(); 00070 00071 protected: 00072 RefCountedBaseVPTR() : ref_cnt(0) {} 00073 RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {} 00074 00075 virtual ~RefCountedBaseVPTR() {} 00076 00077 void Retain() const { ++ref_cnt; } 00078 void Release() const { 00079 assert (ref_cnt > 0 && "Reference count is already zero."); 00080 if (--ref_cnt == 0) delete this; 00081 } 00082 00083 template <typename T> 00084 friend struct IntrusiveRefCntPtrInfo; 00085 }; 00086 00087 00088 template <typename T> struct IntrusiveRefCntPtrInfo { 00089 static void retain(T *obj) { obj->Retain(); } 00090 static void release(T *obj) { obj->Release(); } 00091 }; 00092 00093 /// \brief A thread-safe version of \c llvm::RefCountedBase. 00094 /// 00095 /// A generic base class for objects that wish to have their lifetimes managed 00096 /// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to 00097 /// obtain such functionality, and are typically handled with 00098 /// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the 00099 /// management of reference counts. 00100 template <class Derived> 00101 class ThreadSafeRefCountedBase { 00102 mutable std::atomic<int> RefCount; 00103 00104 protected: 00105 ThreadSafeRefCountedBase() : RefCount(0) {} 00106 00107 public: 00108 void Retain() const { ++RefCount; } 00109 00110 void Release() const { 00111 int NewRefCount = --RefCount; 00112 assert(NewRefCount >= 0 && "Reference count was already zero."); 00113 if (NewRefCount == 0) 00114 delete static_cast<const Derived*>(this); 00115 } 00116 }; 00117 00118 //===----------------------------------------------------------------------===// 00119 /// IntrusiveRefCntPtr - A template class that implements a "smart pointer" 00120 /// that assumes the wrapped object has a reference count associated 00121 /// with it that can be managed via calls to 00122 /// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers 00123 /// manage reference counts via the RAII idiom: upon creation of 00124 /// smart pointer the reference count of the wrapped object is 00125 /// incremented and upon destruction of the smart pointer the 00126 /// reference count is decremented. This class also safely handles 00127 /// wrapping NULL pointers. 00128 /// 00129 /// Reference counting is implemented via calls to 00130 /// Obj->Retain()/Obj->Release(). Release() is required to destroy 00131 /// the object when the reference count reaches zero. Inheriting from 00132 /// RefCountedBase/RefCountedBaseVPTR takes care of this 00133 /// automatically. 00134 //===----------------------------------------------------------------------===// 00135 template <typename T> 00136 class IntrusiveRefCntPtr { 00137 T* Obj; 00138 00139 public: 00140 typedef T element_type; 00141 00142 explicit IntrusiveRefCntPtr() : Obj(nullptr) {} 00143 00144 IntrusiveRefCntPtr(T* obj) : Obj(obj) { 00145 retain(); 00146 } 00147 00148 IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) { 00149 retain(); 00150 } 00151 00152 IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) { 00153 S.Obj = nullptr; 00154 } 00155 00156 template <class X> 00157 IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.get()) { 00158 S.Obj = 0; 00159 } 00160 00161 template <class X> 00162 IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S) 00163 : Obj(S.get()) { 00164 retain(); 00165 } 00166 00167 IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) { 00168 swap(S); 00169 return *this; 00170 } 00171 00172 ~IntrusiveRefCntPtr() { release(); } 00173 00174 T& operator*() const { return *Obj; } 00175 00176 T* operator->() const { return Obj; } 00177 00178 T* get() const { return Obj; } 00179 00180 LLVM_EXPLICIT operator bool() const { return Obj; } 00181 00182 void swap(IntrusiveRefCntPtr& other) { 00183 T* tmp = other.Obj; 00184 other.Obj = Obj; 00185 Obj = tmp; 00186 } 00187 00188 void reset() { 00189 release(); 00190 Obj = nullptr; 00191 } 00192 00193 void resetWithoutRelease() { 00194 Obj = 0; 00195 } 00196 00197 private: 00198 void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); } 00199 void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); } 00200 }; 00201 00202 template<class T, class U> 00203 inline bool operator==(const IntrusiveRefCntPtr<T>& A, 00204 const IntrusiveRefCntPtr<U>& B) 00205 { 00206 return A.get() == B.get(); 00207 } 00208 00209 template<class T, class U> 00210 inline bool operator!=(const IntrusiveRefCntPtr<T>& A, 00211 const IntrusiveRefCntPtr<U>& B) 00212 { 00213 return A.get() != B.get(); 00214 } 00215 00216 template<class T, class U> 00217 inline bool operator==(const IntrusiveRefCntPtr<T>& A, 00218 U* B) 00219 { 00220 return A.get() == B; 00221 } 00222 00223 template<class T, class U> 00224 inline bool operator!=(const IntrusiveRefCntPtr<T>& A, 00225 U* B) 00226 { 00227 return A.get() != B; 00228 } 00229 00230 template<class T, class U> 00231 inline bool operator==(T* A, 00232 const IntrusiveRefCntPtr<U>& B) 00233 { 00234 return A == B.get(); 00235 } 00236 00237 template<class T, class U> 00238 inline bool operator!=(T* A, 00239 const IntrusiveRefCntPtr<U>& B) 00240 { 00241 return A != B.get(); 00242 } 00243 00244 template <class T> 00245 bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { 00246 return !B; 00247 } 00248 00249 template <class T> 00250 bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { 00251 return B == A; 00252 } 00253 00254 template <class T> 00255 bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { 00256 return !(A == B); 00257 } 00258 00259 template <class T> 00260 bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { 00261 return !(A == B); 00262 } 00263 00264 //===----------------------------------------------------------------------===// 00265 // LLVM-style downcasting support for IntrusiveRefCntPtr objects 00266 //===----------------------------------------------------------------------===// 00267 00268 template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > { 00269 typedef T* SimpleType; 00270 static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) { 00271 return Val.get(); 00272 } 00273 }; 00274 00275 template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > { 00276 typedef /*const*/ T* SimpleType; 00277 static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { 00278 return Val.get(); 00279 } 00280 }; 00281 00282 } // end namespace llvm 00283 00284 #endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H