From: Vadim Zeitlin Date: Sun, 6 Jan 2008 18:01:28 +0000 (+0000) Subject: added wxWeakRef (slightly modified patch 1860953) X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/db7035e48a4ccc6265fa01949cb92db3c6b6c17f?ds=inline added wxWeakRef (slightly modified patch 1860953) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@51042 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index 83a2de143e..98e8bf0153 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -529,6 +529,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! wx/thrimpl.cpp wx/timer.h wx/tokenzr.h + wx/tracker.h wx/txtstrm.h wx/types.h wx/unichar.h @@ -538,6 +539,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! wx/vector.h wx/version.h wx/volume.h + wx/weakref.h wx/wfstream.h wx/wx.h wx/wxchar.h diff --git a/include/wx/tracker.h b/include/wx/tracker.h new file mode 100644 index 0000000000..ccb81c8fe5 --- /dev/null +++ b/include/wx/tracker.h @@ -0,0 +1,139 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/tracker.h +// Purpose: Support class for object lifetime tracking (wxWeakRef) +// Author: Arne Steinarson +// Created: 2007-12-28 +// RCS-ID: $Id:$ +// Copyright: (c) 2007 Arne Steinarson +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_TRACKER_H_ +#define _WX_TRACKER_H_ + +// This structure represents an object tracker and is stored in a linked list +// in the tracked object. It is only used in one of its derived forms. +struct wxTrackerNode +{ + wxTrackerNode() : m_next(NULL) { } + virtual ~wxTrackerNode() { } + + virtual void OnObjectDestroy() = 0; + + // This is to tell the difference between different tracker node types. + // It's a replacement of dynamic_cast<> for this class since dynamic_cast + // may be disabled (and we don't have wxDynamicCast since wxTrackerNode + // is not derived wxObject). + enum wxTrackerNodeType { WeakRef, EventConnectionRef }; + + virtual wxTrackerNodeType GetType() = 0; + +protected: + wxTrackerNode *m_next; + + friend class wxTrackableBase; // For list access + friend class wxEvtHandler; // For list access +}; + + +// Add-on base class for a trackable object. +struct wxTrackableBase +{ + wxTrackableBase() : m_first(NULL) { } + + ~wxTrackableBase() + { + // Notify all registered refs + + // OnObjectDestroy has to remove the item from the link chain + while ( m_first ) + { + wxTrackerNode *first = m_first; + first->OnObjectDestroy(); + RemoveNode(first); + } + } + + void AddNode(wxTrackerNode *node) + { + node->m_next = m_first; + m_first = node; + } + + void RemoveNode(wxTrackerNode *node) + { + for ( wxTrackerNode **pn = &m_first; *pn; pn = &(*pn)->m_next ) + { + if ( *pn == node ) + { + *pn = node->m_next; + return; + } + } + + wxFAIL_MSG( "node should be present" ); + } + + wxTrackerNode *GetFirst() { return m_first; } + +protected: + wxTrackerNode *m_first; +}; + +// The difference to wxTrackableBase is that this class adds +// a VTable to enable dynamic_cast query for wxTrackable. +struct wxTrackable : wxTrackableBase +{ + virtual ~wxTrackable() { } +}; + + +// Helper to decide if an object has a base class or not +// (strictly speaking, this test succeeds if a type is convertible +// to another type in some way.) +template +struct wxHasBase +{ + static char Match(B *pb); + static int Match(...); + + enum { value = sizeof(Match((T*)NULL)) == sizeof(char) }; +}; + +// A structure to cast to wxTrackableBase, using either static_cast<> or +// dynamic_cast<>. +template +struct wxTrackableCaster; + +template +struct wxTrackableCaster +{ + static wxTrackableBase* Cast(T* pt) + { + return static_cast(pt); + } +}; + +#ifdef HAVE_DYNAMIC_CAST + +template +struct wxTrackableCaster +{ + static wxTrackableBase *Cast(T* pt) + { + return dynamic_cast(pt); + } +}; + +#else // !HAVE_DYNAMIC_CAST + +template +struct wxTrackableCaster +{ + static wxTrackableBase *Cast(T* pt) { return NULL; } +}; + +#endif // HAVE_DYNAMIC_CAST/!HAVE_DYNAMIC_CAST + +#endif // _WX_TRACKER_H_ + diff --git a/include/wx/weakref.h b/include/wx/weakref.h new file mode 100644 index 0000000000..7d8ac8c5b9 --- /dev/null +++ b/include/wx/weakref.h @@ -0,0 +1,89 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/weakref.h +// Purpose: wxWeakRef - Generic weak references for wxWidgets +// Author: Arne Steinarson +// Created: 2007-12-27 +// RCS-ID: $Id:$ +// Copyright: (c) 2007 Arne Steinarson +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_WEAKREF_H_ +#define _WX_WEAKREF_H_ + +#include + +// A weak reference to an object of type T, where T has type wxTrackable +// as one of its base classes (in a static or dynamic sense). +template +class wxWeakRef : public wxTrackerNode +{ +public: + wxWeakRef(T *pobj = NULL) : m_pobj(NULL) { Assign(pobj); } + + virtual ~wxWeakRef() { Assign(NULL); } + + // Smart pointer functions + operator T*(){ return m_pobj; } + T* operator->(){ return m_pobj; } + T* operator=(T *pobj) + { + Assign(pobj); + return m_pobj; + } + + virtual void OnObjectDestroy() + { + // Tracked object itself removes us from list of trackers + wxASSERT( m_pobj ); + m_pobj = NULL; + } + + virtual wxTrackerNodeType GetType() { return WeakRef; } + +protected: + wxTrackableBase *GetTrackable(T *pobj) + { + // this uses static_cast if possible or dynamic_cast otherwise + return wxTrackableCaster::value> + ::Cast(pobj); + } + + void Assign(T* pobj) + { + if ( m_pobj == pobj ) + return; + + // First release old object if any + if ( m_pobj ) + { + // Remove ourselves from object tracker list + GetTrackable(m_pobj)->RemoveNode(this); + m_pobj = NULL; + } + + // Now set new trackable object + if ( pobj ) + { + wxTrackableBase * const pt = GetTrackable(pobj); + wxCHECK_RET( pt, "type must derive from wxTrackableBase" ); + + pt->AddNode(this); + m_pobj = pobj; + } + } + + T *m_pobj; +}; + +// Provide some basic types of weak references +class WXDLLIMPEXP_FWD_BASE wxObject; +class WXDLLIMPEXP_FWD_BASE wxEvtHandler; +class WXDLLIMPEXP_FWD_CORE wxWindow; + +typedef wxWeakRef wxObjectRef; +typedef wxWeakRef wxEvtHandlerRef; +typedef wxWeakRef wxWindowRef; + +#endif // _WX_WEAKREF_H_ +