1193323Sed//== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- C++ -*-==// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file defines IntrusiveRefCntPtr, a template class that 11193323Sed// implements a "smart" pointer for objects that maintain their own 12193323Sed// internal reference count, and RefCountedBase/RefCountedBaseVPTR, two 13193323Sed// generic base classes for objects that wish to have their lifetimes 14193323Sed// managed using reference counting. 15193323Sed// 16193323Sed// IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added 17193323Sed// LLVM-style casting. 18193323Sed// 19193323Sed//===----------------------------------------------------------------------===// 20193323Sed 21249423Sdim#ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H 22249423Sdim#define LLVM_ADT_INTRUSIVEREFCNTPTR_H 23193323Sed 24193323Sed#include "llvm/Support/Casting.h" 25239462Sdim#include "llvm/Support/Compiler.h" 26239462Sdim#include <memory> 27193323Sed 28193323Sednamespace llvm { 29193323Sed 30193323Sed template <class T> 31193323Sed class IntrusiveRefCntPtr; 32193323Sed 33193323Sed//===----------------------------------------------------------------------===// 34193323Sed/// RefCountedBase - A generic base class for objects that wish to 35193323Sed/// have their lifetimes managed using reference counts. Classes 36193323Sed/// subclass RefCountedBase to obtain such functionality, and are 37239462Sdim/// typically handled with IntrusiveRefCntPtr "smart pointers" (see below) 38193323Sed/// which automatically handle the management of reference counts. 39193323Sed/// Objects that subclass RefCountedBase should not be allocated on 40193323Sed/// the stack, as invoking "delete" (which is called when the 41193323Sed/// reference count hits 0) on such objects is an error. 42193323Sed//===----------------------------------------------------------------------===// 43193323Sed template <class Derived> 44193323Sed class RefCountedBase { 45221345Sdim mutable unsigned ref_cnt; 46193323Sed 47221345Sdim public: 48193323Sed RefCountedBase() : ref_cnt(0) {} 49234353Sdim RefCountedBase(const RefCountedBase &) : ref_cnt(0) {} 50193323Sed 51221345Sdim void Retain() const { ++ref_cnt; } 52221345Sdim void Release() const { 53193323Sed assert (ref_cnt > 0 && "Reference count is already zero."); 54221345Sdim if (--ref_cnt == 0) delete static_cast<const Derived*>(this); 55193323Sed } 56193323Sed }; 57193323Sed 58193323Sed//===----------------------------------------------------------------------===// 59193323Sed/// RefCountedBaseVPTR - A class that has the same function as 60193323Sed/// RefCountedBase, but with a virtual destructor. Should be used 61193323Sed/// instead of RefCountedBase for classes that already have virtual 62193323Sed/// methods to enforce dynamic allocation via 'new'. Classes that 63193323Sed/// inherit from RefCountedBaseVPTR can't be allocated on stack - 64193323Sed/// attempting to do this will produce a compile error. 65193323Sed//===----------------------------------------------------------------------===// 66193323Sed class RefCountedBaseVPTR { 67221345Sdim mutable unsigned ref_cnt; 68234353Sdim virtual void anchor(); 69193323Sed 70193323Sed protected: 71193323Sed RefCountedBaseVPTR() : ref_cnt(0) {} 72234353Sdim RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {} 73234353Sdim 74193323Sed virtual ~RefCountedBaseVPTR() {} 75193323Sed 76221345Sdim void Retain() const { ++ref_cnt; } 77221345Sdim void Release() const { 78193323Sed assert (ref_cnt > 0 && "Reference count is already zero."); 79193323Sed if (--ref_cnt == 0) delete this; 80193323Sed } 81193323Sed 82221345Sdim template <typename T> 83234353Sdim friend struct IntrusiveRefCntPtrInfo; 84193323Sed }; 85193323Sed 86234353Sdim 87234353Sdim template <typename T> struct IntrusiveRefCntPtrInfo { 88234353Sdim static void retain(T *obj) { obj->Retain(); } 89234353Sdim static void release(T *obj) { obj->Release(); } 90234353Sdim }; 91234353Sdim 92193323Sed//===----------------------------------------------------------------------===// 93193323Sed/// IntrusiveRefCntPtr - A template class that implements a "smart pointer" 94193323Sed/// that assumes the wrapped object has a reference count associated 95193323Sed/// with it that can be managed via calls to 96193323Sed/// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers 97193323Sed/// manage reference counts via the RAII idiom: upon creation of 98193323Sed/// smart pointer the reference count of the wrapped object is 99193323Sed/// incremented and upon destruction of the smart pointer the 100193323Sed/// reference count is decremented. This class also safely handles 101193323Sed/// wrapping NULL pointers. 102193323Sed/// 103193323Sed/// Reference counting is implemented via calls to 104193323Sed/// Obj->Retain()/Obj->Release(). Release() is required to destroy 105193323Sed/// the object when the reference count reaches zero. Inheriting from 106193323Sed/// RefCountedBase/RefCountedBaseVPTR takes care of this 107193323Sed/// automatically. 108193323Sed//===----------------------------------------------------------------------===// 109193323Sed template <typename T> 110193323Sed class IntrusiveRefCntPtr { 111193323Sed T* Obj; 112193323Sed typedef IntrusiveRefCntPtr this_type; 113193323Sed public: 114193323Sed typedef T element_type; 115193323Sed 116193323Sed explicit IntrusiveRefCntPtr() : Obj(0) {} 117193323Sed 118234353Sdim IntrusiveRefCntPtr(T* obj) : Obj(obj) { 119193323Sed retain(); 120193323Sed } 121193323Sed 122193323Sed IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) { 123193323Sed retain(); 124193323Sed } 125193323Sed 126249423Sdim#if LLVM_HAS_RVALUE_REFERENCES 127239462Sdim IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) { 128239462Sdim S.Obj = 0; 129193323Sed } 130193323Sed 131239462Sdim template <class X> 132239462Sdim IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.getPtr()) { 133239462Sdim S.Obj = 0; 134193323Sed } 135239462Sdim#endif 136193323Sed 137193323Sed template <class X> 138239462Sdim IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S) 139239462Sdim : Obj(S.getPtr()) { 140239462Sdim retain(); 141193323Sed } 142193323Sed 143239462Sdim IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) { 144239462Sdim swap(S); 145193323Sed return *this; 146193323Sed } 147193323Sed 148193323Sed ~IntrusiveRefCntPtr() { release(); } 149193323Sed 150193323Sed T& operator*() const { return *Obj; } 151193323Sed 152193323Sed T* operator->() const { return Obj; } 153193323Sed 154193323Sed T* getPtr() const { return Obj; } 155193323Sed 156193323Sed typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const; 157193323Sed operator unspecified_bool_type() const { 158193323Sed return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr; 159193323Sed } 160193323Sed 161193323Sed void swap(IntrusiveRefCntPtr& other) { 162193323Sed T* tmp = other.Obj; 163193323Sed other.Obj = Obj; 164193323Sed Obj = tmp; 165193323Sed } 166234353Sdim 167234353Sdim void reset() { 168234353Sdim release(); 169234353Sdim Obj = 0; 170234353Sdim } 171234353Sdim 172221345Sdim void resetWithoutRelease() { 173221345Sdim Obj = 0; 174221345Sdim } 175193323Sed 176193323Sed private: 177234353Sdim void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); } 178234353Sdim void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); } 179193323Sed }; 180193323Sed 181193323Sed template<class T, class U> 182193323Sed inline bool operator==(const IntrusiveRefCntPtr<T>& A, 183193323Sed const IntrusiveRefCntPtr<U>& B) 184193323Sed { 185193323Sed return A.getPtr() == B.getPtr(); 186193323Sed } 187193323Sed 188193323Sed template<class T, class U> 189193323Sed inline bool operator!=(const IntrusiveRefCntPtr<T>& A, 190193323Sed const IntrusiveRefCntPtr<U>& B) 191193323Sed { 192193323Sed return A.getPtr() != B.getPtr(); 193193323Sed } 194193323Sed 195193323Sed template<class T, class U> 196193323Sed inline bool operator==(const IntrusiveRefCntPtr<T>& A, 197193323Sed U* B) 198193323Sed { 199193323Sed return A.getPtr() == B; 200193323Sed } 201193323Sed 202193323Sed template<class T, class U> 203193323Sed inline bool operator!=(const IntrusiveRefCntPtr<T>& A, 204193323Sed U* B) 205193323Sed { 206193323Sed return A.getPtr() != B; 207193323Sed } 208193323Sed 209193323Sed template<class T, class U> 210193323Sed inline bool operator==(T* A, 211193323Sed const IntrusiveRefCntPtr<U>& B) 212193323Sed { 213193323Sed return A == B.getPtr(); 214193323Sed } 215193323Sed 216193323Sed template<class T, class U> 217193323Sed inline bool operator!=(T* A, 218193323Sed const IntrusiveRefCntPtr<U>& B) 219193323Sed { 220193323Sed return A != B.getPtr(); 221193323Sed } 222193323Sed 223193323Sed//===----------------------------------------------------------------------===// 224193323Sed// LLVM-style downcasting support for IntrusiveRefCntPtr objects 225193323Sed//===----------------------------------------------------------------------===// 226193323Sed 227193323Sed template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > { 228193323Sed typedef T* SimpleType; 229249423Sdim static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) { 230193323Sed return Val.getPtr(); 231193323Sed } 232193323Sed }; 233193323Sed 234193323Sed template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > { 235249423Sdim typedef /*const*/ T* SimpleType; 236193323Sed static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { 237193323Sed return Val.getPtr(); 238193323Sed } 239193323Sed }; 240193323Sed 241193323Sed} // end namespace llvm 242193323Sed 243249423Sdim#endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H 244