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_INTRUSIVE_REF_CNT_PTR 00022 #define LLVM_ADT_INTRUSIVE_REF_CNT_PTR 00023 00024 #include <cassert> 00025 00026 #include "llvm/Support/Casting.h" 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 IntrusivePtr "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 unsigned ref_cnt; 00046 00047 protected: 00048 RefCountedBase() : ref_cnt(0) {} 00049 00050 void Retain() { ++ref_cnt; } 00051 void Release() { 00052 assert (ref_cnt > 0 && "Reference count is already zero."); 00053 if (--ref_cnt == 0) delete static_cast<Derived*>(this); 00054 } 00055 00056 friend class IntrusiveRefCntPtr<Derived>; 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 template <class Derived> 00068 class RefCountedBaseVPTR { 00069 unsigned ref_cnt; 00070 00071 protected: 00072 RefCountedBaseVPTR() : ref_cnt(0) {} 00073 virtual ~RefCountedBaseVPTR() {} 00074 00075 void Retain() { ++ref_cnt; } 00076 void Release() { 00077 assert (ref_cnt > 0 && "Reference count is already zero."); 00078 if (--ref_cnt == 0) delete this; 00079 } 00080 00081 friend class IntrusiveRefCntPtr<Derived>; 00082 }; 00083 00084 //===----------------------------------------------------------------------===// 00085 /// IntrusiveRefCntPtr - A template class that implements a "smart pointer" 00086 /// that assumes the wrapped object has a reference count associated 00087 /// with it that can be managed via calls to 00088 /// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers 00089 /// manage reference counts via the RAII idiom: upon creation of 00090 /// smart pointer the reference count of the wrapped object is 00091 /// incremented and upon destruction of the smart pointer the 00092 /// reference count is decremented. This class also safely handles 00093 /// wrapping NULL pointers. 00094 /// 00095 /// Reference counting is implemented via calls to 00096 /// Obj->Retain()/Obj->Release(). Release() is required to destroy 00097 /// the object when the reference count reaches zero. Inheriting from 00098 /// RefCountedBase/RefCountedBaseVPTR takes care of this 00099 /// automatically. 00100 //===----------------------------------------------------------------------===// 00101 template <typename T> 00102 class IntrusiveRefCntPtr { 00103 T* Obj; 00104 typedef IntrusiveRefCntPtr this_type; 00105 public: 00106 typedef T element_type; 00107 00108 explicit IntrusiveRefCntPtr() : Obj(0) {} 00109 00110 explicit IntrusiveRefCntPtr(T* obj) : Obj(obj) { 00111 retain(); 00112 } 00113 00114 IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) { 00115 retain(); 00116 } 00117 00118 template <class X> 00119 IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S) 00120 : Obj(S.getPtr()) { 00121 retain(); 00122 } 00123 00124 IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr& S) { 00125 replace(S.getPtr()); 00126 return *this; 00127 } 00128 00129 template <class X> 00130 IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr<X>& S) { 00131 replace(S.getPtr()); 00132 return *this; 00133 } 00134 00135 IntrusiveRefCntPtr& operator=(T * S) { 00136 replace(S); 00137 return *this; 00138 } 00139 00140 ~IntrusiveRefCntPtr() { release(); } 00141 00142 T& operator*() const { return *Obj; } 00143 00144 T* operator->() const { return Obj; } 00145 00146 T* getPtr() const { return Obj; } 00147 00148 typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const; 00149 operator unspecified_bool_type() const { 00150 return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr; 00151 } 00152 00153 void swap(IntrusiveRefCntPtr& other) { 00154 T* tmp = other.Obj; 00155 other.Obj = Obj; 00156 Obj = tmp; 00157 } 00158 00159 private: 00160 void retain() { if (Obj) Obj->Retain(); } 00161 void release() { if (Obj) Obj->Release(); } 00162 00163 void replace(T* S) { 00164 this_type(S).swap(*this); 00165 } 00166 }; 00167 00168 template<class T, class U> 00169 inline bool operator==(const IntrusiveRefCntPtr<T>& A, 00170 const IntrusiveRefCntPtr<U>& B) 00171 { 00172 return A.getPtr() == B.getPtr(); 00173 } 00174 00175 template<class T, class U> 00176 inline bool operator!=(const IntrusiveRefCntPtr<T>& A, 00177 const IntrusiveRefCntPtr<U>& B) 00178 { 00179 return A.getPtr() != B.getPtr(); 00180 } 00181 00182 template<class T, class U> 00183 inline bool operator==(const IntrusiveRefCntPtr<T>& A, 00184 U* B) 00185 { 00186 return A.getPtr() == B; 00187 } 00188 00189 template<class T, class U> 00190 inline bool operator!=(const IntrusiveRefCntPtr<T>& A, 00191 U* B) 00192 { 00193 return A.getPtr() != B; 00194 } 00195 00196 template<class T, class U> 00197 inline bool operator==(T* A, 00198 const IntrusiveRefCntPtr<U>& B) 00199 { 00200 return A == B.getPtr(); 00201 } 00202 00203 template<class T, class U> 00204 inline bool operator!=(T* A, 00205 const IntrusiveRefCntPtr<U>& B) 00206 { 00207 return A != B.getPtr(); 00208 } 00209 00210 //===----------------------------------------------------------------------===// 00211 // LLVM-style downcasting support for IntrusiveRefCntPtr objects 00212 //===----------------------------------------------------------------------===// 00213 00214 template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > { 00215 typedef T* SimpleType; 00216 static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { 00217 return Val.getPtr(); 00218 } 00219 }; 00220 00221 template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > { 00222 typedef T* SimpleType; 00223 static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { 00224 return Val.getPtr(); 00225 } 00226 }; 00227 00228 } // end namespace llvm 00229 00230 #endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR