1 /* 2 * Copyright (C) 2005, 2006, 2007, 2008, 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 RetainPtr_h 22 #define RetainPtr_h 23 24 #include "HashTraits.h" 25 #include "NullPtr.h" 26 #include "TypeTraits.h" 27 #include <algorithm> 28 29 #if USE(CF) 30 #include <CoreFoundation/CoreFoundation.h> 31 #endif 32 33 #ifdef __OBJC__ 34 #import <Foundation/Foundation.h> 35 #endif 36 37 namespace WTF { 38 39 // Unlike most most of our smart pointers, RetainPtr can take either the pointer type or the pointed-to type, 40 // so both RetainPtr<NSDictionary> and RetainPtr<CFDictionaryRef> will work. 41 42 enum AdoptCFTag { AdoptCF }; 43 enum AdoptNSTag { AdoptNS }; 44 45 #ifdef __OBJC__ adoptNSReference(id ptr)46 inline void adoptNSReference(id ptr) 47 { 48 if (ptr) { 49 CFRetain(ptr); 50 [ptr release]; 51 } 52 } 53 #endif 54 55 template<typename T> class RetainPtr { 56 public: 57 typedef typename RemovePointer<T>::Type ValueType; 58 typedef ValueType* PtrType; 59 RetainPtr()60 RetainPtr() : m_ptr(0) {} RetainPtr(PtrType ptr)61 RetainPtr(PtrType ptr) : m_ptr(ptr) { if (ptr) CFRetain(ptr); } 62 RetainPtr(AdoptCFTag,PtrType ptr)63 RetainPtr(AdoptCFTag, PtrType ptr) : m_ptr(ptr) { } RetainPtr(AdoptNSTag,PtrType ptr)64 RetainPtr(AdoptNSTag, PtrType ptr) : m_ptr(ptr) { adoptNSReference(ptr); } 65 RetainPtr(const RetainPtr & o)66 RetainPtr(const RetainPtr& o) : m_ptr(o.m_ptr) { if (PtrType ptr = m_ptr) CFRetain(ptr); } 67 68 // Hash table deleted values, which are only constructed and never copied or destroyed. RetainPtr(HashTableDeletedValueType)69 RetainPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { } isHashTableDeletedValue()70 bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); } 71 ~RetainPtr()72 ~RetainPtr() { if (PtrType ptr = m_ptr) CFRelease(ptr); } 73 74 template<typename U> RetainPtr(const RetainPtr<U>&); 75 get()76 PtrType get() const { return m_ptr; } 77 78 void clear(); 79 PtrType leakRef() WARN_UNUSED_RETURN; 80 81 PtrType operator->() const { return m_ptr; } 82 83 bool operator!() const { return !m_ptr; } 84 85 // This conversion operator allows implicit conversion to bool but not to other integer types. 86 typedef PtrType RetainPtr::*UnspecifiedBoolType; UnspecifiedBoolType()87 operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; } 88 89 RetainPtr& operator=(const RetainPtr&); 90 template<typename U> RetainPtr& operator=(const RetainPtr<U>&); 91 RetainPtr& operator=(PtrType); 92 template<typename U> RetainPtr& operator=(U*); 93 #if !HAVE(NULLPTR) 94 RetainPtr& operator=(std::nullptr_t) { clear(); return *this; } 95 #endif 96 97 void adoptCF(PtrType); 98 void adoptNS(PtrType); 99 100 void swap(RetainPtr&); 101 102 // FIXME: Remove releaseRef once we change all callers to call leakRef instead. releaseRef()103 PtrType releaseRef() { return leakRef(); } 104 105 private: hashTableDeletedValue()106 static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); } 107 108 PtrType m_ptr; 109 }; 110 RetainPtr(const RetainPtr<U> & o)111 template<typename T> template<typename U> inline RetainPtr<T>::RetainPtr(const RetainPtr<U>& o) 112 : m_ptr(o.get()) 113 { 114 if (PtrType ptr = m_ptr) 115 CFRetain(ptr); 116 } 117 clear()118 template<typename T> inline void RetainPtr<T>::clear() 119 { 120 if (PtrType ptr = m_ptr) { 121 m_ptr = 0; 122 CFRelease(ptr); 123 } 124 } 125 leakRef()126 template<typename T> inline typename RetainPtr<T>::PtrType RetainPtr<T>::leakRef() 127 { 128 PtrType ptr = m_ptr; 129 m_ptr = 0; 130 return ptr; 131 } 132 133 template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<T>& o) 134 { 135 PtrType optr = o.get(); 136 if (optr) 137 CFRetain(optr); 138 PtrType ptr = m_ptr; 139 m_ptr = optr; 140 if (ptr) 141 CFRelease(ptr); 142 return *this; 143 } 144 145 template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o) 146 { 147 PtrType optr = o.get(); 148 if (optr) 149 CFRetain(optr); 150 PtrType ptr = m_ptr; 151 m_ptr = optr; 152 if (ptr) 153 CFRelease(ptr); 154 return *this; 155 } 156 157 template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(PtrType optr) 158 { 159 if (optr) 160 CFRetain(optr); 161 PtrType ptr = m_ptr; 162 m_ptr = optr; 163 if (ptr) 164 CFRelease(ptr); 165 return *this; 166 } 167 adoptCF(PtrType optr)168 template<typename T> inline void RetainPtr<T>::adoptCF(PtrType optr) 169 { 170 PtrType ptr = m_ptr; 171 m_ptr = optr; 172 if (ptr) 173 CFRelease(ptr); 174 } 175 adoptNS(PtrType optr)176 template<typename T> inline void RetainPtr<T>::adoptNS(PtrType optr) 177 { 178 adoptNSReference(optr); 179 180 PtrType ptr = m_ptr; 181 m_ptr = optr; 182 if (ptr) 183 CFRelease(ptr); 184 } 185 186 template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(U* optr) 187 { 188 if (optr) 189 CFRetain(optr); 190 PtrType ptr = m_ptr; 191 m_ptr = optr; 192 if (ptr) 193 CFRelease(ptr); 194 return *this; 195 } 196 swap(RetainPtr<T> & o)197 template<typename T> inline void RetainPtr<T>::swap(RetainPtr<T>& o) 198 { 199 std::swap(m_ptr, o.m_ptr); 200 } 201 swap(RetainPtr<T> & a,RetainPtr<T> & b)202 template<typename T> inline void swap(RetainPtr<T>& a, RetainPtr<T>& b) 203 { 204 a.swap(b); 205 } 206 207 template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b) 208 { 209 return a.get() == b.get(); 210 } 211 212 template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b) 213 { 214 return a.get() == b; 215 } 216 217 template<typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b) 218 { 219 return a == b.get(); 220 } 221 222 template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b) 223 { 224 return a.get() != b.get(); 225 } 226 227 template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b) 228 { 229 return a.get() != b; 230 } 231 232 template<typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b) 233 { 234 return a != b.get(); 235 } 236 237 template<typename P> struct HashTraits<RetainPtr<P> > : SimpleClassHashTraits<RetainPtr<P> > { }; 238 239 template<typename P> struct PtrHash<RetainPtr<P> > : PtrHash<P*> { 240 using PtrHash<P*>::hash; 241 static unsigned hash(const RetainPtr<P>& key) { return hash(key.get()); } 242 using PtrHash<P*>::equal; 243 static bool equal(const RetainPtr<P>& a, const RetainPtr<P>& b) { return a == b; } 244 static bool equal(P* a, const RetainPtr<P>& b) { return a == b; } 245 static bool equal(const RetainPtr<P>& a, P* b) { return a == b; } 246 }; 247 248 template<typename P> struct DefaultHash<RetainPtr<P> > { typedef PtrHash<RetainPtr<P> > Hash; }; 249 250 } // namespace WTF 251 252 using WTF::AdoptCF; 253 using WTF::AdoptNS; 254 using WTF::RetainPtr; 255 256 #endif // WTF_RetainPtr_h 257