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