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:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user