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