mirror of https://github.com/PCSX2/pcsx2.git
wxWidgets/MSW: Applied my custom string/object heap allocators to several more wxWidgets containers and types (helps reduce fragmentation and multi-threaded contention on the main heap).
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3100 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
4a2c5737c0
commit
6ec36fa37d
|
@ -13,8 +13,7 @@
|
||||||
#define _WX_BUFFER_H
|
#define _WX_BUFFER_H
|
||||||
|
|
||||||
#include "wx/wxchar.h"
|
#include "wx/wxchar.h"
|
||||||
|
#include "wx/msw/HeapAllocator.h"
|
||||||
#include <stdlib.h> // malloc() and free()
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Special classes for (wide) character strings: they use malloc/free instead
|
// Special classes for (wide) character strings: they use malloc/free instead
|
||||||
|
@ -31,13 +30,13 @@ public: \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
classname(size_t len) \
|
classname(size_t len) \
|
||||||
: m_str((chartype *)malloc((len + 1)*sizeof(chartype))) \
|
: m_str((chartype *)_allocHeap_wxString((len + 1)*sizeof(chartype))) \
|
||||||
{ \
|
{ \
|
||||||
m_str[len] = (chartype)0; \
|
m_str[len] = (chartype)0; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* no need to check for NULL, free() does it */ \
|
/* no need to check for NULL, free() does it */ \
|
||||||
~classname() { free(m_str); } \
|
~classname() { _freeHeap_wxString(m_str); } \
|
||||||
\
|
\
|
||||||
/* \
|
/* \
|
||||||
WARNING: \
|
WARNING: \
|
||||||
|
@ -66,7 +65,7 @@ public: \
|
||||||
\
|
\
|
||||||
void reset() \
|
void reset() \
|
||||||
{ \
|
{ \
|
||||||
free(m_str); \
|
_freeHeap_wxString(m_str); \
|
||||||
m_str = NULL; \
|
m_str = NULL; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
@ -77,14 +76,14 @@ public: \
|
||||||
\
|
\
|
||||||
classname& operator=(const chartype *str) \
|
classname& operator=(const chartype *str) \
|
||||||
{ \
|
{ \
|
||||||
free(m_str); \
|
_freeHeap_wxString(m_str); \
|
||||||
m_str = str ? strdupfunc(str) : NULL; \
|
m_str = str ? strdupfunc(str) : NULL; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
classname& operator=(const classname& src) \
|
classname& operator=(const classname& src) \
|
||||||
{ \
|
{ \
|
||||||
free(m_str); \
|
_freeHeap_wxString(m_str); \
|
||||||
m_str = src.release(); \
|
m_str = src.release(); \
|
||||||
\
|
\
|
||||||
return *this; \
|
return *this; \
|
||||||
|
@ -93,7 +92,7 @@ public: \
|
||||||
bool extend(size_t len) \
|
bool extend(size_t len) \
|
||||||
{ \
|
{ \
|
||||||
chartype * \
|
chartype * \
|
||||||
str = (chartype *)realloc(m_str, (len + 1)*sizeof(chartype)); \
|
str = (chartype *)_reallocHeap_wxString(m_str, (len + 1)*sizeof(chartype)); \
|
||||||
if ( !str ) \
|
if ( !str ) \
|
||||||
return false; \
|
return false; \
|
||||||
\
|
\
|
||||||
|
@ -124,14 +123,14 @@ public: \
|
||||||
}
|
}
|
||||||
#endif // wxABI_VERSION >= 20804
|
#endif // wxABI_VERSION >= 20804
|
||||||
|
|
||||||
DEFINE_BUFFER(wxCharBuffer, char, wxStrdupA);
|
DEFINE_BUFFER(wxCharBuffer, char, _mswHeap_Strdup);
|
||||||
#if wxABI_VERSION >= 20804
|
#if wxABI_VERSION >= 20804
|
||||||
DEFINE_WRITABLE_BUFFER(wxWritableCharBuffer, wxCharBuffer, char);
|
DEFINE_WRITABLE_BUFFER(wxWritableCharBuffer, wxCharBuffer, char);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if wxUSE_WCHAR_T
|
#if wxUSE_WCHAR_T
|
||||||
|
|
||||||
DEFINE_BUFFER(wxWCharBuffer, wchar_t, wxStrdupW);
|
DEFINE_BUFFER(wxWCharBuffer, wchar_t, _mswHeap_Strdup);
|
||||||
#if wxABI_VERSION >= 20804
|
#if wxABI_VERSION >= 20804
|
||||||
DEFINE_WRITABLE_BUFFER(wxWritableWCharBuffer, wxWCharBuffer, wchar_t);
|
DEFINE_WRITABLE_BUFFER(wxWritableWCharBuffer, wxWCharBuffer, wchar_t);
|
||||||
#endif
|
#endif
|
||||||
|
@ -173,10 +172,10 @@ public:
|
||||||
// everyting is private as it can only be used by wxMemoryBuffer
|
// everyting is private as it can only be used by wxMemoryBuffer
|
||||||
private:
|
private:
|
||||||
wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
|
wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
|
||||||
: m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0)
|
: m_data(size ? _allocHeap_wxObject(size) : NULL), m_size(size), m_len(0), m_ref(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
~wxMemoryBufferData() { free(m_data); }
|
~wxMemoryBufferData() { _freeHeap_wxObject(m_data); }
|
||||||
|
|
||||||
|
|
||||||
void ResizeIfNeeded(size_t newSize)
|
void ResizeIfNeeded(size_t newSize)
|
||||||
|
@ -184,10 +183,10 @@ private:
|
||||||
if (newSize > m_size)
|
if (newSize > m_size)
|
||||||
{
|
{
|
||||||
void *dataOld = m_data;
|
void *dataOld = m_data;
|
||||||
m_data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize);
|
m_data = _reallocHeap_wxObject(m_data, newSize + wxMemoryBufferData::DefBufSize);
|
||||||
if ( !m_data )
|
if ( !m_data )
|
||||||
{
|
{
|
||||||
free(dataOld);
|
_freeHeap_wxObject(dataOld);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_size = newSize + wxMemoryBufferData::DefBufSize;
|
m_size = newSize + wxMemoryBufferData::DefBufSize;
|
||||||
|
|
|
@ -113,7 +113,7 @@ private:
|
||||||
_WX_DECLARE_BASEARRAY_2(T, name, name##_Predicate, classexp)
|
_WX_DECLARE_BASEARRAY_2(T, name, name##_Predicate, classexp)
|
||||||
|
|
||||||
#define _WX_DECLARE_BASEARRAY_2(T, name, predicate, classexp) \
|
#define _WX_DECLARE_BASEARRAY_2(T, name, predicate, classexp) \
|
||||||
classexp name : public std::vector<T> \
|
classexp name : public std::vector< T,wxStringAllocator< T > > \
|
||||||
{ \
|
{ \
|
||||||
typedef predicate Predicate; \
|
typedef predicate Predicate; \
|
||||||
typedef predicate::CMPFUNC SCMPFUNC; \
|
typedef predicate::CMPFUNC SCMPFUNC; \
|
||||||
|
|
|
@ -174,10 +174,10 @@ private:
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
VC6_WORKAROUND(elT, liT, decl) \
|
VC6_WORKAROUND(elT, liT, decl) \
|
||||||
decl liT : public std::list<elT> \
|
decl liT : public std::list< elT, wxObjectAllocator< elT > > \
|
||||||
{ \
|
{ \
|
||||||
private: \
|
private: \
|
||||||
typedef std::list<elT> BaseListType; \
|
typedef std::list< elT, wxObjectAllocator< elT > > BaseListType; \
|
||||||
static BaseListType EmptyList; \
|
static BaseListType EmptyList; \
|
||||||
\
|
\
|
||||||
bool m_destroy; \
|
bool m_destroy; \
|
||||||
|
@ -187,7 +187,7 @@ private:
|
||||||
{ \
|
{ \
|
||||||
private: \
|
private: \
|
||||||
/* Workaround for broken VC6 nested class name resolution */ \
|
/* Workaround for broken VC6 nested class name resolution */ \
|
||||||
typedef std::list<elT>::iterator iterator; \
|
typedef std::list<elT, wxObjectAllocator< elT > >::iterator iterator; \
|
||||||
friend class liT; \
|
friend class liT; \
|
||||||
\
|
\
|
||||||
iterator m_iter; \
|
iterator m_iter; \
|
||||||
|
|
|
@ -1,30 +1,53 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
extern void _allocateHeap_wxString();
|
extern void _createHeap_wxString();
|
||||||
extern void _destroyHeap_wxString();
|
extern void _destroyHeap_wxString();
|
||||||
extern void* _allocHeap_wxString( size_t size );
|
extern void* _allocHeap_wxString( size_t size );
|
||||||
|
extern void* _reallocHeap_wxString( void* original, size_t size );
|
||||||
extern void _freeHeap_wxString( void* ptr );
|
extern void _freeHeap_wxString( void* ptr );
|
||||||
|
extern char* _mswHeap_Strdup( const char* src );
|
||||||
|
extern wchar_t* _mswHeap_Strdup( const wchar_t* src );
|
||||||
|
|
||||||
extern void _allocateHeap_wxObject();
|
|
||||||
|
extern void _createHeap_wxObject();
|
||||||
extern void _destroyHeap_wxObject();
|
extern void _destroyHeap_wxObject();
|
||||||
extern void* _allocHeap_wxObject( size_t size );
|
extern void* _allocHeap_wxObject( size_t size );
|
||||||
|
extern void* _reallocHeap_wxObject( void* original, size_t size );
|
||||||
extern void _freeHeap_wxObject( void* ptr );
|
extern void _freeHeap_wxObject( void* ptr );
|
||||||
|
|
||||||
|
// _pxDestroy_ uses microsoft's internal definition for _Destroy(), found in xmemory;
|
||||||
|
// which suppresses a warning that we otherwise get. The warning appears to be specific
|
||||||
|
// to MSVC, so a basic _MSC_VER define will hopefully do the trick to allow support to
|
||||||
|
// non-Micrsoft compilers.
|
||||||
|
template<class T> inline
|
||||||
|
void _pxDestroy_(T* _Ptr)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
_Destroy( _Ptr );
|
||||||
|
#else
|
||||||
|
(_Ptr)->~T();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// wxStringAllocator
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class wxStringAllocator
|
class wxStringAllocator
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
// typedefs
|
// typedefs
|
||||||
|
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
typedef value_type* pointer;
|
typedef value_type* pointer;
|
||||||
typedef const value_type* const_pointer;
|
typedef const value_type* const_pointer;
|
||||||
typedef value_type& reference;
|
typedef value_type& reference;
|
||||||
typedef const value_type& const_reference;
|
typedef const value_type& const_reference;
|
||||||
typedef std::size_t size_type;
|
typedef std::size_t size_type;
|
||||||
typedef std::ptrdiff_t difference_type;
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
|
||||||
public :
|
public :
|
||||||
// convert an allocator<T> to allocator<U>
|
// convert an allocator<T> to allocator<U>
|
||||||
|
@ -37,7 +60,7 @@ public :
|
||||||
public :
|
public :
|
||||||
wxStringAllocator()
|
wxStringAllocator()
|
||||||
{
|
{
|
||||||
_allocateHeap_wxString();
|
_createHeap_wxString();
|
||||||
}
|
}
|
||||||
|
|
||||||
~wxStringAllocator()
|
~wxStringAllocator()
|
||||||
|
@ -79,15 +102,14 @@ public :
|
||||||
// standard placement-new syntax to initialize the object:
|
// standard placement-new syntax to initialize the object:
|
||||||
void construct(pointer p, const T& t) { new(p) T(t); }
|
void construct(pointer p, const T& t) { new(p) T(t); }
|
||||||
// standard placement destructor:
|
// standard placement destructor:
|
||||||
void destroy(pointer p) { p->~T(); }
|
void destroy(pointer p) { _pxDestroy_(p); }
|
||||||
|
|
||||||
bool operator==(wxStringAllocator const&) { return true; }
|
bool operator==(wxStringAllocator const&) { return true; }
|
||||||
bool operator!=(wxStringAllocator const& a) { return !operator==(a); }
|
bool operator!=(wxStringAllocator const& a) { return !operator==(a); }
|
||||||
}; // end of class Allocator
|
}; // end of class Allocator
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
//
|
// wxObjectAllocator
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class wxObjectAllocator
|
class wxObjectAllocator
|
||||||
|
@ -95,13 +117,13 @@ class wxObjectAllocator
|
||||||
public :
|
public :
|
||||||
// typedefs
|
// typedefs
|
||||||
|
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
typedef value_type* pointer;
|
typedef value_type* pointer;
|
||||||
typedef const value_type* const_pointer;
|
typedef const value_type* const_pointer;
|
||||||
typedef value_type& reference;
|
typedef value_type& reference;
|
||||||
typedef const value_type& const_reference;
|
typedef const value_type& const_reference;
|
||||||
typedef std::size_t size_type;
|
typedef std::size_t size_type;
|
||||||
typedef std::ptrdiff_t difference_type;
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
|
||||||
public :
|
public :
|
||||||
// convert an allocator<T> to allocator<U>
|
// convert an allocator<T> to allocator<U>
|
||||||
|
@ -114,7 +136,7 @@ public :
|
||||||
public :
|
public :
|
||||||
wxObjectAllocator()
|
wxObjectAllocator()
|
||||||
{
|
{
|
||||||
_allocateHeap_wxObject();
|
_createHeap_wxObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
~wxObjectAllocator()
|
~wxObjectAllocator()
|
||||||
|
@ -155,8 +177,9 @@ public :
|
||||||
|
|
||||||
// standard placement-new syntax to initialize the object:
|
// standard placement-new syntax to initialize the object:
|
||||||
void construct(pointer p, const T& t) { new(p) T(t); }
|
void construct(pointer p, const T& t) { new(p) T(t); }
|
||||||
|
|
||||||
// standard placement destructor:
|
// standard placement destructor:
|
||||||
void destroy(pointer p) { p->~T(); }
|
void destroy(pointer p) { _pxDestroy_(p); }
|
||||||
|
|
||||||
bool operator==(wxObjectAllocator const&) { return true; }
|
bool operator==(wxObjectAllocator const&) { return true; }
|
||||||
bool operator!=(wxObjectAllocator const& a) { return !operator==(a); }
|
bool operator!=(wxObjectAllocator const& a) { return !operator==(a); }
|
||||||
|
|
|
@ -436,13 +436,13 @@ public:
|
||||||
#if wxUSE_PRIVATE_HEAP && defined(__WXMSW__)
|
#if wxUSE_PRIVATE_HEAP && defined(__WXMSW__)
|
||||||
void* operator new( size_t size, const wxChar * = NULL, int = 0 )
|
void* operator new( size_t size, const wxChar * = NULL, int = 0 )
|
||||||
{
|
{
|
||||||
_allocateHeap_wxObject();
|
_createHeap_wxObject();
|
||||||
return _allocHeap_wxObject( size );
|
return _allocHeap_wxObject( size );
|
||||||
}
|
}
|
||||||
|
|
||||||
void *operator new[] ( size_t size, const wxChar * = NULL, int = 0 )
|
void *operator new[] ( size_t size, const wxChar * = NULL, int = 0 )
|
||||||
{
|
{
|
||||||
_allocateHeap_wxObject();
|
_createHeap_wxObject();
|
||||||
return _allocHeap_wxObject( size );
|
return _allocHeap_wxObject( size );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,9 @@ wxStringInputStream::~wxStringInputStream()
|
||||||
{
|
{
|
||||||
#if wxUSE_UNICODE
|
#if wxUSE_UNICODE
|
||||||
// Note: wx[W]CharBuffer uses malloc()/free()
|
// Note: wx[W]CharBuffer uses malloc()/free()
|
||||||
free(m_buf);
|
// PCSX2 : wx[W]CharBuffer now uses the wxString local heap! --air
|
||||||
|
//free(m_buf);
|
||||||
|
_freeHeap_wxString(m_buf);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,7 +179,11 @@ bool wxTextFile::OnRead(const wxMBConv& conv)
|
||||||
}
|
}
|
||||||
#endif // wxUSE_UNICODE
|
#endif // wxUSE_UNICODE
|
||||||
|
|
||||||
free(buf.release()); // we don't need this memory any more
|
// we don't need this memory any more
|
||||||
|
// PCSX2 : So let's free it using the buffer object's API, instead of some idiotic
|
||||||
|
// low-level hack (bug found thanks to the use of custom heap allocation). --air
|
||||||
|
//free(buf.release());
|
||||||
|
buf.reset();
|
||||||
|
|
||||||
|
|
||||||
// now break the buffer in lines
|
// now break the buffer in lines
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
|
// HeapAllocator.cpp
|
||||||
|
//
|
||||||
|
// Copyright 2009-2010 by the PCSX Dev Team.
|
||||||
|
// (under whatever license is appropriate for this sort of hack, I guess).
|
||||||
|
//
|
||||||
|
// Provides a specialized heap for wxStrings, which helps keep the main heap from being
|
||||||
|
// excessively fragmented/cluttered by billions of micro-sized string allocations. This
|
||||||
|
// should also improve multithreaded performace since strings can be allocated in parallel
|
||||||
|
// with other "common" allocation tasks on other threads.
|
||||||
|
//
|
||||||
|
|
||||||
// For compilers that support precompilation, includes "wx.h".
|
// For compilers that support precompilation, includes "wx.h".
|
||||||
#include "wx/wxprec.h"
|
#include "wx/wxprec.h"
|
||||||
|
|
||||||
|
@ -26,7 +37,7 @@ static int win32_string_heap_refcount;
|
||||||
static HANDLE win32_object_heap = INVALID_HANDLE_VALUE;
|
static HANDLE win32_object_heap = INVALID_HANDLE_VALUE;
|
||||||
static int win32_object_heap_refcount;
|
static int win32_object_heap_refcount;
|
||||||
|
|
||||||
void _allocateHeap_wxString()
|
void _createHeap_wxString()
|
||||||
{
|
{
|
||||||
if( win32_string_heap == INVALID_HANDLE_VALUE )
|
if( win32_string_heap == INVALID_HANDLE_VALUE )
|
||||||
{
|
{
|
||||||
|
@ -45,13 +56,45 @@ void* _allocHeap_wxString( size_t size )
|
||||||
return (void*)HeapAlloc( win32_string_heap, 0, size );
|
return (void*)HeapAlloc( win32_string_heap, 0, size );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* _reallocHeap_wxString( void* original, size_t size )
|
||||||
|
{
|
||||||
|
if( !original )
|
||||||
|
return _allocHeap_wxString( size );
|
||||||
|
else
|
||||||
|
return (void*)HeapReAlloc( win32_string_heap, 0, original, size );
|
||||||
|
}
|
||||||
|
|
||||||
void _freeHeap_wxString( void* ptr )
|
void _freeHeap_wxString( void* ptr )
|
||||||
{
|
{
|
||||||
HeapFree( win32_string_heap, 0, ptr );
|
HeapFree( win32_string_heap, 0, ptr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _allocateHeap_wxObject()
|
char* _mswHeap_Strdup( const char* src )
|
||||||
|
{
|
||||||
|
if( !src ) return NULL;
|
||||||
|
const size_t len = strlen(src);
|
||||||
|
char* retval = (char*)_allocHeap_wxString( len+1 );
|
||||||
|
if( !retval ) return NULL;
|
||||||
|
memcpy( retval, src, len+1 );
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t* _mswHeap_Strdup( const wchar_t* src )
|
||||||
|
{
|
||||||
|
if( !src ) return NULL;
|
||||||
|
const size_t len = (wcslen(src) + 1) * sizeof(wchar_t);
|
||||||
|
wchar_t* retval = (wchar_t*)_allocHeap_wxString( len );
|
||||||
|
if( !retval ) return NULL;
|
||||||
|
memcpy( retval, src, len );
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void _createHeap_wxObject()
|
||||||
{
|
{
|
||||||
if( win32_object_heap == INVALID_HANDLE_VALUE )
|
if( win32_object_heap == INVALID_HANDLE_VALUE )
|
||||||
{
|
{
|
||||||
|
@ -70,6 +113,14 @@ void* _allocHeap_wxObject( size_t size )
|
||||||
return (void*)HeapAlloc( win32_object_heap, 0, size );
|
return (void*)HeapAlloc( win32_object_heap, 0, size );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* _reallocHeap_wxObject( void* original, size_t size )
|
||||||
|
{
|
||||||
|
if( !original )
|
||||||
|
return _allocHeap_wxObject( size );
|
||||||
|
else
|
||||||
|
return (void*)HeapReAlloc( win32_object_heap, 0, original, size );
|
||||||
|
}
|
||||||
|
|
||||||
void _freeHeap_wxObject( void* ptr )
|
void _freeHeap_wxObject( void* ptr )
|
||||||
{
|
{
|
||||||
HeapFree( win32_object_heap, 0, ptr );
|
HeapFree( win32_object_heap, 0, ptr );
|
||||||
|
|
Loading…
Reference in New Issue