From 4a11340a1c93bb8466ac097ba15a756275067b6a Mon Sep 17 00:00:00 2001 From: Robert Roebling Date: Sat, 17 Feb 2007 09:16:35 +0000 Subject: [PATCH] [1660792 ] wxObject::Dec/IncRef and wxObjectDataPtr git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@44521 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/object.tex | 29 +++++++++++++--- include/wx/object.h | 74 ++++++++++++++++++++++++++++++++++++++-- src/common/object.cpp | 16 +++++++-- 3 files changed, 110 insertions(+), 9 deletions(-) diff --git a/docs/latex/wx/object.tex b/docs/latex/wx/object.tex index e5999513cd..0e2c9d9cf1 100644 --- a/docs/latex/wx/object.tex +++ b/docs/latex/wx/object.tex @@ -202,6 +202,10 @@ The {\it delete} operator is defined for debugging versions of the library only, the identifier \_\_WXDEBUG\_\_ is defined. It takes over memory deallocation, allowing wxDebugContext operations. + + +%% wxObjectRefData + \section{\class{wxObjectRefData}}\label{wxobjectrefdata} This class is used to store reference-counted data. Derive classes from this to @@ -223,19 +227,36 @@ you will need to cast to your own derived class. \func{}{wxObjectRefData}{\void} -Default constructor. Initialises the {\bf m\_count} member to 1. +Default constructor. Initialises the internal reference count to 1. \membersection{wxObjectRefData::\destruct{wxObjectRefData}}\label{wxobjectrefdatadtor} \func{}{wxObjectRefData}{\void} -Destructor. +Destructor. It's declared {\tt protected} so that wxObjectRefData instances will never +be destroyed directly but only as result of a \helpref{DecRef}{wxobjectrefdatadecref} call. \membersection{wxObjectRefData::GetRefCount}\label{wxobjectrefdatagetrefcount} \constfunc{int}{GetRefCount}{\void} Returns the reference count associated with this shared data. -When this goes to zero during a \helpref{wxObject::UnRef}{wxobjectunref}, an object -can delete this {\bf wxObjectRefData} object. +When this goes to zero during a \helpref{DecRef}{wxobjectrefdatadecref} call, the object +will auto-free itself. + +\membersection{wxObjectRefData::DecRef}\label{wxobjectrefdatadecref} + +\func{void}{DecRef}{\void} + +Decrements the reference count associated with this shared data and, if it reaches zero, +destroys this instance of wxObjectRefData releasing its memory. + +Please note that after calling this function, the caller should absolutely avoid to use +the pointer to this instance since it may not be valid anymore. + +\membersection{wxObjectRefData::IncRef}\label{wxobjectrefdataincref} + +\func{void}{IncRef}{\void} + +Increments the reference count associated with this shared data. diff --git a/include/wx/object.h b/include/wx/object.h index f9d9f2be9b..9651bf9b84 100644 --- a/include/wx/object.h +++ b/include/wx/object.h @@ -392,14 +392,83 @@ class WXDLLIMPEXP_BASE wxObjectRefData public: wxObjectRefData() : m_count(1) { } - virtual ~wxObjectRefData() { } int GetRefCount() const { return m_count; } + void IncRef() { m_count++; } + void DecRef(); + +protected: + // this object should never be destroyed directly but only as a + // result of a DecRef() call: + virtual ~wxObjectRefData() { } + private: + // our refcount: int m_count; }; +// ---------------------------------------------------------------------------- +// wxObjectDataPtr: helper class to avoid memleaks because of missing calls +// to wxObjectRefData::DecRef +// ---------------------------------------------------------------------------- + +template +class wxObjectDataPtr +{ +public: + typedef T element_type; + + wxEXPLICIT wxObjectDataPtr(T *ptr = NULL) : m_ptr(ptr) {} + + // copy ctor + wxObjectDataPtr(const wxObjectDataPtr &tocopy) + : m_ptr(tocopy.m_ptr) + { + if (m_ptr) + m_ptr->IncRef(); + } + + ~wxObjectDataPtr() + { + if (m_ptr) + m_ptr->DecRef(); + } + + T *get() const { return m_ptr; } + T *operator->() const { return get(); } + + void reset(T *ptr) + { + if (m_ptr) + m_ptr->DecRef(); + m_ptr = ptr; + } + + wxObjectDataPtr& operator=(const wxObjectDataPtr &tocopy) + { + if (m_ptr) + m_ptr->DecRef(); + m_ptr = tocopy.m_ptr; + if (m_ptr) + m_ptr->IncRef(); + return *this; + } + + wxObjectDataPtr& operator=(T *ptr) + { + if (m_ptr) + m_ptr->DecRef(); + m_ptr = ptr; + if (m_ptr) + m_ptr->IncRef(); + return *this; + } + +private: + T *m_ptr; +}; + // ---------------------------------------------------------------------------- // wxObject: the root class of wxWidgets object hierarchy // ---------------------------------------------------------------------------- @@ -520,7 +589,8 @@ public: #ifdef _MSC_VER return (wxClassInfo*) m_classInfo; #else - return wx_const_cast(wxClassInfo *, m_classInfo); + wxDynamicClassInfo *nonconst = wx_const_cast(wxDynamicClassInfo *, m_classInfo); + return wx_static_cast(wxClassInfo *, nonconst); #endif } diff --git a/src/common/object.cpp b/src/common/object.cpp index 0a77aab57b..0289fc2ec6 100644 --- a/src/common/object.cpp +++ b/src/common/object.cpp @@ -289,6 +289,17 @@ wxObject *wxCreateDynamicObject(const wxChar *name) } +// ---------------------------------------------------------------------------- +// wxObjectRefData +// ---------------------------------------------------------------------------- + +void wxObjectRefData::DecRef() +{ + if ( --m_count == 0 ) + delete this; +} + + // ---------------------------------------------------------------------------- // wxObject // ---------------------------------------------------------------------------- @@ -310,7 +321,7 @@ void wxObject::Ref(const wxObject& clone) if ( clone.m_refData ) { m_refData = clone.m_refData; - ++(m_refData->m_count); + m_refData->IncRef(); } } @@ -320,8 +331,7 @@ void wxObject::UnRef() { wxASSERT_MSG( m_refData->m_count > 0, _T("invalid ref data count") ); - if ( --m_refData->m_count == 0 ) - delete m_refData; + m_refData->DecRef(); m_refData = NULL; } } -- 2.45.2