]>
Commit | Line | Data |
---|---|---|
db7035e4 VZ |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: wx/tracker.h | |
3 | // Purpose: Support class for object lifetime tracking (wxWeakRef<T>) | |
4 | // Author: Arne Steinarson | |
5 | // Created: 2007-12-28 | |
7d23dd28 | 6 | // RCS-ID: $Id$ |
db7035e4 VZ |
7 | // Copyright: (c) 2007 Arne Steinarson |
8 | // Licence: wxWindows licence | |
9 | ///////////////////////////////////////////////////////////////////////////// | |
10 | ||
11 | #ifndef _WX_TRACKER_H_ | |
12 | #define _WX_TRACKER_H_ | |
13 | ||
7d23dd28 | 14 | |
db7035e4 VZ |
15 | // This structure represents an object tracker and is stored in a linked list |
16 | // in the tracked object. It is only used in one of its derived forms. | |
7d23dd28 RR |
17 | struct wxTrackerNode { |
18 | wxTrackerNode( ) : m_nxt(0) { } | |
db7035e4 | 19 | virtual ~wxTrackerNode() { } |
7d23dd28 RR |
20 | |
21 | virtual void OnObjectDestroy( ) = 0; | |
22 | ||
23 | // This is to tell the difference between different tracker node types. | |
24 | // It's a replacement of dynamic_cast<> for this class since dynamic_cast | |
25 | // may be disabled (and we don't have wxDynamicCast since wxTrackerNode | |
db7035e4 | 26 | // is not derived wxObject). |
7d23dd28 | 27 | enum wxTrackerNodeType { WeakRef, EventConnectionRef }; |
db7035e4 VZ |
28 | |
29 | virtual wxTrackerNodeType GetType() = 0; | |
7d23dd28 | 30 | |
db7035e4 | 31 | protected: |
7d23dd28 | 32 | wxTrackerNode *m_nxt; |
db7035e4 VZ |
33 | friend class wxTrackableBase; // For list access |
34 | friend class wxEvtHandler; // For list access | |
35 | }; | |
36 | ||
37 | ||
38 | // Add-on base class for a trackable object. | |
7d23dd28 RR |
39 | struct wxTrackableBase { |
40 | wxTrackableBase() : m_first(0) { } | |
db7035e4 | 41 | ~wxTrackableBase() |
7d23dd28 | 42 | { |
db7035e4 | 43 | // Notify all registered refs |
7d23dd28 RR |
44 | |
45 | wxTrackerNode *first; | |
46 | while( m_first ) | |
db7035e4 | 47 | { |
7d23dd28 RR |
48 | first = m_first; |
49 | first->OnObjectDestroy( ); | |
db7035e4 VZ |
50 | RemoveNode(first); |
51 | } | |
52 | } | |
7d23dd28 RR |
53 | |
54 | void AddNode( wxTrackerNode *prn ) | |
db7035e4 | 55 | { |
7d23dd28 RR |
56 | prn->m_nxt = m_first; |
57 | m_first = prn; | |
db7035e4 | 58 | } |
7d23dd28 | 59 | void RemoveNode( wxTrackerNode *prn ) |
db7035e4 | 60 | { |
7d23dd28 | 61 | for( wxTrackerNode **pprn=&m_first; *pprn; pprn=&(*pprn)->m_nxt ) |
db7035e4 | 62 | { |
7d23dd28 | 63 | if( *pprn==prn ) |
db7035e4 | 64 | { |
7d23dd28 | 65 | *pprn = prn->m_nxt; |
db7035e4 VZ |
66 | return; |
67 | } | |
68 | } | |
7d23dd28 RR |
69 | // Not found, an error. |
70 | wxASSERT( false ); | |
db7035e4 | 71 | } |
7d23dd28 RR |
72 | |
73 | wxTrackerNode* GetFirst( ){ return m_first; } | |
db7035e4 | 74 | |
7d23dd28 | 75 | // If trying to copy this object, then do not copy its ref list. |
2ef989c9 | 76 | wxTrackableBase& operator = (const wxTrackableBase& WXUNUSED(other)) { return *this; } |
7d23dd28 RR |
77 | |
78 | protected: | |
db7035e4 VZ |
79 | wxTrackerNode *m_first; |
80 | }; | |
81 | ||
7d23dd28 RR |
82 | |
83 | // The difference to wxTrackableBase is that this class adds | |
db7035e4 | 84 | // a VTable to enable dynamic_cast query for wxTrackable. |
7d23dd28 | 85 | struct wxTrackable : public wxTrackableBase |
db7035e4 | 86 | { |
7d23dd28 | 87 | virtual ~wxTrackable(){ } |
db7035e4 VZ |
88 | }; |
89 | ||
90 | ||
91 | // Helper to decide if an object has a base class or not | |
92 | // (strictly speaking, this test succeeds if a type is convertible | |
93 | // to another type in some way.) | |
7d23dd28 RR |
94 | template<class T, class B> |
95 | struct wxHasBase{ | |
96 | static char Match( B* pb ); | |
97 | static int Match( ... ); | |
98 | enum { value = (sizeof(Match((T*)NULL))==sizeof(char)) }; | |
db7035e4 VZ |
99 | }; |
100 | ||
7d23dd28 RR |
101 | // VC++ before 7.1 does not have partial template specialization |
102 | #ifdef __VISUALC__ | |
103 | #if __VISUALC__ < 1310 | |
104 | #define HAVE_NO_PARTIAL_SPECIALIZATION | |
105 | #endif | |
106 | #endif | |
107 | ||
108 | #if defined(HAVE_DYNAMIC_CAST) && !defined(HAVE_NO_PARTIAL_SPECIALIZATION) | |
109 | // A structure to cast to wxTrackableBase, using either static_cast<> or dynamic_cast<>. | |
110 | template<class T,bool is_static> | |
111 | struct wxTrackableCaster; | |
112 | ||
113 | template <class T> | |
114 | struct wxTrackableCaster<T,true> { | |
115 | static wxTrackableBase* Cast(T* pt){ return static_cast<wxTrackableBase*>(pt); } | |
116 | }; | |
117 | ||
118 | template <class T> | |
119 | struct wxTrackableCaster<T,false> { | |
120 | static wxTrackableBase* Cast(T* pt){ return dynamic_cast<wxTrackableBase*>(pt); } | |
121 | }; | |
122 | #else | |
123 | #if defined(HAVE_DYNAMIC_CAST) | |
124 | // If we have dynamic_cast, default to that. For gcc, dynamic_cast<> does the job | |
125 | // of both the dynamic and the static case. It could be that all compilers do it | |
126 | // that way, rendering the specialization code above rednundant. | |
127 | template <class T,bool is_static> | |
128 | struct wxTrackableCaster { | |
129 | static wxTrackableBase* Cast(T* pt){ return dynamic_cast<wxTrackableBase*>(pt); } | |
130 | }; | |
131 | #else | |
132 | // No dynamic_cast<> is available. | |
133 | // We use static_cast<>, that gives support for wxEvtHandler and wxWindow references. | |
134 | // We don't get weak refs to other wxObject derived types. | |
135 | template <class T,bool is_static> | |
136 | struct wxTrackableCaster { | |
137 | static wxTrackableBase* Cast(T* pt){ return static_cast<wxTrackableBase*>(pt); } | |
138 | }; | |
139 | #endif | |
140 | #endif | |
db7035e4 VZ |
141 | |
142 | #endif // _WX_TRACKER_H_ | |
143 |