1/*
2 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013 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// RefPtr and PassRefPtr are documented at http://webkit.org/coding/RefPtr.html
22
23#ifndef WTF_RefPtr_h
24#define WTF_RefPtr_h
25
26#include <algorithm>
27#include <utility>
28#include <wtf/FastMalloc.h>
29#include <wtf/GetPtr.h>
30#include <wtf/PassRefPtr.h>
31
32namespace WTF {
33
34enum HashTableDeletedValueType { HashTableDeletedValue };
35
36template<typename T> class RefPtr {
37 WTF_MAKE_FAST_ALLOCATED;
38public:
39 typedef T ValueType;
40 typedef ValueType* PtrType;
41
42 ALWAYS_INLINE RefPtr() : m_ptr(nullptr) { }
43 ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
44 ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(m_ptr); }
45 template<typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { refIfNotNull(m_ptr); }
46
47 ALWAYS_INLINE RefPtr(RefPtr&& o) : m_ptr(o.release().leakRef()) { }
48 template<typename U> RefPtr(RefPtr<U>&& o) : m_ptr(o.release().leakRef()) { }
49
50 // See comments in PassRefPtr.h for an explanation of why this takes a const reference.
51 template<typename U> RefPtr(const PassRefPtr<U>&);
52
53 template<typename U> RefPtr(Ref<U>&&);
54
55 // Hash table deleted values, which are only constructed and never copied or destroyed.
56 RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
57 bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
58
59 ALWAYS_INLINE ~RefPtr() { derefIfNotNull(std::exchange(m_ptr, nullptr)); }
60
61 T* get() const { return m_ptr; }
62
63 PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = nullptr; return tmp; }
64 Ref<T> releaseNonNull() { ASSERT(m_ptr); Ref<T> tmp(adoptRef(*m_ptr)); m_ptr = nullptr; return tmp; }
65
66 T* leakRef() WARN_UNUSED_RETURN;
67
68 T& operator*() const { ASSERT(m_ptr); return *m_ptr; }
69 ALWAYS_INLINE T* operator->() const { return m_ptr; }
70
71 bool operator!() const { return !m_ptr; }
72
73 // This conversion operator allows implicit conversion to bool but not to other integer types.
74 typedef T* (RefPtr::*UnspecifiedBoolType);
75 operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : nullptr; }
76
77 RefPtr& operator=(const RefPtr&);
78 RefPtr& operator=(T*);
79 RefPtr& operator=(std::nullptr_t);
80 RefPtr& operator=(const PassRefPtr<T>&);
81 template<typename U> RefPtr& operator=(const RefPtr<U>&);
82 template<typename U> RefPtr& operator=(const PassRefPtr<U>&);
83 RefPtr& operator=(RefPtr&&);
84 template<typename U> RefPtr& operator=(RefPtr<U>&&);
85 template<typename U> RefPtr& operator=(Ref<U>&&);
86
87 void swap(RefPtr&);
88
89 static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
90
91#if COMPILER_SUPPORTS(CXX_REFERENCE_QUALIFIED_FUNCTIONS)
92 RefPtr copyRef() && = delete;
93 RefPtr copyRef() const & WARN_UNUSED_RETURN { return RefPtr(m_ptr); }
94#else
95 RefPtr copyRef() const WARN_UNUSED_RETURN { return RefPtr(m_ptr); }
96#endif
97
98private:
99 T* m_ptr;
100};
101
102template<typename T> template<typename U> inline RefPtr<T>::RefPtr(const PassRefPtr<U>& o)
103 : m_ptr(o.leakRef())
104{
105}
106
107template<typename T> template<typename U> inline RefPtr<T>::RefPtr(Ref<U>&& reference)
108 : m_ptr(&reference.leakRef())
109{
110}
111
112template<typename T>
113inline T* RefPtr<T>::leakRef()
114{
115 return std::exchange(m_ptr, nullptr);
116}
117
118template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr& o)
119{
120 RefPtr ptr = o;
121 swap(ptr);
122 return *this;
123}
124
125template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o)
126{
127 RefPtr ptr = o;
128 swap(ptr);
129 return *this;
130}
131
132template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr)
133{
134 RefPtr ptr = optr;
135 swap(ptr);
136 return *this;
137}
138
139template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(std::nullptr_t)
140{
141 derefIfNotNull(std::exchange(m_ptr, nullptr));
142 return *this;
143}
144
145template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<T>& o)
146{
147 RefPtr ptr = o;
148 swap(ptr);
149 return *this;
150}
151
152template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<U>& o)
153{
154 RefPtr ptr = o;
155 swap(ptr);
156 return *this;
157}
158
159template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(RefPtr&& o)
160{
161 RefPtr ptr = WTFMove(o);
162 swap(ptr);
163 return *this;
164}
165
166template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(RefPtr<U>&& o)
167{
168 RefPtr ptr = WTFMove(o);
169 swap(ptr);
170 return *this;
171}
172
173template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(Ref<U>&& reference)
174{
175 RefPtr ptr = WTFMove(reference);
176 swap(ptr);
177 return *this;
178}
179
180template<class T> inline void RefPtr<T>::swap(RefPtr& o)
181{
182 std::swap(m_ptr, o.m_ptr);
183}
184
185template<class T> inline void swap(RefPtr<T>& a, RefPtr<T>& b)
186{
187 a.swap(b);
188}
189
190template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
191{
192 return a.get() == b.get();
193}
194
195template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, U* b)
196{
197 return a.get() == b;
198}
199
200template<typename T, typename U> inline bool operator==(T* a, const RefPtr<U>& b)
201{
202 return a == b.get();
203}
204
205template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b)
206{
207 return a.get() != b.get();
208}
209
210template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, U* b)
211{
212 return a.get() != b;
213}
214
215template<typename T, typename U> inline bool operator!=(T* a, const RefPtr<U>& b)
216{
217 return a != b.get();
218}
219
220template<typename T, typename U> inline RefPtr<T> static_pointer_cast(const RefPtr<U>& p)
221{
222 return RefPtr<T>(static_cast<T*>(p.get()));
223}
224
225template <typename T> struct IsSmartPtr<RefPtr<T>> {
226 static const bool value = true;
227};
228
229} // namespace WTF
230
231using WTF::RefPtr;
232using WTF::static_pointer_cast;
233
234#endif // WTF_RefPtr_h
235