1 //== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ----*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
16 // IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added
17 // LLVM-style casting.
19 //===----------------------------------------------------------------------===//
21 #ifndef LLVM_ADT_INTRUSIVE_REF_CNT_PTR
22 #define LLVM_ADT_INTRUSIVE_REF_CNT_PTR
27 #include "llvm/Support/Casting.h"
29 // Forward declarations
36 class RefCountedBaseVPTR;
40 void IntrusivePtrAddRef(llvm::RefCountedBase<T>*);
43 void IntrusivePtrRelease(llvm::RefCountedBase<T>*);
46 void IntrusivePtrAddRef(llvm::RefCountedBaseVPTR<T>*);
49 void IntrusivePtrRelease(llvm::RefCountedBaseVPTR<T>*);
54 //===----------------------------------------------------------------------===//
55 /// RefCountedBase - A generic base class for objects that wish to
56 /// have their lifetimes managed using reference counts. Classes
57 /// subclass RefCountedBase to obtain such functionality, and are
58 /// typically handled with IntrusivePtr "smart pointers" (see below)
59 /// which automatically handle the management of reference counts.
60 /// Objects that subclass RefCountedBase should not be allocated on
61 /// the stack, as invoking "delete" (which is called when the
62 /// reference count hits 0) on such objects is an error.
63 //===----------------------------------------------------------------------===//
64 template <class Derived>
65 class RefCountedBase {
69 RefCountedBase() : ref_cnt(0) {}
71 void Retain() { ++ref_cnt; }
73 assert (ref_cnt > 0 && "Reference count is already zero.");
74 if (--ref_cnt == 0) delete static_cast<Derived*>(this);
77 friend void IntrusivePtrAddRef<Derived>(RefCountedBase<Derived>*);
78 friend void IntrusivePtrRelease<Derived>(RefCountedBase<Derived>*);
81 //===----------------------------------------------------------------------===//
82 /// RefCountedBaseVPTR - A class that has the same function as
83 /// RefCountedBase, but with a virtual destructor. Should be used
84 /// instead of RefCountedBase for classes that have virtual
85 /// destructors. Classes that inherit from RefCountedBaseVPTR can't
86 /// be allocated on stack.
87 //===----------------------------------------------------------------------===//
88 template <class Derived>
89 class RefCountedBaseVPTR {
93 RefCountedBaseVPTR() : ref_cnt(0) {}
94 virtual ~RefCountedBaseVPTR() {}
96 void Retain() { ++ref_cnt; }
98 assert (ref_cnt > 0 && "Reference count is already zero.");
99 if (--ref_cnt == 0) delete this;
102 friend void IntrusivePtrAddRef<Derived>(RefCountedBaseVPTR<Derived>*);
103 friend void IntrusivePtrRelease<Derived>(RefCountedBaseVPTR<Derived>*);
108 //===----------------------------------------------------------------------===//
109 /// IntrusivePtrAddRef - A utility function used by IntrusiveRefCntPtr
110 /// to increment the reference count of an RefCountedBase-derived object.
111 //===----------------------------------------------------------------------===//
113 void IntrusivePtrAddRef(llvm::RefCountedBase<T>* O) {
117 //===----------------------------------------------------------------------===//
118 /// IntrusivePtrRelease - The complement of IntrusivePtrAddRef;
119 /// decrements the reference count of a RefCounted object.
120 //===----------------------------------------------------------------------===//
122 void IntrusivePtrRelease(llvm::RefCountedBase<T>* O) {
129 //===----------------------------------------------------------------------===//
130 /// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
131 /// that assumes the wrapped object has a reference count associated
132 /// with it that can be managed via calls to
133 /// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers
134 /// manage reference counts via the RAII idiom: upon creation of
135 /// smart pointer the reference count of the wrapped object is
136 /// incremented and upon destruction of the smart pointer the
137 /// reference count is decremented. This class also safely handles
138 /// wrapping NULL pointers.
139 //===----------------------------------------------------------------------===//
140 template <typename T>
141 class IntrusiveRefCntPtr {
143 typedef IntrusiveRefCntPtr this_type;
145 typedef T element_type;
147 explicit IntrusiveRefCntPtr() : Obj(NULL) {}
149 explicit IntrusiveRefCntPtr(T* obj) : Obj(obj) {
153 IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) {
158 IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S)
164 IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr<X>& S) {
169 IntrusiveRefCntPtr& operator=(T * S) {
174 ~IntrusiveRefCntPtr() { release(); }
176 T& operator*() const { return *Obj; }
178 T* operator->() const { return Obj; }
180 T* getPtr() const { return Obj; }
182 typedef T * IntrusiveRefCntPtr::*unspecified_bool_type;
183 operator unspecified_bool_type() const {
184 return Obj == NULL ? NULL : &IntrusiveRefCntPtr::getPtr;
187 void swap(IntrusiveRefCntPtr& other) {
194 void retain() { if (Obj) IntrusivePtrAddRef(Obj); }
195 void release() { if (Obj) IntrusivePtrRelease(Obj); }
198 this_type(S).swap(this);
202 template<class T, class U>
203 inline bool operator==(const IntrusiveRefCntPtr<T>& A,
204 const IntrusiveRefCntPtr<U>& B)
206 return A.getPtr() == B.getPtr();
209 template<class T, class U>
210 inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
211 const IntrusiveRefCntPtr<U>& B)
213 return A.getPtr() != B.getPtr();
216 template<class T, class U>
217 inline bool operator==(const IntrusiveRefCntPtr<T>& A,
220 return A.getPtr() == B;
223 template<class T, class U>
224 inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
227 return A.getPtr() != B;
230 template<class T, class U>
231 inline bool operator==(T* A,
232 const IntrusiveRefCntPtr<U>& B)
234 return A == B.getPtr();
237 template<class T, class U>
238 inline bool operator!=(T* A,
239 const IntrusiveRefCntPtr<U>& B)
241 return A != B.getPtr();
244 //===----------------------------------------------------------------------===//
245 // LLVM-style downcasting support for IntrusiveRefCntPtr objects
246 //===----------------------------------------------------------------------===//
248 template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
249 typedef T* SimpleType;
250 static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
255 template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > {
256 typedef T* SimpleType;
257 static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
262 } // end namespace llvm
264 #endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR