weakref.h 8.7 KB

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