]>
Commit | Line | Data |
---|---|---|
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 | |
6 | // RCS-ID: $Id$ | |
7 | // Copyright: (c) 2007 Arne Steinarson | |
8 | // Licence: wxWindows licence | |
9 | ///////////////////////////////////////////////////////////////////////////// | |
10 | ||
11 | #ifndef _WX_TRACKER_H_ | |
12 | #define _WX_TRACKER_H_ | |
13 | ||
14 | ||
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. | |
17 | struct wxTrackerNode { | |
18 | wxTrackerNode( ) : m_nxt(0) { } | |
19 | virtual ~wxTrackerNode() { } | |
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 | |
26 | // is not derived wxObject). | |
27 | enum wxTrackerNodeType { WeakRef, EventConnectionRef }; | |
28 | ||
29 | virtual wxTrackerNodeType GetType() = 0; | |
30 | ||
31 | protected: | |
32 | wxTrackerNode *m_nxt; | |
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. | |
39 | struct wxTrackableBase { | |
40 | wxTrackableBase() : m_first(0) { } | |
41 | ~wxTrackableBase() | |
42 | { | |
43 | // Notify all registered refs | |
44 | ||
45 | wxTrackerNode *first; | |
46 | while( m_first ) | |
47 | { | |
48 | first = m_first; | |
49 | first->OnObjectDestroy( ); | |
50 | RemoveNode(first); | |
51 | } | |
52 | } | |
53 | ||
54 | void AddNode( wxTrackerNode *prn ) | |
55 | { | |
56 | prn->m_nxt = m_first; | |
57 | m_first = prn; | |
58 | } | |
59 | void RemoveNode( wxTrackerNode *prn ) | |
60 | { | |
61 | for( wxTrackerNode **pprn=&m_first; *pprn; pprn=&(*pprn)->m_nxt ) | |
62 | { | |
63 | if( *pprn==prn ) | |
64 | { | |
65 | *pprn = prn->m_nxt; | |
66 | return; | |
67 | } | |
68 | } | |
69 | // Not found, an error. | |
70 | wxASSERT( false ); | |
71 | } | |
72 | ||
73 | wxTrackerNode* GetFirst( ){ return m_first; } | |
74 | ||
75 | // If trying to copy this object, then do not copy its ref list. | |
76 | wxTrackableBase& operator = (const wxTrackableBase& WXUNUSED(other)) { return *this; } | |
77 | ||
78 | protected: | |
79 | wxTrackerNode *m_first; | |
80 | }; | |
81 | ||
82 | ||
83 | // The difference to wxTrackableBase is that this class adds | |
84 | // a VTable to enable dynamic_cast query for wxTrackable. | |
85 | struct wxTrackable : public wxTrackableBase | |
86 | { | |
87 | virtual ~wxTrackable(){ } | |
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.) | |
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)) }; | |
99 | }; | |
100 | ||
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 | |
141 | ||
142 | #endif // _WX_TRACKER_H_ | |
143 |