tizen beta release
[profile/ivi/webkit-efl.git] / Source / JavaScriptCore / 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 "Assertions.h"
25 #include "FastAllocBase.h"
26 #include "ThreadRestrictionVerifier.h"
27 #include "Noncopyable.h"
28 #include "OwnPtr.h"
29 #include "UnusedParam.h"
30
31 namespace WTF {
32
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 {
37 public:
38     void ref()
39     {
40 #ifndef NDEBUG
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.
47         if (m_refCount == 1)
48             m_verifier.setShared(true);
49 #endif
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);
56         ++m_refCount;
57     }
58
59     bool hasOneRef() const
60     {
61         ASSERT(m_verifier.isSafeToUse());
62         ASSERT(!m_deletionHasBegun);
63         return m_refCount == 1;
64     }
65
66     int refCount() const
67     {
68         ASSERT(m_verifier.isSafeToUse());
69         return m_refCount;
70     }
71
72     void setMutexForVerifier(Mutex&);
73
74 #if HAVE(DISPATCH_H)
75     void setDispatchQueueForVerifier(dispatch_queue_t);
76 #endif
77
78     // Turns off verification. Use of this method is discouraged (instead extend
79     // ThreadRestrictionVerifier to verify your case).
80     // FIXME: remove this method.
81     void deprecatedTurnOffVerifier()
82     {
83 #ifndef NDEBUG
84         m_verifier.turnOffVerification();
85 #endif
86     }
87
88     void relaxAdoptionRequirement()
89     {
90 #ifndef NDEBUG
91         ASSERT(!m_deletionHasBegun);
92         ASSERT(m_adoptionIsRequired);
93         m_adoptionIsRequired = false;
94 #endif
95     }
96
97     // Helper for generating JIT code. Please do not use for non-JIT purposes.
98     const int* addressOfCount() const
99     {
100         return &m_refCount;
101     }
102
103 protected:
104     RefCountedBase()
105         : m_refCount(1)
106 #ifndef NDEBUG
107         , m_deletionHasBegun(false)
108         , m_adoptionIsRequired(true)
109 #endif
110     {
111     }
112
113     ~RefCountedBase()
114     {
115         ASSERT(m_deletionHasBegun);
116         ASSERT(!m_adoptionIsRequired);
117     }
118
119     // Returns whether the pointer should be freed or not.
120     bool derefBase()
121     {
122         ASSERT(m_verifier.isSafeToUse());
123         ASSERT(!m_deletionHasBegun);
124         ASSERT(!m_adoptionIsRequired);
125
126         ASSERT(m_refCount > 0);
127         if (m_refCount == 1) {
128 #ifndef NDEBUG
129             m_deletionHasBegun = true;
130 #endif
131             return true;
132         }
133
134         --m_refCount;
135 #ifndef NDEBUG
136         // Stop thread verification when the ref goes to 1 because it
137         // is safe to be passed to another thread at this point.
138         if (m_refCount == 1)
139             m_verifier.setShared(false);
140 #endif
141         return false;
142     }
143
144 #ifndef NDEBUG
145     bool deletionHasBegun() const
146     {
147         return m_deletionHasBegun;
148     }
149 #endif
150
151 private:
152
153 #ifndef NDEBUG
154     friend void adopted(RefCountedBase*);
155 #endif
156
157     int m_refCount;
158 #ifndef NDEBUG
159     bool m_deletionHasBegun;
160     bool m_adoptionIsRequired;
161     ThreadRestrictionVerifier m_verifier;
162 #endif
163 };
164
165 #ifndef NDEBUG
166
167 inline void adopted(RefCountedBase* object)
168 {
169     if (!object)
170         return;
171     ASSERT(!object->m_deletionHasBegun);
172     object->m_adoptionIsRequired = false;
173 }
174
175 #endif
176
177 template<typename T> class RefCounted : public RefCountedBase {
178     WTF_MAKE_NONCOPYABLE(RefCounted); WTF_MAKE_FAST_ALLOCATED;
179 public:
180     void deref()
181     {
182         if (derefBase())
183             delete static_cast<T*>(this);
184     }
185
186 protected:
187     RefCounted() { }
188     ~RefCounted()
189     {
190     }
191 };
192
193 template<typename T> class RefCountedCustomAllocated : public RefCountedBase {
194     WTF_MAKE_NONCOPYABLE(RefCountedCustomAllocated);
195
196 public:
197     void deref()
198     {
199         if (derefBase())
200             delete static_cast<T*>(this);
201     }
202
203 protected:
204     ~RefCountedCustomAllocated()
205     {
206     }
207 };
208
209 #ifdef NDEBUG
210 inline void RefCountedBase::setMutexForVerifier(Mutex&) { }
211 #else
212 inline void RefCountedBase::setMutexForVerifier(Mutex& mutex)
213 {
214     m_verifier.setMutexMode(mutex);
215 }
216 #endif
217
218 #if HAVE(DISPATCH_H)
219 #ifdef NDEBUG
220 inline void RefCountedBase::setDispatchQueueForVerifier(dispatch_queue_t) { }
221 #else
222 inline void RefCountedBase::setDispatchQueueForVerifier(dispatch_queue_t queue)
223 {
224     m_verifier.setDispatchQueueMode(queue);
225 }
226 #endif // NDEBUG
227 #endif // HAVE(DISPATCH_H)
228
229 } // namespace WTF
230
231 using WTF::RefCounted;
232 using WTF::RefCountedCustomAllocated;
233
234 #endif // RefCounted_h