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
This commit is contained in:
Jaakko Salli
2010-04-30 13:32:41 +00:00
parent e5e5b843dd
commit 0cc226ad75
2 changed files with 45 additions and 65 deletions

View File

@@ -56,7 +56,9 @@ public:
/** /**
Default constructor. Default constructor.
*/ */
wxAnyValueType(); wxAnyValueType()
{
}
/** /**
Destructor. Destructor.
@@ -114,6 +116,26 @@ public:
private: 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 // This method of checking the type is compatible with VC6
#define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) \ #define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) \
@@ -127,6 +149,11 @@ private:
facilitate sub-type system which allows, for instance, wxAny with facilitate sub-type system which allows, for instance, wxAny with
signed short '15' to be treated equal to wxAny with signed long long '15'. signed short '15' to be treated equal to wxAny with signed long long '15'.
Having sm_instance is important here. 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) \ #define WX_DECLARE_ANY_VALUE_TYPE(CLS) \
friend class wxAny; \ friend class wxAny; \
@@ -134,23 +161,23 @@ private:
public: \ public: \
static bool IsSameClass(const wxAnyValueType* otherType) \ 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 \ virtual bool IsSameType(const wxAnyValueType* otherType) const \
{ \ { \
return IsSameClass(otherType); \ return IsSameClass(otherType); \
} \ } \
private: \ private: \
static CLS* sm_instance; \ static wxAnyValueTypeScopedPtr sm_instance; \
public: \ public: \
static wxAnyValueType* GetInstance() \ static wxAnyValueType* GetInstance() \
{ \ { \
return sm_instance; \ return sm_instance.get(); \
} }
#define WX_IMPLEMENT_ANY_VALUE_TYPE(CLS) \ #define WX_IMPLEMENT_ANY_VALUE_TYPE(CLS) \
CLS* CLS::sm_instance = new CLS(); wxAnyValueTypeScopedPtr CLS::sm_instance(new CLS());
#ifdef __VISUALC6__ #ifdef __VISUALC6__
@@ -309,8 +336,7 @@ public:
}; };
template<typename T> template<typename T>
wxAnyValueTypeImpl<T>* wxAnyValueTypeImpl<T>::sm_instance = wxAnyValueTypeScopedPtr wxAnyValueTypeImpl<T>::sm_instance = new wxAnyValueTypeImpl<T>();
new wxAnyValueTypeImpl<T>();
// //
@@ -702,19 +728,19 @@ public:
template<typename T> template<typename T>
wxAny(const T& value) wxAny(const T& value)
{ {
m_type = wxAnyValueTypeImpl<T>::sm_instance; m_type = wxAnyValueTypeImpl<T>::sm_instance.get();
wxAnyValueTypeImpl<T>::SetValue(value, m_buffer); wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
} }
// These two constructors are needed to deal with string literals // These two constructors are needed to deal with string literals
wxAny(const char* value) wxAny(const char* value)
{ {
m_type = wxAnyValueTypeImpl<const char*>::sm_instance; m_type = wxAnyValueTypeImpl<const char*>::sm_instance.get();
wxAnyValueTypeImpl<const char*>::SetValue(value, m_buffer); wxAnyValueTypeImpl<const char*>::SetValue(value, m_buffer);
} }
wxAny(const wchar_t* value) wxAny(const wchar_t* value)
{ {
m_type = wxAnyValueTypeImpl<const wchar_t*>::sm_instance; m_type = wxAnyValueTypeImpl<const wchar_t*>::sm_instance.get();
wxAnyValueTypeImpl<const wchar_t*>::SetValue(value, m_buffer); wxAnyValueTypeImpl<const wchar_t*>::SetValue(value, m_buffer);
} }
@@ -789,7 +815,7 @@ public:
wxAny& operator=(const T &value) wxAny& operator=(const T &value)
{ {
m_type->DeleteValue(m_buffer); m_type->DeleteValue(m_buffer);
m_type = wxAnyValueTypeImpl<T>::sm_instance; m_type = wxAnyValueTypeImpl<T>::sm_instance.get();
wxAnyValueTypeImpl<T>::SetValue(value, m_buffer); wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
return *this; return *this;
} }
@@ -938,7 +964,7 @@ public:
if ( !wxAnyValueTypeImpl<T>::IsSameClass(m_type) ) if ( !wxAnyValueTypeImpl<T>::IsSameClass(m_type) )
{ {
wxAnyValueType* otherType = wxAnyValueType* otherType =
wxAnyValueTypeImpl<T>::sm_instance; wxAnyValueTypeImpl<T>::sm_instance.get();
wxAnyValueBuffer temp_buf; wxAnyValueBuffer temp_buf;
if ( !m_type->ConvertValue(m_buffer, otherType, temp_buf) ) if ( !m_type->ConvertValue(m_buffer, otherType, temp_buf) )
@@ -995,7 +1021,7 @@ private:
else else
{ {
// If everything else fails, wrap the whole wxVariantData // If everything else fails, wrap the whole wxVariantData
m_type = wxAnyValueTypeImpl<wxVariantData*>::sm_instance; m_type = wxAnyValueTypeImpl<wxVariantData*>::sm_instance.get();
wxAnyValueTypeImpl<wxVariantData*>::SetValue(data, m_buffer); wxAnyValueTypeImpl<wxVariantData*>::SetValue(data, m_buffer);
} }
} }
@@ -1005,7 +1031,7 @@ private:
void Assign(const T &value) void Assign(const T &value)
{ {
m_type->DeleteValue(m_buffer); m_type->DeleteValue(m_buffer);
m_type = wxAnyValueTypeImpl<T>::sm_instance; m_type = wxAnyValueTypeImpl<T>::sm_instance.get();
wxAnyValueTypeImpl<T>::SetValue(value, m_buffer); wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
} }

View File

@@ -32,33 +32,21 @@
using namespace wxPrivate; using namespace wxPrivate;
#if wxUSE_VARIANT
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// wxAnyValueTypeGlobals // wxAnyValueTypeGlobals
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
#if wxUSE_VARIANT
WX_DECLARE_HASH_MAP(wxAnyValueType*, WX_DECLARE_HASH_MAP(wxAnyValueType*,
wxVariantDataFactory, wxVariantDataFactory,
wxPointerHash, wxPointerHash,
wxPointerEqual, wxPointerEqual,
wxAnyTypeToVariantDataFactoryMap); wxAnyTypeToVariantDataFactoryMap);
#endif
WX_DECLARE_HASH_SET(wxAnyValueType*,
wxPointerHash,
wxPointerEqual,
wxAnyValueTypePtrSet);
// //
// Helper class to manage wxAnyValueType instances and and other // Helper class to manage global variables related to type conversion
// related global variables (such as wxAny<->wxVariant type association). // between wxAny and wxVariant.
//
// 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).
// //
class wxAnyValueTypeGlobals class wxAnyValueTypeGlobals
{ {
@@ -68,26 +56,9 @@ public:
} }
~wxAnyValueTypeGlobals() ~wxAnyValueTypeGlobals()
{ {
#if wxUSE_VARIANT
m_anyToVariant.clear(); 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) void PreRegisterAnyToVariant(wxAnyToVariantRegistration* reg)
{ {
m_anyToVariantRegs.push_back(reg); m_anyToVariantRegs.push_back(reg);
@@ -144,19 +115,14 @@ public:
// Nothing found // Nothing found
return NULL; return NULL;
} }
#endif
private: private:
wxAnyValueTypePtrSet m_valueTypes;
#if wxUSE_VARIANT
wxAnyTypeToVariantDataFactoryMap m_anyToVariant; wxAnyTypeToVariantDataFactoryMap m_anyToVariant;
wxVector<wxAnyToVariantRegistration*> m_anyToVariantRegs; wxVector<wxAnyToVariantRegistration*> m_anyToVariantRegs;
#endif
}; };
static wxAnyValueTypeGlobals* g_wxAnyValueTypeGlobals = NULL; static wxAnyValueTypeGlobals* g_wxAnyValueTypeGlobals = NULL;
#if wxUSE_VARIANT
WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData) WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData)
@@ -239,8 +205,6 @@ bool wxConvertAnyToVariant(const wxAny& any, wxVariant* variant)
return true; return true;
} }
#endif // wxUSE_VARIANT
// //
// This class is to make sure that wxAnyValueType instances // This class is to make sure that wxAnyValueType instances
// etc. get freed correctly. We must use a separate wxAnyValueTypeGlobals // etc. get freed correctly. We must use a separate wxAnyValueTypeGlobals
@@ -267,18 +231,8 @@ private:
IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager, wxModule) 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 // Dynamic conversion member functions