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