2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
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.
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.
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.
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>
33 // This base class holds the non-template methods and attributes.
34 // The RefCounted class inherits from it reducing the template bloat
35 // generated by the compiler (technique called template hoisting).
36 class RefCountedBase {
41 // Start thread verification as soon as the ref count gets to 2. This
42 // heuristic reflects the fact that items are often created on one thread
43 // and then given to another thread to be used.
44 // FIXME: Make this restriction tigher. Especially as we move to more
45 // common methods for sharing items across threads like CrossThreadCopier.h
46 // We should be able to add a "detachFromThread" method to make this explicit.
48 m_verifier.setShared(true);
50 // If this assert fires, it either indicates a thread safety issue or
51 // that the verification needs to change. See ThreadRestrictionVerifier for
52 // the different modes.
53 ASSERT(m_verifier.isSafeToUse());
54 ASSERT(!m_deletionHasBegun);
55 ASSERT(!m_adoptionIsRequired);
59 bool hasOneRef() const
61 ASSERT(m_verifier.isSafeToUse());
62 ASSERT(!m_deletionHasBegun);
63 return m_refCount == 1;
68 ASSERT(m_verifier.isSafeToUse());
72 void setMutexForVerifier(Mutex&);
75 void setDispatchQueueForVerifier(dispatch_queue_t);
78 // Turns off verification. Use of this method is discouraged (instead extend
79 // ThreadRestrictionVerifier to verify your case).
80 // NB. It is necessary to call this in the constructor of many objects in
81 // JavaScriptCore, because JavaScriptCore objects may be used from multiple
82 // threads even if the reference counting is done in a racy manner. This is
83 // because a JSC instance may be used from multiple threads so long as all
84 // accesses into that instance are protected by a per-instance lock. It would
85 // be absolutely wrong to prohibit this pattern, and it would be a disastrous
86 // regression to require that the objects within that instance use a thread-
87 // safe version of reference counting.
88 void turnOffVerifier()
91 m_verifier.turnOffVerification();
95 void relaxAdoptionRequirement()
98 ASSERT(!m_deletionHasBegun);
99 ASSERT(m_adoptionIsRequired);
100 m_adoptionIsRequired = false;
104 // Helper for generating JIT code. Please do not use for non-JIT purposes.
105 const int* addressOfCount() const
114 , m_deletionHasBegun(false)
115 , m_adoptionIsRequired(true)
122 ASSERT(m_deletionHasBegun);
123 ASSERT(!m_adoptionIsRequired);
126 // Returns whether the pointer should be freed or not.
129 ASSERT(m_verifier.isSafeToUse());
130 ASSERT(!m_deletionHasBegun);
131 ASSERT(!m_adoptionIsRequired);
133 ASSERT(m_refCount > 0);
134 if (m_refCount == 1) {
136 m_deletionHasBegun = true;
143 // Stop thread verification when the ref goes to 1 because it
144 // is safe to be passed to another thread at this point.
146 m_verifier.setShared(false);
152 bool deletionHasBegun() const
154 return m_deletionHasBegun;
161 friend void adopted(RefCountedBase*);
166 bool m_deletionHasBegun;
167 bool m_adoptionIsRequired;
168 ThreadRestrictionVerifier m_verifier;
174 inline void adopted(RefCountedBase* object)
178 ASSERT(!object->m_deletionHasBegun);
179 object->m_adoptionIsRequired = false;
184 template<typename T> class RefCounted : public RefCountedBase {
185 WTF_MAKE_NONCOPYABLE(RefCounted); WTF_MAKE_FAST_ALLOCATED;
190 delete static_cast<T*>(this);
200 template<typename T> class RefCountedCustomAllocated : public RefCountedBase {
201 WTF_MAKE_NONCOPYABLE(RefCountedCustomAllocated);
207 delete static_cast<T*>(this);
211 ~RefCountedCustomAllocated()
217 inline void RefCountedBase::setMutexForVerifier(Mutex&) { }
219 inline void RefCountedBase::setMutexForVerifier(Mutex& mutex)
221 m_verifier.setMutexMode(mutex);
227 inline void RefCountedBase::setDispatchQueueForVerifier(dispatch_queue_t) { }
229 inline void RefCountedBase::setDispatchQueueForVerifier(dispatch_queue_t queue)
231 m_verifier.setDispatchQueueMode(queue);
234 #endif // HAVE(DISPATCH_H)
238 using WTF::RefCounted;
239 using WTF::RefCountedCustomAllocated;
241 #endif // RefCounted_h