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_INTRUSIVE_REF_CNT_PTR
00022 #define LLVM_ADT_INTRUSIVE_REF_CNT_PTR
00023 
00024 #include <cassert>
00025 
00026 #include "llvm/Support/Casting.h"
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 IntrusivePtr "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     unsigned ref_cnt;
00046 
00047   protected:
00048     RefCountedBase() : ref_cnt(0) {}
00049 
00050     void Retain() { ++ref_cnt; }
00051     void Release() {
00052       assert (ref_cnt > 0 && "Reference count is already zero.");
00053       if (--ref_cnt == 0) delete static_cast<Derived*>(this);
00054     }
00055 
00056     friend class IntrusiveRefCntPtr<Derived>;
00057   };
00058 
00059 //===----------------------------------------------------------------------===//
00060 /// RefCountedBaseVPTR - A class that has the same function as
00061 ///  RefCountedBase, but with a virtual destructor. Should be used
00062 ///  instead of RefCountedBase for classes that already have virtual
00063 ///  methods to enforce dynamic allocation via 'new'. Classes that
00064 ///  inherit from RefCountedBaseVPTR can't be allocated on stack -
00065 ///  attempting to do this will produce a compile error.
00066 //===----------------------------------------------------------------------===//
00067   template <class Derived>
00068   class RefCountedBaseVPTR {
00069     unsigned ref_cnt;
00070 
00071   protected:
00072     RefCountedBaseVPTR() : ref_cnt(0) {}
00073     virtual ~RefCountedBaseVPTR() {}
00074 
00075     void Retain() { ++ref_cnt; }
00076     void Release() {
00077       assert (ref_cnt > 0 && "Reference count is already zero.");
00078       if (--ref_cnt == 0) delete this;
00079     }
00080 
00081     friend class IntrusiveRefCntPtr<Derived>;
00082   };
00083 
00084 //===----------------------------------------------------------------------===//
00085 /// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
00086 ///  that assumes the wrapped object has a reference count associated
00087 ///  with it that can be managed via calls to
00088 ///  IntrusivePtrAddRef/IntrusivePtrRelease.  The smart pointers
00089 ///  manage reference counts via the RAII idiom: upon creation of
00090 ///  smart pointer the reference count of the wrapped object is
00091 ///  incremented and upon destruction of the smart pointer the
00092 ///  reference count is decremented.  This class also safely handles
00093 ///  wrapping NULL pointers.
00094 ///
00095 /// Reference counting is implemented via calls to
00096 ///  Obj->Retain()/Obj->Release(). Release() is required to destroy
00097 ///  the object when the reference count reaches zero. Inheriting from
00098 ///  RefCountedBase/RefCountedBaseVPTR takes care of this
00099 ///  automatically.
00100 //===----------------------------------------------------------------------===//
00101   template <typename T>
00102   class IntrusiveRefCntPtr {
00103     T* Obj;
00104     typedef IntrusiveRefCntPtr this_type;
00105   public:
00106     typedef T element_type;
00107 
00108     explicit IntrusiveRefCntPtr() : Obj(0) {}
00109 
00110     explicit IntrusiveRefCntPtr(T* obj) : Obj(obj) {
00111       retain();
00112     }
00113 
00114     IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) {
00115       retain();
00116     }
00117 
00118     template <class X>
00119     IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S)
00120       : Obj(S.getPtr()) {
00121       retain();
00122     }
00123 
00124     IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr& S) {
00125       replace(S.getPtr());
00126       return *this;
00127     }
00128 
00129     template <class X>
00130     IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr<X>& S) {
00131       replace(S.getPtr());
00132       return *this;
00133     }
00134 
00135     IntrusiveRefCntPtr& operator=(T * S) {
00136       replace(S);
00137       return *this;
00138     }
00139 
00140     ~IntrusiveRefCntPtr() { release(); }
00141 
00142     T& operator*() const { return *Obj; }
00143 
00144     T* operator->() const { return Obj; }
00145 
00146     T* getPtr() const { return Obj; }
00147 
00148     typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const;
00149     operator unspecified_bool_type() const {
00150       return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr;
00151     }
00152 
00153     void swap(IntrusiveRefCntPtr& other) {
00154       T* tmp = other.Obj;
00155       other.Obj = Obj;
00156       Obj = tmp;
00157     }
00158 
00159   private:
00160     void retain() { if (Obj) Obj->Retain(); }
00161     void release() { if (Obj) Obj->Release(); }
00162 
00163     void replace(T* S) {
00164       this_type(S).swap(*this);
00165     }
00166   };
00167 
00168   template<class T, class U>
00169   inline bool operator==(const IntrusiveRefCntPtr<T>& A,
00170                          const IntrusiveRefCntPtr<U>& B)
00171   {
00172     return A.getPtr() == B.getPtr();
00173   }
00174 
00175   template<class T, class U>
00176   inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
00177                          const IntrusiveRefCntPtr<U>& B)
00178   {
00179     return A.getPtr() != B.getPtr();
00180   }
00181 
00182   template<class T, class U>
00183   inline bool operator==(const IntrusiveRefCntPtr<T>& A,
00184                          U* B)
00185   {
00186     return A.getPtr() == B;
00187   }
00188 
00189   template<class T, class U>
00190   inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
00191                          U* B)
00192   {
00193     return A.getPtr() != B;
00194   }
00195 
00196   template<class T, class U>
00197   inline bool operator==(T* A,
00198                          const IntrusiveRefCntPtr<U>& B)
00199   {
00200     return A == B.getPtr();
00201   }
00202 
00203   template<class T, class U>
00204   inline bool operator!=(T* A,
00205                          const IntrusiveRefCntPtr<U>& B)
00206   {
00207     return A != B.getPtr();
00208   }
00209 
00210 //===----------------------------------------------------------------------===//
00211 // LLVM-style downcasting support for IntrusiveRefCntPtr objects
00212 //===----------------------------------------------------------------------===//
00213 
00214   template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
00215     typedef T* SimpleType;
00216     static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
00217       return Val.getPtr();
00218     }
00219   };
00220 
00221   template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > {
00222     typedef T* SimpleType;
00223     static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
00224       return Val.getPtr();
00225     }
00226   };
00227 
00228 } // end namespace llvm
00229 
00230 #endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR