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_INTRUSIVEREFCNTPTR_H
22 #define LLVM_ADT_INTRUSIVEREFCNTPTR_H
31 class IntrusiveRefCntPtr;
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;
48 RefCountedBase() : ref_cnt(0) {}
49 RefCountedBase(const RefCountedBase &) : ref_cnt(0) {}
51 void Retain() const { ++ref_cnt; }
52 void Release() const {
53 assert (ref_cnt > 0 && "Reference count is already zero.");
54 if (--ref_cnt == 0) delete static_cast<const Derived*>(this);
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 virtual void anchor();
71 RefCountedBaseVPTR() : ref_cnt(0) {}
72 RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {}
74 virtual ~RefCountedBaseVPTR() {}
76 void Retain() const { ++ref_cnt; }
77 void Release() const {
78 assert (ref_cnt > 0 && "Reference count is already zero.");
79 if (--ref_cnt == 0) delete this;
83 friend struct IntrusiveRefCntPtrInfo;
87 template <typename T> struct IntrusiveRefCntPtrInfo {
88 static void retain(T *obj) { obj->Retain(); }
89 static void release(T *obj) { obj->Release(); }
92 /// \brief A thread-safe version of \c llvm::RefCountedBase.
94 /// A generic base class for objects that wish to have their lifetimes managed
95 /// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to
96 /// obtain such functionality, and are typically handled with
97 /// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the
98 /// management of reference counts.
99 template <class Derived>
100 class ThreadSafeRefCountedBase {
101 mutable std::atomic<int> RefCount;
104 ThreadSafeRefCountedBase() : RefCount(0) {}
107 void Retain() const { ++RefCount; }
109 void Release() const {
110 int NewRefCount = --RefCount;
111 assert(NewRefCount >= 0 && "Reference count was already zero.");
112 if (NewRefCount == 0)
113 delete static_cast<const Derived*>(this);
117 //===----------------------------------------------------------------------===//
118 /// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
119 /// that assumes the wrapped object has a reference count associated
120 /// with it that can be managed via calls to
121 /// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers
122 /// manage reference counts via the RAII idiom: upon creation of
123 /// smart pointer the reference count of the wrapped object is
124 /// incremented and upon destruction of the smart pointer the
125 /// reference count is decremented. This class also safely handles
126 /// wrapping NULL pointers.
128 /// Reference counting is implemented via calls to
129 /// Obj->Retain()/Obj->Release(). Release() is required to destroy
130 /// the object when the reference count reaches zero. Inheriting from
131 /// RefCountedBase/RefCountedBaseVPTR takes care of this
133 //===----------------------------------------------------------------------===//
134 template <typename T>
135 class IntrusiveRefCntPtr {
139 typedef T element_type;
141 explicit IntrusiveRefCntPtr() : Obj(nullptr) {}
143 IntrusiveRefCntPtr(T* obj) : Obj(obj) {
147 IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) {
151 IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) {
156 IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.get()) {
161 IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S)
166 IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) {
171 ~IntrusiveRefCntPtr() { release(); }
173 T& operator*() const { return *Obj; }
175 T* operator->() const { return Obj; }
177 T* get() const { return Obj; }
179 explicit operator bool() const { return Obj; }
181 void swap(IntrusiveRefCntPtr& other) {
192 void resetWithoutRelease() {
197 void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); }
198 void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); }
200 template <typename X>
201 friend class IntrusiveRefCntPtr;
204 template<class T, class U>
205 inline bool operator==(const IntrusiveRefCntPtr<T>& A,
206 const IntrusiveRefCntPtr<U>& B)
208 return A.get() == B.get();
211 template<class T, class U>
212 inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
213 const IntrusiveRefCntPtr<U>& B)
215 return A.get() != B.get();
218 template<class T, class U>
219 inline bool operator==(const IntrusiveRefCntPtr<T>& A,
225 template<class T, class U>
226 inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
232 template<class T, class U>
233 inline bool operator==(T* A,
234 const IntrusiveRefCntPtr<U>& B)
239 template<class T, class U>
240 inline bool operator!=(T* A,
241 const IntrusiveRefCntPtr<U>& B)
247 bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
252 bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
257 bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
262 bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
266 //===----------------------------------------------------------------------===//
267 // LLVM-style downcasting support for IntrusiveRefCntPtr objects
268 //===----------------------------------------------------------------------===//
270 template <typename From> struct simplify_type;
272 template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
273 typedef T* SimpleType;
274 static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) {
279 template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > {
280 typedef /*const*/ T* SimpleType;
281 static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
286 } // end namespace llvm
288 #endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H