Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / wtf / RefCounted.h
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/InstanceCounter.h"
27 #include "wtf/Noncopyable.h"
28 #include "wtf/WTFExport.h"
29
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
36
37 namespace WTF {
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 WTF_EXPORT 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 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;
63     }
64
65     bool hasOneRef() const
66     {
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;
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 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
91     {
92     }
93
94     ~RefCountedBase()
95     {
96         ASSERT_WITH_SECURITY_IMPLICATION(m_deletionHasBegun);
97 #if CHECK_REF_COUNTED_LIFECYCLE
98         ASSERT(!m_adoptionIsRequired);
99 #endif
100     }
101
102     // Returns whether the pointer should be freed or not.
103     bool derefBase()
104     {
105         ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);
106 #if CHECK_REF_COUNTED_LIFECYCLE
107         ASSERT(m_verifier.isSafeToUse());
108         ASSERT(!m_adoptionIsRequired);
109 #endif
110
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;
118         }
119
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;
127     }
128
129 #if CHECK_REF_COUNTED_LIFECYCLE
130     bool deletionHasBegun() const
131     {
132         return m_deletionHasBegun;
133     }
134 #endif
135
136 private:
137
138 #if CHECK_REF_COUNTED_LIFECYCLE || ENABLE(SECURITY_ASSERT)
139     friend void adopted(RefCountedBase*);
140 #endif
141
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
150 };
151
152 #if CHECK_REF_COUNTED_LIFECYCLE || ENABLE(SECURITY_ASSERT)
153 inline void adopted(RefCountedBase* object)
154 {
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
161 }
162 #endif
163
164 template<typename T> class RefCounted : public RefCountedBase {
165     WTF_MAKE_NONCOPYABLE(RefCounted);
166     WTF_MAKE_FAST_ALLOCATED;
167
168 public:
169     void deref()
170     {
171         if (derefBase())
172             delete static_cast<T*>(this);
173     }
174
175 protected:
176 #ifdef ENABLE_INSTANCE_COUNTER
177     RefCounted()
178     {
179         incrementInstanceCount<T>(static_cast<T*>(this));
180     }
181
182     ~RefCounted()
183     {
184         decrementInstanceCount<T>(static_cast<T*>(this));
185     }
186 #else
187     RefCounted()
188     {
189     }
190 #endif
191 };
192
193 } // namespace WTF
194
195 using WTF::RefCounted;
196
197 #endif // RefCounted_h