]> git.saurik.com Git - wxWidgets.git/blob - include/wx/osx/core/cfref.h
404c099fa5b1bf2c035bdd867eef022f3e4c545a
[wxWidgets.git] / include / wx / osx / core / cfref.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/osx/core/cfref.h
3 // Purpose: wxCFRef template class
4 // Author: David Elliott <dfe@cox.net>
5 // Modified by: Stefan Csomor
6 // Created: 2007/05/10
7 // RCS-ID: $Id$
8 // Copyright: (c) 2007 David Elliott <dfe@cox.net>, Stefan Csomor
9 // Licence: wxWindows licence
10 // Notes: See http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/index.html
11 /////////////////////////////////////////////////////////////////////////////
12 /*! @header wx/osx/core/cfref.h
13 @abstract wxCFRef template class
14 @discussion FIXME: Convert doc tags to something less buggy with C++
15 */
16
17 #ifndef _WX_MAC_COREFOUNDATION_CFREF_H__
18 #define _WX_MAC_COREFOUNDATION_CFREF_H__
19
20 // Include unistd to ensure that NULL is defined
21 #include <unistd.h>
22 // Include AvailabilityMacros for DEPRECATED_ATTRIBUTE
23 #include <AvailabilityMacros.h>
24
25 // #include <CoreFoundation/CFBase.h>
26 /* Don't include CFBase.h such that this header can be included from public
27 * headers with minimal namespace pollution.
28 * Note that Darwin CF uses extern for CF_EXPORT. If we need this on Win32
29 * or non-Darwin Mac OS we'll need to define the appropriate __declspec.
30 */
31 typedef const void *CFTypeRef;
32 extern "C" {
33 extern /* CF_EXPORT */
34 CFTypeRef CFRetain(CFTypeRef cf);
35 extern /* CF_EXPORT */
36 void CFRelease(CFTypeRef cf);
37 } // extern "C"
38
39
40 /*! @function wxCFRelease
41 @abstract A CFRelease variant that checks for NULL before releasing.
42 @discussion The parameter is template not for type safety but to ensure the argument
43 is a raw pointer and not a ref holder of any type.
44 */
45 template <class Type>
46 inline void wxCFRelease(Type *r)
47 {
48 if ( r != NULL )
49 ::CFRelease((CFTypeRef)r);
50 }
51
52 /*! @function wxCFRetain
53 @abstract A typesafe CFRetain variant that checks for NULL.
54 */
55 template <class Type>
56 inline Type* wxCFRetain(Type *r)
57 {
58 // NOTE(DE): Setting r to the result of CFRetain improves efficiency on both x86 and PPC
59 // Casting r to CFTypeRef ensures we are calling the real C version defined in CFBase.h
60 // and not any possibly templated/overloaded CFRetain.
61 if ( r != NULL )
62 r = (Type*)::CFRetain((CFTypeRef)r);
63 return r;
64 }
65
66 template <class refType>
67 class wxCFRef;
68
69 /*! @class wxCFWeakRef
70 @templatefield refType The CF reference type (e.g. CFStringRef, CFRunLoopRef, etc.)
71 It should already be a pointer. This is different from
72 shared_ptr where the template parameter is the pointee type.
73 @discussion Wraps a raw pointer without any retain or release.
74 Provides a way to get what amounts to a raw pointer from a wxCFRef without
75 using a raw pointer. Unlike a raw pointer, constructing a wxCFRef from this
76 class will cause it to be retained because it is assumed that a wxCFWeakRef
77 does not own its pointer.
78 */
79 template <class refType>
80 class wxCFWeakRef
81 {
82 template <class refTypeA, class otherRefType>
83 friend wxCFWeakRef<refTypeA> static_cfref_cast(const wxCFRef<otherRefType> &otherRef);
84 public:
85 /*! @method wxCFWeakRef
86 @abstract Creates a NULL reference
87 */
88 wxCFWeakRef()
89 : m_ptr(NULL)
90 {}
91
92 // Default copy constructor is fine.
93 // Default destructor is fine but we'll set NULL to avoid bugs
94 ~wxCFWeakRef()
95 { m_ptr = NULL; }
96
97 // Do not implement a raw-pointer constructor.
98
99 /*! @method wxCFWeakRef
100 @abstract Copies another ref holder where its type can be converted to ours
101 @templatefield otherRefType Any type held by another wxCFWeakRef.
102 @param otherRef The other weak ref holder to copy.
103 @discussion This is merely a copy or implicit cast.
104 */
105 template <class otherRefType>
106 wxCFWeakRef(const wxCFWeakRef<otherRefType>& otherRef)
107 : m_ptr(otherRef.get()) // Implicit conversion from otherRefType to refType should occur
108 {}
109
110 /*! @method wxCFWeakRef
111 @abstract Copies a strong ref holder where its type can be converted to ours
112 @templatefield otherRefType Any type held by a wxCFRef.
113 @param otherRef The strong ref holder to copy.
114 @discussion This ref is merely a pointer copy, the strong ref still holds the pointer.
115 */
116 template <class otherRefType>
117 wxCFWeakRef(const wxCFRef<otherRefType>& otherRef)
118 : m_ptr(otherRef.get()) // Implicit conversion from otherRefType to refType should occur
119 {}
120
121 /*! @method get
122 @abstract Explicit conversion to the underlying pointer type
123 @discussion Allows the caller to explicitly get the underlying pointer.
124 */
125 refType get() const
126 { return m_ptr; }
127
128 /*! @method operator refType
129 @abstract Implicit conversion to the underlying pointer type
130 @discussion Allows the ref to be used in CF function calls.
131 */
132 operator refType() const
133 { return m_ptr; }
134
135 protected:
136 /*! @method wxCFWeakRef
137 @abstract Constructs a weak reference to the raw pointer
138 @templatefield otherType Any type.
139 @param p The raw pointer to assume ownership of. May be NULL.
140 @discussion This method is private so that the friend static_cfref_cast can use it
141 */
142 template <class otherType>
143 explicit wxCFWeakRef(otherType *p)
144 : m_ptr(p) // Implicit conversion from otherType* to refType should occur.
145 {}
146
147 /*! @var m_ptr The raw pointer.
148 */
149 refType m_ptr;
150 };
151
152 /*! @class wxCFRef
153 @templatefield refType The CF reference type (e.g. CFStringRef, CFRunLoopRef, etc.)
154 It should already be a pointer. This is different from
155 shared_ptr where the template parameter is the pointee type.
156 @discussion Properly retains/releases reference to CoreFoundation objects
157 */
158 template <class refType>
159 class wxCFRef
160 {
161 public:
162 /*! @method wxCFRef
163 @abstract Creates a NULL reference
164 */
165 wxCFRef()
166 : m_ptr(NULL)
167 {}
168
169 /*! @method wxCFRef
170 @abstract Assumes ownership of p and creates a reference to it.
171 @templatefield otherType Any type.
172 @param p The raw pointer to assume ownership of. May be NULL.
173 @discussion Like shared_ptr, it is assumed that the caller has a strong reference to p and intends
174 to transfer ownership of that reference to this ref holder. If the object comes from
175 a Create or Copy method then this is the correct behaviour. If the object comes from
176 a Get method then you must CFRetain it yourself before passing it to this constructor.
177 A handy way to do this is to use the non-member wxCFRefFromGet factory funcion.
178 This method is templated and takes an otherType *p. This prevents implicit conversion
179 using an operator refType() in a different ref-holding class type.
180 */
181 template <class otherType>
182 explicit wxCFRef(otherType *p)
183 : m_ptr(p) // Implicit conversion from otherType* to refType should occur.
184 {}
185
186 /*! @method wxCFRef
187 @abstract Copies a ref holder of the same type
188 @param otherRef The other ref holder to copy.
189 @discussion Ownership will be shared by the original ref and the newly created ref. That is,
190 the object will be explicitly retained by this new ref.
191 */
192 wxCFRef(const wxCFRef& otherRef)
193 : m_ptr(wxCFRetain(otherRef.m_ptr))
194 {}
195
196 /*! @method wxCFRef
197 @abstract Copies a ref holder where its type can be converted to ours
198 @templatefield otherRefType Any type held by another wxCFRef.
199 @param otherRef The other ref holder to copy.
200 @discussion Ownership will be shared by the original ref and the newly created ref. That is,
201 the object will be explicitly retained by this new ref.
202 */
203 template <class otherRefType>
204 wxCFRef(const wxCFRef<otherRefType>& otherRef)
205 : m_ptr(wxCFRetain(otherRef.get())) // Implicit conversion from otherRefType to refType should occur
206 {}
207
208 /*! @method wxCFRef
209 @abstract Copies a weak ref holder where its type can be converted to ours
210 @templatefield otherRefType Any type held by a wxCFWeakRef.
211 @param otherRef The weak ref holder to copy.
212 @discussion Ownership will be taken by this newly created ref. That is,
213 the object will be explicitly retained by this new ref.
214 Ownership is most likely shared with some other ref as well.
215 */
216 template <class otherRefType>
217 wxCFRef(const wxCFWeakRef<otherRefType>& otherRef)
218 : m_ptr(wxCFRetain(otherRef.get())) // Implicit conversion from otherRefType to refType should occur
219 {}
220
221 /*! @method ~wxCFRef
222 @abstract Releases (potentially shared) ownership of the ref.
223 @discussion A ref holder instance is always assumed to have ownership so ownership is always
224 released (CFRelease called) upon destruction.
225 */
226 ~wxCFRef()
227 { reset(); }
228
229 /*! @method operator=
230 @abstract Assigns the other ref's pointer to us when the otherRef is the same type.
231 @param otherRef The other ref holder to copy.
232 @discussion The incoming pointer is retained, the original pointer is released, and this object
233 is made to point to the new pointer.
234 */
235 wxCFRef& operator=(const wxCFRef& otherRef)
236 {
237 if (this != &otherRef)
238 {
239 wxCFRetain(otherRef.m_ptr);
240 wxCFRelease(m_ptr);
241 m_ptr = otherRef.m_ptr;
242 }
243 return *this;
244 }
245
246 /*! @method operator=
247 @abstract Assigns the other ref's pointer to us when the other ref can be converted to our type.
248 @templatefield otherRefType Any type held by another wxCFRef
249 @param otherRef The other ref holder to copy.
250 @discussion The incoming pointer is retained, the original pointer is released, and this object
251 is made to point to the new pointer.
252 */
253 template <class otherRefType>
254 wxCFRef& operator=(const wxCFRef<otherRefType>& otherRef)
255 {
256 wxCFRetain(otherRef.get());
257 wxCFRelease(m_ptr);
258 m_ptr = otherRef.get(); // Implicit conversion from otherRefType to refType should occur
259 return *this;
260 }
261
262 /*! @method get
263 @abstract Explicit conversion to the underlying pointer type
264 @discussion Allows the caller to explicitly get the underlying pointer.
265 */
266 refType get() const
267 { return m_ptr; }
268
269 /*! @method operator refType
270 @abstract Implicit conversion to the underlying pointer type
271 @discussion Allows the ref to be used in CF function calls.
272 */
273 operator refType() const
274 { return m_ptr; }
275
276 #if 0
277 < // HeaderDoc is retarded and thinks the GT from operator-> is part of a template param.
278 // So give it that < outside of a comment to fake it out. (if 0 is not a comment to HeaderDoc)
279 #endif
280
281 /*! @method operator-&gt;
282 @abstract Implicit conversion to the underlying pointer type
283 @discussion This is nearly useless for CF types which are nearly always opaque
284 */
285 refType operator-> () const
286 { return m_ptr; }
287
288 /*! @method reset
289 @abstract Nullifies the reference
290 @discussion Releases ownership (calls CFRelease) before nullifying the pointer.
291 */
292 void reset()
293 {
294 wxCFRelease(m_ptr);
295 m_ptr = NULL;
296 }
297
298 /*! @method reset
299 @abstract Sets this to a new reference
300 @templatefield otherType Any type.
301 @param p The raw pointer to assume ownership of
302 @discussion The existing reference is released (like destruction). It is assumed that the caller
303 has a strong reference to the new p and intends to transfer ownership of that reference
304 to this ref holder. Take care to call CFRetain if you received the object from a Get method.
305 This method is templated and takes an otherType *p. This prevents implicit conversion
306 using an operator refType() in a different ref-holding class type.
307 */
308 template <class otherType>
309 void reset(otherType* p)
310 {
311 wxCFRelease(m_ptr);
312 m_ptr = p; // Automatic conversion should occur
313 }
314
315 // Release the pointer, i.e. give up its ownership.
316 refType release()
317 {
318 refType p = m_ptr;
319 m_ptr = NULL;
320 return p;
321 }
322
323 protected:
324 /*! @var m_ptr The raw pointer.
325 */
326 refType m_ptr;
327 };
328
329 /*! @function wxCFRefFromGet
330 @abstract Factory function to create wxCFRef from a raw pointer obtained from a Get-rule function
331 @param p The pointer to retain and create a wxCFRef from. May be NULL.
332 @discussion Unlike the wxCFRef raw pointer constructor, this function explicitly retains its
333 argument. This can be used for functions such as CFDictionaryGetValue() or
334 CFAttributedStringGetString() which return a temporary reference (Get-rule functions).
335 FIXME: Anybody got a better name?
336 */
337 template <typename Type>
338 inline wxCFRef<Type*> wxCFRefFromGet(Type *p)
339 {
340 return wxCFRef<Type*>(wxCFRetain(p));
341 }
342
343 /*! @function static_cfref_cast
344 @abstract Works like static_cast but with a wxCFRef as the argument.
345 @param refType Template parameter. The destination raw pointer type
346 @param otherRef Normal parameter. The source wxCFRef<> object.
347 @discussion This is intended to be a clever way to make static_cast work while allowing
348 the return value to be converted to either a strong ref or a raw pointer
349 while ensuring that the retain count is updated appropriately.
350
351 This is modeled after shared_ptr's static_pointer_cast. Just as wxCFRef is
352 parameterized on a pointer to an opaque type so is this class. Note that
353 this differs from shared_ptr which is parameterized on the pointee type.
354
355 FIXME: Anybody got a better name?
356 */
357 template <class refType, class otherRefType>
358 inline wxCFWeakRef<refType> static_cfref_cast(const wxCFRef<otherRefType> &otherRef);
359
360 template <class refType, class otherRefType>
361 inline wxCFWeakRef<refType> static_cfref_cast(const wxCFRef<otherRefType> &otherRef)
362 {
363 return wxCFWeakRef<refType>(static_cast<refType>(otherRef.get()));
364 }
365
366 /*! @function CFRelease
367 @abstract Overloads CFRelease so that the user is warned of bad behaviour.
368 @discussion It is rarely appropriate to retain or release a wxCFRef. If one absolutely
369 must do it he can explicitly get() the raw pointer
370 Normally, this function is unimplemented resulting in a linker error if used.
371 */
372 template <class T>
373 inline void CFRelease(const wxCFRef<T*> & cfref) DEPRECATED_ATTRIBUTE;
374
375 /*! @function CFRetain
376 @abstract Overloads CFRetain so that the user is warned of bad behaviour.
377 @discussion It is rarely appropriate to retain or release a wxCFRef. If one absolutely
378 must do it he can explicitly get() the raw pointer
379 Normally, this function is unimplemented resulting in a linker error if used.
380 */
381 template <class T>
382 inline void CFRetain(const wxCFRef<T*>& cfref) DEPRECATED_ATTRIBUTE;
383
384 // Change the 0 to a 1 if you want the functions to work (no link errors)
385 // Neither function will cause retain/release side-effects if implemented.
386 #if 0
387 template <class T>
388 void CFRelease(const wxCFRef<T*> & cfref)
389 {
390 CFRelease(cfref.get());
391 }
392
393 template <class T>
394 void CFRetain(const wxCFRef<T*> & cfref)
395 {
396 CFRetain(cfref.get());
397 }
398 #endif
399
400 #endif //ndef _WX_MAC_COREFOUNDATION_CFREF_H__
401