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