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