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