1 /* 2 * Copyright (C) 2005, 2006, 2007 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 26 namespace WTF { 27 28 template<typename T> class RefPtr; 29 template<typename T> class PassRefPtr; 30 template <typename T> PassRefPtr<T> adoptRef(T*); 31 32 33 // Remove inline for WINSCW compiler to prevent the compiler agressively resolving 34 // T::ref() and T::deref(), which will fail compiling when PassRefPtr<T> is used as 35 // a class member or function arguments before T is defined. 36 template<typename T> 37 #if !COMPILER(WINSCW) 38 inline 39 #endif refIfNotNull(T * ptr)40 void refIfNotNull(T* ptr) 41 { 42 if (UNLIKELY(ptr != 0)) 43 ptr->ref(); 44 } 45 46 template<typename T> 47 #if !COMPILER(WINSCW) 48 inline 49 #endif derefIfNotNull(T * ptr)50 void derefIfNotNull(T* ptr) 51 { 52 if (UNLIKELY(ptr != 0)) 53 ptr->deref(); 54 } 55 56 template<typename T> class PassRefPtr { 57 public: PassRefPtr()58 PassRefPtr() : m_ptr(0) {} PassRefPtr(T * ptr)59 PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } 60 // It somewhat breaks the type system to allow transfer of ownership out of 61 // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr 62 // temporaries, and we don't really have a need to use real const PassRefPtrs 63 // anyway. PassRefPtr(const PassRefPtr & o)64 PassRefPtr(const PassRefPtr& o) : m_ptr(o.releaseRef()) {} PassRefPtr(const PassRefPtr<U> & o)65 template <typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.releaseRef()) { } 66 ~PassRefPtr()67 ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); } 68 69 template <class U> PassRefPtr(const RefPtr<U> & o)70 PassRefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { T* ptr = m_ptr; refIfNotNull(ptr); } 71 get()72 T* get() const { return m_ptr; } 73 clear()74 void clear() { T* ptr = m_ptr; derefIfNotNull(ptr); m_ptr = 0; } releaseRef()75 T* releaseRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; } 76 77 T& operator*() const { return *m_ptr; } 78 T* operator->() const { return m_ptr; } 79 80 bool operator!() const { return !m_ptr; } 81 82 // This conversion operator allows implicit conversion to bool but not to other integer types. 83 typedef T* (PassRefPtr::*UnspecifiedBoolType); UnspecifiedBoolType()84 operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; } 85 86 PassRefPtr& operator=(T*); 87 PassRefPtr& operator=(const PassRefPtr&); 88 template <typename U> PassRefPtr& operator=(const PassRefPtr<U>&); 89 template <typename U> PassRefPtr& operator=(const RefPtr<U>&); 90 91 friend PassRefPtr adoptRef<T>(T*); 92 private: 93 // adopting constructor PassRefPtr(T * ptr,bool)94 PassRefPtr(T* ptr, bool) : m_ptr(ptr) {} 95 mutable T* m_ptr; 96 }; 97 98 // NonNullPassRefPtr: Optimized for passing non-null pointers. A NonNullPassRefPtr 99 // begins life non-null, and can only become null through a call to releaseRef() 100 // or clear(). 101 102 // FIXME: NonNullPassRefPtr could just inherit from PassRefPtr. However, 103 // if we use inheritance, GCC's optimizer fails to realize that destruction 104 // of a released NonNullPassRefPtr is a no-op. So, for now, just copy the 105 // most important code from PassRefPtr. 106 template <typename T> class NonNullPassRefPtr { 107 public: NonNullPassRefPtr(T * ptr)108 NonNullPassRefPtr(T* ptr) 109 : m_ptr(ptr) 110 { 111 ASSERT(m_ptr); 112 m_ptr->ref(); 113 } 114 NonNullPassRefPtr(const RefPtr<U> & o)115 template <class U> NonNullPassRefPtr(const RefPtr<U>& o) 116 : m_ptr(o.get()) 117 { 118 ASSERT(m_ptr); 119 m_ptr->ref(); 120 } 121 NonNullPassRefPtr(const NonNullPassRefPtr & o)122 NonNullPassRefPtr(const NonNullPassRefPtr& o) 123 : m_ptr(o.releaseRef()) 124 { 125 ASSERT(m_ptr); 126 } 127 NonNullPassRefPtr(const NonNullPassRefPtr<U> & o)128 template <class U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o) 129 : m_ptr(o.releaseRef()) 130 { 131 ASSERT(m_ptr); 132 } 133 NonNullPassRefPtr(const PassRefPtr<U> & o)134 template <class U> NonNullPassRefPtr(const PassRefPtr<U>& o) 135 : m_ptr(o.releaseRef()) 136 { 137 ASSERT(m_ptr); 138 } 139 ~NonNullPassRefPtr()140 ALWAYS_INLINE ~NonNullPassRefPtr() { derefIfNotNull(m_ptr); } 141 get()142 T* get() const { return m_ptr; } 143 clear()144 void clear() { derefIfNotNull(m_ptr); m_ptr = 0; } releaseRef()145 T* releaseRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; } 146 147 T& operator*() const { return *m_ptr; } 148 T* operator->() const { return m_ptr; } 149 150 private: 151 mutable T* m_ptr; 152 }; 153 154 template <typename T> template <typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const RefPtr<U>& o) 155 { 156 T* optr = o.get(); 157 refIfNotNull(optr); 158 T* ptr = m_ptr; 159 m_ptr = optr; 160 derefIfNotNull(ptr); 161 return *this; 162 } 163 164 template <typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(T* optr) 165 { 166 refIfNotNull(optr); 167 T* ptr = m_ptr; 168 m_ptr = optr; 169 derefIfNotNull(ptr); 170 return *this; 171 } 172 173 template <typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<T>& ref) 174 { 175 T* ptr = m_ptr; 176 m_ptr = ref.releaseRef(); 177 derefIfNotNull(ptr); 178 return *this; 179 } 180 181 template <typename T> template <typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<U>& ref) 182 { 183 T* ptr = m_ptr; 184 m_ptr = ref.releaseRef(); 185 derefIfNotNull(ptr); 186 return *this; 187 } 188 189 template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b) 190 { 191 return a.get() == b.get(); 192 } 193 194 template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b) 195 { 196 return a.get() == b.get(); 197 } 198 199 template <typename T, typename U> inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b) 200 { 201 return a.get() == b.get(); 202 } 203 204 template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, U* b) 205 { 206 return a.get() == b; 207 } 208 209 template <typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b) 210 { 211 return a == b.get(); 212 } 213 214 template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b) 215 { 216 return a.get() != b.get(); 217 } 218 219 template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b) 220 { 221 return a.get() != b.get(); 222 } 223 224 template <typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b) 225 { 226 return a.get() != b.get(); 227 } 228 229 template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b) 230 { 231 return a.get() != b; 232 } 233 234 template <typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b) 235 { 236 return a != b.get(); 237 } 238 adoptRef(T * p)239 template <typename T> inline PassRefPtr<T> adoptRef(T* p) 240 { 241 return PassRefPtr<T>(p, true); 242 } 243 static_pointer_cast(const PassRefPtr<U> & p)244 template <typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p) 245 { 246 return adoptRef(static_cast<T*>(p.releaseRef())); 247 } 248 const_pointer_cast(const PassRefPtr<U> & p)249 template <typename T, typename U> inline PassRefPtr<T> const_pointer_cast(const PassRefPtr<U>& p) 250 { 251 return adoptRef(const_cast<T*>(p.releaseRef())); 252 } 253 getPtr(const PassRefPtr<T> & p)254 template <typename T> inline T* getPtr(const PassRefPtr<T>& p) 255 { 256 return p.get(); 257 } 258 259 } // namespace WTF 260 261 using WTF::PassRefPtr; 262 using WTF::NonNullPassRefPtr; 263 using WTF::adoptRef; 264 using WTF::static_pointer_cast; 265 using WTF::const_pointer_cast; 266 267 #endif // WTF_PassRefPtr_h 268