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