LLVM API Documentation

IntrusiveRefCntPtr.h
Go to the documentation of this file.
00001 //== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- C++ -*-==//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines IntrusiveRefCntPtr, a template class that
00011 // implements a "smart" pointer for objects that maintain their own
00012 // internal reference count, and RefCountedBase/RefCountedBaseVPTR, two
00013 // generic base classes for objects that wish to have their lifetimes
00014 // managed using reference counting.
00015 //
00016 // IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added
00017 // LLVM-style casting.
00018 //
00019 //===----------------------------------------------------------------------===//
00020 
00021 #ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H
00022 #define LLVM_ADT_INTRUSIVEREFCNTPTR_H
00023 
00024 #include "llvm/Support/Casting.h"
00025 #include "llvm/Support/Compiler.h"
00026 #include <memory>
00027 
00028 namespace llvm {
00029 
00030   template <class T>
00031   class IntrusiveRefCntPtr;
00032 
00033 //===----------------------------------------------------------------------===//
00034 /// RefCountedBase - A generic base class for objects that wish to
00035 ///  have their lifetimes managed using reference counts. Classes
00036 ///  subclass RefCountedBase to obtain such functionality, and are
00037 ///  typically handled with IntrusiveRefCntPtr "smart pointers" (see below)
00038 ///  which automatically handle the management of reference counts.
00039 ///  Objects that subclass RefCountedBase should not be allocated on
00040 ///  the stack, as invoking "delete" (which is called when the
00041 ///  reference count hits 0) on such objects is an error.
00042 //===----------------------------------------------------------------------===//
00043   template <class Derived>
00044   class RefCountedBase {
00045     mutable unsigned ref_cnt;
00046 
00047   public:
00048     RefCountedBase() : ref_cnt(0) {}
00049     RefCountedBase(const RefCountedBase &) : ref_cnt(0) {}
00050 
00051     void Retain() const { ++ref_cnt; }
00052     void Release() const {
00053       assert (ref_cnt > 0 && "Reference count is already zero.");
00054       if (--ref_cnt == 0) delete static_cast<const Derived*>(this);
00055     }
00056   };
00057 
00058 //===----------------------------------------------------------------------===//
00059 /// RefCountedBaseVPTR - A class that has the same function as
00060 ///  RefCountedBase, but with a virtual destructor. Should be used
00061 ///  instead of RefCountedBase for classes that already have virtual
00062 ///  methods to enforce dynamic allocation via 'new'. Classes that
00063 ///  inherit from RefCountedBaseVPTR can't be allocated on stack -
00064 ///  attempting to do this will produce a compile error.
00065 //===----------------------------------------------------------------------===//
00066   class RefCountedBaseVPTR {
00067     mutable unsigned ref_cnt;
00068     virtual void anchor();
00069 
00070   protected:
00071     RefCountedBaseVPTR() : ref_cnt(0) {}
00072     RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {}
00073 
00074     virtual ~RefCountedBaseVPTR() {}
00075 
00076     void Retain() const { ++ref_cnt; }
00077     void Release() const {
00078       assert (ref_cnt > 0 && "Reference count is already zero.");
00079       if (--ref_cnt == 0) delete this;
00080     }
00081 
00082     template <typename T>
00083     friend struct IntrusiveRefCntPtrInfo;
00084   };
00085 
00086   
00087   template <typename T> struct IntrusiveRefCntPtrInfo {
00088     static void retain(T *obj) { obj->Retain(); }
00089     static void release(T *obj) { obj->Release(); }
00090   };
00091   
00092 //===----------------------------------------------------------------------===//
00093 /// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
00094 ///  that assumes the wrapped object has a reference count associated
00095 ///  with it that can be managed via calls to
00096 ///  IntrusivePtrAddRef/IntrusivePtrRelease.  The smart pointers
00097 ///  manage reference counts via the RAII idiom: upon creation of
00098 ///  smart pointer the reference count of the wrapped object is
00099 ///  incremented and upon destruction of the smart pointer the
00100 ///  reference count is decremented.  This class also safely handles
00101 ///  wrapping NULL pointers.
00102 ///
00103 /// Reference counting is implemented via calls to
00104 ///  Obj->Retain()/Obj->Release(). Release() is required to destroy
00105 ///  the object when the reference count reaches zero. Inheriting from
00106 ///  RefCountedBase/RefCountedBaseVPTR takes care of this
00107 ///  automatically.
00108 //===----------------------------------------------------------------------===//
00109   template <typename T>
00110   class IntrusiveRefCntPtr {
00111     T* Obj;
00112     typedef IntrusiveRefCntPtr this_type;
00113   public:
00114     typedef T element_type;
00115 
00116     explicit IntrusiveRefCntPtr() : Obj(0) {}
00117 
00118     IntrusiveRefCntPtr(T* obj) : Obj(obj) {
00119       retain();
00120     }
00121 
00122     IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) {
00123       retain();
00124     }
00125 
00126 #if LLVM_HAS_RVALUE_REFERENCES
00127     IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) {
00128       S.Obj = 0;
00129     }
00130 
00131     template <class X>
00132     IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.getPtr()) {
00133       S.Obj = 0;
00134     }
00135 #endif
00136 
00137     template <class X>
00138     IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S)
00139       : Obj(S.getPtr()) {
00140       retain();
00141     }
00142 
00143     IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) {
00144       swap(S);
00145       return *this;
00146     }
00147 
00148     ~IntrusiveRefCntPtr() { release(); }
00149 
00150     T& operator*() const { return *Obj; }
00151 
00152     T* operator->() const { return Obj; }
00153 
00154     T* getPtr() const { return Obj; }
00155 
00156     typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const;
00157     operator unspecified_bool_type() const {
00158       return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr;
00159     }
00160 
00161     void swap(IntrusiveRefCntPtr& other) {
00162       T* tmp = other.Obj;
00163       other.Obj = Obj;
00164       Obj = tmp;
00165     }
00166 
00167     void reset() {
00168       release();
00169       Obj = 0;
00170     }
00171 
00172     void resetWithoutRelease() {
00173       Obj = 0;
00174     }
00175 
00176   private:
00177     void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); }
00178     void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); }
00179   };
00180 
00181   template<class T, class U>
00182   inline bool operator==(const IntrusiveRefCntPtr<T>& A,
00183                          const IntrusiveRefCntPtr<U>& B)
00184   {
00185     return A.getPtr() == B.getPtr();
00186   }
00187 
00188   template<class T, class U>
00189   inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
00190                          const IntrusiveRefCntPtr<U>& B)
00191   {
00192     return A.getPtr() != B.getPtr();
00193   }
00194 
00195   template<class T, class U>
00196   inline bool operator==(const IntrusiveRefCntPtr<T>& A,
00197                          U* B)
00198   {
00199     return A.getPtr() == B;
00200   }
00201 
00202   template<class T, class U>
00203   inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
00204                          U* B)
00205   {
00206     return A.getPtr() != B;
00207   }
00208 
00209   template<class T, class U>
00210   inline bool operator==(T* A,
00211                          const IntrusiveRefCntPtr<U>& B)
00212   {
00213     return A == B.getPtr();
00214   }
00215 
00216   template<class T, class U>
00217   inline bool operator!=(T* A,
00218                          const IntrusiveRefCntPtr<U>& B)
00219   {
00220     return A != B.getPtr();
00221   }
00222 
00223 //===----------------------------------------------------------------------===//
00224 // LLVM-style downcasting support for IntrusiveRefCntPtr objects
00225 //===----------------------------------------------------------------------===//
00226 
00227   template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
00228     typedef T* SimpleType;
00229     static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) {
00230       return Val.getPtr();
00231     }
00232   };
00233 
00234   template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > {
00235     typedef /*const*/ T* SimpleType;
00236     static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
00237       return Val.getPtr();
00238     }
00239   };
00240 
00241 } // end namespace llvm
00242 
00243 #endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H