Add PassRef and createRefCounted so we can improve creation of RefCounted objects
[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 "FastMalloc.h"
27 #include "PassRefPtr.h"
28 #include <algorithm>
29 #include <utility>
30
31 namespace WTF {
32
33     enum HashTableDeletedValueType { HashTableDeletedValue };
34
35     template<typename T> class RefPtr {
36         WTF_MAKE_FAST_ALLOCATED;
37     public:
38         ALWAYS_INLINE RefPtr() : m_ptr(nullptr) { }
39         ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
40         ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(m_ptr); }
41         template<typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { refIfNotNull(m_ptr); }
42
43         ALWAYS_INLINE RefPtr(RefPtr&& o) : m_ptr(o.release().leakRef()) { }
44         template<typename U> RefPtr(RefPtr<U>&& o) : m_ptr(o.release().leakRef()) { }
45
46         // See comments in PassRefPtr.h for an explanation of why this takes a const reference.
47         template<typename U> RefPtr(const PassRefPtr<U>&);
48
49         template<typename U> RefPtr(PassRef<U>);
50
51         // Hash table deleted values, which are only constructed and never copied or destroyed.
52         RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
53         bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
54
55         ALWAYS_INLINE ~RefPtr() { derefIfNotNull(m_ptr); }
56
57         T* get() const { return m_ptr; }
58         
59         void clear();
60         PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = nullptr; return tmp; }
61
62         T& operator*() const { return *m_ptr; }
63         ALWAYS_INLINE T* operator->() const { return m_ptr; }
64         
65         bool operator!() const { return !m_ptr; }
66     
67         // This conversion operator allows implicit conversion to bool but not to other integer types.
68         typedef T* (RefPtr::*UnspecifiedBoolType);
69         operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : nullptr; }
70         
71         RefPtr& operator=(const RefPtr&);
72         RefPtr& operator=(T*);
73         RefPtr& operator=(const PassRefPtr<T>&);
74 #if !COMPILER_SUPPORTS(CXX_NULLPTR)
75         RefPtr& operator=(std::nullptr_t) { clear(); return *this; }
76 #endif
77         template<typename U> RefPtr& operator=(const RefPtr<U>&);
78         template<typename U> RefPtr& operator=(const PassRefPtr<U>&);
79         RefPtr& operator=(RefPtr&&);
80         template<typename U> RefPtr& operator=(RefPtr<U>&&);
81         template<typename U> RefPtr& operator=(PassRef<U>);
82
83         void swap(RefPtr&);
84
85         static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
86
87     private:
88         T* m_ptr;
89     };
90     
91     template<typename T> template<typename U> inline RefPtr<T>::RefPtr(const PassRefPtr<U>& o)
92         : m_ptr(o.leakRef())
93     {
94     }
95
96     template<typename T> template<typename U> inline RefPtr<T>::RefPtr(PassRef<U> reference)
97         : m_ptr(&reference.takeReference())
98     {
99     }
100
101     template<typename T> inline void RefPtr<T>::clear()
102     {
103         T* ptr = m_ptr;
104         m_ptr = nullptr;
105         derefIfNotNull(ptr);
106     }
107
108     template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr& o)
109     {
110         RefPtr ptr = o;
111         swap(ptr);
112         return *this;
113     }
114     
115     template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o)
116     {
117         RefPtr ptr = o;
118         swap(ptr);
119         return *this;
120     }
121     
122     template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr)
123     {
124         RefPtr ptr = optr;
125         swap(ptr);
126         return *this;
127     }
128
129     template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<T>& 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 PassRefPtr<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=(RefPtr&& o)
144     {
145         RefPtr ptr = std::move(o);
146         swap(ptr);
147         return *this;
148     }
149
150     template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(RefPtr<U>&& o)
151     {
152         RefPtr ptr = std::move(o);
153         swap(ptr);
154         return *this;
155     }
156
157     template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(PassRef<U> reference)
158     {
159         RefPtr ptr = reference;
160         swap(ptr);
161         return *this;
162     }
163
164     template<class T> inline void RefPtr<T>::swap(RefPtr& o)
165     {
166         std::swap(m_ptr, o.m_ptr);
167     }
168
169     template<class T> inline void swap(RefPtr<T>& a, RefPtr<T>& b)
170     {
171         a.swap(b);
172     }
173
174     template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
175     { 
176         return a.get() == b.get(); 
177     }
178
179     template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, U* b)
180     { 
181         return a.get() == b; 
182     }
183     
184     template<typename T, typename U> inline bool operator==(T* a, const RefPtr<U>& b) 
185     {
186         return a == b.get(); 
187     }
188     
189     template<typename T, typename U> inline bool operator!=(const RefPtr<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, U* b)
195     {
196         return a.get() != b; 
197     }
198
199     template<typename T, typename U> inline bool operator!=(T* a, const RefPtr<U>& b)
200     { 
201         return a != b.get(); 
202     }
203     
204     template<typename T, typename U> inline RefPtr<T> static_pointer_cast(const RefPtr<U>& p)
205     { 
206         return RefPtr<T>(static_cast<T*>(p.get())); 
207     }
208
209     template<typename T> inline T* getPtr(const RefPtr<T>& p)
210     {
211         return p.get();
212     }
213
214 } // namespace WTF
215
216 using WTF::RefPtr;
217 using WTF::static_pointer_cast;
218
219 #endif // WTF_RefPtr_h