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