LCOV - code coverage report
Current view: top level - llvm/ADT - IntrusiveRefCntPtr.h (source / functions) Hit Total Coverage
Test: clang.info Lines: 3 4 75.0 %
Date: 2016-01-31 12:01:00 Functions: 3 4 75.0 %

          Line data    Source code
       1             : //== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- C++ -*-==//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file defines IntrusiveRefCntPtr, a template class that
      11             : // implements a "smart" pointer for objects that maintain their own
      12             : // internal reference count, and RefCountedBase/RefCountedBaseVPTR, two
      13             : // generic base classes for objects that wish to have their lifetimes
      14             : // managed using reference counting.
      15             : //
      16             : // IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added
      17             : // LLVM-style casting.
      18             : //
      19             : //===----------------------------------------------------------------------===//
      20             : 
      21             : #ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H
      22             : #define LLVM_ADT_INTRUSIVEREFCNTPTR_H
      23             : 
      24             : #include <atomic>
      25             : #include <cassert>
      26             : #include <cstddef>
      27             : 
      28             : namespace llvm {
      29             : 
      30             :   template <class T>
      31             :   class IntrusiveRefCntPtr;
      32             : 
      33             : //===----------------------------------------------------------------------===//
      34             : /// RefCountedBase - A generic base class for objects that wish to
      35             : ///  have their lifetimes managed using reference counts. Classes
      36             : ///  subclass RefCountedBase to obtain such functionality, and are
      37             : ///  typically handled with IntrusiveRefCntPtr "smart pointers" (see below)
      38             : ///  which automatically handle the management of reference counts.
      39             : ///  Objects that subclass RefCountedBase should not be allocated on
      40             : ///  the stack, as invoking "delete" (which is called when the
      41             : ///  reference count hits 0) on such objects is an error.
      42             : //===----------------------------------------------------------------------===//
      43             :   template <class Derived>
      44             :   class RefCountedBase {
      45             :     mutable unsigned ref_cnt;
      46             : 
      47             :   public:
      48             :     RefCountedBase() : ref_cnt(0) {}
      49             :     RefCountedBase(const RefCountedBase &) : ref_cnt(0) {}
      50             : 
      51             :     void Retain() const { ++ref_cnt; }
      52             :     void Release() const {
      53             :       assert (ref_cnt > 0 && "Reference count is already zero.");
      54             :       if (--ref_cnt == 0) delete static_cast<const Derived*>(this);
      55             :     }
      56             :   };
      57             : 
      58             : //===----------------------------------------------------------------------===//
      59             : /// RefCountedBaseVPTR - A class that has the same function as
      60             : ///  RefCountedBase, but with a virtual destructor. Should be used
      61             : ///  instead of RefCountedBase for classes that already have virtual
      62             : ///  methods to enforce dynamic allocation via 'new'. Classes that
      63             : ///  inherit from RefCountedBaseVPTR can't be allocated on stack -
      64             : ///  attempting to do this will produce a compile error.
      65             : //===----------------------------------------------------------------------===//
      66             :   class RefCountedBaseVPTR {
      67             :     mutable unsigned ref_cnt;
      68             :     virtual void anchor();
      69             : 
      70             :   protected:
      71             :     RefCountedBaseVPTR() : ref_cnt(0) {}
      72             :     RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {}
      73             : 
      74             :     virtual ~RefCountedBaseVPTR() {}
      75             : 
      76             :     void Retain() const { ++ref_cnt; }
      77             :     void Release() const {
      78             :       assert (ref_cnt > 0 && "Reference count is already zero.");
      79             :       if (--ref_cnt == 0) delete this;
      80             :     }
      81             : 
      82             :     template <typename T>
      83             :     friend struct IntrusiveRefCntPtrInfo;
      84             :   };
      85             : 
      86             : 
      87             :   template <typename T> struct IntrusiveRefCntPtrInfo {
      88             :     static void retain(T *obj) { obj->Retain(); }
      89          12 :     static void release(T *obj) { obj->Release(); }
      90             :   };
      91             : 
      92             : /// \brief A thread-safe version of \c llvm::RefCountedBase.
      93             : ///
      94             : /// A generic base class for objects that wish to have their lifetimes managed
      95             : /// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to
      96             : /// obtain such functionality, and are typically handled with
      97             : /// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the
      98             : /// management of reference counts.
      99             : template <class Derived>
     100             : class ThreadSafeRefCountedBase {
     101             :   mutable std::atomic<int> RefCount;
     102             : 
     103             : protected:
     104             :   ThreadSafeRefCountedBase() : RefCount(0) {}
     105             : 
     106             : public:
     107             :   void Retain() const { ++RefCount; }
     108             : 
     109             :   void Release() const {
     110             :     int NewRefCount = --RefCount;
     111             :     assert(NewRefCount >= 0 && "Reference count was already zero.");
     112             :     if (NewRefCount == 0)
     113             :       delete static_cast<const Derived*>(this);
     114             :   }
     115             : };
     116             : 
     117             : //===----------------------------------------------------------------------===//
     118             : /// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
     119             : ///  that assumes the wrapped object has a reference count associated
     120             : ///  with it that can be managed via calls to
     121             : ///  IntrusivePtrAddRef/IntrusivePtrRelease.  The smart pointers
     122             : ///  manage reference counts via the RAII idiom: upon creation of
     123             : ///  smart pointer the reference count of the wrapped object is
     124             : ///  incremented and upon destruction of the smart pointer the
     125             : ///  reference count is decremented.  This class also safely handles
     126             : ///  wrapping NULL pointers.
     127             : ///
     128             : /// Reference counting is implemented via calls to
     129             : ///  Obj->Retain()/Obj->Release(). Release() is required to destroy
     130             : ///  the object when the reference count reaches zero. Inheriting from
     131             : ///  RefCountedBase/RefCountedBaseVPTR takes care of this
     132             : ///  automatically.
     133             : //===----------------------------------------------------------------------===//
     134             :   template <typename T>
     135             :   class IntrusiveRefCntPtr {
     136             :     T* Obj;
     137             : 
     138             :   public:
     139             :     typedef T element_type;
     140             : 
     141             :     explicit IntrusiveRefCntPtr() : Obj(nullptr) {}
     142             : 
     143             :     IntrusiveRefCntPtr(T* obj) : Obj(obj) {
     144             :       retain();
     145             :     }
     146             : 
     147             :     IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) {
     148             :       retain();
     149             :     }
     150             : 
     151             :     IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) {
     152             :       S.Obj = nullptr;
     153             :     }
     154             : 
     155             :     template <class X>
     156             :     IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.get()) {
     157             :       S.Obj = 0;
     158             :     }
     159             : 
     160             :     template <class X>
     161             :     IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S)
     162             :       : Obj(S.get()) {
     163             :       retain();
     164             :     }
     165             : 
     166             :     IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) {
     167             :       swap(S);
     168             :       return *this;
     169             :     }
     170             : 
     171          24 :     ~IntrusiveRefCntPtr() { release(); }
     172             : 
     173             :     T& operator*() const { return *Obj; }
     174             : 
     175             :     T* operator->() const { return Obj; }
     176             : 
     177           0 :     T* get() const { return Obj; }
     178             : 
     179             :     explicit operator bool() const { return Obj; }
     180             : 
     181             :     void swap(IntrusiveRefCntPtr& other) {
     182             :       T* tmp = other.Obj;
     183             :       other.Obj = Obj;
     184             :       Obj = tmp;
     185             :     }
     186             : 
     187             :     void reset() {
     188             :       release();
     189             :       Obj = nullptr;
     190             :     }
     191             : 
     192             :     void resetWithoutRelease() {
     193             :       Obj = 0;
     194             :     }
     195             : 
     196             :   private:
     197             :     void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); }
     198          36 :     void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); }
     199             : 
     200             :     template <typename X>
     201             :     friend class IntrusiveRefCntPtr;
     202             :   };
     203             : 
     204             :   template<class T, class U>
     205             :   inline bool operator==(const IntrusiveRefCntPtr<T>& A,
     206             :                          const IntrusiveRefCntPtr<U>& B)
     207             :   {
     208             :     return A.get() == B.get();
     209             :   }
     210             : 
     211             :   template<class T, class U>
     212             :   inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
     213             :                          const IntrusiveRefCntPtr<U>& B)
     214             :   {
     215             :     return A.get() != B.get();
     216             :   }
     217             : 
     218             :   template<class T, class U>
     219             :   inline bool operator==(const IntrusiveRefCntPtr<T>& A,
     220             :                          U* B)
     221             :   {
     222             :     return A.get() == B;
     223             :   }
     224             : 
     225             :   template<class T, class U>
     226             :   inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
     227             :                          U* B)
     228             :   {
     229             :     return A.get() != B;
     230             :   }
     231             : 
     232             :   template<class T, class U>
     233             :   inline bool operator==(T* A,
     234             :                          const IntrusiveRefCntPtr<U>& B)
     235             :   {
     236             :     return A == B.get();
     237             :   }
     238             : 
     239             :   template<class T, class U>
     240             :   inline bool operator!=(T* A,
     241             :                          const IntrusiveRefCntPtr<U>& B)
     242             :   {
     243             :     return A != B.get();
     244             :   }
     245             : 
     246             :   template <class T>
     247             :   bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
     248             :     return !B;
     249             :   }
     250             : 
     251             :   template <class T>
     252             :   bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
     253             :     return B == A;
     254             :   }
     255             : 
     256             :   template <class T>
     257             :   bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
     258             :     return !(A == B);
     259             :   }
     260             : 
     261             :   template <class T>
     262             :   bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
     263             :     return !(A == B);
     264             :   }
     265             : 
     266             : //===----------------------------------------------------------------------===//
     267             : // LLVM-style downcasting support for IntrusiveRefCntPtr objects
     268             : //===----------------------------------------------------------------------===//
     269             : 
     270             :   template <typename From> struct simplify_type;
     271             : 
     272             :   template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
     273             :     typedef T* SimpleType;
     274             :     static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) {
     275             :       return Val.get();
     276             :     }
     277             :   };
     278             : 
     279             :   template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > {
     280             :     typedef /*const*/ T* SimpleType;
     281             :     static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
     282             :       return Val.get();
     283             :     }
     284             :   };
     285             : 
     286             : } // end namespace llvm
     287             : 
     288             : #endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H

Generated by: LCOV version 1.11