Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / wtf / RefCounted.h
blob547a9271767c29b7eb90a118daeacfa5c831bcfd
1 /*
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.
21 #ifndef RefCounted_h
22 #define RefCounted_h
24 #include "wtf/Assertions.h"
25 #include "wtf/FastAllocBase.h"
26 #include "wtf/InstanceCounter.h"
27 #include "wtf/Noncopyable.h"
28 #include "wtf/WTFExport.h"
30 #if ENABLE(ASSERT)
31 #define CHECK_REF_COUNTED_LIFECYCLE 1
32 #include "wtf/ThreadRestrictionVerifier.h"
33 #else
34 #define CHECK_REF_COUNTED_LIFECYCLE 0
35 #endif
37 namespace WTF {
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 WTF_EXPORT RefCountedBase {
43 public:
44 void ref()
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 thread
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 CrossThreadCopier.h
52 // We should be able to add a "detachFromThread" method to make this explicit.
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_adoptionIsRequired);
60 #endif
61 ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);
62 ++m_refCount;
65 bool hasOneRef() const
67 ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);
68 #if CHECK_REF_COUNTED_LIFECYCLE
69 ASSERT(m_verifier.isSafeToUse());
70 #endif
71 return m_refCount == 1;
74 int refCount() const
76 #if CHECK_REF_COUNTED_LIFECYCLE
77 ASSERT(m_verifier.isSafeToUse());
78 #endif
79 return m_refCount;
82 protected:
83 RefCountedBase()
84 : m_refCount(1)
85 #if ENABLE(SECURITY_ASSERT)
86 , m_deletionHasBegun(false)
87 #endif
88 #if CHECK_REF_COUNTED_LIFECYCLE
89 , m_adoptionIsRequired(true)
90 #endif
94 ~RefCountedBase()
96 ASSERT_WITH_SECURITY_IMPLICATION(m_deletionHasBegun);
97 #if CHECK_REF_COUNTED_LIFECYCLE
98 ASSERT(!m_adoptionIsRequired);
99 #endif
102 // Returns whether the pointer should be freed or not.
103 bool derefBase()
105 ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);
106 #if CHECK_REF_COUNTED_LIFECYCLE
107 ASSERT(m_verifier.isSafeToUse());
108 ASSERT(!m_adoptionIsRequired);
109 #endif
111 ASSERT(m_refCount > 0);
112 --m_refCount;
113 if (!m_refCount) {
114 #if ENABLE(SECURITY_ASSERT)
115 m_deletionHasBegun = true;
116 #endif
117 return true;
120 #if CHECK_REF_COUNTED_LIFECYCLE
121 // Stop thread verification when the ref goes to 1 because it
122 // is safe to be passed to another thread at this point.
123 if (m_refCount == 1)
124 m_verifier.setShared(false);
125 #endif
126 return false;
129 #if CHECK_REF_COUNTED_LIFECYCLE
130 bool deletionHasBegun() const
132 return m_deletionHasBegun;
134 #endif
136 private:
138 #if CHECK_REF_COUNTED_LIFECYCLE || ENABLE(SECURITY_ASSERT)
139 friend void adopted(RefCountedBase*);
140 #endif
142 int m_refCount;
143 #if ENABLE(SECURITY_ASSERT)
144 bool m_deletionHasBegun;
145 #endif
146 #if CHECK_REF_COUNTED_LIFECYCLE
147 bool m_adoptionIsRequired;
148 ThreadRestrictionVerifier m_verifier;
149 #endif
152 #if CHECK_REF_COUNTED_LIFECYCLE || ENABLE(SECURITY_ASSERT)
153 inline void adopted(RefCountedBase* object)
155 if (!object)
156 return;
157 ASSERT_WITH_SECURITY_IMPLICATION(!object->m_deletionHasBegun);
158 #if CHECK_REF_COUNTED_LIFECYCLE
159 object->m_adoptionIsRequired = false;
160 #endif
162 #endif
164 template<typename T> class RefCounted : public RefCountedBase {
165 WTF_MAKE_NONCOPYABLE(RefCounted);
166 WTF_MAKE_FAST_ALLOCATED(RefCounted);
168 public:
169 void deref()
171 if (derefBase())
172 delete static_cast<T*>(this);
175 protected:
176 #ifdef ENABLE_INSTANCE_COUNTER
177 RefCounted()
179 incrementInstanceCount<T>(static_cast<T*>(this));
182 ~RefCounted()
184 decrementInstanceCount<T>(static_cast<T*>(this));
186 #else
187 RefCounted()
190 #endif
193 } // namespace WTF
195 using WTF::RefCounted;
197 #endif // RefCounted_h