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
27namespace WTF {
28
29    template<typename T> class RefPtr;
30    template<typename T> class PassRefPtr;
31    template<typename T> PassRefPtr<T> adoptRef(T*);
32
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
50    template<typename T> REF_DEREF_INLINE void refIfNotNull(T* ptr)
51    {
52        if (LIKELY(ptr != 0))
53            ptr->ref();
54    }
55
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:
66        PassRefPtr() : m_ptr(0) { }
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.
71        PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) { }
72        template<typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.leakRef()) { }
73
74        ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); }
75
76        template<typename U> PassRefPtr(const RefPtr<U>&);
77
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);
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.
103        T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); }
104
105    private:
106        // adopting constructor
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:
122        NonNullPassRefPtr(T* ptr)
123            : m_ptr(ptr)
124        {
125            ASSERT(m_ptr);
126            m_ptr->ref();
127        }
128
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
136        NonNullPassRefPtr(const NonNullPassRefPtr& o)
137            : m_ptr(o.leakRef())
138        {
139            ASSERT(m_ptr);
140        }
141
142        template<typename U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o)
143            : m_ptr(o.leakRef())
144        {
145            ASSERT(m_ptr);
146        }
147
148        template<typename U> NonNullPassRefPtr(const PassRefPtr<U>& o)
149            : m_ptr(o.leakRef())
150        {
151            ASSERT(m_ptr);
152        }
153
154        ALWAYS_INLINE ~NonNullPassRefPtr() { derefIfNotNull(m_ptr); }
155
156        T* get() const { return m_ptr; }
157
158        void clear();
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.
165        T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); }
166
167    private:
168        mutable T* m_ptr;
169    };
170
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)
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
277    template<typename T> inline PassRefPtr<T> adoptRef(T* p)
278    {
279        adopted(p);
280        return PassRefPtr<T>(p, true);
281    }
282
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
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
293    template<typename T> inline T* getPtr(const PassRefPtr<T>& p)
294    {
295        return p.get();
296    }
297
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
307using WTF::PassRefPtr;
308using WTF::NonNullPassRefPtr;
309using WTF::adoptRef;
310using WTF::static_pointer_cast;
311using WTF::const_pointer_cast;
312
313#endif // WTF_PassRefPtr_h
314