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.
*/
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<typename T>
wxAnyValueTypeImpl<T>* wxAnyValueTypeImpl<T>::sm_instance =
new wxAnyValueTypeImpl<T>();
wxAnyValueTypeScopedPtr wxAnyValueTypeImpl<T>::sm_instance = new wxAnyValueTypeImpl<T>();
//
@@ -702,19 +728,19 @@ public:
template<typename T>
wxAny(const T& value)
{
m_type = wxAnyValueTypeImpl<T>::sm_instance;
m_type = wxAnyValueTypeImpl<T>::sm_instance.get();
wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
}
// These two constructors are needed to deal with string literals
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);
}
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);
}
@@ -789,7 +815,7 @@ public:
wxAny& operator=(const T &value)
{
m_type->DeleteValue(m_buffer);
m_type = wxAnyValueTypeImpl<T>::sm_instance;
m_type = wxAnyValueTypeImpl<T>::sm_instance.get();
wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
return *this;
}
@@ -938,7 +964,7 @@ public:
if ( !wxAnyValueTypeImpl<T>::IsSameClass(m_type) )
{
wxAnyValueType* otherType =
wxAnyValueTypeImpl<T>::sm_instance;
wxAnyValueTypeImpl<T>::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<wxVariantData*>::sm_instance;
m_type = wxAnyValueTypeImpl<wxVariantData*>::sm_instance.get();
wxAnyValueTypeImpl<wxVariantData*>::SetValue(data, m_buffer);
}
}
@@ -1005,7 +1031,7 @@ private:
void Assign(const T &value)
{
m_type->DeleteValue(m_buffer);
m_type = wxAnyValueTypeImpl<T>::sm_instance;
m_type = wxAnyValueTypeImpl<T>::sm_instance.get();
wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
}

View File

@@ -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<wxAnyToVariantRegistration*> 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