From 9dd5ff5baafda3cd6c427047b92886933bdec6a5 Mon Sep 17 00:00:00 2001 From: Robert Roebling Date: Tue, 8 Jan 2008 09:55:21 +0000 Subject: [PATCH] Updated wxWeakRef to patch Weak references for wx - part 2, removed T*() and added T* get(), other minor docs corr git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@51100 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/scopedptr.tex | 8 +-- docs/latex/wx/sharedptr.tex | 12 ++++- docs/latex/wx/weakref.tex | 103 ++++++++++++++++++++++++++++-------- include/wx/weakref.h | 65 ++++++++++++++++------- 4 files changed, 142 insertions(+), 46 deletions(-) diff --git a/docs/latex/wx/scopedptr.tex b/docs/latex/wx/scopedptr.tex index 1da69e6dfe..952c0d451f 100644 --- a/docs/latex/wx/scopedptr.tex +++ b/docs/latex/wx/scopedptr.tex @@ -40,12 +40,12 @@ Destructor. Returns pointer to object or NULL. -\membersection{wxScopedPtr::operator*}\label{wxscopedptrtemplateoperatorptrt} +\membersection{wxScopedPtr::operator*}\label{wxscopedptrtemplateoperatorreft} \constfunc{T \&}{operator*}{\void} -Returns pointer to object. If the pointer is NULL this method will -cause an assert in debug mode. +Returns a reference to the object. If the internal pointer is NULL +this method will cause an assert in debug mode. \membersection{wxScopedPtr::operator->}\label{wxscopedptrtemplateoperatorderef} @@ -58,7 +58,7 @@ cause an assert in debug mode. \func{T*}{release}{\void} -Returns pointer to object or NULL. +Releases the current pointer and returns NULL. \membersection{wxScopedPtr::reset}\label{wxscopedptrtemplatereset} diff --git a/docs/latex/wx/sharedptr.tex b/docs/latex/wx/sharedptr.tex index 31f4ae9a5c..fb6b9d84bd 100644 --- a/docs/latex/wx/sharedptr.tex +++ b/docs/latex/wx/sharedptr.tex @@ -41,11 +41,12 @@ Destructor. Returns pointer to its object or NULL. -\membersection{wxSharedPtr::operator*}\label{wxsharedptroperatorptrt} +\membersection{wxSharedPtr::operator*}\label{wxsharedptroperatorreft} \constfunc{T\&}{operator*}{\void} -Returns pointer to its object or NULL. +Returns a reference to the object. If the internal pointer is NULL this +method will cause an assert in debug mode. \membersection{wxSharedPtr::operator->}\label{wxsharedptroperatorderef} @@ -71,3 +72,10 @@ Returns true if this is the only pointer pointing to its object. Returns the number of pointers pointing to its object. +\membersection{wxSharedPtr::reset}\label{wxsharedptrreset} + +\func{void}{reset}{\param{T * }{ptr = NULL}} + +Reset pointer to {\it ptr}. Afterwards the caller is responsible +for deleting the data contained in the pointer before. + diff --git a/docs/latex/wx/weakref.tex b/docs/latex/wx/weakref.tex index bda7029a8c..35e965c334 100644 --- a/docs/latex/wx/weakref.tex +++ b/docs/latex/wx/weakref.tex @@ -1,18 +1,66 @@ \section{\class{wxWeakRef}}\label{wxweakref} -A weak reference to an object of type T, where T has type -\helpref{wxTrackableBase}{wxtrackablebase} as one of its -base classes (in a static or dynamic sense). +{\bf wxWeakRef} is a template class for weak references to wxWidgets objects, +such as {\bf wxEvtHandler}, {\bf wxWindow} and {\bf wxObject}. A weak +reference behaves much like an ordinary pointer, but when the object pointed +to goes out of scope (is destroyed), the weak reference is automatically +reset to a NULL pointer. + +wxWeakref can be used whenever one must keep a pointer to an object +that does not directly own, and that may be destroyed before the object +holding the reference. + +wxWeakref is a small object and the mechanism behind it is fast +({\bf O(1)}). So the overall cost of using it is small. + + +\wxheading{Example} + +\begin{verbatim} + wxWindow *parent = /* Get parent window from somewhere */; + wxWindow *wnd = new wxWindow( parent, wxID_ANY, "wxWindow" ); + wxWeakRef wr = wnd; + wxWindowRef wr2 = wnd; // Same as above, but using a typedef + // Do things with window + wnd->Show( true ); + // Weak ref is used like an ordinary pointer + wr->Show( false ); + wnd->Destroy(); + // Now the weak ref has been reset, so we don't risk accessing + // a dangling pointer: + wxASSERT( wr==NULL ); +\end{verbatim} + +wxWeakref works for any objects that are derived from {\bf wxTrackableBase} +or {\bf wxTrackable}. By default, wxEvtHandler and wxWindow derive from +wxTrackableBase. However, wxObject does not, so types like {\bf wxFont} and +{\bf wxColour} are not trackable. The example below shows how to create a +wxObject derived class that is trackable: \begin{verbatim} -class MyClass: public Foo, public TrackableBase -{ - // whatever -} + class wxMyTrackableObject : public wxObject, public wxTrackable { + // ... other members here + }; +\end{verbatim} + +{\bf Note:} Custom trackable objects should derive from wxTrackable +if one wants to reference them from a {\bf wxWeakRef}. The +difference between the two base classes is that wxTrackableBase +has no virtual member functions (no VTable), and thus cannot be detected +through {\bf dynamic_cast<>}. + + +\wxheading{Predefined types} -typedef wxWeakRef MyClassRef; +The following types of weak references are predefined: + +\begin{verbatim} +typedef wxWeakRef wxObjectRef; +typedef wxWeakRef wxEvtHandlerRef; +typedef wxWeakRef wxWindowRef; \end{verbatim} + \wxheading{Derived from} wxTrackerNode @@ -30,7 +78,8 @@ wxTrackerNode \func{}{wxWeakRef}{\param{T* }{pobj = NULL}} -Constructor. +Constructor. The weak reference is initialized to {\it pobj}. + \membersection{wxWeakRef::\destruct{wxWeakRef}}\label{wxweakrefdtor} @@ -38,36 +87,46 @@ Constructor. Destructor. -\membersection{wxWeakRef::T*}\label{wxweakreft} -\func{operator}{T*}{\void} +\membersection{wxWeakRef::get}\label{wxweakrefget} + +\constfunc{T *}{get}{\void} + +Returns pointer to the tracked object or NULL. + + +\membersection{wxWeakRef::operator*}\label{wxweakrefoperatorreft} + +\constfunc{T \&}{operator*}{\void} + +Returns a reference to the tracked object. If the internal pointer is NULL +this method will cause an assert in debug mode. -Returns pointer to tracked object or NULL. \membersection{wxWeakRef::operator->}\label{wxweakrefoperatorderef} \func{T*}{operator->}{\void} -Returns pointer to tracked object or NULL. +Smart pointer member access. Returns a pointer to the +tracked object. If the internal pointer is NULL this +method will cause an assert in debug mode. + \membersection{wxWeakRef::operator=}\label{wxweakrefoperatorassign} \func{T* operator}{operator=}{\param{T* }{pobj}} -Assigns pointer to trackable object to this weak reference. - -\membersection{wxWeakRef::Assign}\label{wxweakrefassign} +Releases the currently tracked object and starts tracking {\it pobj}. +A weak reference may be reset by passing {\it NULL} as {\it pobj}. -\func{void}{Assign}{\param{T* }{pobj}} -This uses static\_cast if possible or dynamic\_cast otherwise. +\membersection{wxWeakRef::operator =}\label{wxweakrefoperatorassign2} -\membersection{wxWeakRef::GetTrackable}\label{wxweakrefgettrackable} +\func{T* operator}{operator =}{\param{wxWeakRef\& }{wr}} -\func{wxTrackableBase*}{GetTrackable}{\param{T* }{pobj}} +Release currently tracked object and start tracking the same object as +the wxWeakRef {\it wr}. -Returns the trackable objects to which the weak reference -points or NULL if it has been destroyed. \membersection{wxWeakRef::OnObjectDestroy}\label{wxweakrefonobjectdestroy} diff --git a/include/wx/weakref.h b/include/wx/weakref.h index 7d8ac8c5b9..a893ba4049 100644 --- a/include/wx/weakref.h +++ b/include/wx/weakref.h @@ -3,7 +3,7 @@ // Purpose: wxWeakRef - Generic weak references for wxWidgets // Author: Arne Steinarson // Created: 2007-12-27 -// RCS-ID: $Id:$ +// RCS-ID: $Id$ // Copyright: (c) 2007 Arne Steinarson // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -19,19 +19,42 @@ template class wxWeakRef : public wxTrackerNode { public: + typedef T element_type; + 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 * get() const + { + return m_pobj; + } + + T* operator->() + { + wxASSERT(m_pobj != NULL); + return m_pobj; + } + + T& operator*() const + { + wxASSERT(m_pobj != NULL); + return *m_pobj; + } + T* operator=(T *pobj) { Assign(pobj); return m_pobj; } + // Assign from another weak ref, point to same object + T* operator = (const wxWeakRef &wr) + { + Assign(wr); + return m_pobj; + } + virtual void OnObjectDestroy() { // Tracked object itself removes us from list of trackers @@ -39,16 +62,12 @@ public: 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); - } + friend class wxTrackableBase; + friend class wxEvtHandler; + virtual wxTrackerNodeType GetType() { return WeakRef; } + void Assign(T* pobj) { if ( m_pobj == pobj ) @@ -58,18 +77,28 @@ protected: if ( m_pobj ) { // Remove ourselves from object tracker list - GetTrackable(m_pobj)->RemoveNode(this); + // This does static_cast if available, otherwise it tries dynamic cast + wxTrackableBase *pt = wxTrackableCaster::value >::Cast(m_pobj); + wxASSERT(pt); + pt->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; + wxTrackableBase *pt = wxTrackableCaster::value >::Cast(pobj); + if( pt ) + { + pt->AddNode( this ); + m_pobj = pobj; + } + else + { + // If the tracked we want to track does not support wxTackableBase, then + // log a message and keep the NULL object pointer. + wxLogWarning( _T("wxWeakRef::Assign - Type does not provide wxTrackableBase - resetting tracked object") ); + } } } -- 2.45.2