]>
Commit | Line | Data |
---|---|---|
b37bf2e1 | 1 | /* |
14957cd0 | 2 | * Copyright (C) 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. |
b37bf2e1 A |
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 | ||
14957cd0 A |
24 | #include "HashTraits.h" |
25 | #include "NullPtr.h" | |
ba379fdc | 26 | #include "TypeTraits.h" |
b37bf2e1 | 27 | #include <algorithm> |
14957cd0 A |
28 | |
29 | #if USE(CF) | |
b37bf2e1 | 30 | #include <CoreFoundation/CoreFoundation.h> |
14957cd0 | 31 | #endif |
b37bf2e1 A |
32 | |
33 | #ifdef __OBJC__ | |
34 | #import <Foundation/Foundation.h> | |
35 | #endif | |
36 | ||
37 | namespace WTF { | |
38 | ||
b37bf2e1 A |
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__ | |
46 | inline void adoptNSReference(id ptr) | |
47 | { | |
48 | if (ptr) { | |
49 | CFRetain(ptr); | |
50 | [ptr release]; | |
51 | } | |
52 | } | |
53 | #endif | |
54 | ||
14957cd0 | 55 | template<typename T> class RetainPtr { |
b37bf2e1 | 56 | public: |
ba379fdc | 57 | typedef typename RemovePointer<T>::Type ValueType; |
b37bf2e1 A |
58 | typedef ValueType* PtrType; |
59 | ||
60 | RetainPtr() : m_ptr(0) {} | |
61 | RetainPtr(PtrType ptr) : m_ptr(ptr) { if (ptr) CFRetain(ptr); } | |
62 | ||
63 | RetainPtr(AdoptCFTag, PtrType ptr) : m_ptr(ptr) { } | |
64 | RetainPtr(AdoptNSTag, PtrType ptr) : m_ptr(ptr) { adoptNSReference(ptr); } | |
65 | ||
66 | RetainPtr(const RetainPtr& o) : m_ptr(o.m_ptr) { if (PtrType ptr = m_ptr) CFRetain(ptr); } | |
67 | ||
14957cd0 A |
68 | // Hash table deleted values, which are only constructed and never copied or destroyed. |
69 | RetainPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { } | |
70 | bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); } | |
71 | ||
b37bf2e1 A |
72 | ~RetainPtr() { if (PtrType ptr = m_ptr) CFRelease(ptr); } |
73 | ||
14957cd0 | 74 | template<typename U> RetainPtr(const RetainPtr<U>&); |
b37bf2e1 A |
75 | |
76 | PtrType get() const { return m_ptr; } | |
14957cd0 A |
77 | |
78 | void clear(); | |
79 | PtrType leakRef() WARN_UNUSED_RETURN; | |
80 | ||
b37bf2e1 A |
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; | |
87 | operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; } | |
88 | ||
89 | RetainPtr& operator=(const RetainPtr&); | |
14957cd0 | 90 | template<typename U> RetainPtr& operator=(const RetainPtr<U>&); |
b37bf2e1 | 91 | RetainPtr& operator=(PtrType); |
14957cd0 A |
92 | template<typename U> RetainPtr& operator=(U*); |
93 | #if !HAVE(NULLPTR) | |
94 | RetainPtr& operator=(std::nullptr_t) { clear(); return *this; } | |
95 | #endif | |
b37bf2e1 A |
96 | |
97 | void adoptCF(PtrType); | |
98 | void adoptNS(PtrType); | |
99 | ||
100 | void swap(RetainPtr&); | |
101 | ||
14957cd0 A |
102 | // FIXME: Remove releaseRef once we change all callers to call leakRef instead. |
103 | PtrType releaseRef() { return leakRef(); } | |
104 | ||
b37bf2e1 | 105 | private: |
14957cd0 A |
106 | static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); } |
107 | ||
b37bf2e1 A |
108 | PtrType m_ptr; |
109 | }; | |
110 | ||
14957cd0 A |
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 | ||
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 | ||
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) | |
b37bf2e1 A |
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 | ||
14957cd0 | 145 | template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o) |
b37bf2e1 A |
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 | ||
14957cd0 | 157 | template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(PtrType optr) |
b37bf2e1 A |
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 | ||
14957cd0 | 168 | template<typename T> inline void RetainPtr<T>::adoptCF(PtrType optr) |
b37bf2e1 A |
169 | { |
170 | PtrType ptr = m_ptr; | |
171 | m_ptr = optr; | |
172 | if (ptr) | |
173 | CFRelease(ptr); | |
174 | } | |
175 | ||
14957cd0 | 176 | template<typename T> inline void RetainPtr<T>::adoptNS(PtrType optr) |
b37bf2e1 A |
177 | { |
178 | adoptNSReference(optr); | |
179 | ||
180 | PtrType ptr = m_ptr; | |
181 | m_ptr = optr; | |
182 | if (ptr) | |
183 | CFRelease(ptr); | |
184 | } | |
185 | ||
14957cd0 | 186 | template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(U* optr) |
b37bf2e1 A |
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 | ||
14957cd0 | 197 | template<typename T> inline void RetainPtr<T>::swap(RetainPtr<T>& o) |
b37bf2e1 A |
198 | { |
199 | std::swap(m_ptr, o.m_ptr); | |
200 | } | |
201 | ||
14957cd0 | 202 | template<typename T> inline void swap(RetainPtr<T>& a, RetainPtr<T>& b) |
b37bf2e1 A |
203 | { |
204 | a.swap(b); | |
205 | } | |
206 | ||
14957cd0 | 207 | template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b) |
b37bf2e1 A |
208 | { |
209 | return a.get() == b.get(); | |
210 | } | |
211 | ||
14957cd0 | 212 | template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b) |
b37bf2e1 A |
213 | { |
214 | return a.get() == b; | |
215 | } | |
216 | ||
14957cd0 | 217 | template<typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b) |
b37bf2e1 A |
218 | { |
219 | return a == b.get(); | |
220 | } | |
221 | ||
14957cd0 | 222 | template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b) |
b37bf2e1 A |
223 | { |
224 | return a.get() != b.get(); | |
225 | } | |
226 | ||
14957cd0 | 227 | template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b) |
b37bf2e1 A |
228 | { |
229 | return a.get() != b; | |
230 | } | |
231 | ||
14957cd0 | 232 | template<typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b) |
b37bf2e1 A |
233 | { |
234 | return a != b.get(); | |
235 | } | |
14957cd0 A |
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; }; | |
b37bf2e1 A |
249 | |
250 | } // namespace WTF | |
251 | ||
252 | using WTF::AdoptCF; | |
253 | using WTF::AdoptNS; | |
254 | using WTF::RetainPtr; | |
255 | ||
256 | #endif // WTF_RetainPtr_h |