Move-enable IntrusiveRefCntPtr.
[oota-llvm.git] / include / llvm / ADT / IntrusiveRefCntPtr.h
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_INTRUSIVE_REF_CNT_PTR
22 #define LLVM_ADT_INTRUSIVE_REF_CNT_PTR
23
24 #include "llvm/Support/Casting.h"
25 #include "llvm/Support/Compiler.h"
26
27 namespace llvm {
28
29   template <class T>
30   class IntrusiveRefCntPtr;
31
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;
45
46   public:
47     RefCountedBase() : ref_cnt(0) {}
48     RefCountedBase(const RefCountedBase &) : ref_cnt(0) {}
49
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);
54     }
55   };
56
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();
68
69   protected:
70     RefCountedBaseVPTR() : ref_cnt(0) {}
71     RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {}
72
73     virtual ~RefCountedBaseVPTR() {}
74
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;
79     }
80
81     template <typename T>
82     friend struct IntrusiveRefCntPtrInfo;
83   };
84
85   
86   template <typename T> struct IntrusiveRefCntPtrInfo {
87     static void retain(T *obj) { obj->Retain(); }
88     static void release(T *obj) { obj->Release(); }
89   };
90   
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.
101 ///
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
106 ///  automatically.
107 //===----------------------------------------------------------------------===//
108   template <typename T>
109   class IntrusiveRefCntPtr {
110     T* Obj;
111     typedef IntrusiveRefCntPtr this_type;
112   public:
113     typedef T element_type;
114
115     explicit IntrusiveRefCntPtr() : Obj(0) {}
116
117     IntrusiveRefCntPtr(T* obj) : Obj(obj) {
118       retain();
119     }
120
121     IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) {
122       retain();
123     }
124
125 #if LLVM_USE_RVALUE_REFERENCES
126     IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) {
127       S.Obj = 0;
128     }
129
130     template <class X>
131     IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.getPtr()) {
132       S.Obj = 0;
133     }
134 #endif
135
136     template <class X>
137     IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S)
138       : Obj(S.getPtr()) {
139       retain();
140     }
141
142     IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr& S) {
143       replace(S.getPtr());
144       return *this;
145     }
146
147 #if LLVM_USE_RVALUE_REFERENCES
148     IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr&& S) {
149       Obj = S.Obj;
150       S.Obj = 0;
151       return *this;
152     }
153
154     template <class X>
155     IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr<X>&& S) {
156       Obj = S.getPtr();
157       S.Obj = 0;
158       return *this;
159     }
160 #endif
161
162     template <class X>
163     IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr<X>& 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) () const;
182     operator unspecified_bool_type() const {
183       return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr;
184     }
185
186     void swap(IntrusiveRefCntPtr& other) {
187       T* tmp = other.Obj;
188       other.Obj = Obj;
189       Obj = tmp;
190     }
191
192     void reset() {
193       release();
194       Obj = 0;
195     }
196
197     void resetWithoutRelease() {
198       Obj = 0;
199     }
200
201   private:
202     void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); }
203     void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); }
204
205     void replace(T* S) {
206       this_type(S).swap(*this);
207     }
208   };
209
210   template<class T, class U>
211   inline bool operator==(const IntrusiveRefCntPtr<T>& A,
212                          const IntrusiveRefCntPtr<U>& B)
213   {
214     return A.getPtr() == B.getPtr();
215   }
216
217   template<class T, class U>
218   inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
219                          const IntrusiveRefCntPtr<U>& B)
220   {
221     return A.getPtr() != B.getPtr();
222   }
223
224   template<class T, class U>
225   inline bool operator==(const IntrusiveRefCntPtr<T>& A,
226                          U* B)
227   {
228     return A.getPtr() == B;
229   }
230
231   template<class T, class U>
232   inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
233                          U* B)
234   {
235     return A.getPtr() != B;
236   }
237
238   template<class T, class U>
239   inline bool operator==(T* A,
240                          const IntrusiveRefCntPtr<U>& B)
241   {
242     return A == B.getPtr();
243   }
244
245   template<class T, class U>
246   inline bool operator!=(T* A,
247                          const IntrusiveRefCntPtr<U>& B)
248   {
249     return A != B.getPtr();
250   }
251
252 //===----------------------------------------------------------------------===//
253 // LLVM-style downcasting support for IntrusiveRefCntPtr objects
254 //===----------------------------------------------------------------------===//
255
256   template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
257     typedef T* SimpleType;
258     static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
259       return Val.getPtr();
260     }
261   };
262
263   template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > {
264     typedef T* SimpleType;
265     static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
266       return Val.getPtr();
267     }
268   };
269
270 } // end namespace llvm
271
272 #endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR