| OLD | NEW |
| (Empty) |
| 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 <wtf/Assertions.h> | |
| 25 #include <wtf/FastAllocBase.h> | |
| 26 #include <wtf/Noncopyable.h> | |
| 27 #include <wtf/OwnPtr.h> | |
| 28 #include <wtf/ThreadRestrictionVerifier.h> | |
| 29 #include <wtf/UnusedParam.h> | |
| 30 | |
| 31 namespace WTF { | |
| 32 | |
| 33 #ifdef NDEBUG | |
| 34 #define CHECK_REF_COUNTED_LIFECYCLE 0 | |
| 35 #else | |
| 36 #define CHECK_REF_COUNTED_LIFECYCLE 1 | |
| 37 #endif | |
| 38 | |
| 39 // This base class holds the non-template methods and attributes. | |
| 40 // The RefCounted class inherits from it reducing the template bloat | |
| 41 // generated by the compiler (technique called template hoisting). | |
| 42 class RefCountedBase { | |
| 43 public: | |
| 44 void ref() | |
| 45 { | |
| 46 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 47 // Start thread verification as soon as the ref count gets to 2. This | |
| 48 // heuristic reflects the fact that items are often created on one threa
d | |
| 49 // and then given to another thread to be used. | |
| 50 // FIXME: Make this restriction tigher. Especially as we move to more | |
| 51 // common methods for sharing items across threads like CrossThreadCopie
r.h | |
| 52 // We should be able to add a "detachFromThread" method to make this exp
licit. | |
| 53 if (m_refCount == 1) | |
| 54 m_verifier.setShared(true); | |
| 55 // If this assert fires, it either indicates a thread safety issue or | |
| 56 // that the verification needs to change. See ThreadRestrictionVerifier
for | |
| 57 // the different modes. | |
| 58 ASSERT(m_verifier.isSafeToUse()); | |
| 59 ASSERT(!m_deletionHasBegun); | |
| 60 ASSERT(!m_adoptionIsRequired); | |
| 61 #endif | |
| 62 ++m_refCount; | |
| 63 } | |
| 64 | |
| 65 bool hasOneRef() const | |
| 66 { | |
| 67 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 68 ASSERT(m_verifier.isSafeToUse()); | |
| 69 ASSERT(!m_deletionHasBegun); | |
| 70 #endif | |
| 71 return m_refCount == 1; | |
| 72 } | |
| 73 | |
| 74 int refCount() const | |
| 75 { | |
| 76 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 77 ASSERT(m_verifier.isSafeToUse()); | |
| 78 #endif | |
| 79 return m_refCount; | |
| 80 } | |
| 81 | |
| 82 void setMutexForVerifier(Mutex&); | |
| 83 | |
| 84 #if HAVE(DISPATCH_H) | |
| 85 void setDispatchQueueForVerifier(dispatch_queue_t); | |
| 86 #endif | |
| 87 | |
| 88 // Turns off verification. Use of this method is discouraged (instead extend | |
| 89 // ThreadRestrictionVerifier to verify your case). | |
| 90 // NB. It is necessary to call this in the constructor of many objects in | |
| 91 // JavaScriptCore, because JavaScriptCore objects may be used from multiple | |
| 92 // threads even if the reference counting is done in a racy manner. This is | |
| 93 // because a JSC instance may be used from multiple threads so long as all | |
| 94 // accesses into that instance are protected by a per-instance lock. It woul
d | |
| 95 // be absolutely wrong to prohibit this pattern, and it would be a disastrou
s | |
| 96 // regression to require that the objects within that instance use a thread- | |
| 97 // safe version of reference counting. | |
| 98 void turnOffVerifier() | |
| 99 { | |
| 100 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 101 m_verifier.turnOffVerification(); | |
| 102 #endif | |
| 103 } | |
| 104 | |
| 105 void relaxAdoptionRequirement() | |
| 106 { | |
| 107 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 108 ASSERT(!m_deletionHasBegun); | |
| 109 ASSERT(m_adoptionIsRequired); | |
| 110 m_adoptionIsRequired = false; | |
| 111 #endif | |
| 112 } | |
| 113 | |
| 114 // Helper for generating JIT code. Please do not use for non-JIT purposes. | |
| 115 const int* addressOfCount() const | |
| 116 { | |
| 117 return &m_refCount; | |
| 118 } | |
| 119 | |
| 120 protected: | |
| 121 RefCountedBase() | |
| 122 : m_refCount(1) | |
| 123 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 124 , m_deletionHasBegun(false) | |
| 125 , m_adoptionIsRequired(true) | |
| 126 #endif | |
| 127 { | |
| 128 } | |
| 129 | |
| 130 ~RefCountedBase() | |
| 131 { | |
| 132 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 133 ASSERT(m_deletionHasBegun); | |
| 134 ASSERT(!m_adoptionIsRequired); | |
| 135 #endif | |
| 136 } | |
| 137 | |
| 138 // Returns whether the pointer should be freed or not. | |
| 139 bool derefBase() | |
| 140 { | |
| 141 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 142 ASSERT(m_verifier.isSafeToUse()); | |
| 143 ASSERT(!m_deletionHasBegun); | |
| 144 ASSERT(!m_adoptionIsRequired); | |
| 145 #endif | |
| 146 | |
| 147 ASSERT(m_refCount > 0); | |
| 148 if (m_refCount == 1) { | |
| 149 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 150 m_deletionHasBegun = true; | |
| 151 #endif | |
| 152 return true; | |
| 153 } | |
| 154 | |
| 155 --m_refCount; | |
| 156 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 157 // Stop thread verification when the ref goes to 1 because it | |
| 158 // is safe to be passed to another thread at this point. | |
| 159 if (m_refCount == 1) | |
| 160 m_verifier.setShared(false); | |
| 161 #endif | |
| 162 return false; | |
| 163 } | |
| 164 | |
| 165 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 166 bool deletionHasBegun() const | |
| 167 { | |
| 168 return m_deletionHasBegun; | |
| 169 } | |
| 170 #endif | |
| 171 | |
| 172 private: | |
| 173 | |
| 174 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 175 friend void adopted(RefCountedBase*); | |
| 176 #endif | |
| 177 | |
| 178 int m_refCount; | |
| 179 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 180 bool m_deletionHasBegun; | |
| 181 bool m_adoptionIsRequired; | |
| 182 ThreadRestrictionVerifier m_verifier; | |
| 183 #endif | |
| 184 }; | |
| 185 | |
| 186 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 187 inline void adopted(RefCountedBase* object) | |
| 188 { | |
| 189 if (!object) | |
| 190 return; | |
| 191 ASSERT(!object->m_deletionHasBegun); | |
| 192 object->m_adoptionIsRequired = false; | |
| 193 } | |
| 194 #endif | |
| 195 | |
| 196 template<typename T> class RefCounted : public RefCountedBase { | |
| 197 WTF_MAKE_NONCOPYABLE(RefCounted); WTF_MAKE_FAST_ALLOCATED; | |
| 198 public: | |
| 199 void deref() | |
| 200 { | |
| 201 if (derefBase()) | |
| 202 delete static_cast<T*>(this); | |
| 203 } | |
| 204 | |
| 205 protected: | |
| 206 RefCounted() { } | |
| 207 ~RefCounted() | |
| 208 { | |
| 209 } | |
| 210 }; | |
| 211 | |
| 212 template<typename T> class RefCountedCustomAllocated : public RefCountedBase { | |
| 213 WTF_MAKE_NONCOPYABLE(RefCountedCustomAllocated); | |
| 214 | |
| 215 public: | |
| 216 void deref() | |
| 217 { | |
| 218 if (derefBase()) | |
| 219 delete static_cast<T*>(this); | |
| 220 } | |
| 221 | |
| 222 protected: | |
| 223 ~RefCountedCustomAllocated() | |
| 224 { | |
| 225 } | |
| 226 }; | |
| 227 | |
| 228 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 229 inline void RefCountedBase::setMutexForVerifier(Mutex& mutex) | |
| 230 { | |
| 231 m_verifier.setMutexMode(mutex); | |
| 232 } | |
| 233 #else | |
| 234 inline void RefCountedBase::setMutexForVerifier(Mutex&) { } | |
| 235 #endif | |
| 236 | |
| 237 #if HAVE(DISPATCH_H) | |
| 238 #if CHECK_REF_COUNTED_LIFECYCLE | |
| 239 inline void RefCountedBase::setDispatchQueueForVerifier(dispatch_queue_t queue) | |
| 240 { | |
| 241 m_verifier.setDispatchQueueMode(queue); | |
| 242 } | |
| 243 #else | |
| 244 inline void RefCountedBase::setDispatchQueueForVerifier(dispatch_queue_t) { } | |
| 245 #endif | |
| 246 #endif // HAVE(DISPATCH_H) | |
| 247 | |
| 248 } // namespace WTF | |
| 249 | |
| 250 using WTF::RefCounted; | |
| 251 using WTF::RefCountedCustomAllocated; | |
| 252 | |
| 253 #endif // RefCounted_h | |
| OLD | NEW |