1 //== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- C++ -*-==// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines IntrusiveRefCntPtr, a template class that 11 // implements a "smart" pointer for objects that maintain their own 12 // internal reference count, and RefCountedBase/RefCountedBaseVPTR, two 13 // generic base classes for objects that wish to have their lifetimes 14 // managed using reference counting. 15 // 16 // IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added 17 // LLVM-style casting. 18 // 19 //===----------------------------------------------------------------------===// 20 21 #ifndef LLVM_ADT_INTRUSIVE_REF_CNT_PTR 22 #define LLVM_ADT_INTRUSIVE_REF_CNT_PTR 23 24 #include <cassert> 25 26 #include "llvm/Support/Casting.h" 27 28 namespace llvm { 29 30 template <class T> 31 class IntrusiveRefCntPtr; 32 33 //===----------------------------------------------------------------------===// 34 /// RefCountedBase - A generic base class for objects that wish to 35 /// have their lifetimes managed using reference counts. Classes 36 /// subclass RefCountedBase to obtain such functionality, and are 37 /// typically handled with IntrusivePtr "smart pointers" (see below) 38 /// which automatically handle the management of reference counts. 39 /// Objects that subclass RefCountedBase should not be allocated on 40 /// the stack, as invoking "delete" (which is called when the 41 /// reference count hits 0) on such objects is an error. 42 //===----------------------------------------------------------------------===// 43 template <class Derived> 44 class RefCountedBase { 45 mutable unsigned ref_cnt; 46 47 public: RefCountedBase()48 RefCountedBase() : ref_cnt(0) {} 49 Retain()50 void Retain() const { ++ref_cnt; } Release()51 void Release() const { 52 assert (ref_cnt > 0 && "Reference count is already zero."); 53 if (--ref_cnt == 0) delete static_cast<const Derived*>(this); 54 } 55 }; 56 57 //===----------------------------------------------------------------------===// 58 /// RefCountedBaseVPTR - A class that has the same function as 59 /// RefCountedBase, but with a virtual destructor. Should be used 60 /// instead of RefCountedBase for classes that already have virtual 61 /// methods to enforce dynamic allocation via 'new'. Classes that 62 /// inherit from RefCountedBaseVPTR can't be allocated on stack - 63 /// attempting to do this will produce a compile error. 64 //===----------------------------------------------------------------------===// 65 class RefCountedBaseVPTR { 66 mutable unsigned ref_cnt; 67 68 protected: RefCountedBaseVPTR()69 RefCountedBaseVPTR() : ref_cnt(0) {} ~RefCountedBaseVPTR()70 virtual ~RefCountedBaseVPTR() {} 71 Retain()72 void Retain() const { ++ref_cnt; } Release()73 void Release() const { 74 assert (ref_cnt > 0 && "Reference count is already zero."); 75 if (--ref_cnt == 0) delete this; 76 } 77 78 template <typename T> 79 friend class IntrusiveRefCntPtr; 80 }; 81 82 //===----------------------------------------------------------------------===// 83 /// IntrusiveRefCntPtr - A template class that implements a "smart pointer" 84 /// that assumes the wrapped object has a reference count associated 85 /// with it that can be managed via calls to 86 /// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers 87 /// manage reference counts via the RAII idiom: upon creation of 88 /// smart pointer the reference count of the wrapped object is 89 /// incremented and upon destruction of the smart pointer the 90 /// reference count is decremented. This class also safely handles 91 /// wrapping NULL pointers. 92 /// 93 /// Reference counting is implemented via calls to 94 /// Obj->Retain()/Obj->Release(). Release() is required to destroy 95 /// the object when the reference count reaches zero. Inheriting from 96 /// RefCountedBase/RefCountedBaseVPTR takes care of this 97 /// automatically. 98 //===----------------------------------------------------------------------===// 99 template <typename T> 100 class IntrusiveRefCntPtr { 101 T* Obj; 102 typedef IntrusiveRefCntPtr this_type; 103 public: 104 typedef T element_type; 105 IntrusiveRefCntPtr()106 explicit IntrusiveRefCntPtr() : Obj(0) {} 107 IntrusiveRefCntPtr(T * obj)108 explicit IntrusiveRefCntPtr(T* obj) : Obj(obj) { 109 retain(); 110 } 111 IntrusiveRefCntPtr(const IntrusiveRefCntPtr & S)112 IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) { 113 retain(); 114 } 115 116 template <class X> IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X> & S)117 IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S) 118 : Obj(S.getPtr()) { 119 retain(); 120 } 121 122 IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr& S) { 123 replace(S.getPtr()); 124 return *this; 125 } 126 127 template <class X> 128 IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr<X>& S) { 129 replace(S.getPtr()); 130 return *this; 131 } 132 133 IntrusiveRefCntPtr& operator=(T * S) { 134 replace(S); 135 return *this; 136 } 137 ~IntrusiveRefCntPtr()138 ~IntrusiveRefCntPtr() { release(); } 139 140 T& operator*() const { return *Obj; } 141 142 T* operator->() const { return Obj; } 143 getPtr()144 T* getPtr() const { return Obj; } 145 146 typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const; unspecified_bool_type()147 operator unspecified_bool_type() const { 148 return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr; 149 } 150 swap(IntrusiveRefCntPtr & other)151 void swap(IntrusiveRefCntPtr& other) { 152 T* tmp = other.Obj; 153 other.Obj = Obj; 154 Obj = tmp; 155 } 156 resetWithoutRelease()157 void resetWithoutRelease() { 158 Obj = 0; 159 } 160 161 private: retain()162 void retain() { if (Obj) Obj->Retain(); } release()163 void release() { if (Obj) Obj->Release(); } 164 replace(T * S)165 void replace(T* S) { 166 this_type(S).swap(*this); 167 } 168 }; 169 170 template<class T, class U> 171 inline bool operator==(const IntrusiveRefCntPtr<T>& A, 172 const IntrusiveRefCntPtr<U>& B) 173 { 174 return A.getPtr() == B.getPtr(); 175 } 176 177 template<class T, class U> 178 inline bool operator!=(const IntrusiveRefCntPtr<T>& A, 179 const IntrusiveRefCntPtr<U>& B) 180 { 181 return A.getPtr() != B.getPtr(); 182 } 183 184 template<class T, class U> 185 inline bool operator==(const IntrusiveRefCntPtr<T>& A, 186 U* B) 187 { 188 return A.getPtr() == B; 189 } 190 191 template<class T, class U> 192 inline bool operator!=(const IntrusiveRefCntPtr<T>& A, 193 U* B) 194 { 195 return A.getPtr() != B; 196 } 197 198 template<class T, class U> 199 inline bool operator==(T* A, 200 const IntrusiveRefCntPtr<U>& B) 201 { 202 return A == B.getPtr(); 203 } 204 205 template<class T, class U> 206 inline bool operator!=(T* A, 207 const IntrusiveRefCntPtr<U>& B) 208 { 209 return A != B.getPtr(); 210 } 211 212 //===----------------------------------------------------------------------===// 213 // LLVM-style downcasting support for IntrusiveRefCntPtr objects 214 //===----------------------------------------------------------------------===// 215 216 template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > { 217 typedef T* SimpleType; 218 static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { 219 return Val.getPtr(); 220 } 221 }; 222 223 template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > { 224 typedef T* SimpleType; 225 static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { 226 return Val.getPtr(); 227 } 228 }; 229 230 } // end namespace llvm 231 232 #endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR 233