X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/db7035e48a4ccc6265fa01949cb92db3c6b6c17f..f6669958924c3c3833e2932b65598b06073d2e65:/include/wx/weakref.h diff --git a/include/wx/weakref.h b/include/wx/weakref.h index 7d8ac8c5b9..e612db81b2 100644 --- a/include/wx/weakref.h +++ b/include/wx/weakref.h @@ -2,8 +2,8 @@ // Name: wx/weakref.h // Purpose: wxWeakRef - Generic weak references for wxWidgets // Author: Arne Steinarson -// Created: 2007-12-27 -// RCS-ID: $Id:$ +// Created: 27 Dec 07 +// RCS-ID: $Id$ // Copyright: (c) 2007 Arne Steinarson // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -11,77 +11,341 @@ #ifndef _WX_WEAKREF_H_ #define _WX_WEAKREF_H_ -#include +#include "wx/tracker.h" -// 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 + +// Some compilers (VC6, Borland, g++ < 3.3) have problem with template specialization. +// However, this is only used for optimization purposes (a smaller wxWeakRef pointer) +// (and the corner case of wxWeakRef). So for those compilers, we can fall +// back to the non-optimal case, where we use the same type of weak ref (static one) +// in all cases. See defs.h for various setting these defines depending on compiler. + +#if !defined(HAVE_PARTIAL_SPECIALIZATION) || \ + !defined(HAVE_TEMPLATE_OVERLOAD_RESOLUTION) || \ + (defined(__GNUC__) && !wxCHECK_GCC_VERSION(3, 3)) + #define USE_ONLY_STATIC_WEAKREF +#endif + + +#ifndef USE_ONLY_STATIC_WEAKREF + +// Avoid including this for simpler compilers +#include "wx/meta/convertible.h" +#include "wx/meta/int2type.h" + +template +struct wxIsStaticTrackable { -public: - wxWeakRef(T *pobj = NULL) : m_pobj(NULL) { Assign(pobj); } + enum { value = wxConvertibleTo::value }; +}; - virtual ~wxWeakRef() { Assign(NULL); } +#endif // !USE_ONLY_STATIC_WEAKREF - // Smart pointer functions - operator T*(){ return m_pobj; } - T* operator->(){ return m_pobj; } - T* operator=(T *pobj) + +// Weak ref implementation when T has wxTrackable as a known base class +template +class wxWeakRefStatic : public wxTrackerNode +{ +public: + wxWeakRefStatic() : m_pobj(NULL) { } + + void Release() { - Assign(pobj); - return m_pobj; + // Release old object if any + if ( m_pobj ) + { + // Remove ourselves from object tracker list + wxTrackable *pt = static_cast(m_pobj); + pt->RemoveNode(this); + m_pobj = NULL; + } } virtual void OnObjectDestroy() { // Tracked object itself removes us from list of trackers - wxASSERT( m_pobj ); + wxASSERT(m_pobj != NULL); 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 + Release(); + + // Now set new trackable object + if ( pobj ) + { + // Add ourselves to object tracker list + wxTrackable *pt = static_cast(pobj); + pt->AddNode(this); + m_pobj = pobj; + } + } + + void AssignCopy(const wxWeakRefStatic& wr) + { + Assign( wr.m_pobj ); + } + + T *m_pobj; +}; + + + +#ifndef USE_ONLY_STATIC_WEAKREF + +template +struct wxWeakRefImpl; + +// Intermediate class, to select the static case above. +template +struct wxWeakRefImpl : public wxWeakRefStatic +{ + enum { value = 1 }; +}; + +// Weak ref implementation when T does not have wxTrackable as known base class +template +struct wxWeakRefImpl : public wxTrackerNode +{ + void Release() + { + // Release old object if any if ( m_pobj ) { // Remove ourselves from object tracker list - GetTrackable(m_pobj)->RemoveNode(this); + m_ptbase->RemoveNode(this); m_pobj = NULL; + m_ptbase = NULL; } + } - // Now set new trackable object - if ( pobj ) + virtual void OnObjectDestroy() + { + // Tracked object itself removes us from list of trackers + wxASSERT(m_pobj != NULL); + m_pobj = NULL; + m_ptbase = NULL; + } + +protected: + wxWeakRefImpl() : m_pobj(NULL), m_ptbase(NULL) { } + + // Assign receives most derived class here and can use that + template + void Assign( TDerived* pobj ) + { + AssignHelper( pobj, wxInt2Type::value>() ); + } + + template + void AssignHelper(TDerived* pobj, wxInt2Type) + { + wxTrackable *ptbase = static_cast(pobj); + DoAssign( pobj, ptbase ); + } + +#ifndef wxNO_RTTI + void AssignHelper(T* pobj, wxInt2Type) + { + // A last way to get a trackable pointer + wxTrackable *ptbase = dynamic_cast(pobj); + if ( ptbase ) { - wxTrackableBase * const pt = GetTrackable(pobj); - wxCHECK_RET( pt, "type must derive from wxTrackableBase" ); + DoAssign( pobj, ptbase ); + } + else + { + wxFAIL_MSG( "Tracked class should inherit from wxTrackable" ); - pt->AddNode(this); + Release(); + } + } +#endif // RTTI enabled + + void AssignCopy(const wxWeakRefImpl& wr) + { + DoAssign(wr.m_pobj, wr.m_ptbase); + } + + void DoAssign( T* pobj, wxTrackable *ptbase ) { + if( m_pobj==pobj ) return; + Release(); + + // Now set new trackable object + if( pobj ) + { + // Add ourselves to object tracker list + wxASSERT( ptbase ); + ptbase->AddNode( this ); m_pobj = pobj; + m_ptbase = ptbase; + } + } + + T *m_pobj; + wxTrackable *m_ptbase; +}; + +#endif // #ifndef USE_ONLY_STATIC_WEAKREF + + + +// A weak reference to an object of type T, where T has base wxTrackable +// (usually statically but if not dynamic_cast<> is tried). +template +class wxWeakRef : public +#ifdef USE_ONLY_STATIC_WEAKREF + wxWeakRefStatic +#else + wxWeakRefImpl::value != 0> +#endif +{ +public: + typedef T element_type; + + // Default ctor + wxWeakRef() { } + + // Enabling this ctor for VC6 results in mysterious compilation failures in + // wx/window.h when assigning wxWindow pointers (FIXME-VC6) +#ifndef __VISUALC6__ + // Ctor from the object of this type: this is needed as the template ctor + // below is not used by at least g++4 when a literal NULL is used + wxWeakRef(T *pobj) + { + this->Assign(pobj); + } +#endif // !__VISUALC6__ + + // When we have the full type here, static_cast<> will always work + // (or give a straight compiler error). + template + wxWeakRef(TDerived* pobj) + { + this->Assign(pobj); + } + + // We need this copy ctor, since otherwise a default compiler (binary) copy + // happens (if embedded as an object member). + wxWeakRef(const wxWeakRef& wr) + { + this->Assign(wr.get()); + } + + wxWeakRef& operator=(const wxWeakRef& wr) + { + this->AssignCopy(wr); + return *this; + } + + virtual ~wxWeakRef() { this->Release(); } + + // Smart pointer functions + T& operator*() const { return *this->m_pobj; } + T* operator->() const { return this->m_pobj; } + + T* get() const { return this->m_pobj; } + operator T*() const { return this->m_pobj; } +}; + + +#ifndef wxNO_RTTI + +// Weak ref implementation assign objects are queried for wxTrackable +// using dynamic_cast<> +template +class wxWeakRefDynamic : public wxTrackerNode +{ +public: + wxWeakRefDynamic() : m_pobj(NULL) { } + + wxWeakRefDynamic(T* pobj) : m_pobj(pobj) + { + Assign(pobj); + } + + wxWeakRefDynamic(const wxWeakRef& wr) + { + Assign(wr.get()); + } + + virtual ~wxWeakRefDynamic() { Release(); } + + // Smart pointer functions + T& operator*() const { wxASSERT(m_pobj); return *m_pobj; } + T* operator->() const { wxASSERT(m_pobj); return m_pobj; } + + T* get() const { return m_pobj; } + operator T* () const { 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.get() ); return m_pobj; } + + void Release() + { + // Release old object if any + if( m_pobj ) + { + // Remove ourselves from object tracker list + wxTrackable *pt = dynamic_cast(m_pobj); + wxASSERT(pt); + pt->RemoveNode(this); + m_pobj = NULL; + } + } + + virtual void OnObjectDestroy() + { + wxASSERT_MSG(m_pobj, "tracked object should have removed us itself"); + + m_pobj = NULL; + } + +protected: + void Assign(T *pobj) + { + if ( m_pobj == pobj ) + return; + + Release(); + + // Now set new trackable object + if ( pobj ) + { + // Add ourselves to object tracker list + wxTrackable *pt = dynamic_cast(pobj); + if ( pt ) + { + pt->AddNode(this); + m_pobj = pobj; + } + else + { + // If the object we want to track does not support wxTackable, then + // log a message and keep the NULL object pointer. + wxFAIL_MSG( "Tracked class should inherit from wxTrackable" ); + } } } T *m_pobj; }; +#endif // RTTI enabled + + // 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;