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() | |
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 | 50 bool hasOneRef() const |
66 { | 51 { |
67 #if CHECK_REF_COUNTED_LIFECYCLE | 52 #if CHECK_REF_COUNTED_LIFECYCLE |
68 ASSERT(m_verifier.isSafeToUse()); | 53 ASSERT(m_verifier.isSafeToUse()); |
69 ASSERT(!m_deletionHasBegun); | 54 ASSERT(!m_deletionHasBegun); |
70 #endif | 55 #endif |
71 return m_refCount == 1; | 56 return m_refCount == 1; |
72 } | 57 } |
73 | 58 |
74 int refCount() const | 59 int refCount() const |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
128 } | 113 } |
129 | 114 |
130 ~RefCountedBase() | 115 ~RefCountedBase() |
131 { | 116 { |
132 #if CHECK_REF_COUNTED_LIFECYCLE | 117 #if CHECK_REF_COUNTED_LIFECYCLE |
133 ASSERT(m_deletionHasBegun); | 118 ASSERT(m_deletionHasBegun); |
134 ASSERT(!m_adoptionIsRequired); | 119 ASSERT(!m_adoptionIsRequired); |
135 #endif | 120 #endif |
136 } | 121 } |
137 | 122 |
123 void refBase() | |
124 { | |
125 #if CHECK_REF_COUNTED_LIFECYCLE | |
126 // Start thread verification as soon as the ref count gets to 2. This | |
127 // heuristic reflects the fact that items are often created on one threa d | |
128 // and then given to another thread to be used. | |
129 // FIXME: Make this restriction tigher. Especially as we move to more | |
130 // common methods for sharing items across threads like CrossThreadCopie r.h | |
131 // We should be able to add a "detachFromThread" method to make this exp licit. | |
132 if (m_refCount == 1) | |
133 m_verifier.setShared(true); | |
134 // If this assert fires, it either indicates a thread safety issue or | |
135 // that the verification needs to change. See ThreadRestrictionVerifier for | |
136 // the different modes. | |
137 ASSERT(m_verifier.isSafeToUse()); | |
138 ASSERT(!m_deletionHasBegun); | |
139 ASSERT(!m_adoptionIsRequired); | |
140 #endif | |
141 ++m_refCount; | |
142 } | |
143 | |
138 // Returns whether the pointer should be freed or not. | 144 // Returns whether the pointer should be freed or not. |
139 bool derefBase() | 145 bool derefBase() |
140 { | 146 { |
141 #if CHECK_REF_COUNTED_LIFECYCLE | 147 #if CHECK_REF_COUNTED_LIFECYCLE |
142 ASSERT(m_verifier.isSafeToUse()); | 148 ASSERT(m_verifier.isSafeToUse()); |
143 ASSERT(!m_deletionHasBegun); | 149 ASSERT(!m_deletionHasBegun); |
144 ASSERT(!m_adoptionIsRequired); | 150 ASSERT(!m_adoptionIsRequired); |
145 #endif | 151 #endif |
146 | 152 |
147 ASSERT(m_refCount > 0); | 153 ASSERT(m_refCount > 0); |
148 if (m_refCount == 1) { | 154 if (m_refCount == 1) { |
149 #if CHECK_REF_COUNTED_LIFECYCLE | 155 #if CHECK_REF_COUNTED_LIFECYCLE |
150 m_deletionHasBegun = true; | 156 m_deletionHasBegun = true; |
151 #endif | 157 #endif |
158 --m_refCount; | |
haraken
2013/05/29 14:53:45
This is critical :)
Mads Ager (chromium)
2013/05/29 16:46:38
Yeah, I see, otherwise the ref will actually never
| |
152 return true; | 159 return true; |
153 } | 160 } |
154 | 161 |
155 --m_refCount; | 162 --m_refCount; |
156 #if CHECK_REF_COUNTED_LIFECYCLE | 163 #if CHECK_REF_COUNTED_LIFECYCLE |
157 // Stop thread verification when the ref goes to 1 because it | 164 // Stop thread verification when the ref goes to 1 because it |
158 // is safe to be passed to another thread at this point. | 165 // is safe to be passed to another thread at this point. |
159 if (m_refCount == 1) | 166 if (m_refCount == 1) |
160 m_verifier.setShared(false); | 167 m_verifier.setShared(false); |
161 #endif | 168 #endif |
(...skipping 27 matching lines...) Expand all Loading... | |
189 if (!object) | 196 if (!object) |
190 return; | 197 return; |
191 ASSERT(!object->m_deletionHasBegun); | 198 ASSERT(!object->m_deletionHasBegun); |
192 object->m_adoptionIsRequired = false; | 199 object->m_adoptionIsRequired = false; |
193 } | 200 } |
194 #endif | 201 #endif |
195 | 202 |
196 template<typename T> class RefCounted : public RefCountedBase { | 203 template<typename T> class RefCounted : public RefCountedBase { |
197 WTF_MAKE_NONCOPYABLE(RefCounted); WTF_MAKE_FAST_ALLOCATED; | 204 WTF_MAKE_NONCOPYABLE(RefCounted); WTF_MAKE_FAST_ALLOCATED; |
198 public: | 205 public: |
206 void ref() | |
207 { | |
208 refBase(); | |
209 } | |
210 | |
199 void deref() | 211 void deref() |
200 { | 212 { |
201 if (derefBase()) | 213 if (derefBase()) |
202 delete static_cast<T*>(this); | 214 delete static_cast<T*>(this); |
203 } | 215 } |
204 | 216 |
205 protected: | 217 protected: |
206 RefCounted() { } | 218 RefCounted() { } |
207 ~RefCounted() | 219 ~RefCounted() |
208 { | 220 { |
209 } | 221 } |
210 }; | 222 }; |
211 | 223 |
212 template<typename T> class RefCountedCustomAllocated : public RefCountedBase { | 224 template<typename T> class RefCountedCustomAllocated : public RefCountedBase { |
213 WTF_MAKE_NONCOPYABLE(RefCountedCustomAllocated); | 225 WTF_MAKE_NONCOPYABLE(RefCountedCustomAllocated); |
214 | 226 |
215 public: | 227 public: |
228 void ref() | |
229 { | |
230 refBase(); | |
231 } | |
232 | |
216 void deref() | 233 void deref() |
217 { | 234 { |
218 if (derefBase()) | 235 if (derefBase()) |
219 delete static_cast<T*>(this); | 236 delete static_cast<T*>(this); |
220 } | 237 } |
221 | 238 |
222 protected: | 239 protected: |
223 ~RefCountedCustomAllocated() | 240 ~RefCountedCustomAllocated() |
224 { | 241 { |
225 } | 242 } |
(...skipping 18 matching lines...) Expand all Loading... | |
244 inline void RefCountedBase::setDispatchQueueForVerifier(dispatch_queue_t) { } | 261 inline void RefCountedBase::setDispatchQueueForVerifier(dispatch_queue_t) { } |
245 #endif | 262 #endif |
246 #endif // HAVE(DISPATCH_H) | 263 #endif // HAVE(DISPATCH_H) |
247 | 264 |
248 } // namespace WTF | 265 } // namespace WTF |
249 | 266 |
250 using WTF::RefCounted; | 267 using WTF::RefCounted; |
251 using WTF::RefCountedCustomAllocated; | 268 using WTF::RefCountedCustomAllocated; |
252 | 269 |
253 #endif // RefCounted_h | 270 #endif // RefCounted_h |
OLD | NEW |