]> git.saurik.com Git - apple/javascriptcore.git/blame - wtf/PassRefPtr.h
JavaScriptCore-903.tar.gz
[apple/javascriptcore.git] / wtf / PassRefPtr.h
CommitLineData
b37bf2e1 1/*
14957cd0 2 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
b37bf2e1
A
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 WTF_PassRefPtr_h
22#define WTF_PassRefPtr_h
23
24#include "AlwaysInline.h"
14957cd0 25#include "NullPtr.h"
b37bf2e1
A
26
27namespace WTF {
28
29 template<typename T> class RefPtr;
30 template<typename T> class PassRefPtr;
14957cd0 31 template<typename T> PassRefPtr<T> adoptRef(T*);
4e4e5a6f 32
14957cd0 33 inline void adopted(const void*) { }
4e4e5a6f 34
4e4e5a6f
A
35#if !COMPILER(WINSCW)
36#if !PLATFORM(QT)
14957cd0 37 #define REF_DEREF_INLINE ALWAYS_INLINE
4e4e5a6f 38#else
14957cd0
A
39 // Using ALWAYS_INLINE broke the Qt build. This may be a GCC bug.
40 // See https://bugs.webkit.org/show_bug.cgi?id=37253 for details.
41 #define REF_DEREF_INLINE inline
4e4e5a6f 42#endif
14957cd0
A
43#else
44 // No inlining for WINSCW compiler to prevent the compiler agressively resolving
45 // T::ref() and T::deref(), which will fail compiling when PassRefPtr<T> is used as
46 // a class member or function arguments before T is defined.
47 #define REF_DEREF_INLINE
4e4e5a6f 48#endif
14957cd0
A
49
50 template<typename T> REF_DEREF_INLINE void refIfNotNull(T* ptr)
4e4e5a6f
A
51 {
52 if (LIKELY(ptr != 0))
53 ptr->ref();
54 }
55
14957cd0 56 template<typename T> REF_DEREF_INLINE void derefIfNotNull(T* ptr)
f9bf01c6 57 {
4e4e5a6f 58 if (LIKELY(ptr != 0))
f9bf01c6
A
59 ptr->deref();
60 }
b37bf2e1 61
14957cd0
A
62 #undef REF_DEREF_INLINE
63
b37bf2e1
A
64 template<typename T> class PassRefPtr {
65 public:
14957cd0 66 PassRefPtr() : m_ptr(0) { }
4e4e5a6f 67 PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
b37bf2e1
A
68 // It somewhat breaks the type system to allow transfer of ownership out of
69 // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr
14957cd0
A
70 // temporaries, and we don't have a need to use real const PassRefPtrs anyway.
71 PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) { }
72 template<typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.leakRef()) { }
b37bf2e1 73
4e4e5a6f 74 ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); }
f9bf01c6 75
14957cd0 76 template<typename U> PassRefPtr(const RefPtr<U>&);
b37bf2e1
A
77
78 T* get() const { return m_ptr; }
79
14957cd0
A
80 void clear();
81 T* leakRef() const WARN_UNUSED_RETURN;
b37bf2e1
A
82
83 T& operator*() const { return *m_ptr; }
84 T* operator->() const { return m_ptr; }
14957cd0 85
b37bf2e1
A
86 bool operator!() const { return !m_ptr; }
87
88 // This conversion operator allows implicit conversion to bool but not to other integer types.
f9bf01c6 89 typedef T* (PassRefPtr::*UnspecifiedBoolType);
b37bf2e1 90 operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; }
f9bf01c6 91
b37bf2e1
A
92 PassRefPtr& operator=(T*);
93 PassRefPtr& operator=(const PassRefPtr&);
14957cd0
A
94#if !HAVE(NULLPTR)
95 PassRefPtr& operator=(std::nullptr_t) { clear(); return *this; }
96#endif
97 template<typename U> PassRefPtr& operator=(const PassRefPtr<U>&);
98 template<typename U> PassRefPtr& operator=(const RefPtr<U>&);
b37bf2e1
A
99
100 friend PassRefPtr adoptRef<T>(T*);
14957cd0
A
101
102 // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
103 T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); }
104
b37bf2e1
A
105 private:
106 // adopting constructor
14957cd0
A
107 PassRefPtr(T* ptr, bool) : m_ptr(ptr) { }
108
b37bf2e1
A
109 mutable T* m_ptr;
110 };
111
f9bf01c6 112 // NonNullPassRefPtr: Optimized for passing non-null pointers. A NonNullPassRefPtr
14957cd0 113 // begins life non-null, and can only become null through a call to leakRef()
f9bf01c6
A
114 // or clear().
115
116 // FIXME: NonNullPassRefPtr could just inherit from PassRefPtr. However,
117 // if we use inheritance, GCC's optimizer fails to realize that destruction
118 // of a released NonNullPassRefPtr is a no-op. So, for now, just copy the
119 // most important code from PassRefPtr.
14957cd0 120 template<typename T> class NonNullPassRefPtr {
f9bf01c6
A
121 public:
122 NonNullPassRefPtr(T* ptr)
123 : m_ptr(ptr)
124 {
125 ASSERT(m_ptr);
126 m_ptr->ref();
127 }
128
14957cd0 129 template<typename U> NonNullPassRefPtr(const RefPtr<U>& o)
f9bf01c6
A
130 : m_ptr(o.get())
131 {
132 ASSERT(m_ptr);
133 m_ptr->ref();
134 }
135
136 NonNullPassRefPtr(const NonNullPassRefPtr& o)
14957cd0 137 : m_ptr(o.leakRef())
f9bf01c6
A
138 {
139 ASSERT(m_ptr);
140 }
141
14957cd0
A
142 template<typename U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o)
143 : m_ptr(o.leakRef())
f9bf01c6
A
144 {
145 ASSERT(m_ptr);
146 }
147
14957cd0
A
148 template<typename U> NonNullPassRefPtr(const PassRefPtr<U>& o)
149 : m_ptr(o.leakRef())
f9bf01c6
A
150 {
151 ASSERT(m_ptr);
152 }
153
154 ALWAYS_INLINE ~NonNullPassRefPtr() { derefIfNotNull(m_ptr); }
155
156 T* get() const { return m_ptr; }
157
14957cd0
A
158 void clear();
159 T* leakRef() const WARN_UNUSED_RETURN { T* tmp = m_ptr; m_ptr = 0; return tmp; }
f9bf01c6
A
160
161 T& operator*() const { return *m_ptr; }
162 T* operator->() const { return m_ptr; }
163
14957cd0
A
164 // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
165 T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); }
166
f9bf01c6
A
167 private:
168 mutable T* m_ptr;
169 };
170
14957cd0
A
171 template<typename T> template<typename U> inline PassRefPtr<T>::PassRefPtr(const RefPtr<U>& o)
172 : m_ptr(o.get())
173 {
174 T* ptr = m_ptr;
175 refIfNotNull(ptr);
176 }
177
178 template<typename T> inline void PassRefPtr<T>::clear()
179 {
180 T* ptr = m_ptr;
181 m_ptr = 0;
182 derefIfNotNull(ptr);
183 }
184
185 template<typename T> inline T* PassRefPtr<T>::leakRef() const
186 {
187 T* ptr = m_ptr;
188 m_ptr = 0;
189 return ptr;
190 }
191
192 template<typename T> template<typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const RefPtr<U>& o)
b37bf2e1
A
193 {
194 T* optr = o.get();
4e4e5a6f 195 refIfNotNull(optr);
b37bf2e1
A
196 T* ptr = m_ptr;
197 m_ptr = optr;
4e4e5a6f 198 derefIfNotNull(ptr);
b37bf2e1
A
199 return *this;
200 }
201
14957cd0 202 template<typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(T* optr)
b37bf2e1 203 {
4e4e5a6f 204 refIfNotNull(optr);
b37bf2e1
A
205 T* ptr = m_ptr;
206 m_ptr = optr;
4e4e5a6f 207 derefIfNotNull(ptr);
b37bf2e1
A
208 return *this;
209 }
210
14957cd0 211 template<typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<T>& ref)
b37bf2e1
A
212 {
213 T* ptr = m_ptr;
14957cd0 214 m_ptr = ref.leakRef();
4e4e5a6f 215 derefIfNotNull(ptr);
b37bf2e1
A
216 return *this;
217 }
218
14957cd0 219 template<typename T> template<typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<U>& ref)
b37bf2e1
A
220 {
221 T* ptr = m_ptr;
14957cd0 222 m_ptr = ref.leakRef();
4e4e5a6f 223 derefIfNotNull(ptr);
b37bf2e1
A
224 return *this;
225 }
226
14957cd0 227 template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
b37bf2e1
A
228 {
229 return a.get() == b.get();
230 }
231
14957cd0 232 template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b)
b37bf2e1
A
233 {
234 return a.get() == b.get();
235 }
236
14957cd0 237 template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b)
b37bf2e1
A
238 {
239 return a.get() == b.get();
240 }
241
14957cd0 242 template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, U* b)
b37bf2e1
A
243 {
244 return a.get() == b;
245 }
246
14957cd0 247 template<typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b)
b37bf2e1
A
248 {
249 return a == b.get();
250 }
251
14957cd0 252 template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
b37bf2e1
A
253 {
254 return a.get() != b.get();
255 }
256
14957cd0 257 template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b)
b37bf2e1
A
258 {
259 return a.get() != b.get();
260 }
261
14957cd0 262 template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b)
b37bf2e1
A
263 {
264 return a.get() != b.get();
265 }
266
14957cd0 267 template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b)
b37bf2e1
A
268 {
269 return a.get() != b;
270 }
271
14957cd0 272 template<typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b)
b37bf2e1
A
273 {
274 return a != b.get();
275 }
276
14957cd0 277 template<typename T> inline PassRefPtr<T> adoptRef(T* p)
b37bf2e1 278 {
14957cd0 279 adopted(p);
b37bf2e1
A
280 return PassRefPtr<T>(p, true);
281 }
282
14957cd0 283 template<typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p)
b37bf2e1 284 {
14957cd0 285 return adoptRef(static_cast<T*>(p.leakRef()));
b37bf2e1
A
286 }
287
14957cd0 288 template<typename T, typename U> inline PassRefPtr<T> const_pointer_cast(const PassRefPtr<U>& p)
b37bf2e1 289 {
14957cd0 290 return adoptRef(const_cast<T*>(p.leakRef()));
b37bf2e1
A
291 }
292
14957cd0 293 template<typename T> inline T* getPtr(const PassRefPtr<T>& p)
b37bf2e1
A
294 {
295 return p.get();
296 }
297
14957cd0
A
298 template<typename T> inline void NonNullPassRefPtr<T>::clear()
299 {
300 T* ptr = m_ptr;
301 m_ptr = 0;
302 derefIfNotNull(ptr);
303 }
304
b37bf2e1
A
305} // namespace WTF
306
307using WTF::PassRefPtr;
f9bf01c6 308using WTF::NonNullPassRefPtr;
b37bf2e1
A
309using WTF::adoptRef;
310using WTF::static_pointer_cast;
311using WTF::const_pointer_cast;
312
313#endif // WTF_PassRefPtr_h