]> git.saurik.com Git - wxWidgets.git/blob - include/wx/mac/corefoundation/cfref.h
53d46e78c1f228f7b02759c7d5365ab19844bc34
[wxWidgets.git] / include / wx / mac / corefoundation / cfref.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/mac/corefoundation/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/mac/corefoundation/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 <CoreFoundation/CFBase.h>
21 /* Don't include CFBase.h such that this header can be included from public
22 * headers with minimal namespace pollution.
23 * Note that Darwin CF uses extern for CF_EXPORT. If we need this on Win32
24 * or non-Darwin Mac OS we'll need to define the appropriate __declspec.
25 */
26 extern "C" {
27 typedef const void *CFTypeRef;
28 extern /* CF_EXPORT */
29 CFTypeRef CFRetain(CFTypeRef cf);
30 extern /* CF_EXPORT */
31 void CFRelease(CFTypeRef cf);
32 } // extern "C"
33
34
35 /*! @function wxCFRelease
36 @abstract A CFRelease variant that checks for NULL before releasing.
37 @discussion The parameter is template not for type safety but to ensure the argument
38 is a raw pointer and not a ref holder of any type.
39 */
40 template <class Type>
41 inline void wxCFRelease(Type *r)
42 {
43 if ( r != NULL )
44 ::CFRelease((CFTypeRef)r);
45 }
46
47 /*! @function wxCFRetain
48 @abstract A typesafe CFRetain variant that checks for NULL.
49 */
50 template <class Type>
51 inline Type* wxCFRetain(Type *r)
52 {
53 // NOTE(DE): Setting r to the result of CFRetain improves efficiency on both x86 and PPC
54 // Casting r to CFTypeRef ensures we are calling the real C version defined in CFBase.h
55 // and not any possibly templated/overloaded CFRetain.
56 if ( r != NULL )
57 r = (Type*)::CFRetain((CFTypeRef)r);
58 return r;
59 }
60
61 /*! @class wxCFRef
62 @templatefield refType The CF reference type (e.g. CFStringRef, CFRunLoopRef, etc.)
63 It should already be a pointer. This is different from
64 shared_ptr where the template parameter is the pointee type.
65 @discussion Properly retains/releases reference to CoreFoundation objects
66 */
67 template <class refType>
68 class wxCFRef
69 {
70 public:
71 /*! @method wxCFRef
72 @abstract Creates a NULL reference
73 */
74 wxCFRef()
75 : m_ptr(NULL)
76 {}
77
78 /*! @method wxCFRef
79 @abstract Assumes ownership of p and creates a reference to it.
80 @templatefield otherType Any type.
81 @param p The raw pointer to assume ownership of. May be NULL.
82 @discussion Like shared_ptr, it is assumed that the caller has a strong reference to p and intends
83 to transfer ownership of that reference to this ref holder. If the object comes from
84 a Create or Copy method then this is the correct behavior. If the object comes from
85 a Get method then you must CFRetain it yourself before passing it to this constructor.
86 A handy way to do this is to use the non-member wxCFRefFromGet factory funcion.
87 This method is templated and takes an otherType *p. This prevents implicit conversion
88 using an operator refType() in a different ref-holding class type.
89 */
90 template <class otherType>
91 explicit wxCFRef(otherType *p)
92 : m_ptr(p) // Implicit conversion from otherType* to refType should occur.
93 {}
94
95 /*! @method wxCFRef
96 @abstract Copies a ref holder of the same type
97 @param otherRef The other ref holder to copy.
98 @discussion Ownership will be shared by the original ref and the newly created ref. That is,
99 the object will be explicitly retained by this new ref.
100 */
101 wxCFRef(const wxCFRef& otherRef)
102 : m_ptr(wxCFRetain(otherRef.m_ptr))
103 {}
104
105 /*! @method wxCFRef
106 @abstract Copies a ref holder where its type can be converted to ours
107 @templatefield otherRefType Any type held by another wxCFRef.
108 @param otherRef The other ref holder to copy.
109 @discussion Ownership will be shared by the original ref and the newly created ref. That is,
110 the object will be explicitly retained by this new ref.
111 */
112 template <class otherRefType>
113 wxCFRef(const wxCFRef<otherRefType>& otherRef)
114 : m_ptr(wxCFRetain(otherRef.get())) // Implicit conversion from otherRefType to refType should occur
115 {}
116
117 /*! @method ~wxCFRef
118 @abstract Releases (potentially shared) ownership of the ref.
119 @discussion A ref holder instance is always assumed to have ownership so ownership is always
120 released (CFRelease called) upon destruction.
121 */
122 ~wxCFRef()
123 { reset(); }
124
125 /*! @method operator=
126 @abstract Assigns the other ref's pointer to us when the otherRef is the same type.
127 @param otherRef The other ref holder to copy.
128 @discussion The incoming pointer is retained, the original pointer is released, and this object
129 is made to point to the new pointer.
130 */
131 wxCFRef& operator=(const wxCFRef& otherRef)
132 {
133 wxCFRetain(otherRef.m_ptr);
134 wxCFRelease(m_ptr);
135 m_ptr = otherRef.m_ptr;
136 return *this;
137 }
138
139 /*! @method operator=
140 @abstract Assigns the other ref's pointer to us when the other ref can be converted to our type.
141 @templatefield otherRefType Any type held by another wxCFRef
142 @param otherRef The other ref holder to copy.
143 @discussion The incoming pointer is retained, the original pointer is released, and this object
144 is made to point to the new pointer.
145 */
146 template <class otherRefType>
147 wxCFRef& operator=(const wxCFRef<otherRefType>& otherRef)
148 {
149 wxCFRetain(otherRef.get());
150 wxCFRelease(m_ptr);
151 m_ptr = otherRef.get(); // Implicit conversion from otherRefType to refType should occur
152 return *this;
153 }
154
155 /*! @method get
156 @abstract Explicit conversion to the underlying pointer type
157 @discussion Allows the caller to explicitly get the underlying pointer.
158 */
159 refType get() const
160 { return m_ptr; }
161
162 /*! @method operator refType
163 @abstract Implicit conversion to the underlying pointer type
164 @discussion Allows the ref to be used in CF function calls.
165 */
166 operator refType() const
167 { return m_ptr; }
168
169 #if 0
170 < // HeaderDoc is retarded and thinks the GT from operator-> is part of a template param.
171 // So give it that < outside of a comment to fake it out. (if 0 is not a comment to HeaderDoc)
172 #endif
173
174 /*! @method operator-&gt;
175 @abstract Implicit conversion to the underlying pointer type
176 @discussion This is nearly useless for CF types which are nearly always opaque
177 */
178 refType operator-> () const
179 { return m_ptr; }
180
181 /*! @method reset
182 @abstract Nullifies the reference
183 @discussion Releases ownership (calls CFRelease) before nullifying the pointer.
184 */
185 void reset()
186 {
187 wxCFRelease(m_ptr);
188 m_ptr = NULL;
189 }
190
191 /*! @method reset
192 @abstract Sets this to a new reference
193 @templatefield otherType Any type.
194 @param p The raw pointer to assume ownership of
195 @discussion The existing reference is released (like destruction). It is assumed that the caller
196 has a strong reference to the new p and intends to transfer ownership of that reference
197 to this ref holder. Take care to call CFRetain if you received the object from a Get method.
198 This method is templated and takes an otherType *p. This prevents implicit conversion
199 using an operator refType() in a different ref-holding class type.
200 */
201 template <class otherType>
202 void reset(otherType* p)
203 {
204 wxCFRelease(m_ptr);
205 m_ptr = p; // Automatic conversion should occur
206 }
207 protected:
208 /*! @var m_ptr The raw pointer.
209 */
210 refType m_ptr;
211 };
212
213 /*! @function wxCFRefFromGet
214 @abstract Factory function to create wxCFRef from a raw pointer obtained from a Get-rule function
215 @param p The pointer to retain and create a wxCFRef from. May be NULL.
216 @discussion Unlike the wxCFRef raw pointer constructor, this function explicitly retains its
217 argument. This can be used for functions such as CFDictionaryGetValue() or
218 CFAttributedStringGetString() which return a temporary reference (Get-rule functions).
219 FIXME: Anybody got a better name?
220 */
221 template <typename Type>
222 inline wxCFRef<Type*> wxCFRefFromGet(Type *p)
223 {
224 return wxCFRef<Type*>(wxCFRetain(p));
225 }
226
227 /*! @function static_cfref_cast
228 @abstract Works like static_cast but from one wxCFRef to another
229 @param refType Template parameter. The destination raw pointer type
230 @param otherRef Normal parameter. The source wxCFRef<> object.
231 @discussion This is modeled after shared_ptr's static_pointer_cast. Just as wxCFRef is
232 parameterized on a pointer to an opaque type so is this class. Note that
233 this differs from shared_ptr which is parameterized on the pointee type.
234 FIXME: Anybody got a better name?
235 */
236 template <class refType, class otherRefType>
237 inline wxCFRef<refType> static_cfref_cast(const wxCFRef<otherRefType> &otherRef);
238
239 template <class refType, class otherRefType>
240 inline wxCFRef<refType> static_cfref_cast(const wxCFRef<otherRefType> &otherRef)
241 {
242 return wxCFRef<refType>(static_cast<refType>(wxCFRetain(otherRef.get())));
243 }
244
245 /*! @function CFRelease
246 @abstract Overloads CFRelease so that the user is warned of bad behavior.
247 @discussion It is rarely appropriate to retain or release a wxCFRef. If one absolutely
248 must do it he can explicitly get() the raw pointer
249 Normally, this function is unimplemented resulting in a linker error if used.
250 */
251 template <class T>
252 inline void CFRelease(const wxCFRef<T*> & cfref) DEPRECATED_ATTRIBUTE;
253
254 /*! @function CFRetain
255 @abstract Overloads CFRetain so that the user is warned of bad behavior.
256 @discussion It is rarely appropriate to retain or release a wxCFRef. If one absolutely
257 must do it he can explicitly get() the raw pointer
258 Normally, this function is unimplemented resulting in a linker error if used.
259 */
260 template <class T>
261 inline void CFRetain(const wxCFRef<T*>& cfref) DEPRECATED_ATTRIBUTE;
262
263 // Change the 0 to a 1 if you want the functions to work (no link errors)
264 // Neither function will cause retain/release side-effects if implemented.
265 #if 0
266 template <class T>
267 void CFRelease(const wxCFRef<T*> & cfref)
268 {
269 CFRelease(cfref.get());
270 }
271
272 template <class T>
273 void CFRetain(const wxCFRef<T*> & cfref)
274 {
275 CFRetain(cfref.get());
276 }
277 #endif
278
279 #endif //ndef _WX_MAC_COREFOUNDATION_CFREF_H__
280