/src/keystone/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h
Line | Count | Source |
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_INTRUSIVEREFCNTPTR_H |
22 | | #define LLVM_ADT_INTRUSIVEREFCNTPTR_H |
23 | | |
24 | | #include <atomic> |
25 | | #include <cassert> |
26 | | #include <cstddef> |
27 | | |
28 | | namespace llvm_ks { |
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 IntrusiveRefCntPtr "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: |
48 | | RefCountedBase() : ref_cnt(0) {} |
49 | | RefCountedBase(const RefCountedBase &) : ref_cnt(0) {} |
50 | | |
51 | 0 | void Retain() const { ++ref_cnt; }Unexecuted instantiation: llvm_ks::RefCountedBase<llvm_ks::sys::fs::detail::DirIterState>::Retain() const Unexecuted instantiation: llvm_ks::RefCountedBase<llvm_ks::sys::fs::detail::RecDirIterState>::Retain() const |
52 | 0 | void Release() const { |
53 | 0 | assert (ref_cnt > 0 && "Reference count is already zero."); |
54 | 0 | if (--ref_cnt == 0) delete static_cast<const Derived*>(this); |
55 | 0 | } Unexecuted instantiation: llvm_ks::RefCountedBase<llvm_ks::sys::fs::detail::DirIterState>::Release() const Unexecuted instantiation: llvm_ks::RefCountedBase<llvm_ks::sys::fs::detail::RecDirIterState>::Release() const |
56 | | }; |
57 | | |
58 | | //===----------------------------------------------------------------------===// |
59 | | /// RefCountedBaseVPTR - A class that has the same function as |
60 | | /// RefCountedBase, but with a virtual destructor. Should be used |
61 | | /// instead of RefCountedBase for classes that already have virtual |
62 | | /// methods to enforce dynamic allocation via 'new'. Classes that |
63 | | /// inherit from RefCountedBaseVPTR can't be allocated on stack - |
64 | | /// attempting to do this will produce a compile error. |
65 | | //===----------------------------------------------------------------------===// |
66 | | class RefCountedBaseVPTR { |
67 | | mutable unsigned ref_cnt; |
68 | | |
69 | | protected: |
70 | 0 | RefCountedBaseVPTR() : ref_cnt(0) {} |
71 | 0 | RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {} |
72 | | |
73 | 0 | virtual ~RefCountedBaseVPTR() {} |
74 | | |
75 | 0 | void Retain() const { ++ref_cnt; } |
76 | 0 | void Release() const { |
77 | 0 | assert (ref_cnt > 0 && "Reference count is already zero."); |
78 | 0 | if (--ref_cnt == 0) delete this; |
79 | 0 | } |
80 | | |
81 | | template <typename T> |
82 | | friend struct IntrusiveRefCntPtrInfo; |
83 | | }; |
84 | | |
85 | | |
86 | | template <typename T> struct IntrusiveRefCntPtrInfo { |
87 | 0 | static void retain(T *obj) { obj->Retain(); }Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtrInfo<llvm_ks::sys::fs::detail::DirIterState>::retain(llvm_ks::sys::fs::detail::DirIterState*) Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtrInfo<llvm_ks::sys::fs::detail::RecDirIterState>::retain(llvm_ks::sys::fs::detail::RecDirIterState*) |
88 | 0 | static void release(T *obj) { obj->Release(); }Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtrInfo<llvm_ks::sys::fs::detail::DirIterState>::release(llvm_ks::sys::fs::detail::DirIterState*) Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtrInfo<llvm_ks::sys::fs::detail::RecDirIterState>::release(llvm_ks::sys::fs::detail::RecDirIterState*) |
89 | | }; |
90 | | |
91 | | /// \brief A thread-safe version of \c llvm_ks::RefCountedBase. |
92 | | /// |
93 | | /// A generic base class for objects that wish to have their lifetimes managed |
94 | | /// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to |
95 | | /// obtain such functionality, and are typically handled with |
96 | | /// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the |
97 | | /// management of reference counts. |
98 | | template <class Derived> |
99 | | class ThreadSafeRefCountedBase { |
100 | | mutable std::atomic<int> RefCount; |
101 | | |
102 | | protected: |
103 | | ThreadSafeRefCountedBase() : RefCount(0) {} |
104 | | |
105 | | public: |
106 | | void Retain() const { ++RefCount; } |
107 | | |
108 | | void Release() const { |
109 | | int NewRefCount = --RefCount; |
110 | | assert(NewRefCount >= 0 && "Reference count was already zero."); |
111 | | if (NewRefCount == 0) |
112 | | delete static_cast<const Derived*>(this); |
113 | | } |
114 | | }; |
115 | | |
116 | | //===----------------------------------------------------------------------===// |
117 | | /// IntrusiveRefCntPtr - A template class that implements a "smart pointer" |
118 | | /// that assumes the wrapped object has a reference count associated |
119 | | /// with it that can be managed via calls to |
120 | | /// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers |
121 | | /// manage reference counts via the RAII idiom: upon creation of |
122 | | /// smart pointer the reference count of the wrapped object is |
123 | | /// incremented and upon destruction of the smart pointer the |
124 | | /// reference count is decremented. This class also safely handles |
125 | | /// wrapping NULL pointers. |
126 | | /// |
127 | | /// Reference counting is implemented via calls to |
128 | | /// Obj->Retain()/Obj->Release(). Release() is required to destroy |
129 | | /// the object when the reference count reaches zero. Inheriting from |
130 | | /// RefCountedBase/RefCountedBaseVPTR takes care of this |
131 | | /// automatically. |
132 | | //===----------------------------------------------------------------------===// |
133 | | template <typename T> |
134 | | class IntrusiveRefCntPtr { |
135 | | T* Obj; |
136 | | |
137 | | public: |
138 | | typedef T element_type; |
139 | | |
140 | | explicit IntrusiveRefCntPtr() : Obj(nullptr) {} |
141 | | |
142 | | IntrusiveRefCntPtr(T* obj) : Obj(obj) { |
143 | | retain(); |
144 | | } |
145 | | |
146 | | IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) { |
147 | | retain(); |
148 | | } |
149 | | |
150 | | IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) { |
151 | | S.Obj = nullptr; |
152 | | } |
153 | | |
154 | | template <class X> |
155 | | IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.get()) { |
156 | | S.Obj = nullptr; |
157 | | } |
158 | | |
159 | | template <class X> |
160 | | IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S) |
161 | | : Obj(S.get()) { |
162 | | retain(); |
163 | | } |
164 | | |
165 | 0 | IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) { |
166 | 0 | swap(S); |
167 | 0 | return *this; |
168 | 0 | } |
169 | | |
170 | | ~IntrusiveRefCntPtr() { release(); } |
171 | | |
172 | 0 | T& operator*() const { return *Obj; } |
173 | | |
174 | 0 | T* operator->() const { return Obj; }Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::DirIterState>::operator->() const Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::RecDirIterState>::operator->() const |
175 | | |
176 | 0 | T* get() const { return Obj; }Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::DirIterState>::get() const Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::RecDirIterState>::get() const |
177 | | |
178 | 0 | explicit operator bool() const { return Obj; }Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::DirIterState>::operator bool() const Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::RecDirIterState>::operator bool() const |
179 | | |
180 | 0 | void swap(IntrusiveRefCntPtr& other) { |
181 | 0 | T* tmp = other.Obj; |
182 | 0 | other.Obj = Obj; |
183 | 0 | Obj = tmp; |
184 | 0 | } |
185 | | |
186 | 0 | void reset() { |
187 | 0 | release(); |
188 | 0 | Obj = nullptr; |
189 | 0 | } |
190 | | |
191 | | void resetWithoutRelease() { |
192 | | Obj = nullptr; |
193 | | } |
194 | | |
195 | | private: |
196 | 0 | void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); }Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::DirIterState>::retain() Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::RecDirIterState>::retain() |
197 | 0 | void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); }Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::DirIterState>::release() Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::RecDirIterState>::release() |
198 | | |
199 | | template <typename X> |
200 | | friend class IntrusiveRefCntPtr; |
201 | | }; |
202 | | |
203 | | template<class T, class U> |
204 | | inline bool operator==(const IntrusiveRefCntPtr<T>& A, |
205 | | const IntrusiveRefCntPtr<U>& B) |
206 | 0 | { |
207 | 0 | return A.get() == B.get(); |
208 | 0 | } Unexecuted instantiation: bool llvm_ks::operator==<llvm_ks::sys::fs::detail::DirIterState, llvm_ks::sys::fs::detail::DirIterState>(llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::DirIterState> const&, llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::DirIterState> const&) Unexecuted instantiation: bool llvm_ks::operator==<llvm_ks::sys::fs::detail::RecDirIterState, llvm_ks::sys::fs::detail::RecDirIterState>(llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::RecDirIterState> const&, llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::RecDirIterState> const&) |
209 | | |
210 | | template<class T, class U> |
211 | | inline bool operator!=(const IntrusiveRefCntPtr<T>& A, |
212 | | const IntrusiveRefCntPtr<U>& B) |
213 | | { |
214 | | return A.get() != B.get(); |
215 | | } |
216 | | |
217 | | template<class T, class U> |
218 | | inline bool operator==(const IntrusiveRefCntPtr<T>& A, |
219 | | U* B) |
220 | | { |
221 | | return A.get() == B; |
222 | | } |
223 | | |
224 | | template<class T, class U> |
225 | | inline bool operator!=(const IntrusiveRefCntPtr<T>& A, |
226 | | U* B) |
227 | | { |
228 | | return A.get() != B; |
229 | | } |
230 | | |
231 | | template<class T, class U> |
232 | | inline bool operator==(T* A, |
233 | | const IntrusiveRefCntPtr<U>& B) |
234 | | { |
235 | | return A == B.get(); |
236 | | } |
237 | | |
238 | | template<class T, class U> |
239 | | inline bool operator!=(T* A, |
240 | | const IntrusiveRefCntPtr<U>& B) |
241 | | { |
242 | | return A != B.get(); |
243 | | } |
244 | | |
245 | | template <class T> |
246 | | bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { |
247 | | return !B; |
248 | | } |
249 | | |
250 | | template <class T> |
251 | | bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { |
252 | | return B == A; |
253 | | } |
254 | | |
255 | | template <class T> |
256 | | bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { |
257 | | return !(A == B); |
258 | | } |
259 | | |
260 | | template <class T> |
261 | | bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { |
262 | | return !(A == B); |
263 | | } |
264 | | |
265 | | //===----------------------------------------------------------------------===// |
266 | | // LLVM-style downcasting support for IntrusiveRefCntPtr objects |
267 | | //===----------------------------------------------------------------------===// |
268 | | |
269 | | template <typename From> struct simplify_type; |
270 | | |
271 | | template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > { |
272 | | typedef T* SimpleType; |
273 | | static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) { |
274 | | return Val.get(); |
275 | | } |
276 | | }; |
277 | | |
278 | | template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > { |
279 | | typedef /*const*/ T* SimpleType; |
280 | | static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { |
281 | | return Val.get(); |
282 | | } |
283 | | }; |
284 | | |
285 | | } // end namespace llvm_ks |
286 | | |
287 | | #endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H |