RetainPtr.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  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. #ifndef RetainPtr_h
  21. #define RetainPtr_h
  22. #include <wtf/HashTraits.h>
  23. #include <wtf/NullPtr.h>
  24. #include <wtf/TypeTraits.h>
  25. #include <algorithm>
  26. #if USE(CF)
  27. #include <CoreFoundation/CoreFoundation.h>
  28. #endif
  29. #ifdef __OBJC__
  30. #import <Foundation/Foundation.h>
  31. #endif
  32. #ifndef CF_RELEASES_ARGUMENT
  33. #define CF_RELEASES_ARGUMENT
  34. #endif
  35. #ifndef NS_RELEASES_ARGUMENT
  36. #define NS_RELEASES_ARGUMENT
  37. #endif
  38. namespace WTF {
  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. enum AdoptCFTag { AdoptCF };
  42. enum AdoptNSTag { AdoptNS };
  43. #ifdef __OBJC__
  44. #ifdef OBJC_NO_GC
  45. inline void adoptNSReference(id)
  46. {
  47. }
  48. #else
  49. inline void adoptNSReference(id ptr)
  50. {
  51. if (ptr) {
  52. CFRetain(ptr);
  53. [ptr release];
  54. }
  55. }
  56. #endif
  57. #endif
  58. template<typename T> class RetainPtr {
  59. public:
  60. typedef typename RemovePointer<T>::Type ValueType;
  61. typedef ValueType* PtrType;
  62. RetainPtr() : m_ptr(0) {}
  63. RetainPtr(PtrType ptr) : m_ptr(ptr) { if (ptr) CFRetain(ptr); }
  64. RetainPtr(AdoptCFTag, PtrType ptr)
  65. : m_ptr(ptr)
  66. {
  67. #ifdef __OBJC__
  68. static_assert((!std::is_convertible<T, id>::value), "Don't use adoptCF with Objective-C pointer types, use adoptNS.");
  69. #endif
  70. }
  71. RetainPtr(AdoptNSTag, PtrType ptr)
  72. : m_ptr(ptr)
  73. {
  74. adoptNSReference(ptr);
  75. }
  76. RetainPtr(const RetainPtr& o) : m_ptr(o.m_ptr) { if (PtrType ptr = m_ptr) CFRetain(ptr); }
  77. #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
  78. RetainPtr(RetainPtr&& o) : m_ptr(o.leakRef()) { }
  79. #endif
  80. // Hash table deleted values, which are only constructed and never copied or destroyed.
  81. RetainPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
  82. bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
  83. ~RetainPtr() { if (PtrType ptr = m_ptr) CFRelease(ptr); }
  84. template<typename U> RetainPtr(const RetainPtr<U>&);
  85. void clear();
  86. PtrType leakRef() WARN_UNUSED_RETURN;
  87. PtrType get() const { return m_ptr; }
  88. PtrType operator->() const { return m_ptr; }
  89. #if COMPILER_SUPPORTS(CXX_EXPLICIT_CONVERSIONS)
  90. explicit operator PtrType() const { return m_ptr; }
  91. #endif
  92. bool operator!() const { return !m_ptr; }
  93. // This conversion operator allows implicit conversion to bool but not to other integer types.
  94. typedef PtrType RetainPtr::*UnspecifiedBoolType;
  95. operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; }
  96. RetainPtr& operator=(const RetainPtr&);
  97. template<typename U> RetainPtr& operator=(const RetainPtr<U>&);
  98. RetainPtr& operator=(PtrType);
  99. template<typename U> RetainPtr& operator=(U*);
  100. #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
  101. RetainPtr& operator=(RetainPtr&&);
  102. template<typename U> RetainPtr& operator=(RetainPtr<U>&&);
  103. #endif
  104. #if !COMPILER_SUPPORTS(CXX_NULLPTR)
  105. RetainPtr& operator=(std::nullptr_t) { clear(); return *this; }
  106. #endif
  107. void swap(RetainPtr&);
  108. private:
  109. static PtrType hashTableDeletedValue() { return reinterpret_cast<PtrType>(-1); }
  110. PtrType m_ptr;
  111. };
  112. template<typename T> template<typename U> inline RetainPtr<T>::RetainPtr(const RetainPtr<U>& o)
  113. : m_ptr(o.get())
  114. {
  115. if (PtrType ptr = m_ptr)
  116. CFRetain(ptr);
  117. }
  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. template<typename T> inline typename RetainPtr<T>::PtrType RetainPtr<T>::leakRef()
  126. {
  127. PtrType ptr = m_ptr;
  128. m_ptr = 0;
  129. return ptr;
  130. }
  131. template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<T>& o)
  132. {
  133. PtrType optr = o.get();
  134. if (optr)
  135. CFRetain(optr);
  136. PtrType ptr = m_ptr;
  137. m_ptr = optr;
  138. if (ptr)
  139. CFRelease(ptr);
  140. return *this;
  141. }
  142. template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o)
  143. {
  144. PtrType optr = o.get();
  145. if (optr)
  146. CFRetain(optr);
  147. PtrType ptr = m_ptr;
  148. m_ptr = optr;
  149. if (ptr)
  150. CFRelease(ptr);
  151. return *this;
  152. }
  153. template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(PtrType optr)
  154. {
  155. if (optr)
  156. CFRetain(optr);
  157. PtrType ptr = m_ptr;
  158. m_ptr = optr;
  159. if (ptr)
  160. CFRelease(ptr);
  161. return *this;
  162. }
  163. template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(U* optr)
  164. {
  165. if (optr)
  166. CFRetain(optr);
  167. PtrType ptr = m_ptr;
  168. m_ptr = optr;
  169. if (ptr)
  170. CFRelease(ptr);
  171. return *this;
  172. }
  173. #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
  174. template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<T>&& o)
  175. {
  176. PtrType ptr = m_ptr;
  177. m_ptr = o.leakRef();
  178. if (ptr)
  179. CFRelease(ptr);
  180. return *this;
  181. }
  182. template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<U>&& o)
  183. {
  184. PtrType ptr = m_ptr;
  185. m_ptr = o.leakRef();
  186. if (ptr)
  187. CFRelease(ptr);
  188. return *this;
  189. }
  190. #endif
  191. template<typename T> inline void RetainPtr<T>::swap(RetainPtr<T>& o)
  192. {
  193. std::swap(m_ptr, o.m_ptr);
  194. }
  195. template<typename T> inline void swap(RetainPtr<T>& a, RetainPtr<T>& b)
  196. {
  197. a.swap(b);
  198. }
  199. template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b)
  200. {
  201. return a.get() == b.get();
  202. }
  203. template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b)
  204. {
  205. return a.get() == b;
  206. }
  207. template<typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b)
  208. {
  209. return a == b.get();
  210. }
  211. template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b)
  212. {
  213. return a.get() != b.get();
  214. }
  215. template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b)
  216. {
  217. return a.get() != b;
  218. }
  219. template<typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b)
  220. {
  221. return a != b.get();
  222. }
  223. template<typename T> inline RetainPtr<T> adoptCF(T CF_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
  224. template<typename T> inline RetainPtr<T> adoptCF(T o)
  225. {
  226. return RetainPtr<T>(AdoptCF, o);
  227. }
  228. template<typename T> inline RetainPtr<T> adoptNS(T NS_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
  229. template<typename T> inline RetainPtr<T> adoptNS(T o)
  230. {
  231. return RetainPtr<T>(AdoptNS, o);
  232. }
  233. // Helper function for creating a RetainPtr using template argument deduction.
  234. template<typename T> inline RetainPtr<T> retainPtr(T) WARN_UNUSED_RETURN;
  235. template<typename T> inline RetainPtr<T> retainPtr(T o)
  236. {
  237. return RetainPtr<T>(o);
  238. }
  239. template<typename P> struct HashTraits<RetainPtr<P> > : SimpleClassHashTraits<RetainPtr<P> > { };
  240. template<typename P> struct PtrHash<RetainPtr<P> > : PtrHash<typename RetainPtr<P>::PtrType> {
  241. using PtrHash<typename RetainPtr<P>::PtrType>::hash;
  242. static unsigned hash(const RetainPtr<P>& key) { return hash(key.get()); }
  243. using PtrHash<typename RetainPtr<P>::PtrType>::equal;
  244. static bool equal(const RetainPtr<P>& a, const RetainPtr<P>& b) { return a == b; }
  245. static bool equal(typename RetainPtr<P>::PtrType a, const RetainPtr<P>& b) { return a == b; }
  246. static bool equal(const RetainPtr<P>& a, typename RetainPtr<P>::PtrType b) { return a == b; }
  247. };
  248. template<typename P> struct DefaultHash<RetainPtr<P> > { typedef PtrHash<RetainPtr<P> > Hash; };
  249. template <typename P>
  250. struct RetainPtrObjectHashTraits : SimpleClassHashTraits<RetainPtr<P> > {
  251. static const RetainPtr<P>& emptyValue()
  252. {
  253. static RetainPtr<P>& null = *(new RetainPtr<P>);
  254. return null;
  255. }
  256. };
  257. template <typename P>
  258. struct RetainPtrObjectHash {
  259. static unsigned hash(const RetainPtr<P>& o)
  260. {
  261. ASSERT_WITH_MESSAGE(o.get(), "attempt to use null RetainPtr in HashTable");
  262. return static_cast<unsigned>(CFHash(o.get()));
  263. }
  264. static bool equal(const RetainPtr<P>& a, const RetainPtr<P>& b)
  265. {
  266. return CFEqual(a.get(), b.get());
  267. }
  268. static const bool safeToCompareToEmptyOrDeleted = false;
  269. };
  270. } // namespace WTF
  271. using WTF::AdoptCF;
  272. using WTF::AdoptNS;
  273. using WTF::adoptCF;
  274. using WTF::adoptNS;
  275. using WTF::RetainPtr;
  276. using WTF::retainPtr;
  277. #endif // WTF_RetainPtr_h