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 <atomic>
00027 #include <memory>
00028 
00029 namespace llvm {
00030 
00031   template <class T>
00032   class IntrusiveRefCntPtr;
00033 
00034 //===----------------------------------------------------------------------===//
00035 /// RefCountedBase - A generic base class for objects that wish to
00036 ///  have their lifetimes managed using reference counts. Classes
00037 ///  subclass RefCountedBase to obtain such functionality, and are
00038 ///  typically handled with IntrusiveRefCntPtr "smart pointers" (see below)
00039 ///  which automatically handle the management of reference counts.
00040 ///  Objects that subclass RefCountedBase should not be allocated on
00041 ///  the stack, as invoking "delete" (which is called when the
00042 ///  reference count hits 0) on such objects is an error.
00043 //===----------------------------------------------------------------------===//
00044   template <class Derived>
00045   class RefCountedBase {
00046     mutable unsigned ref_cnt;
00047 
00048   public:
00049     RefCountedBase() : ref_cnt(0) {}
00050     RefCountedBase(const RefCountedBase &) : ref_cnt(0) {}
00051 
00052     void Retain() const { ++ref_cnt; }
00053     void Release() const {
00054       assert (ref_cnt > 0 && "Reference count is already zero.");
00055       if (--ref_cnt == 0) delete static_cast<const Derived*>(this);
00056     }
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   class RefCountedBaseVPTR {
00068     mutable unsigned ref_cnt;
00069     virtual void anchor();
00070 
00071   protected:
00072     RefCountedBaseVPTR() : ref_cnt(0) {}
00073     RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {}
00074 
00075     virtual ~RefCountedBaseVPTR() {}
00076 
00077     void Retain() const { ++ref_cnt; }
00078     void Release() const {
00079       assert (ref_cnt > 0 && "Reference count is already zero.");
00080       if (--ref_cnt == 0) delete this;
00081     }
00082 
00083     template <typename T>
00084     friend struct IntrusiveRefCntPtrInfo;
00085   };
00086 
00087   
00088   template <typename T> struct IntrusiveRefCntPtrInfo {
00089     static void retain(T *obj) { obj->Retain(); }
00090     static void release(T *obj) { obj->Release(); }
00091   };
00092 
00093 /// \brief A thread-safe version of \c llvm::RefCountedBase.
00094 ///
00095 /// A generic base class for objects that wish to have their lifetimes managed
00096 /// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to
00097 /// obtain such functionality, and are typically handled with
00098 /// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the
00099 /// management of reference counts.
00100 template <class Derived>
00101 class ThreadSafeRefCountedBase {
00102   mutable std::atomic<int> RefCount;
00103 
00104 protected:
00105   ThreadSafeRefCountedBase() : RefCount(0) {}
00106 
00107 public:
00108   void Retain() const { ++RefCount; }
00109 
00110   void Release() const {
00111     int NewRefCount = --RefCount;
00112     assert(NewRefCount >= 0 && "Reference count was already zero.");
00113     if (NewRefCount == 0)
00114       delete static_cast<const Derived*>(this);
00115   }
00116 };
00117   
00118 //===----------------------------------------------------------------------===//
00119 /// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
00120 ///  that assumes the wrapped object has a reference count associated
00121 ///  with it that can be managed via calls to
00122 ///  IntrusivePtrAddRef/IntrusivePtrRelease.  The smart pointers
00123 ///  manage reference counts via the RAII idiom: upon creation of
00124 ///  smart pointer the reference count of the wrapped object is
00125 ///  incremented and upon destruction of the smart pointer the
00126 ///  reference count is decremented.  This class also safely handles
00127 ///  wrapping NULL pointers.
00128 ///
00129 /// Reference counting is implemented via calls to
00130 ///  Obj->Retain()/Obj->Release(). Release() is required to destroy
00131 ///  the object when the reference count reaches zero. Inheriting from
00132 ///  RefCountedBase/RefCountedBaseVPTR takes care of this
00133 ///  automatically.
00134 //===----------------------------------------------------------------------===//
00135   template <typename T>
00136   class IntrusiveRefCntPtr {
00137     T* Obj;
00138 
00139   public:
00140     typedef T element_type;
00141 
00142     explicit IntrusiveRefCntPtr() : Obj(nullptr) {}
00143 
00144     IntrusiveRefCntPtr(T* obj) : Obj(obj) {
00145       retain();
00146     }
00147 
00148     IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) {
00149       retain();
00150     }
00151 
00152     IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) {
00153       S.Obj = nullptr;
00154     }
00155 
00156     template <class X>
00157     IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.get()) {
00158       S.Obj = 0;
00159     }
00160 
00161     template <class X>
00162     IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S)
00163       : Obj(S.get()) {
00164       retain();
00165     }
00166 
00167     IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) {
00168       swap(S);
00169       return *this;
00170     }
00171 
00172     ~IntrusiveRefCntPtr() { release(); }
00173 
00174     T& operator*() const { return *Obj; }
00175 
00176     T* operator->() const { return Obj; }
00177 
00178     T* get() const { return Obj; }
00179 
00180     LLVM_EXPLICIT operator bool() const { return Obj; }
00181 
00182     void swap(IntrusiveRefCntPtr& other) {
00183       T* tmp = other.Obj;
00184       other.Obj = Obj;
00185       Obj = tmp;
00186     }
00187 
00188     void reset() {
00189       release();
00190       Obj = nullptr;
00191     }
00192 
00193     void resetWithoutRelease() {
00194       Obj = 0;
00195     }
00196 
00197   private:
00198     void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); }
00199     void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); }
00200 
00201     template <typename X>
00202     friend class IntrusiveRefCntPtr;
00203   };
00204 
00205   template<class T, class U>
00206   inline bool operator==(const IntrusiveRefCntPtr<T>& A,
00207                          const IntrusiveRefCntPtr<U>& B)
00208   {
00209     return A.get() == B.get();
00210   }
00211 
00212   template<class T, class U>
00213   inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
00214                          const IntrusiveRefCntPtr<U>& B)
00215   {
00216     return A.get() != B.get();
00217   }
00218 
00219   template<class T, class U>
00220   inline bool operator==(const IntrusiveRefCntPtr<T>& A,
00221                          U* B)
00222   {
00223     return A.get() == B;
00224   }
00225 
00226   template<class T, class U>
00227   inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
00228                          U* B)
00229   {
00230     return A.get() != B;
00231   }
00232 
00233   template<class T, class U>
00234   inline bool operator==(T* A,
00235                          const IntrusiveRefCntPtr<U>& B)
00236   {
00237     return A == B.get();
00238   }
00239 
00240   template<class T, class U>
00241   inline bool operator!=(T* A,
00242                          const IntrusiveRefCntPtr<U>& B)
00243   {
00244     return A != B.get();
00245   }
00246 
00247   template <class T>
00248   bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
00249     return !B;
00250   }
00251 
00252   template <class T>
00253   bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
00254     return B == A;
00255   }
00256 
00257   template <class T>
00258   bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
00259     return !(A == B);
00260   }
00261 
00262   template <class T>
00263   bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
00264     return !(A == B);
00265   }
00266 
00267 //===----------------------------------------------------------------------===//
00268 // LLVM-style downcasting support for IntrusiveRefCntPtr objects
00269 //===----------------------------------------------------------------------===//
00270 
00271   template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
00272     typedef T* SimpleType;
00273     static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) {
00274       return Val.get();
00275     }
00276   };
00277 
00278   template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > {
00279     typedef /*const*/ T* SimpleType;
00280     static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
00281       return Val.get();
00282     }
00283   };
00284 
00285 } // end namespace llvm
00286 
00287 #endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H