]> git.saurik.com Git - wxWidgets.git/blame - include/wx/cocoa/ObjcRef.h
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / include / wx / cocoa / ObjcRef.h
CommitLineData
fa8114de
DE
1/////////////////////////////////////////////////////////////////////////////
2// Name: wx/cocoa/ObjcRef.h
3// Purpose: wxObjcAutoRef template class
4// Author: David Elliott
03647350 5// Modified by:
fa8114de 6// Created: 2004/03/28
fa8114de 7// Copyright: (c) 2004 David Elliott <dfe@cox.net>
65571936 8// Licence: wxWindows licence
fa8114de
DE
9/////////////////////////////////////////////////////////////////////////////
10
256af34f
DE
11#ifndef _WX_COCOA_OBJCREF_H__
12#define _WX_COCOA_OBJCREF_H__
ddfdef64
DE
13
14// Reuse wxCFRef-related code (e.g. wxCFRetain/wxCFRelease)
ef0e9220 15#include "wx/osx/core/cfref.h"
ddfdef64 16
74b57569 17// NOTE WELL: We can only know whether or not GC can be used when compiling Objective-C.
6ecc2922
DE
18// Therefore we cannot implement these functions except when compiling Objective-C.
19#ifdef __OBJC__
20/*! @function wxGCSafeRetain
21 @templatefield Type (implicit) An Objective-C class type
22 @arg r Pointer to Objective-C object. May be null.
23 @abstract Retains the Objective-C object, even when using Apple's garbage collector
24 @discussion
25 When Apple's garbage collector is enabled, the usual [obj retain] and [obj release] messages
26 are ignored. Instead the collector with help from compiler-generated write-barriers tracks
27 reachable objects. The write-barriers are generated when setting i-vars of C++ classes but
28 they are ignored by the garbage collector unless the C++ object is in GC-managed memory.
29
30 The simple solution is to use CFRetain on the Objective-C object which has been enhanced in
31 GC mode to forcibly retain the object. In Retain/Release (RR) mode the CFRetain function has
32 the same effect as [obj retain]. Note that GC vs. RR is selected at runtime.
33
34 Take care that wxGCSafeRetain must be balanced with wxGCSafeRelease and that conversely
35 wxGCSafeRelease must only be called on objects to balance wxGCSafeRetain. In particular when
36 receiving an Objective-C object from an alloc or copy method take care that you must retain
37 it with wxGCSafeRetain and balance the initial alloc with a standard release.
38
39 Example:
40 wxGCSafeRelease(m_obj); // release current object (if any)
41 NSObject *obj = [[NSObject alloc] init];
42 m_obj = wxGCSafeRetain(obj);
43 [obj release];
44
45 Alternatively (same effect, perhaps less clear):
46 wxGCSafeRelease(m_obj); // release current object (if any)
47 m_obj = wxGCSafeRetain([[NSObject alloc] init]);
48 [m_obj release]; // balance alloc
03647350 49
6ecc2922
DE
50 Consider the effect on the retain count from each statement (alloc, CFRetain, release)
51 In RR mode: retainCount = 1, +1, -1
52 In GC mode: strongRetainCount = 0, +1, -0
53
54 This is a template function to ensure it is used on raw pointers and never on pointer-holder
55 objects via implicit conversion operators.
56*/
57template <class Type>
58inline Type * wxGCSafeRetain(Type *r)
59{
74b57569 60#ifdef __OBJC_GC__
6ecc2922
DE
61 return static_cast<Type*>(wxCFRetain(r));
62#else
63 return [r retain];
64#endif
65}
66
67/*! @function wxGCSafeRelease
68 @templatefield Type (implicit) An Objective-C class type
69 @arg r Pointer to Objective-C object. May be null.
70 @abstract Balances wxGCSafeRetain. Particularly useful with the Apple Garbage Collector.
71 @discussion
72 See the wxGCSafeRetain documentation for more details.
73
74 Example (from wxGCSafeRetain documentation):
75 wxGCSafeRelease(m_obj); // release current object (if any)
76 m_obj = wxGCSafeRetain([[NSObject alloc] init]);
77 [m_obj release]; // balance alloc
78
79 When viewed from the start, m_obj ought to start as nil. However, the second time through
80 the wxGCSafeRelease call becomes critical as it releases the retain from the first time
81 through.
82
83 In the destructor for this C++ object with the m_obj i-var you ought to do the following:
84 wxGCSafeRelease(m_obj);
85 m_obj = nil; // Not strictly needed, but safer.
86
87 Under no circumstances should you balance an alloc or copy with a wxGCSafeRelease.
88*/
89template <class Type>
90inline void wxGCSafeRelease(Type *r)
91{
74b57569 92#ifdef __OBJC_GC__
6ecc2922
DE
93 wxCFRelease(r);
94#else
95 [r release];
96#endif
97}
98#else
99// NOTE: When not compiling Objective-C, declare these functions such that they can be
100// used by other inline-implemented methods. Since those methods in turn will not actually
7a71aa14
DE
101// be used from non-ObjC code the compiler ought not emit them. If it emits an out of
102// line copy of those methods then presumably it will have also emitted at least one
103// out of line copy of these functions from at least one Objective-C++ translation unit.
104// That means the out of line implementation will be available at link time.
6ecc2922
DE
105
106template <class Type>
107inline Type * wxGCSafeRetain(Type *r);
108
109template <class Type>
110inline void wxGCSafeRelease(Type *r);
111
112#endif //def __OBJC__
113
fa8114de
DE
114/*
115wxObjcAutoRefFromAlloc: construct a reference to an object that was
116[NSObject -alloc]'ed and thus does not need a retain
117wxObjcAutoRef: construct a reference to an object that was
118either autoreleased or is retained by something else.
119*/
120
121struct objc_object;
122
123// We must do any calls to Objective-C from an Objective-C++ source file
124class wxObjcAutoRefBase
125{
126protected:
ddfdef64
DE
127 /*! @function ObjcRetain
128 @abstract Simply does [p retain].
129 */
fa8114de 130 static struct objc_object* ObjcRetain(struct objc_object*);
ddfdef64
DE
131
132 /*! @function ObjcRelease
133 @abstract Simply does [p release].
134 */
e76d459d 135 static void ObjcRelease(struct objc_object*);
fa8114de
DE
136};
137
ddfdef64
DE
138/*! @class wxObjcAutoRefFromAlloc
139 @templatefield T The type of _pointer_ (e.g. NSString*, NSRunLoop*)
140 @abstract Pointer-holder for Objective-C objects
141 @discussion
142 When constructing this object from a raw pointer, the pointer is assumed to have
143 come from an alloc-style method. That is, once you construct this object from
144 the pointer you must not balance your alloc with a call to release.
fa8114de 145
ddfdef64
DE
146 This class has been carefully designed to work with both the traditional Retain/Release
147 and the new Garbage Collected modes. In RR-mode it will prevent the object from being
148 released by managing the reference count using the retain/release semantics. In GC-mode
149 it will use a method (currently CFRetain/CFRelease) to ensure the object will never be
150 finalized until this object is destroyed.
151 */
03647350 152
fa8114de
DE
153template <class T>
154class wxObjcAutoRefFromAlloc: wxObjcAutoRefBase
155{
156public:
157 wxObjcAutoRefFromAlloc(T p = 0)
158 : m_ptr(p)
159 // NOTE: this is from alloc. Do NOT retain
ddfdef64
DE
160 {
161 // CFRetain
162 // GC: Object is strongly retained and prevented from being collected
163 // non-GC: Simply realizes it's an Objective-C object and calls [p retain]
6ecc2922 164 wxGCSafeRetain(p);
ddfdef64
DE
165 // ObjcRelease (e.g. [p release])
166 // GC: Objective-C retain/release mean nothing in GC mode
167 // non-GC: This is a normal release call, balancing the retain
168 ObjcRelease(static_cast<T>(p));
169 // The overall result:
170 // GC: Object is strongly retained
171 // non-GC: Retain count is the same as it was (retain then release)
172 }
fa8114de
DE
173 wxObjcAutoRefFromAlloc(const wxObjcAutoRefFromAlloc& otherRef)
174 : m_ptr(otherRef.m_ptr)
6ecc2922 175 { wxGCSafeRetain(m_ptr); }
fa8114de 176 ~wxObjcAutoRefFromAlloc()
6ecc2922 177 { wxGCSafeRelease(m_ptr); }
fa8114de 178 wxObjcAutoRefFromAlloc& operator=(const wxObjcAutoRefFromAlloc& otherRef)
6ecc2922
DE
179 { wxGCSafeRetain(otherRef.m_ptr);
180 wxGCSafeRelease(m_ptr);
fa8114de
DE
181 m_ptr = otherRef.m_ptr;
182 return *this;
183 }
184 operator T() const
ddfdef64 185 { return static_cast<T>(m_ptr); }
fa8114de 186 T operator->() const
ddfdef64 187 { return static_cast<T>(m_ptr); }
fa8114de 188protected:
ddfdef64
DE
189 /*! @field m_ptr The pointer to the Objective-C object
190 @discussion
191 The pointer to the Objective-C object is typed as void* to avoid compiler-generated write
192 barriers as would be used for implicitly __strong object pointers and to avoid the similar
193 read barriers as would be used for an explicitly __weak object pointer. The write barriers
6ecc2922
DE
194 are useless unless this object is located in GC-managed heap which is highly unlikely.
195
196 Since we guarantee strong reference via CFRetain/CFRelease the write-barriers are not needed
197 at all, even if this object does happen to be allocated in GC-managed heap.
ddfdef64
DE
198 */
199 void *m_ptr;
fa8114de
DE
200};
201
ddfdef64
DE
202/*!
203 @class wxObjcAutoRef
204 @description
205 A pointer holder that does retain its argument.
206 NOTE: It is suggest that you instead use wxObjcAutoRefFromAlloc<T> foo([aRawPointer retain])
207 */
fa8114de
DE
208template <class T>
209class wxObjcAutoRef: public wxObjcAutoRefFromAlloc<T>
210{
211public:
ddfdef64
DE
212 /*! @method wxObjcAutoRef
213 @description
214 Uses the underlying wxObjcAutoRefFromAlloc and simply does a typical [p retain] such that
215 in RR-mode the object is in effectively the same retain-count state as it would have been
216 coming straight from an alloc method.
217 */
fa8114de
DE
218 wxObjcAutoRef(T p = 0)
219 : wxObjcAutoRefFromAlloc<T>(p)
ddfdef64
DE
220 { // NOTE: ObjcRetain is correct because in GC-mode it balances ObjcRelease in our superclass constructor
221 // In RR mode it does retain and the superclass does retain/release thus resulting in an overall retain.
222 ObjcRetain(static_cast<T>(wxObjcAutoRefFromAlloc<T>::m_ptr));
223 }
fa8114de
DE
224 ~wxObjcAutoRef() {}
225 wxObjcAutoRef(const wxObjcAutoRef& otherRef)
226 : wxObjcAutoRefFromAlloc<T>(otherRef)
227 {}
228 wxObjcAutoRef(const wxObjcAutoRefFromAlloc<T>& otherRef)
229 : wxObjcAutoRefFromAlloc<T>(otherRef)
230 {}
231 wxObjcAutoRef& operator=(const wxObjcAutoRef& otherRef)
232 { return wxObjcAutoRefFromAlloc<T>::operator=(otherRef); }
233};
234
256af34f 235#endif //ndef _WX_COCOA_OBJCREF_H__