• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (C) 2005, 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 WTF_PassRefPtr_h
22 #define WTF_PassRefPtr_h
23 
24 #include "AlwaysInline.h"
25 #include "NullPtr.h"
26 
27 namespace WTF {
28 
29     template<typename T> class RefPtr;
30     template<typename T> class PassRefPtr;
31     template<typename T> PassRefPtr<T> adoptRef(T*);
32 
adopted(const void *)33     inline void adopted(const void*) { }
34 
35 #if !COMPILER(WINSCW)
36 #if !PLATFORM(QT)
37     #define REF_DEREF_INLINE ALWAYS_INLINE
38 #else
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
42 #endif
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
48 #endif
49 
refIfNotNull(T * ptr)50     template<typename T> REF_DEREF_INLINE void refIfNotNull(T* ptr)
51     {
52         if (LIKELY(ptr != 0))
53             ptr->ref();
54     }
55 
derefIfNotNull(T * ptr)56     template<typename T> REF_DEREF_INLINE void derefIfNotNull(T* ptr)
57     {
58         if (LIKELY(ptr != 0))
59             ptr->deref();
60     }
61 
62     #undef REF_DEREF_INLINE
63 
64     template<typename T> class PassRefPtr {
65     public:
PassRefPtr()66         PassRefPtr() : m_ptr(0) { }
PassRefPtr(T * ptr)67         PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
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
70         // temporaries, and we don't have a need to use real const PassRefPtrs anyway.
PassRefPtr(const PassRefPtr & o)71         PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) { }
PassRefPtr(const PassRefPtr<U> & o)72         template<typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.leakRef()) { }
73 
~PassRefPtr()74         ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); }
75 
76         template<typename U> PassRefPtr(const RefPtr<U>&);
77 
get()78         T* get() const { return m_ptr; }
79 
80         void clear();
81         T* leakRef() const WARN_UNUSED_RETURN;
82 
83         T& operator*() const { return *m_ptr; }
84         T* operator->() const { return m_ptr; }
85 
86         bool operator!() const { return !m_ptr; }
87 
88         // This conversion operator allows implicit conversion to bool but not to other integer types.
89         typedef T* (PassRefPtr::*UnspecifiedBoolType);
UnspecifiedBoolType()90         operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; }
91 
92         PassRefPtr& operator=(T*);
93         PassRefPtr& operator=(const PassRefPtr&);
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>&);
99 
100         friend PassRefPtr adoptRef<T>(T*);
101 
102         // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
releaseRef()103         T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); }
104 
105     private:
106         // adopting constructor
PassRefPtr(T * ptr,bool)107         PassRefPtr(T* ptr, bool) : m_ptr(ptr) { }
108 
109         mutable T* m_ptr;
110     };
111 
112     // NonNullPassRefPtr: Optimized for passing non-null pointers. A NonNullPassRefPtr
113     // begins life non-null, and can only become null through a call to leakRef()
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.
120     template<typename T> class NonNullPassRefPtr {
121     public:
NonNullPassRefPtr(T * ptr)122         NonNullPassRefPtr(T* ptr)
123             : m_ptr(ptr)
124         {
125             ASSERT(m_ptr);
126             m_ptr->ref();
127         }
128 
NonNullPassRefPtr(const RefPtr<U> & o)129         template<typename U> NonNullPassRefPtr(const RefPtr<U>& o)
130             : m_ptr(o.get())
131         {
132             ASSERT(m_ptr);
133             m_ptr->ref();
134         }
135 
NonNullPassRefPtr(const NonNullPassRefPtr & o)136         NonNullPassRefPtr(const NonNullPassRefPtr& o)
137             : m_ptr(o.leakRef())
138         {
139             ASSERT(m_ptr);
140         }
141 
NonNullPassRefPtr(const NonNullPassRefPtr<U> & o)142         template<typename U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o)
143             : m_ptr(o.leakRef())
144         {
145             ASSERT(m_ptr);
146         }
147 
NonNullPassRefPtr(const PassRefPtr<U> & o)148         template<typename U> NonNullPassRefPtr(const PassRefPtr<U>& o)
149             : m_ptr(o.leakRef())
150         {
151             ASSERT(m_ptr);
152         }
153 
~NonNullPassRefPtr()154         ALWAYS_INLINE ~NonNullPassRefPtr() { derefIfNotNull(m_ptr); }
155 
get()156         T* get() const { return m_ptr; }
157 
158         void clear();
leakRef()159         T* leakRef() const WARN_UNUSED_RETURN { T* tmp = m_ptr; m_ptr = 0; return tmp; }
160 
161         T& operator*() const { return *m_ptr; }
162         T* operator->() const { return m_ptr; }
163 
164         // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
releaseRef()165         T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); }
166 
167     private:
168         mutable T* m_ptr;
169     };
170 
PassRefPtr(const RefPtr<U> & o)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 
clear()178     template<typename T> inline void PassRefPtr<T>::clear()
179     {
180         T* ptr = m_ptr;
181         m_ptr = 0;
182         derefIfNotNull(ptr);
183     }
184 
leakRef()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)
193     {
194         T* optr = o.get();
195         refIfNotNull(optr);
196         T* ptr = m_ptr;
197         m_ptr = optr;
198         derefIfNotNull(ptr);
199         return *this;
200     }
201 
202     template<typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(T* optr)
203     {
204         refIfNotNull(optr);
205         T* ptr = m_ptr;
206         m_ptr = optr;
207         derefIfNotNull(ptr);
208         return *this;
209     }
210 
211     template<typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<T>& ref)
212     {
213         T* ptr = m_ptr;
214         m_ptr = ref.leakRef();
215         derefIfNotNull(ptr);
216         return *this;
217     }
218 
219     template<typename T> template<typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<U>& ref)
220     {
221         T* ptr = m_ptr;
222         m_ptr = ref.leakRef();
223         derefIfNotNull(ptr);
224         return *this;
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, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
253     {
254         return a.get() != b.get();
255     }
256 
257     template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b)
258     {
259         return a.get() != b.get();
260     }
261 
262     template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b)
263     {
264         return a.get() != b.get();
265     }
266 
267     template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b)
268     {
269         return a.get() != b;
270     }
271 
272     template<typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b)
273     {
274         return a != b.get();
275     }
276 
adoptRef(T * p)277     template<typename T> inline PassRefPtr<T> adoptRef(T* p)
278     {
279         adopted(p);
280         return PassRefPtr<T>(p, true);
281     }
282 
static_pointer_cast(const PassRefPtr<U> & p)283     template<typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p)
284     {
285         return adoptRef(static_cast<T*>(p.leakRef()));
286     }
287 
const_pointer_cast(const PassRefPtr<U> & p)288     template<typename T, typename U> inline PassRefPtr<T> const_pointer_cast(const PassRefPtr<U>& p)
289     {
290         return adoptRef(const_cast<T*>(p.leakRef()));
291     }
292 
getPtr(const PassRefPtr<T> & p)293     template<typename T> inline T* getPtr(const PassRefPtr<T>& p)
294     {
295         return p.get();
296     }
297 
clear()298     template<typename T> inline void NonNullPassRefPtr<T>::clear()
299     {
300         T* ptr = m_ptr;
301         m_ptr = 0;
302         derefIfNotNull(ptr);
303     }
304 
305 } // namespace WTF
306 
307 using WTF::PassRefPtr;
308 using WTF::NonNullPassRefPtr;
309 using WTF::adoptRef;
310 using WTF::static_pointer_cast;
311 using WTF::const_pointer_cast;
312 
313 #endif // WTF_PassRefPtr_h
314