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 "wtf/Assertions.h" 25 #include "wtf/NullPtr.h" 26 #include "wtf/RawPtr.h" 27 #include "wtf/TypeTraits.h" 28 29 namespace WTF { 30 31 template<typename T> class RefPtr; 32 template<typename T> class PassRefPtr; 33 template<typename T> PassRefPtr<T> adoptRef(T*); 34 adopted(const void *)35 inline void adopted(const void*) { } 36 37 // requireAdoption() is not overloaded for WTF::RefCounted, which has a 38 // built-in assumption that adoption is required. requireAdoption() is 39 // for bootstrapping alternate reference count classes that are compatible 40 // with ReftPtr/PassRefPtr but cannot have adoption checks enabled 41 // by default, such as skia's SkRefCnt. The purpose of requireAdoption() 42 // is to enable adoption checks only once it is known that the object will 43 // be used with RefPtr/PassRefPtr. requireAdoption(const void *)44 inline void requireAdoption(const void*) { } 45 refIfNotNull(T * ptr)46 template<typename T> ALWAYS_INLINE void refIfNotNull(T* ptr) 47 { 48 if (LIKELY(ptr != 0)) { 49 requireAdoption(ptr); 50 ptr->ref(); 51 } 52 } 53 derefIfNotNull(T * ptr)54 template<typename T> ALWAYS_INLINE void derefIfNotNull(T* ptr) 55 { 56 if (LIKELY(ptr != 0)) 57 ptr->deref(); 58 } 59 60 template<typename T> class PassRefPtr { 61 WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(PassRefPtr); 62 public: PassRefPtr()63 PassRefPtr() : m_ptr(0) { } PassRefPtr(std::nullptr_t)64 PassRefPtr(std::nullptr_t) : m_ptr(0) { } PassRefPtr(T * ptr)65 PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } PassRefPtr(const RawPtr<U> & ptr,EnsurePtrConvertibleArgDecl (U,T))66 template<typename U> PassRefPtr(const RawPtr<U>& ptr, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(ptr.get()) { refIfNotNull(m_ptr); } PassRefPtr(T & ptr)67 explicit PassRefPtr(T& ptr) : m_ptr(&ptr) { m_ptr->ref(); } 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,EnsurePtrConvertibleArgDecl (U,T))72 template<typename U> PassRefPtr(const PassRefPtr<U>& o, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(o.leakRef()) { } 73 ~PassRefPtr()74 ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); } 75 76 template<typename U> PassRefPtr(const RefPtr<U>&, EnsurePtrConvertibleArgDecl(U, T)); 77 get()78 T* get() const { return m_ptr; } 79 80 T* leakRef() const WARN_UNUSED_RETURN; 81 82 T& operator*() const { return *m_ptr; } 83 T* operator->() const { return m_ptr; } 84 85 bool operator!() const { return !m_ptr; } 86 87 // This conversion operator allows implicit conversion to bool but not to other integer types. 88 typedef T* (PassRefPtr::*UnspecifiedBoolType); UnspecifiedBoolType()89 operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; } 90 91 friend PassRefPtr adoptRef<T>(T*); 92 93 private: 94 enum AdoptRefTag { AdoptRef }; PassRefPtr(T * ptr,AdoptRefTag)95 PassRefPtr(T* ptr, AdoptRefTag) : m_ptr(ptr) { } 96 97 PassRefPtr& operator=(const PassRefPtr&) { COMPILE_ASSERT(!sizeof(T*), PassRefPtr_should_never_be_assigned_to); return *this; } 98 99 mutable T* m_ptr; 100 }; 101 PassRefPtr(const RefPtr<U> & o,EnsurePtrConvertibleArgDefn (U,T))102 template<typename T> template<typename U> inline PassRefPtr<T>::PassRefPtr(const RefPtr<U>& o, EnsurePtrConvertibleArgDefn(U, T)) 103 : m_ptr(o.get()) 104 { 105 T* ptr = m_ptr; 106 refIfNotNull(ptr); 107 } 108 leakRef()109 template<typename T> inline T* PassRefPtr<T>::leakRef() const 110 { 111 T* ptr = m_ptr; 112 m_ptr = 0; 113 return ptr; 114 } 115 116 template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b) 117 { 118 return a.get() == b.get(); 119 } 120 121 template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b) 122 { 123 return a.get() == b.get(); 124 } 125 126 template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b) 127 { 128 return a.get() == b.get(); 129 } 130 131 template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, U* b) 132 { 133 return a.get() == b; 134 } 135 136 template<typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b) 137 { 138 return a == b.get(); 139 } 140 141 template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RawPtr<U>& b) 142 { 143 return a.get() == b.get(); 144 } 145 146 template<typename T, typename U> inline bool operator==(const RawPtr<T>& a, const PassRefPtr<U>& b) 147 { 148 return a.get() == b.get(); 149 } 150 151 template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b) 152 { 153 return a.get() != b.get(); 154 } 155 156 template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b) 157 { 158 return a.get() != b.get(); 159 } 160 161 template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b) 162 { 163 return a.get() != b.get(); 164 } 165 166 template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b) 167 { 168 return a.get() != b; 169 } 170 171 template<typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b) 172 { 173 return a != b.get(); 174 } 175 176 template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RawPtr<U>& b) 177 { 178 return a.get() != b.get(); 179 } 180 181 template<typename T, typename U> inline bool operator!=(const RawPtr<T>& a, const PassRefPtr<U>& b) 182 { 183 return a.get() != b.get(); 184 } 185 adoptRef(T * p)186 template<typename T> PassRefPtr<T> adoptRef(T* p) 187 { 188 adopted(p); 189 return PassRefPtr<T>(p, PassRefPtr<T>::AdoptRef); 190 } 191 static_pointer_cast(const PassRefPtr<U> & p)192 template<typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p) 193 { 194 return adoptRef(static_cast<T*>(p.leakRef())); 195 } 196 getPtr(const PassRefPtr<T> & p)197 template<typename T> inline T* getPtr(const PassRefPtr<T>& p) 198 { 199 return p.get(); 200 } 201 202 } // namespace WTF 203 204 using WTF::PassRefPtr; 205 using WTF::adoptRef; 206 using WTF::static_pointer_cast; 207 208 #endif // WTF_PassRefPtr_h 209