• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "wtf/HashTableDeletedValueType.h"
25 #include "wtf/HashTraits.h"
26 #include "wtf/NullPtr.h"
27 #include "wtf/TypeTraits.h"
28 #include <algorithm>
29 
30 #if USE(CF)
31 #include <CoreFoundation/CoreFoundation.h>
32 #endif
33 
34 #ifdef __OBJC__
35 #import <Foundation/Foundation.h>
36 #endif
37 
38 #ifndef CF_RELEASES_ARGUMENT
39 #define CF_RELEASES_ARGUMENT
40 #endif
41 
42 #ifndef NS_RELEASES_ARGUMENT
43 #define NS_RELEASES_ARGUMENT
44 #endif
45 
46 namespace WTF {
47 
48     // Unlike most most of our smart pointers, RetainPtr can take either the pointer type or the pointed-to type,
49     // so both RetainPtr<NSDictionary> and RetainPtr<CFDictionaryRef> will work.
50 
51     enum AdoptCFTag { AdoptCF };
52     enum AdoptNSTag { AdoptNS };
53 
54 #ifdef __OBJC__
adoptNSReference(id ptr)55     inline void adoptNSReference(id ptr)
56     {
57         if (ptr) {
58             CFRetain(ptr);
59             [ptr release];
60         }
61     }
62 #endif
63 
64     template<typename T> class RetainPtr {
65     public:
66         typedef typename RemovePointer<T>::Type ValueType;
67         typedef ValueType* PtrType;
68 
RetainPtr()69         RetainPtr() : m_ptr(0) {}
RetainPtr(PtrType ptr)70         RetainPtr(PtrType ptr) : m_ptr(ptr) { if (ptr) CFRetain(ptr); }
71 
RetainPtr(AdoptCFTag,PtrType ptr)72         RetainPtr(AdoptCFTag, PtrType ptr) : m_ptr(ptr) { }
RetainPtr(AdoptNSTag,PtrType ptr)73         RetainPtr(AdoptNSTag, PtrType ptr) : m_ptr(ptr) { adoptNSReference(ptr); }
74 
RetainPtr(const RetainPtr & o)75         RetainPtr(const RetainPtr& o) : m_ptr(o.m_ptr) { if (PtrType ptr = m_ptr) CFRetain(ptr); }
76 
77 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
RetainPtr(RetainPtr && o)78         RetainPtr(RetainPtr&& o) : m_ptr(o.leakRef()) { }
79 #endif
80 
81         // Hash table deleted values, which are only constructed and never copied or destroyed.
RetainPtr(HashTableDeletedValueType)82         RetainPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
isHashTableDeletedValue()83         bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
84 
~RetainPtr()85         ~RetainPtr() { if (PtrType ptr = m_ptr) CFRelease(ptr); }
86 
87         template<typename U> RetainPtr(const RetainPtr<U>&);
88 
89         void clear();
90         PtrType leakRef() WARN_UNUSED_RETURN;
91 
get()92         PtrType get() const { return m_ptr; }
93         PtrType operator->() const { return m_ptr; }
94 #if COMPILER_SUPPORTS(CXX_EXPLICIT_CONVERSIONS)
PtrType()95         explicit operator PtrType() const { return m_ptr; }
96 #endif
97 
98         bool operator!() const { return !m_ptr; }
99 
100         // This conversion operator allows implicit conversion to bool but not to other integer types.
101         typedef PtrType RetainPtr::*UnspecifiedBoolType;
UnspecifiedBoolType()102         operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; }
103 
104         RetainPtr& operator=(const RetainPtr&);
105         template<typename U> RetainPtr& operator=(const RetainPtr<U>&);
106         RetainPtr& operator=(PtrType);
107         template<typename U> RetainPtr& operator=(U*);
108 
109 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
110         RetainPtr& operator=(RetainPtr&&);
111         template<typename U> RetainPtr& operator=(RetainPtr<U>&&);
112 #endif
113 
114 #if !COMPILER_SUPPORTS(CXX_NULLPTR)
115         RetainPtr& operator=(std::nullptr_t) { clear(); return *this; }
116 #endif
117 
118         void adoptCF(PtrType);
119         void adoptNS(PtrType);
120 
121         void swap(RetainPtr&);
122 
123     private:
hashTableDeletedValue()124         static PtrType hashTableDeletedValue() { return reinterpret_cast<PtrType>(-1); }
125 
126         PtrType m_ptr;
127     };
128 
RetainPtr(const RetainPtr<U> & o)129     template<typename T> template<typename U> inline RetainPtr<T>::RetainPtr(const RetainPtr<U>& o)
130         : m_ptr(o.get())
131     {
132         if (PtrType ptr = m_ptr)
133             CFRetain(ptr);
134     }
135 
clear()136     template<typename T> inline void RetainPtr<T>::clear()
137     {
138         if (PtrType ptr = m_ptr) {
139             m_ptr = 0;
140             CFRelease(ptr);
141         }
142     }
143 
leakRef()144     template<typename T> inline typename RetainPtr<T>::PtrType RetainPtr<T>::leakRef()
145     {
146         PtrType ptr = m_ptr;
147         m_ptr = 0;
148         return ptr;
149     }
150 
151     template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<T>& o)
152     {
153         PtrType optr = o.get();
154         if (optr)
155             CFRetain(optr);
156         PtrType ptr = m_ptr;
157         m_ptr = optr;
158         if (ptr)
159             CFRelease(ptr);
160         return *this;
161     }
162 
163     template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o)
164     {
165         PtrType optr = o.get();
166         if (optr)
167             CFRetain(optr);
168         PtrType ptr = m_ptr;
169         m_ptr = optr;
170         if (ptr)
171             CFRelease(ptr);
172         return *this;
173     }
174 
175     template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(PtrType optr)
176     {
177         if (optr)
178             CFRetain(optr);
179         PtrType ptr = m_ptr;
180         m_ptr = optr;
181         if (ptr)
182             CFRelease(ptr);
183         return *this;
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 
197 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
198     template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<T>&& o)
199     {
200         adoptCF(o.leakRef());
201         return *this;
202     }
203 
204     template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<U>&& o)
205     {
206         adoptCF(o.leakRef());
207         return *this;
208     }
209 #endif
210 
adoptCF(PtrType optr)211     template<typename T> inline void RetainPtr<T>::adoptCF(PtrType optr)
212     {
213         PtrType ptr = m_ptr;
214         m_ptr = optr;
215         if (ptr)
216             CFRelease(ptr);
217     }
218 
adoptNS(PtrType optr)219     template<typename T> inline void RetainPtr<T>::adoptNS(PtrType optr)
220     {
221         adoptNSReference(optr);
222 
223         PtrType ptr = m_ptr;
224         m_ptr = optr;
225         if (ptr)
226             CFRelease(ptr);
227     }
228 
swap(RetainPtr<T> & o)229     template<typename T> inline void RetainPtr<T>::swap(RetainPtr<T>& o)
230     {
231         std::swap(m_ptr, o.m_ptr);
232     }
233 
swap(RetainPtr<T> & a,RetainPtr<T> & b)234     template<typename T> inline void swap(RetainPtr<T>& a, RetainPtr<T>& b)
235     {
236         a.swap(b);
237     }
238 
239     template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b)
240     {
241         return a.get() == b.get();
242     }
243 
244     template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b)
245     {
246         return a.get() == b;
247     }
248 
249     template<typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b)
250     {
251         return a == b.get();
252     }
253 
254     template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b)
255     {
256         return a.get() != b.get();
257     }
258 
259     template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b)
260     {
261         return a.get() != b;
262     }
263 
264     template<typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b)
265     {
266         return a != b.get();
267     }
268 
269     template<typename T> inline RetainPtr<T> adoptCF(T CF_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
adoptCF(T o)270     template<typename T> inline RetainPtr<T> adoptCF(T o)
271     {
272         return RetainPtr<T>(AdoptCF, o);
273     }
274 
275     template<typename T> inline RetainPtr<T> adoptNS(T NS_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
adoptNS(T o)276     template<typename T> inline RetainPtr<T> adoptNS(T o)
277     {
278         return RetainPtr<T>(AdoptNS, o);
279     }
280 
281     // Helper function for creating a RetainPtr using template argument deduction.
282     template<typename T> inline RetainPtr<T> retainPtr(T) WARN_UNUSED_RETURN;
retainPtr(T o)283     template<typename T> inline RetainPtr<T> retainPtr(T o)
284     {
285         return RetainPtr<T>(o);
286     }
287 
288     template<typename P> struct HashTraits<RetainPtr<P> > : SimpleClassHashTraits<RetainPtr<P> > { };
289 
290     template<typename P> struct PtrHash<RetainPtr<P> > : PtrHash<typename RetainPtr<P>::PtrType> {
291         using PtrHash<typename RetainPtr<P>::PtrType>::hash;
292         static unsigned hash(const RetainPtr<P>& key) { return hash(key.get()); }
293         using PtrHash<typename RetainPtr<P>::PtrType>::equal;
294         static bool equal(const RetainPtr<P>& a, const RetainPtr<P>& b) { return a == b; }
295         static bool equal(typename RetainPtr<P>::PtrType a, const RetainPtr<P>& b) { return a == b; }
296         static bool equal(const RetainPtr<P>& a, typename RetainPtr<P>::PtrType b) { return a == b; }
297     };
298 
299     template<typename P> struct DefaultHash<RetainPtr<P> > { typedef PtrHash<RetainPtr<P> > Hash; };
300 } // namespace WTF
301 
302 using WTF::AdoptCF;
303 using WTF::AdoptNS;
304 using WTF::adoptCF;
305 using WTF::adoptNS;
306 using WTF::RetainPtr;
307 using WTF::retainPtr;
308 
309 #endif // WTF_RetainPtr_h
310