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
24 #include "llvm/Support/Casting.h"
25 #include "llvm/Support/Compiler.h"
30 class IntrusiveRefCntPtr;
32 //===----------------------------------------------------------------------===//
33 /// RefCountedBase - A generic base class for objects that wish to
34 /// have their lifetimes managed using reference counts. Classes
35 /// subclass RefCountedBase to obtain such functionality, and are
36 /// typically handled with IntrusivePtr "smart pointers" (see below)
37 /// which automatically handle the management of reference counts.
38 /// Objects that subclass RefCountedBase should not be allocated on
39 /// the stack, as invoking "delete" (which is called when the
40 /// reference count hits 0) on such objects is an error.
41 //===----------------------------------------------------------------------===//
42 template <class Derived>
43 class RefCountedBase {
44 mutable unsigned ref_cnt;
47 RefCountedBase() : ref_cnt(0) {}
48 RefCountedBase(const RefCountedBase &) : ref_cnt(0) {}
50 void Retain() const { ++ref_cnt; }
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);
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 virtual void anchor();
70 RefCountedBaseVPTR() : ref_cnt(0) {}
71 RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {}
73 virtual ~RefCountedBaseVPTR() {}
75 void Retain() const { ++ref_cnt; }
76 void Release() const {
77 assert (ref_cnt > 0 && "Reference count is already zero.");
78 if (--ref_cnt == 0) delete this;
82 friend struct IntrusiveRefCntPtrInfo;
86 template <typename T> struct IntrusiveRefCntPtrInfo {
87 static void retain(T *obj) { obj->Retain(); }
88 static void release(T *obj) { obj->Release(); }
91 //===----------------------------------------------------------------------===//
92 /// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
93 /// that assumes the wrapped object has a reference count associated
94 /// with it that can be managed via calls to
95 /// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers
96 /// manage reference counts via the RAII idiom: upon creation of
97 /// smart pointer the reference count of the wrapped object is
98 /// incremented and upon destruction of the smart pointer the
99 /// reference count is decremented. This class also safely handles
100 /// wrapping NULL pointers.
102 /// Reference counting is implemented via calls to
103 /// Obj->Retain()/Obj->Release(). Release() is required to destroy
104 /// the object when the reference count reaches zero. Inheriting from
105 /// RefCountedBase/RefCountedBaseVPTR takes care of this
107 //===----------------------------------------------------------------------===//
108 template <typename T>
109 class IntrusiveRefCntPtr {
111 typedef IntrusiveRefCntPtr this_type;
113 typedef T element_type;
115 explicit IntrusiveRefCntPtr() : Obj(0) {}
117 IntrusiveRefCntPtr(T* obj) : Obj(obj) {
121 IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) {
125 #if LLVM_USE_RVALUE_REFERENCES
126 IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) {
131 IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.getPtr()) {
137 IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S)
142 IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr& S) {
147 #if LLVM_USE_RVALUE_REFERENCES
148 IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr&& S) {
155 IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr<X>&& S) {
163 IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr<X>& S) {
168 IntrusiveRefCntPtr& operator=(T * S) {
173 ~IntrusiveRefCntPtr() { release(); }
175 T& operator*() const { return *Obj; }
177 T* operator->() const { return Obj; }
179 T* getPtr() const { return Obj; }
181 typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const;
182 operator unspecified_bool_type() const {
183 return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr;
186 void swap(IntrusiveRefCntPtr& other) {
197 void resetWithoutRelease() {
202 void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); }
203 void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); }
206 this_type(S).swap(*this);
210 template<class T, class U>
211 inline bool operator==(const IntrusiveRefCntPtr<T>& A,
212 const IntrusiveRefCntPtr<U>& B)
214 return A.getPtr() == B.getPtr();
217 template<class T, class U>
218 inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
219 const IntrusiveRefCntPtr<U>& B)
221 return A.getPtr() != B.getPtr();
224 template<class T, class U>
225 inline bool operator==(const IntrusiveRefCntPtr<T>& A,
228 return A.getPtr() == B;
231 template<class T, class U>
232 inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
235 return A.getPtr() != B;
238 template<class T, class U>
239 inline bool operator==(T* A,
240 const IntrusiveRefCntPtr<U>& B)
242 return A == B.getPtr();
245 template<class T, class U>
246 inline bool operator!=(T* A,
247 const IntrusiveRefCntPtr<U>& B)
249 return A != B.getPtr();
252 //===----------------------------------------------------------------------===//
253 // LLVM-style downcasting support for IntrusiveRefCntPtr objects
254 //===----------------------------------------------------------------------===//
256 template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
257 typedef T* SimpleType;
258 static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
263 template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > {
264 typedef T* SimpleType;
265 static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
270 } // end namespace llvm
272 #endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR