From: Jaakko Salli Date: Fri, 30 Apr 2010 13:32:41 +0000 (+0000) Subject: Use scoped ptrs to managed wxAnyValueType instances. This fixes deallocation issues... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/0cc226ad756817bb711fb882f28e3a308f262687 Use scoped ptrs to managed wxAnyValueType instances. This fixes deallocation issues in some dynamic library use cases. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64179 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/any.h b/include/wx/any.h index b5dac8fb7c..2a1bf7142a 100644 --- a/include/wx/any.h +++ b/include/wx/any.h @@ -56,7 +56,9 @@ public: /** Default constructor. */ - wxAnyValueType(); + wxAnyValueType() + { + } /** Destructor. @@ -114,6 +116,26 @@ public: private: }; + +// +// We need to allocate wxAnyValueType instances in heap, and need to use +// scoped ptr to properly deallocate them in dynamic library use cases. +// Here we have a minimal specialized scoped ptr implementation to deal +// with various compiler-specific problems with template class' static +// member variable of template type with explicit constructor which +// is initialized in global scope. +// +class wxAnyValueTypeScopedPtr +{ +public: + wxAnyValueTypeScopedPtr(wxAnyValueType* ptr) : m_ptr(ptr) { } + ~wxAnyValueTypeScopedPtr() { delete m_ptr; } + wxAnyValueType* get() const { return m_ptr; } +private: + wxAnyValueType* m_ptr; +}; + + // // This method of checking the type is compatible with VC6 #define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) \ @@ -127,6 +149,11 @@ private: facilitate sub-type system which allows, for instance, wxAny with signed short '15' to be treated equal to wxAny with signed long long '15'. Having sm_instance is important here. + + NB: We really need to have wxAnyValueType instances allocated + in heap. They are stored as static template member variables, + and with them we just can't be too careful (eg. not allocating + them in heap broke the type identification in GCC). */ #define WX_DECLARE_ANY_VALUE_TYPE(CLS) \ friend class wxAny; \ @@ -134,23 +161,23 @@ private: public: \ static bool IsSameClass(const wxAnyValueType* otherType) \ { \ - return wxTypeId(*sm_instance) == wxTypeId(*otherType); \ + return wxTypeId(*sm_instance.get()) == wxTypeId(*otherType); \ } \ virtual bool IsSameType(const wxAnyValueType* otherType) const \ { \ return IsSameClass(otherType); \ } \ private: \ - static CLS* sm_instance; \ + static wxAnyValueTypeScopedPtr sm_instance; \ public: \ static wxAnyValueType* GetInstance() \ { \ - return sm_instance; \ + return sm_instance.get(); \ } #define WX_IMPLEMENT_ANY_VALUE_TYPE(CLS) \ - CLS* CLS::sm_instance = new CLS(); +wxAnyValueTypeScopedPtr CLS::sm_instance(new CLS()); #ifdef __VISUALC6__ @@ -309,8 +336,7 @@ public: }; template -wxAnyValueTypeImpl* wxAnyValueTypeImpl::sm_instance = - new wxAnyValueTypeImpl(); +wxAnyValueTypeScopedPtr wxAnyValueTypeImpl::sm_instance = new wxAnyValueTypeImpl(); // @@ -702,19 +728,19 @@ public: template wxAny(const T& value) { - m_type = wxAnyValueTypeImpl::sm_instance; + m_type = wxAnyValueTypeImpl::sm_instance.get(); wxAnyValueTypeImpl::SetValue(value, m_buffer); } // These two constructors are needed to deal with string literals wxAny(const char* value) { - m_type = wxAnyValueTypeImpl::sm_instance; + m_type = wxAnyValueTypeImpl::sm_instance.get(); wxAnyValueTypeImpl::SetValue(value, m_buffer); } wxAny(const wchar_t* value) { - m_type = wxAnyValueTypeImpl::sm_instance; + m_type = wxAnyValueTypeImpl::sm_instance.get(); wxAnyValueTypeImpl::SetValue(value, m_buffer); } @@ -789,7 +815,7 @@ public: wxAny& operator=(const T &value) { m_type->DeleteValue(m_buffer); - m_type = wxAnyValueTypeImpl::sm_instance; + m_type = wxAnyValueTypeImpl::sm_instance.get(); wxAnyValueTypeImpl::SetValue(value, m_buffer); return *this; } @@ -938,7 +964,7 @@ public: if ( !wxAnyValueTypeImpl::IsSameClass(m_type) ) { wxAnyValueType* otherType = - wxAnyValueTypeImpl::sm_instance; + wxAnyValueTypeImpl::sm_instance.get(); wxAnyValueBuffer temp_buf; if ( !m_type->ConvertValue(m_buffer, otherType, temp_buf) ) @@ -995,7 +1021,7 @@ private: else { // If everything else fails, wrap the whole wxVariantData - m_type = wxAnyValueTypeImpl::sm_instance; + m_type = wxAnyValueTypeImpl::sm_instance.get(); wxAnyValueTypeImpl::SetValue(data, m_buffer); } } @@ -1005,7 +1031,7 @@ private: void Assign(const T &value) { m_type->DeleteValue(m_buffer); - m_type = wxAnyValueTypeImpl::sm_instance; + m_type = wxAnyValueTypeImpl::sm_instance.get(); wxAnyValueTypeImpl::SetValue(value, m_buffer); } diff --git a/src/common/any.cpp b/src/common/any.cpp index 79aed46067..5136577dc5 100644 --- a/src/common/any.cpp +++ b/src/common/any.cpp @@ -32,33 +32,21 @@ using namespace wxPrivate; +#if wxUSE_VARIANT + //------------------------------------------------------------------------- // wxAnyValueTypeGlobals //------------------------------------------------------------------------- -#if wxUSE_VARIANT - WX_DECLARE_HASH_MAP(wxAnyValueType*, wxVariantDataFactory, wxPointerHash, wxPointerEqual, wxAnyTypeToVariantDataFactoryMap); -#endif - -WX_DECLARE_HASH_SET(wxAnyValueType*, - wxPointerHash, - wxPointerEqual, - wxAnyValueTypePtrSet); - -// -// Helper class to manage wxAnyValueType instances and and other -// related global variables (such as wxAny<->wxVariant type association). // -// NB: We really need to have wxAnyValueType instances allocated -// in heap. They are stored as static template member variables, -// and with them we just can't be too careful (eg. not allocating -// them in heap broke the type identification in GCC). +// Helper class to manage global variables related to type conversion +// between wxAny and wxVariant. // class wxAnyValueTypeGlobals { @@ -68,26 +56,9 @@ public: } ~wxAnyValueTypeGlobals() { - #if wxUSE_VARIANT m_anyToVariant.clear(); - #endif - - wxAnyValueTypePtrSet::iterator it; - for ( it = m_valueTypes.begin(); it != m_valueTypes.end(); ++it ) - { - delete *it; - } - } - - void RegisterValueType(wxAnyValueType* valueType) - { - // Let's store value types in set to prevent deleting the same object - // several times (it may be possible, under certain conditions, that - // the same wxAnyValueType instance gets registered twice) - m_valueTypes.insert(valueType); } -#if wxUSE_VARIANT void PreRegisterAnyToVariant(wxAnyToVariantRegistration* reg) { m_anyToVariantRegs.push_back(reg); @@ -144,19 +115,14 @@ public: // Nothing found return NULL; } -#endif private: - wxAnyValueTypePtrSet m_valueTypes; -#if wxUSE_VARIANT wxAnyTypeToVariantDataFactoryMap m_anyToVariant; wxVector m_anyToVariantRegs; -#endif }; static wxAnyValueTypeGlobals* g_wxAnyValueTypeGlobals = NULL; -#if wxUSE_VARIANT WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData) @@ -239,8 +205,6 @@ bool wxConvertAnyToVariant(const wxAny& any, wxVariant* variant) return true; } -#endif // wxUSE_VARIANT - // // This class is to make sure that wxAnyValueType instances // etc. get freed correctly. We must use a separate wxAnyValueTypeGlobals @@ -267,18 +231,8 @@ private: IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager, wxModule) +#endif // wxUSE_VARIANT -//------------------------------------------------------------------------- -// wxAnyValueType -//------------------------------------------------------------------------- - -wxAnyValueType::wxAnyValueType() -{ - if ( !g_wxAnyValueTypeGlobals ) - g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals(); - - g_wxAnyValueTypeGlobals->RegisterValueType(this); -} //------------------------------------------------------------------------- // Dynamic conversion member functions