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
26
#include "llvm/Support/Casting.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 IntrusivePtr "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 {
48
RefCountedBase() : ref_cnt(0) {}
50
void Retain() { ++ref_cnt; }
52
assert (ref_cnt > 0 && "Reference count is already zero.");
53
if (--ref_cnt == 0) delete static_cast<Derived*>(this);
56
friend class IntrusiveRefCntPtr<Derived>;
59
//===----------------------------------------------------------------------===//
60
/// RefCountedBaseVPTR - A class that has the same function as
61
/// RefCountedBase, but with a virtual destructor. Should be used
62
/// instead of RefCountedBase for classes that already have virtual
63
/// methods to enforce dynamic allocation via 'new'. Classes that
64
/// inherit from RefCountedBaseVPTR can't be allocated on stack -
65
/// attempting to do this will produce a compile error.
66
//===----------------------------------------------------------------------===//
67
template <class Derived>
68
class RefCountedBaseVPTR {
72
RefCountedBaseVPTR() : ref_cnt(0) {}
73
virtual ~RefCountedBaseVPTR() {}
75
void Retain() { ++ref_cnt; }
77
assert (ref_cnt > 0 && "Reference count is already zero.");
78
if (--ref_cnt == 0) delete this;
81
friend class IntrusiveRefCntPtr<Derived>;
84
//===----------------------------------------------------------------------===//
85
/// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
86
/// that assumes the wrapped object has a reference count associated
87
/// with it that can be managed via calls to
88
/// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers
89
/// manage reference counts via the RAII idiom: upon creation of
90
/// smart pointer the reference count of the wrapped object is
91
/// incremented and upon destruction of the smart pointer the
92
/// reference count is decremented. This class also safely handles
93
/// wrapping NULL pointers.
95
/// Reference counting is implemented via calls to
96
/// Obj->Retain()/Obj->Release(). Release() is required to destroy
97
/// the object when the reference count reaches zero. Inheriting from
98
/// RefCountedBase/RefCountedBaseVPTR takes care of this
100
//===----------------------------------------------------------------------===//
101
template <typename T>
102
class IntrusiveRefCntPtr {
104
typedef IntrusiveRefCntPtr this_type;
106
typedef T element_type;
108
explicit IntrusiveRefCntPtr() : Obj(0) {}
110
explicit IntrusiveRefCntPtr(T* obj) : Obj(obj) {
114
IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) {
119
IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S)
124
IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr& S) {
130
IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr<X>& S) {
135
IntrusiveRefCntPtr& operator=(T * S) {
140
~IntrusiveRefCntPtr() { release(); }
142
T& operator*() const { return *Obj; }
144
T* operator->() const { return Obj; }
146
T* getPtr() const { return Obj; }
148
typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const;
149
operator unspecified_bool_type() const {
150
return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr;
153
void swap(IntrusiveRefCntPtr& other) {
160
void retain() { if (Obj) Obj->Retain(); }
161
void release() { if (Obj) Obj->Release(); }
164
this_type(S).swap(*this);
168
template<class T, class U>
169
inline bool operator==(const IntrusiveRefCntPtr<T>& A,
170
const IntrusiveRefCntPtr<U>& B)
172
return A.getPtr() == B.getPtr();
175
template<class T, class U>
176
inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
177
const IntrusiveRefCntPtr<U>& B)
179
return A.getPtr() != B.getPtr();
182
template<class T, class U>
183
inline bool operator==(const IntrusiveRefCntPtr<T>& A,
186
return A.getPtr() == B;
189
template<class T, class U>
190
inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
193
return A.getPtr() != B;
196
template<class T, class U>
197
inline bool operator==(T* A,
198
const IntrusiveRefCntPtr<U>& B)
200
return A == B.getPtr();
203
template<class T, class U>
204
inline bool operator!=(T* A,
205
const IntrusiveRefCntPtr<U>& B)
207
return A != B.getPtr();
210
//===----------------------------------------------------------------------===//
211
// LLVM-style downcasting support for IntrusiveRefCntPtr objects
212
//===----------------------------------------------------------------------===//
214
template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
215
typedef T* SimpleType;
216
static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
221
template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > {
222
typedef T* SimpleType;
223
static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
228
} // end namespace llvm
230
#endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR