]> git.saurik.com Git - wxWidgets.git/blame - include/wx/weakref.h
temporary fix the linking problem due to making GSocket::Detected_Read/Write() non...
[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
RR
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
cc6ceca7
VZ
31#include "wx/meta/convertible.h"
32#include "wx/meta/int2type.h"
33
34template <class T>
35struct wxIsStaticTrackable
36{
37 enum { value = wxConvertibleTo<T, wxTrackable>::value };
38};
39
26c66bc6
RR
40#endif // !USE_ONLY_STATIC_WEAKREF
41
42
cc6ceca7
VZ
43// Weak ref implementation when T has wxTrackable as a known base class
44template <class T>
45class wxWeakRefStatic : public wxTrackerNode
46{
47public:
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
470f357f
PC
62 virtual void OnObjectDestroy()
63 {
64 // Tracked object itself removes us from list of trackers
65 wxASSERT(m_pobj != NULL);
66 m_pobj = NULL;
67 }
68
cc6ceca7
VZ
69protected:
70 void Assign(T* pobj)
71 {
72 if ( m_pobj == pobj )
73 return;
74
75 Release();
76
77 // Now set new trackable object
78 if ( pobj )
79 {
80 // Add ourselves to object tracker list
81 wxTrackable *pt = static_cast<wxTrackable*>(pobj);
82 pt->AddNode(this);
83 m_pobj = pobj;
84 }
85 }
86
42d9ad79 87 void AssignCopy(const wxWeakRefStatic& wr)
cc6ceca7
VZ
88 {
89 Assign( wr.m_pobj );
90 }
91
cc6ceca7
VZ
92 T *m_pobj;
93};
94
cc6ceca7 95
7005cf44 96
26c66bc6 97#ifndef USE_ONLY_STATIC_WEAKREF
7005cf44 98
cc6ceca7
VZ
99template<class T,bool use_static>
100struct wxWeakRefImpl;
101
102// Intermediate class, to select the static case above.
103template <class T>
104struct 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
db7035e4 110template<class T>
cc6ceca7
VZ
111struct 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
470f357f
PC
125 virtual void OnObjectDestroy()
126 {
127 // Tracked object itself removes us from list of trackers
128 wxASSERT(m_pobj != NULL);
129 m_pobj = NULL;
130 m_ptbase = NULL;
131 }
132
cc6ceca7
VZ
133protected:
134 wxWeakRefImpl() : m_pobj(NULL), m_ptbase(NULL) { }
135
136 // Assign receives most derived class here and can use that
137 template <class TDerived>
138 void Assign( TDerived* pobj )
139 {
140 AssignHelper( pobj, wxInt2Type<wxIsStaticTrackable<TDerived>::value>() );
141 }
142
143 template <class TDerived>
144 void AssignHelper(TDerived* pobj, wxInt2Type<true>)
145 {
146 wxTrackable *ptbase = static_cast<wxTrackable*>(pobj);
147 DoAssign( pobj, ptbase );
148 }
149
150#ifdef HAVE_DYNAMIC_CAST
151 void AssignHelper(T* pobj, wxInt2Type<false>)
152 {
153 // A last way to get a trackable pointer
154 wxTrackable *ptbase = dynamic_cast<wxTrackable*>(pobj);
155 if ( ptbase )
156 {
157 DoAssign( pobj, ptbase );
158 }
159 else
160 {
161 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
162
163 Release();
164 }
165 }
166#endif // HAVE_DYNAMIC_CAST
167
168 void AssignCopy(const wxWeakRefImpl& wr)
169 {
42d9ad79 170 DoAssign(wr.m_pobj, wr.m_ptbase);
cc6ceca7
VZ
171 }
172
173 void DoAssign( T* pobj, wxTrackable *ptbase ) {
174 if( m_pobj==pobj ) return;
175 Release();
176
177 // Now set new trackable object
178 if( pobj )
179 {
180 // Add ourselves to object tracker list
181 wxASSERT( ptbase );
182 ptbase->AddNode( this );
183 m_pobj = pobj;
184 m_ptbase = ptbase;
185 }
186 }
187
cc6ceca7
VZ
188 T *m_pobj;
189 wxTrackable *m_ptbase;
190};
191
26c66bc6 192#endif // #ifndef USE_ONLY_STATIC_WEAKREF
7005cf44 193
cc6ceca7
VZ
194
195
26c66bc6 196// A weak reference to an object of type T, where T has base wxTrackable
cc6ceca7
VZ
197// (usually statically but if not dynamic_cast<> is tried).
198template <class T>
199class wxWeakRef : public
26c66bc6 200#ifdef USE_ONLY_STATIC_WEAKREF
cc6ceca7 201 wxWeakRefStatic<T>
7005cf44
VZ
202#else
203 wxWeakRefImpl<T, wxIsStaticTrackable<T>::value>
cc6ceca7 204#endif
db7035e4
VZ
205{
206public:
cc6ceca7
VZ
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
26c66bc6
RR
218 // We need this copy ctor, since otherwise a default compiler (binary) copy
219 // happens (if embedded as an object member).
6dd21c54
RR
220 wxWeakRef(const wxWeakRef<T>& wr)
221 {
222 Assign(wr.get());
223 }
224
cc6ceca7
VZ
225 template <class TDerived>
226 wxWeakRef<T>& operator=(TDerived* pobj)
227 {
074574b4 228 this->Assign(pobj);
cc6ceca7
VZ
229 return *this;
230 }
231
232 wxWeakRef<T>& operator=(const wxWeakRef<T>& wr)
233 {
234 AssignCopy(wr);
235 return *this;
236 }
db7035e4 237
34bfda8a 238 virtual ~wxWeakRef() { this->Release(); }
cc6ceca7
VZ
239
240 // Smart pointer functions
26c66bc6
RR
241 T& operator*() const { return *this->m_pobj; }
242 T* operator->() const { return this->m_pobj; }
cc6ceca7 243
26c66bc6
RR
244 T* get() const { return this->m_pobj; }
245 operator T*() const { return this->m_pobj; }
cc6ceca7
VZ
246};
247
248
26c66bc6
RR
249#ifdef HAVE_DYNAMIC_CAST
250
cc6ceca7
VZ
251// Weak ref implementation assign objects are queried for wxTrackable
252// using dynamic_cast<>
42d9ad79 253template <class T>
cc6ceca7
VZ
254class wxWeakRefDynamic : public wxTrackerNode
255{
256public:
257 wxWeakRefDynamic() : m_pobj(NULL) { }
1e9192d0 258
cc6ceca7 259 wxWeakRefDynamic(T* pobj) : m_pobj(pobj)
db7035e4
VZ
260 {
261 Assign(pobj);
db7035e4
VZ
262 }
263
26c66bc6
RR
264 wxWeakRefDynamic(const wxWeakRef<T>& wr)
265 {
266 Assign(wr.get());
267 }
268
cc6ceca7
VZ
269 virtual ~wxWeakRefDynamic() { Release(); }
270
271 // Smart pointer functions
26c66bc6
RR
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; }
db7035e4 277
26c66bc6
RR
278 T* operator = (T* pobj) { Assign(pobj); return m_pobj; }
279
cc6ceca7 280 // Assign from another weak ref, point to same object
26c66bc6 281 T* operator = (const wxWeakRef<T> &wr) { Assign( wr.get() ); return m_pobj; }
db7035e4 282
cc6ceca7 283 void Release()
db7035e4 284 {
cc6ceca7
VZ
285 // Release old object if any
286 if( m_pobj )
db7035e4
VZ
287 {
288 // Remove ourselves from object tracker list
cc6ceca7 289 wxTrackable *pt = dynamic_cast<wxTrackable*>(m_pobj);
9dd5ff5b
RR
290 wxASSERT(pt);
291 pt->RemoveNode(this);
db7035e4
VZ
292 m_pobj = NULL;
293 }
cc6ceca7
VZ
294 }
295
470f357f
PC
296 virtual void OnObjectDestroy()
297 {
298 wxASSERT_MSG(m_pobj, "tracked object should have removed us itself");
299
300 m_pobj = NULL;
301 }
302
cc6ceca7
VZ
303protected:
304 void Assign(T *pobj)
305 {
306 if ( m_pobj == pobj )
307 return;
308
309 Release();
db7035e4
VZ
310
311 // Now set new trackable object
312 if ( pobj )
313 {
cc6ceca7
VZ
314 // Add ourselves to object tracker list
315 wxTrackable *pt = dynamic_cast<wxTrackable*>(pobj);
316 if ( pt )
9dd5ff5b 317 {
cc6ceca7 318 pt->AddNode(this);
9dd5ff5b
RR
319 m_pobj = pobj;
320 }
321 else
322 {
cc6ceca7
VZ
323 // If the object we want to track does not support wxTackable, then
324 // log a message and keep the NULL object pointer.
325 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
9dd5ff5b 326 }
db7035e4
VZ
327 }
328 }
329
330 T *m_pobj;
331};
332
26c66bc6
RR
333#endif // #ifdef HAVE_DYNAMIC_CAST
334
335
db7035e4 336// Provide some basic types of weak references
db7035e4 337class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
5a0c7d66 338class WXDLLIMPEXP_FWD_CORE wxWindow;
db7035e4 339
26c66bc6 340
db7035e4
VZ
341typedef wxWeakRef<wxEvtHandler> wxEvtHandlerRef;
342typedef wxWeakRef<wxWindow> wxWindowRef;
343
344#endif // _WX_WEAKREF_H_
345