Home | History | Annotate | Download | only in wtf
      1 /*
      2  * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Library General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Library General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Library General Public License
     15  * along with this library; see the file COPYING.LIB.  If not, write to
     16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  * Boston, MA 02110-1301, USA.
     18  *
     19  */
     20 
     21 #ifndef RefCounted_h
     22 #define RefCounted_h
     23 
     24 #include "Assertions.h"
     25 #include "FastAllocBase.h"
     26 #include "Noncopyable.h"
     27 
     28 namespace WTF {
     29 
     30 // This base class holds the non-template methods and attributes.
     31 // The RefCounted class inherits from it reducing the template bloat
     32 // generated by the compiler (technique called template hoisting).
     33 class RefCountedBase {
     34 public:
     35     void ref()
     36     {
     37         ASSERT(!m_deletionHasBegun);
     38         ASSERT(!m_adoptionIsRequired);
     39         ++m_refCount;
     40     }
     41 
     42     bool hasOneRef() const
     43     {
     44         ASSERT(!m_deletionHasBegun);
     45         return m_refCount == 1;
     46     }
     47 
     48     int refCount() const
     49     {
     50         return m_refCount;
     51     }
     52 
     53     void relaxAdoptionRequirement()
     54     {
     55 #ifndef NDEBUG
     56         ASSERT(!m_deletionHasBegun);
     57         ASSERT(m_adoptionIsRequired);
     58         m_adoptionIsRequired = false;
     59 #endif
     60     }
     61 
     62     // Helper for generating JIT code. Please do not use for non-JIT purposes.
     63     const int* addressOfCount() const
     64     {
     65         return &m_refCount;
     66     }
     67 
     68 protected:
     69     RefCountedBase()
     70         : m_refCount(1)
     71 #ifndef NDEBUG
     72         , m_deletionHasBegun(false)
     73         , m_adoptionIsRequired(true)
     74 #endif
     75     {
     76     }
     77 
     78     ~RefCountedBase()
     79     {
     80         ASSERT(m_deletionHasBegun);
     81         ASSERT(!m_adoptionIsRequired);
     82     }
     83 
     84     // Returns whether the pointer should be freed or not.
     85     bool derefBase()
     86     {
     87         ASSERT(!m_deletionHasBegun);
     88         ASSERT(!m_adoptionIsRequired);
     89 
     90         ASSERT(m_refCount > 0);
     91         if (m_refCount == 1) {
     92 #ifndef NDEBUG
     93             m_deletionHasBegun = true;
     94 #endif
     95             return true;
     96         }
     97 
     98         --m_refCount;
     99         return false;
    100     }
    101 
    102 #ifndef NDEBUG
    103     bool deletionHasBegun() const
    104     {
    105         return m_deletionHasBegun;
    106     }
    107 #endif
    108 
    109 private:
    110     template<typename T> friend class CrossThreadRefCounted;
    111 
    112 #ifndef NDEBUG
    113     friend void adopted(RefCountedBase*);
    114 #endif
    115 
    116     int m_refCount;
    117 #ifndef NDEBUG
    118     bool m_deletionHasBegun;
    119     bool m_adoptionIsRequired;
    120 #endif
    121 };
    122 
    123 #ifndef NDEBUG
    124 
    125 inline void adopted(RefCountedBase* object)
    126 {
    127     if (!object)
    128         return;
    129     ASSERT(!object->m_deletionHasBegun);
    130     object->m_adoptionIsRequired = false;
    131 }
    132 
    133 #endif
    134 
    135 template<typename T> class RefCounted : public RefCountedBase {
    136     WTF_MAKE_NONCOPYABLE(RefCounted); WTF_MAKE_FAST_ALLOCATED;
    137 public:
    138     void deref()
    139     {
    140         if (derefBase())
    141             delete static_cast<T*>(this);
    142     }
    143 
    144 protected:
    145     RefCounted() { }
    146     ~RefCounted()
    147     {
    148     }
    149 };
    150 
    151 template<typename T> class RefCountedCustomAllocated : public RefCountedBase {
    152     WTF_MAKE_NONCOPYABLE(RefCountedCustomAllocated);
    153 
    154 public:
    155     void deref()
    156     {
    157         if (derefBase())
    158             delete static_cast<T*>(this);
    159     }
    160 
    161 protected:
    162     ~RefCountedCustomAllocated()
    163     {
    164     }
    165 };
    166 
    167 } // namespace WTF
    168 
    169 using WTF::RefCounted;
    170 using WTF::RefCountedCustomAllocated;
    171 
    172 #endif // RefCounted_h
    173