| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
| 5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
| 6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
| 7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
| 8 * | 8 * |
| 9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #include <wtf/Noncopyable.h> | 26 #include <wtf/Noncopyable.h> |
| 27 #include <wtf/OwnPtr.h> | 27 #include <wtf/OwnPtr.h> |
| 28 #include <wtf/ThreadRestrictionVerifier.h> | 28 #include <wtf/ThreadRestrictionVerifier.h> |
| 29 #include <wtf/UnusedParam.h> | 29 #include <wtf/UnusedParam.h> |
| 30 | 30 |
| 31 namespace WTF { | 31 namespace WTF { |
| 32 | 32 |
| 33 #ifdef NDEBUG | 33 #ifdef NDEBUG |
| 34 #define CHECK_REF_COUNTED_LIFECYCLE 0 | 34 #define CHECK_REF_COUNTED_LIFECYCLE 0 |
| 35 #else | 35 #else |
| 36 #define CHECK_REF_COUNTED_LIFECYCLE 1 | 36 // FIXME(oilpan): Enable this check once we replace all |
| 37 // RefCountedHeapAllocated with HeapAllocated. |
| 38 // We have to disable the check for RefCountedHeapAllocated |
| 39 // since we have to allow the following situation in RefCountedHeapAllocated. |
| 40 // (1) A reference count becomes 0, but Handles keep references to the object. |
| 41 // (2) The Handle is assigned to a RefPtr. The reference count becomes 1. |
| 42 #define CHECK_REF_COUNTED_LIFECYCLE 0 |
| 37 #endif | 43 #endif |
| 38 | 44 |
| 39 // This base class holds the non-template methods and attributes. | 45 // This base class holds the non-template methods and attributes. |
| 40 // The RefCounted class inherits from it reducing the template bloat | 46 // The RefCounted class inherits from it reducing the template bloat |
| 41 // generated by the compiler (technique called template hoisting). | 47 // generated by the compiler (technique called template hoisting). |
| 42 class RefCountedBase { | 48 class RefCountedBase { |
| 43 public: | 49 public: |
| 44 void ref() | 50 void ref() |
| 45 { | 51 { |
| 46 #if CHECK_REF_COUNTED_LIFECYCLE | 52 refBase(); |
| 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 } | 53 } |
| 64 | 54 |
| 65 bool hasOneRef() const | 55 bool hasOneRef() const |
| 66 { | 56 { |
| 67 #if CHECK_REF_COUNTED_LIFECYCLE | 57 #if CHECK_REF_COUNTED_LIFECYCLE |
| 68 ASSERT(m_verifier.isSafeToUse()); | 58 ASSERT(m_verifier.isSafeToUse()); |
| 69 ASSERT(!m_deletionHasBegun); | 59 ASSERT(!m_deletionHasBegun); |
| 70 #endif | 60 #endif |
| 71 return m_refCount == 1; | 61 return m_refCount == 1; |
| 72 } | 62 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 } | 118 } |
| 129 | 119 |
| 130 ~RefCountedBase() | 120 ~RefCountedBase() |
| 131 { | 121 { |
| 132 #if CHECK_REF_COUNTED_LIFECYCLE | 122 #if CHECK_REF_COUNTED_LIFECYCLE |
| 133 ASSERT(m_deletionHasBegun); | 123 ASSERT(m_deletionHasBegun); |
| 134 ASSERT(!m_adoptionIsRequired); | 124 ASSERT(!m_adoptionIsRequired); |
| 135 #endif | 125 #endif |
| 136 } | 126 } |
| 137 | 127 |
| 128 void refBase() |
| 129 { |
| 130 #if CHECK_REF_COUNTED_LIFECYCLE |
| 131 // Start thread verification as soon as the ref count gets to 2. This |
| 132 // heuristic reflects the fact that items are often created on one threa
d |
| 133 // and then given to another thread to be used. |
| 134 // FIXME: Make this restriction tigher. Especially as we move to more |
| 135 // common methods for sharing items across threads like CrossThreadCopie
r.h |
| 136 // We should be able to add a "detachFromThread" method to make this exp
licit. |
| 137 if (m_refCount == 1) |
| 138 m_verifier.setShared(true); |
| 139 // If this assert fires, it either indicates a thread safety issue or |
| 140 // that the verification needs to change. See ThreadRestrictionVerifier
for |
| 141 // the different modes. |
| 142 ASSERT(m_verifier.isSafeToUse()); |
| 143 ASSERT(!m_deletionHasBegun); |
| 144 ASSERT(!m_adoptionIsRequired); |
| 145 #endif |
| 146 ++m_refCount; |
| 147 } |
| 148 |
| 138 // Returns whether the pointer should be freed or not. | 149 // Returns whether the pointer should be freed or not. |
| 139 bool derefBase() | 150 bool derefBase() |
| 140 { | 151 { |
| 141 #if CHECK_REF_COUNTED_LIFECYCLE | 152 #if CHECK_REF_COUNTED_LIFECYCLE |
| 142 ASSERT(m_verifier.isSafeToUse()); | 153 ASSERT(m_verifier.isSafeToUse()); |
| 143 ASSERT(!m_deletionHasBegun); | 154 ASSERT(!m_deletionHasBegun); |
| 144 ASSERT(!m_adoptionIsRequired); | 155 ASSERT(!m_adoptionIsRequired); |
| 145 #endif | 156 #endif |
| 146 | 157 |
| 147 ASSERT(m_refCount > 0); | 158 ASSERT(m_refCount > 0); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 if (!object) | 200 if (!object) |
| 190 return; | 201 return; |
| 191 ASSERT(!object->m_deletionHasBegun); | 202 ASSERT(!object->m_deletionHasBegun); |
| 192 object->m_adoptionIsRequired = false; | 203 object->m_adoptionIsRequired = false; |
| 193 } | 204 } |
| 194 #endif | 205 #endif |
| 195 | 206 |
| 196 template<typename T> class RefCounted : public RefCountedBase { | 207 template<typename T> class RefCounted : public RefCountedBase { |
| 197 WTF_MAKE_NONCOPYABLE(RefCounted); WTF_MAKE_FAST_ALLOCATED; | 208 WTF_MAKE_NONCOPYABLE(RefCounted); WTF_MAKE_FAST_ALLOCATED; |
| 198 public: | 209 public: |
| 210 void ref() |
| 211 { |
| 212 refBase(); |
| 213 } |
| 214 |
| 199 void deref() | 215 void deref() |
| 200 { | 216 { |
| 201 if (derefBase()) | 217 if (derefBase()) |
| 202 delete static_cast<T*>(this); | 218 delete static_cast<T*>(this); |
| 203 } | 219 } |
| 204 | 220 |
| 205 protected: | 221 protected: |
| 206 RefCounted() { } | 222 RefCounted() { } |
| 207 ~RefCounted() | 223 ~RefCounted() |
| 208 { | 224 { |
| 209 } | 225 } |
| 210 }; | 226 }; |
| 211 | 227 |
| 212 template<typename T> class RefCountedCustomAllocated : public RefCountedBase { | 228 template<typename T> class RefCountedCustomAllocated : public RefCountedBase { |
| 213 WTF_MAKE_NONCOPYABLE(RefCountedCustomAllocated); | 229 WTF_MAKE_NONCOPYABLE(RefCountedCustomAllocated); |
| 214 | 230 |
| 215 public: | 231 public: |
| 232 void ref() |
| 233 { |
| 234 refBase(); |
| 235 } |
| 236 |
| 216 void deref() | 237 void deref() |
| 217 { | 238 { |
| 218 if (derefBase()) | 239 if (derefBase()) |
| 219 delete static_cast<T*>(this); | 240 delete static_cast<T*>(this); |
| 220 } | 241 } |
| 221 | 242 |
| 222 protected: | 243 protected: |
| 223 ~RefCountedCustomAllocated() | 244 ~RefCountedCustomAllocated() |
| 224 { | 245 { |
| 225 } | 246 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 244 inline void RefCountedBase::setDispatchQueueForVerifier(dispatch_queue_t) { } | 265 inline void RefCountedBase::setDispatchQueueForVerifier(dispatch_queue_t) { } |
| 245 #endif | 266 #endif |
| 246 #endif // HAVE(DISPATCH_H) | 267 #endif // HAVE(DISPATCH_H) |
| 247 | 268 |
| 248 } // namespace WTF | 269 } // namespace WTF |
| 249 | 270 |
| 250 using WTF::RefCounted; | 271 using WTF::RefCounted; |
| 251 using WTF::RefCountedCustomAllocated; | 272 using WTF::RefCountedCustomAllocated; |
| 252 | 273 |
| 253 #endif // RefCounted_h | 274 #endif // RefCounted_h |
| OLD | NEW |