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 <memory> 00027 00028 namespace llvm { 00029 00030 template <class T> 00031 class IntrusiveRefCntPtr; 00032 00033 //===----------------------------------------------------------------------===// 00034 /// RefCountedBase - A generic base class for objects that wish to 00035 /// have their lifetimes managed using reference counts. Classes 00036 /// subclass RefCountedBase to obtain such functionality, and are 00037 /// typically handled with IntrusiveRefCntPtr "smart pointers" (see below) 00038 /// which automatically handle the management of reference counts. 00039 /// Objects that subclass RefCountedBase should not be allocated on 00040 /// the stack, as invoking "delete" (which is called when the 00041 /// reference count hits 0) on such objects is an error. 00042 //===----------------------------------------------------------------------===// 00043 template <class Derived> 00044 class RefCountedBase { 00045 mutable unsigned ref_cnt; 00046 00047 public: 00048 RefCountedBase() : ref_cnt(0) {} 00049 RefCountedBase(const RefCountedBase &) : ref_cnt(0) {} 00050 00051 void Retain() const { ++ref_cnt; } 00052 void Release() const { 00053 assert (ref_cnt > 0 && "Reference count is already zero."); 00054 if (--ref_cnt == 0) delete static_cast<const Derived*>(this); 00055 } 00056 }; 00057 00058 //===----------------------------------------------------------------------===// 00059 /// RefCountedBaseVPTR - A class that has the same function as 00060 /// RefCountedBase, but with a virtual destructor. Should be used 00061 /// instead of RefCountedBase for classes that already have virtual 00062 /// methods to enforce dynamic allocation via 'new'. Classes that 00063 /// inherit from RefCountedBaseVPTR can't be allocated on stack - 00064 /// attempting to do this will produce a compile error. 00065 //===----------------------------------------------------------------------===// 00066 class RefCountedBaseVPTR { 00067 mutable unsigned ref_cnt; 00068 virtual void anchor(); 00069 00070 protected: 00071 RefCountedBaseVPTR() : ref_cnt(0) {} 00072 RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {} 00073 00074 virtual ~RefCountedBaseVPTR() {} 00075 00076 void Retain() const { ++ref_cnt; } 00077 void Release() const { 00078 assert (ref_cnt > 0 && "Reference count is already zero."); 00079 if (--ref_cnt == 0) delete this; 00080 } 00081 00082 template <typename T> 00083 friend struct IntrusiveRefCntPtrInfo; 00084 }; 00085 00086 00087 template <typename T> struct IntrusiveRefCntPtrInfo { 00088 static void retain(T *obj) { obj->Retain(); } 00089 static void release(T *obj) { obj->Release(); } 00090 }; 00091 00092 //===----------------------------------------------------------------------===// 00093 /// IntrusiveRefCntPtr - A template class that implements a "smart pointer" 00094 /// that assumes the wrapped object has a reference count associated 00095 /// with it that can be managed via calls to 00096 /// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers 00097 /// manage reference counts via the RAII idiom: upon creation of 00098 /// smart pointer the reference count of the wrapped object is 00099 /// incremented and upon destruction of the smart pointer the 00100 /// reference count is decremented. This class also safely handles 00101 /// wrapping NULL pointers. 00102 /// 00103 /// Reference counting is implemented via calls to 00104 /// Obj->Retain()/Obj->Release(). Release() is required to destroy 00105 /// the object when the reference count reaches zero. Inheriting from 00106 /// RefCountedBase/RefCountedBaseVPTR takes care of this 00107 /// automatically. 00108 //===----------------------------------------------------------------------===// 00109 template <typename T> 00110 class IntrusiveRefCntPtr { 00111 T* Obj; 00112 typedef IntrusiveRefCntPtr this_type; 00113 public: 00114 typedef T element_type; 00115 00116 explicit IntrusiveRefCntPtr() : Obj(0) {} 00117 00118 IntrusiveRefCntPtr(T* obj) : Obj(obj) { 00119 retain(); 00120 } 00121 00122 IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) { 00123 retain(); 00124 } 00125 00126 #if LLVM_HAS_RVALUE_REFERENCES 00127 IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) { 00128 S.Obj = 0; 00129 } 00130 00131 template <class X> 00132 IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.getPtr()) { 00133 S.Obj = 0; 00134 } 00135 #endif 00136 00137 template <class X> 00138 IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S) 00139 : Obj(S.getPtr()) { 00140 retain(); 00141 } 00142 00143 IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) { 00144 swap(S); 00145 return *this; 00146 } 00147 00148 ~IntrusiveRefCntPtr() { release(); } 00149 00150 T& operator*() const { return *Obj; } 00151 00152 T* operator->() const { return Obj; } 00153 00154 T* getPtr() const { return Obj; } 00155 00156 typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const; 00157 operator unspecified_bool_type() const { 00158 return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr; 00159 } 00160 00161 void swap(IntrusiveRefCntPtr& other) { 00162 T* tmp = other.Obj; 00163 other.Obj = Obj; 00164 Obj = tmp; 00165 } 00166 00167 void reset() { 00168 release(); 00169 Obj = 0; 00170 } 00171 00172 void resetWithoutRelease() { 00173 Obj = 0; 00174 } 00175 00176 private: 00177 void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); } 00178 void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); } 00179 }; 00180 00181 template<class T, class U> 00182 inline bool operator==(const IntrusiveRefCntPtr<T>& A, 00183 const IntrusiveRefCntPtr<U>& B) 00184 { 00185 return A.getPtr() == B.getPtr(); 00186 } 00187 00188 template<class T, class U> 00189 inline bool operator!=(const IntrusiveRefCntPtr<T>& A, 00190 const IntrusiveRefCntPtr<U>& B) 00191 { 00192 return A.getPtr() != B.getPtr(); 00193 } 00194 00195 template<class T, class U> 00196 inline bool operator==(const IntrusiveRefCntPtr<T>& A, 00197 U* B) 00198 { 00199 return A.getPtr() == B; 00200 } 00201 00202 template<class T, class U> 00203 inline bool operator!=(const IntrusiveRefCntPtr<T>& A, 00204 U* B) 00205 { 00206 return A.getPtr() != B; 00207 } 00208 00209 template<class T, class U> 00210 inline bool operator==(T* A, 00211 const IntrusiveRefCntPtr<U>& B) 00212 { 00213 return A == B.getPtr(); 00214 } 00215 00216 template<class T, class U> 00217 inline bool operator!=(T* A, 00218 const IntrusiveRefCntPtr<U>& B) 00219 { 00220 return A != B.getPtr(); 00221 } 00222 00223 //===----------------------------------------------------------------------===// 00224 // LLVM-style downcasting support for IntrusiveRefCntPtr objects 00225 //===----------------------------------------------------------------------===// 00226 00227 template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > { 00228 typedef T* SimpleType; 00229 static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) { 00230 return Val.getPtr(); 00231 } 00232 }; 00233 00234 template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > { 00235 typedef /*const*/ T* SimpleType; 00236 static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { 00237 return Val.getPtr(); 00238 } 00239 }; 00240 00241 } // end namespace llvm 00242 00243 #endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H