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