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