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