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