[ 1960295 ] wxWeakRef - Reorganization and comments
[wxWidgets.git] / include / wx / weakref.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/weakref.h
3 // Purpose: wxWeakRef - Generic weak references for wxWidgets
4 // Author: Arne Steinarson
5 // Created: 27 Dec 07
6 // RCS-ID: $Id$
7 // Copyright: (c) 2007 Arne Steinarson
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #ifndef _WX_WEAKREF_H_
12 #define _WX_WEAKREF_H_
13
14 #include "wx/tracker.h"
15
16
17 // Some compilers (VC6, Borland, otehrs?) have problem with template specialization.
18 // However, this is only used for optimization purposes (a smaller wxWeakRef pointer)
19 // (and the corner case of wxWeakRef<wxObject>). So for those compilers, we can fall
20 // back to the non-optimal case, where we use a the same type of weak ref (static one)
21 // in all cases. See defs.h for various setting these defines depending on compiler.
22
23 #if !defined(HAVE_PARTIAL_SPECIALIZATION) || !defined(HAVE_TEMPLATE_OVERLOAD_RESOLUTION)
24 #define USE_ONLY_STATIC_WEAKREF
25 #endif
26
27
28 #ifndef USE_ONLY_STATIC_WEAKREF
29
30 // Avoid including this for simpler compilers
31 #include "wx/meta/convertible.h"
32 #include "wx/meta/int2type.h"
33
34 template <class T>
35 struct wxIsStaticTrackable
36 {
37 enum { value = wxConvertibleTo<T, wxTrackable>::value };
38 };
39
40 #endif // !USE_ONLY_STATIC_WEAKREF
41
42
43 // Weak ref implementation when T has wxTrackable as a known base class
44 template <class T>
45 class wxWeakRefStatic : public wxTrackerNode
46 {
47 public:
48 wxWeakRefStatic() : m_pobj(NULL) { }
49
50 void Release()
51 {
52 // Release old object if any
53 if ( m_pobj )
54 {
55 // Remove ourselves from object tracker list
56 wxTrackable *pt = static_cast<wxTrackable*>(m_pobj);
57 pt->RemoveNode(this);
58 m_pobj = NULL;
59 }
60 }
61
62 protected:
63 void Assign(T* pobj)
64 {
65 if ( m_pobj == pobj )
66 return;
67
68 Release();
69
70 // Now set new trackable object
71 if ( pobj )
72 {
73 // Add ourselves to object tracker list
74 wxTrackable *pt = static_cast<wxTrackable*>(pobj);
75 pt->AddNode(this);
76 m_pobj = pobj;
77 }
78 }
79
80 void AssignCopy(const wxWeakRefStatic& wr)
81 {
82 Assign( wr.m_pobj );
83 }
84
85 virtual void OnObjectDestroy()
86 {
87 // Tracked object itself removes us from list of trackers
88 wxASSERT( m_pobj!=NULL );
89 m_pobj = NULL;
90 }
91
92 T *m_pobj;
93 };
94
95
96
97 #ifndef USE_ONLY_STATIC_WEAKREF
98
99 template<class T,bool use_static>
100 struct wxWeakRefImpl;
101
102 // Intermediate class, to select the static case above.
103 template <class T>
104 struct wxWeakRefImpl<T, true> : public wxWeakRefStatic<T>
105 {
106 enum { value = 1 };
107 };
108
109 // Weak ref implementation when T does not have wxTrackable as known base class
110 template<class T>
111 struct wxWeakRefImpl<T, false> : public wxTrackerNode
112 {
113 void Release()
114 {
115 // Release old object if any
116 if ( m_pobj )
117 {
118 // Remove ourselves from object tracker list
119 m_ptbase->RemoveNode(this);
120 m_pobj = NULL;
121 m_ptbase = NULL;
122 }
123 }
124
125 protected:
126 wxWeakRefImpl() : m_pobj(NULL), m_ptbase(NULL) { }
127
128 // Assign receives most derived class here and can use that
129 template <class TDerived>
130 void Assign( TDerived* pobj )
131 {
132 AssignHelper( pobj, wxInt2Type<wxIsStaticTrackable<TDerived>::value>() );
133 }
134
135 template <class TDerived>
136 void AssignHelper(TDerived* pobj, wxInt2Type<true>)
137 {
138 wxTrackable *ptbase = static_cast<wxTrackable*>(pobj);
139 DoAssign( pobj, ptbase );
140 }
141
142 #ifdef HAVE_DYNAMIC_CAST
143 void AssignHelper(T* pobj, wxInt2Type<false>)
144 {
145 // A last way to get a trackable pointer
146 wxTrackable *ptbase = dynamic_cast<wxTrackable*>(pobj);
147 if ( ptbase )
148 {
149 DoAssign( pobj, ptbase );
150 }
151 else
152 {
153 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
154
155 Release();
156 }
157 }
158 #endif // HAVE_DYNAMIC_CAST
159
160 void AssignCopy(const wxWeakRefImpl& wr)
161 {
162 DoAssign(wr.m_pobj, wr.m_ptbase);
163 }
164
165 void DoAssign( T* pobj, wxTrackable *ptbase ) {
166 if( m_pobj==pobj ) return;
167 Release();
168
169 // Now set new trackable object
170 if( pobj )
171 {
172 // Add ourselves to object tracker list
173 wxASSERT( ptbase );
174 ptbase->AddNode( this );
175 m_pobj = pobj;
176 m_ptbase = ptbase;
177 }
178 }
179
180 virtual void OnObjectDestroy()
181 {
182 // Tracked object itself removes us from list of trackers
183 wxASSERT( m_pobj!=NULL );
184 m_pobj = NULL;
185 m_ptbase = NULL;
186 }
187
188 T *m_pobj;
189 wxTrackable *m_ptbase;
190 };
191
192 #endif // #ifndef USE_ONLY_STATIC_WEAKREF
193
194
195
196 // A weak reference to an object of type T, where T has base wxTrackable
197 // (usually statically but if not dynamic_cast<> is tried).
198 template <class T>
199 class wxWeakRef : public
200 #ifdef USE_ONLY_STATIC_WEAKREF
201 wxWeakRefStatic<T>
202 #else
203 wxWeakRefImpl<T, wxIsStaticTrackable<T>::value>
204 #endif
205 {
206 public:
207 // Default ctor
208 wxWeakRef() { }
209
210 // When we have the full type here, static_cast<> will always work
211 // (or give a straight compiler error).
212 template <class TDerived>
213 wxWeakRef(TDerived* pobj)
214 {
215 Assign(pobj);
216 }
217
218 // We need this copy ctor, since otherwise a default compiler (binary) copy
219 // happens (if embedded as an object member).
220 wxWeakRef(const wxWeakRef<T>& wr)
221 {
222 Assign(wr.get());
223 }
224
225 template <class TDerived>
226 wxWeakRef<T>& operator=(TDerived* pobj)
227 {
228 Assign(pobj);
229 return *this;
230 }
231
232 wxWeakRef<T>& operator=(const wxWeakRef<T>& wr)
233 {
234 AssignCopy(wr);
235 return *this;
236 }
237
238 virtual ~wxWeakRef() { this->Release(); }
239
240 // Smart pointer functions
241 T& operator*() const { return *this->m_pobj; }
242 T* operator->() const { return this->m_pobj; }
243
244 T* get() const { return this->m_pobj; }
245 operator T*() const { return this->m_pobj; }
246 };
247
248
249 #ifdef HAVE_DYNAMIC_CAST
250
251 // Weak ref implementation assign objects are queried for wxTrackable
252 // using dynamic_cast<>
253 template <class T>
254 class wxWeakRefDynamic : public wxTrackerNode
255 {
256 public:
257 wxWeakRefDynamic() : m_pobj(NULL) { }
258
259 wxWeakRefDynamic(T* pobj) : m_pobj(pobj)
260 {
261 Assign(pobj);
262 }
263
264 wxWeakRefDynamic(const wxWeakRef<T>& wr)
265 {
266 Assign(wr.get());
267 }
268
269 virtual ~wxWeakRefDynamic() { Release(); }
270
271 // Smart pointer functions
272 T& operator*() const { wxASSERT(m_pobj); return *m_pobj; }
273 T* operator->() const { wxASSERT(m_pobj); return m_pobj; }
274
275 T* get() const { return m_pobj; }
276 operator T* () const { return m_pobj; }
277
278 T* operator = (T* pobj) { Assign(pobj); return m_pobj; }
279
280 // Assign from another weak ref, point to same object
281 T* operator = (const wxWeakRef<T> &wr) { Assign( wr.get() ); return m_pobj; }
282
283 void Release()
284 {
285 // Release old object if any
286 if( m_pobj )
287 {
288 // Remove ourselves from object tracker list
289 wxTrackable *pt = dynamic_cast<wxTrackable*>(m_pobj);
290 wxASSERT(pt);
291 pt->RemoveNode(this);
292 m_pobj = NULL;
293 }
294 }
295
296 protected:
297 void Assign(T *pobj)
298 {
299 if ( m_pobj == pobj )
300 return;
301
302 Release();
303
304 // Now set new trackable object
305 if ( pobj )
306 {
307 // Add ourselves to object tracker list
308 wxTrackable *pt = dynamic_cast<wxTrackable*>(pobj);
309 if ( pt )
310 {
311 pt->AddNode(this);
312 m_pobj = pobj;
313 }
314 else
315 {
316 // If the object we want to track does not support wxTackable, then
317 // log a message and keep the NULL object pointer.
318 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
319 }
320 }
321 }
322
323 virtual void OnObjectDestroy()
324 {
325 wxASSERT_MSG( m_pobj, "tracked object should have removed us itself" );
326
327 m_pobj = NULL;
328 }
329
330 T *m_pobj;
331 };
332
333 #endif // #ifdef HAVE_DYNAMIC_CAST
334
335
336 // Provide some basic types of weak references
337 class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
338 class WXDLLIMPEXP_FWD_CORE wxWindow;
339
340
341 typedef wxWeakRef<wxEvtHandler> wxEvtHandlerRef;
342 typedef wxWeakRef<wxWindow> wxWindowRef;
343
344 #endif // _WX_WEAKREF_H_
345