You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1267 lines
40 KiB
C++
1267 lines
40 KiB
C++
// XTPCustomHeap.h: *** template definition.
|
|
//
|
|
// This file is a part of the XTREME TOOLKIT PRO MFC class library.
|
|
// (c)1998-2012 Codejock Software, All Rights Reserved.
|
|
//
|
|
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
|
|
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
|
|
// CONSENT OF CODEJOCK SOFTWARE.
|
|
//
|
|
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
|
|
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
|
|
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
|
|
// SINGLE COMPUTER.
|
|
//
|
|
// CONTACT INFORMATION:
|
|
// support@codejock.com
|
|
// http://www.codejock.com
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//{{AFX_CODEJOCK_PRIVATE
|
|
#if !defined(_XTPCUSTOMHEAP_H__)
|
|
#define _XTPCUSTOMHEAP_H__
|
|
|
|
#if _MSC_VER > 1000
|
|
#pragma once
|
|
#endif // _MSC_VER > 1000
|
|
//}}AFX_CODEJOCK_PRIVATE
|
|
|
|
#include "XTPVC80Helpers.h"
|
|
|
|
|
|
//{{AFX_CODEJOCK_PRIVATE
|
|
#define XTP_EXPORT_PARAMS_NO
|
|
|
|
typedef enum _XTP_HEAP_INFORMATION_CLASS
|
|
{
|
|
xtpHeapCompatibilityInformation
|
|
}
|
|
XTP_HEAP_INFORMATION_CLASS;
|
|
//}}AFX_CODEJOCK_PRIVATE
|
|
|
|
//===========================================================================
|
|
// Summary:
|
|
// This function enables features for a specified heap.
|
|
// Parameters:
|
|
// hHeapHandle - [in] Handle to the heap where information is to be set.
|
|
// This handle is returned by either the HeapCreate or
|
|
// GetProcessHeap function.
|
|
//
|
|
// pHeapInformation - [in] Heap information buffer. The format of this data
|
|
// depends on the HeapCompatibilityInformation class.
|
|
//
|
|
// nHeapInformationLength - [in] Size of the pHeapInformation buffer, in bytes.
|
|
// Remarks:
|
|
// This function is a wrapper to HeapSetInformation windows API function.
|
|
// If HeapSetInformation is not supported by windows, this function exits
|
|
// without any actions.
|
|
// Returns:
|
|
// If the function succeeds, the return value is nonzero
|
|
// If the function fails, the return value is 0 (zero). To get extended
|
|
// error information, call GetLastError.
|
|
// If HeapSetInformation is not supported by windows return value is also TRUE.
|
|
// See Also:
|
|
// HeapSetInformation, XTPHeapSetLowFragmentation
|
|
//===========================================================================
|
|
AFX_INLINE BOOL XTPHeapSetCompatibilityInformation(HANDLE hHeapHandle, PVOID pHeapInformation, ULONG_PTR nHeapInformationLength)
|
|
{
|
|
#ifdef _WIN32_WCE
|
|
return TRUE; // Not supported;
|
|
#else
|
|
typedef BOOL (WINAPI *PFNHEAPSETINFORMATION)(HANDLE HeapHandle, XTP_HEAP_INFORMATION_CLASS eHICls, PVOID HeapInformation, ULONG_PTR HeapInformationLength);
|
|
|
|
HMODULE hKernel = ::GetModuleHandle(_T("KERNEL32.DLL"));
|
|
ASSERT(NULL != hKernel);
|
|
|
|
if (NULL != hKernel)
|
|
{
|
|
PFNHEAPSETINFORMATION pfHeapSetInformation = (PFNHEAPSETINFORMATION)::GetProcAddress(hKernel, "HeapSetInformation");
|
|
if (NULL != pfHeapSetInformation)
|
|
{
|
|
return pfHeapSetInformation(hHeapHandle, xtpHeapCompatibilityInformation,
|
|
pHeapInformation, nHeapInformationLength);
|
|
}
|
|
}
|
|
return TRUE; // Not supported;
|
|
#endif
|
|
}
|
|
|
|
//===========================================================================
|
|
// Summary:
|
|
// Call this member to enable "Low-fragmentation Heap" (LFH) feature for
|
|
// a given heap.
|
|
// Parameters:
|
|
// hHeapHandle - [in] Handle to the heap where information is to be set.
|
|
// This handle is returned by either the HeapCreate or
|
|
// GetProcessHeap function.
|
|
// Remarks:
|
|
// This function is a wrapper to HeapSetInformation windows API function.
|
|
// If HeapSetInformation is not supported by windows, this function exits
|
|
// without any actions.
|
|
// Returns:
|
|
// If the function succeeds, the return value is nonzero
|
|
// If the function fails, the return value is 0 (zero). To get extended
|
|
// error information, call GetLastError.
|
|
// If HeapSetInformation is not supported by windows return value is also TRUE.
|
|
// See Also:
|
|
// HeapSetInformation, XTPHeapSetCompatibilityInformation
|
|
//===========================================================================
|
|
AFX_INLINE BOOL XTPHeapSetLowFragmentation(HANDLE hHeapHandle)
|
|
{
|
|
// LFH mode does not enabled under debugger,
|
|
// only under 'clear' run.
|
|
ULONG uHI = 2;
|
|
return XTPHeapSetCompatibilityInformation(hHeapHandle, &uHI, sizeof(uHI));
|
|
}
|
|
|
|
//===========================================================================
|
|
// Summary:
|
|
// This template class used as a base class for allocators which can use
|
|
// a custom (separate) heap. Each allocator use own heap or standard heap.
|
|
// To use custom heap set ms_bUseCustomHeap member to TRUE.
|
|
// Parameters:
|
|
// _TData - This class must contain following static members for allocator:
|
|
//
|
|
// struct allocatorClassData
|
|
// {
|
|
// static HANDLE ms_hCustomHeap; // handle to the custom heap
|
|
// static LONG ms_dwRefs; // allocated blocks count;
|
|
// static BOOL ms_bLFHEnabled; // report is LFH enabled for custom heap;
|
|
// static BOOL ms_bUseCustomHeap; // Define does allocator use custom heap or default heap;
|
|
// };
|
|
// See Also:
|
|
// XTP_DECLARE_HEAP_ALLOCATOR, XTP_IMPLEMENT_HEAP_ALLOCATOR,
|
|
// CXTPHeapObjectT
|
|
//===========================================================================
|
|
template<class _TData>
|
|
class CXTPHeapAllocatorT : public _TData
|
|
{
|
|
public:
|
|
//{{AFX_CODEJOCK_PRIVATE
|
|
typedef _TData TData;
|
|
//}}AFX_CODEJOCK_PRIVATE
|
|
|
|
|
|
//*** Allocator Interface ***
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Allocate memory block of nBytes size.
|
|
// Returns:
|
|
// A pointer to allocated block or NULL.
|
|
// See Also:
|
|
// Free_mem
|
|
//-----------------------------------------------------------------------
|
|
static void* AFX_CDECL Alloc_mem(size_t nBytes)
|
|
{
|
|
InterlockedIncrement(&ms_dwRefs); //ms_dwRefs++;
|
|
|
|
if (ms_bUseCustomHeap)
|
|
{
|
|
CreateHeapIfNeed();
|
|
|
|
return ::HeapAlloc(ms_hCustomHeap, 0, nBytes);
|
|
}
|
|
else
|
|
{
|
|
#ifdef _DEBUG
|
|
return DEBUG_NEW char[nBytes];
|
|
#else
|
|
return new char[nBytes];
|
|
#endif
|
|
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Free memory block previously allocated by Alloc_mem.
|
|
// Parameters:
|
|
// p - [in] Pointer to a memory block.
|
|
// See Also:
|
|
// Alloc_mem
|
|
//-----------------------------------------------------------------------
|
|
static void AFX_CDECL Free_mem(void* p)
|
|
{
|
|
LONG nRefs = 0;
|
|
if (ms_dwRefs)
|
|
nRefs = InterlockedDecrement(&ms_dwRefs); //ms_dwRefs--;
|
|
|
|
if (ms_bUseCustomHeap)
|
|
{
|
|
VERIFY(::HeapFree(ms_hCustomHeap, 0, p));
|
|
|
|
if (nRefs == 0)
|
|
ClearHeap();
|
|
}
|
|
else
|
|
{
|
|
delete p;
|
|
}
|
|
};
|
|
|
|
|
|
//*** Implementation ***
|
|
|
|
//{{AFX_CODEJOCK_PRIVATE
|
|
CXTPHeapAllocatorT()
|
|
{
|
|
};
|
|
|
|
virtual ~CXTPHeapAllocatorT()
|
|
{
|
|
// When other static objects use this allocator,
|
|
// they may be destroyed later (and free memory later)
|
|
// Each static object, which use this allocator,
|
|
// should check ms_dwRefs and destroy heap if no more refs.
|
|
if (ms_dwRefs == 0)
|
|
ClearHeap();
|
|
};
|
|
|
|
static void AFX_CDECL CreateHeapIfNeed()
|
|
{
|
|
if (!ms_hCustomHeap)
|
|
{
|
|
ms_hCustomHeap = ::HeapCreate(0, 0, 0);
|
|
ASSERT(ms_hCustomHeap);
|
|
ms_bLFHEnabled = XTPHeapSetLowFragmentation(ms_hCustomHeap);
|
|
}
|
|
}
|
|
|
|
static void AFX_CDECL ClearHeap()
|
|
{
|
|
ASSERT(ms_dwRefs == 0);
|
|
if (ms_hCustomHeap)
|
|
VERIFY(::HeapDestroy(ms_hCustomHeap));
|
|
ms_hCustomHeap = NULL;
|
|
}
|
|
//}}AFX_CODEJOCK_PRIVATE
|
|
};
|
|
|
|
|
|
//{{AFX_CODEJOCK_PRIVATE
|
|
#define XTP_DECLARE_HEAP_ALLOCATOR_(allocatorClass, EXPORT_PARAMS) \
|
|
struct EXPORT_PARAMS allocatorClass##Data \
|
|
{ \
|
|
static HANDLE ms_hCustomHeap; \
|
|
static LONG ms_dwRefs; \
|
|
static BOOL ms_bLFHEnabled; \
|
|
static BOOL ms_bUseCustomHeap; \
|
|
}; \
|
|
class EXPORT_PARAMS allocatorClass : public CXTPHeapAllocatorT<allocatorClass##Data> {};
|
|
//}}AFX_CODEJOCK_PRIVATE
|
|
|
|
//===========================================================================
|
|
// Summary:
|
|
// This macros used to declare allocator class derived from CXTPHeapAllocatorT
|
|
// which can use default or custom (separate) heap.
|
|
// Such allocator can be used as parameter for CXTPHeapObjectT template or
|
|
// for other cases.
|
|
// Parameters:
|
|
// allocatorClass - [in] Name of the allocator class.
|
|
// Remarks:
|
|
// Used together with XTP_IMPLEMENT_HEAP_ALLOCATOR macro.
|
|
// Example:
|
|
// <code>
|
|
//
|
|
// // probably in header (*.h) file:
|
|
// XTP_DECLARE_HEAP_ALLOCATOR(CXTPReportRowAllocator)
|
|
//
|
|
// // in implementation (*.cpp) file:
|
|
// XTP_IMPLEMENT_HEAP_ALLOCATOR(CXTPReportRowAllocator)
|
|
//
|
|
// </code>
|
|
// See Also:
|
|
// XTP_IMPLEMENT_HEAP_ALLOCATOR, CXTPHeapAllocatorT, CXTPHeapObjectT
|
|
//===========================================================================
|
|
#define XTP_DECLARE_HEAP_ALLOCATOR(allocatorClass) XTP_DECLARE_HEAP_ALLOCATOR_(allocatorClass, XTP_EXPORT_PARAMS_NO)
|
|
|
|
|
|
//===========================================================================
|
|
// Summary:
|
|
// This macros used to implement allocator class previously declared by
|
|
// XTP_DECLARE_HEAP_ALLOCATOR macro.
|
|
// Such allocator can be used as parameter for CXTPHeapObjectT template or
|
|
// for other cases.
|
|
// Parameters:
|
|
// allocatorClass - [in] Name of the allocator class.
|
|
// bUseCustomHeap - [in] Set as TRUE to enable custom heap by default for this allocator and FALSE to disable.
|
|
// Remarks:
|
|
// Used together with XTP_DECLARE_HEAP_ALLOCATOR macro.
|
|
// Example:
|
|
// <code>
|
|
//
|
|
// // probably in header (*.h) file:
|
|
// XTP_DECLARE_HEAP_ALLOCATOR(CXTPReportRowAllocator)
|
|
//
|
|
// // in implementation (*.cpp) file:
|
|
// XTP_IMPLEMENT_HEAP_ALLOCATOR(CXTPReportRowAllocator)
|
|
//
|
|
// </code>
|
|
// See Also:
|
|
// XTP_DECLARE_HEAP_ALLOCATOR, CXTPHeapAllocatorT, CXTPHeapObjectT
|
|
//===========================================================================
|
|
#define XTP_IMPLEMENT_HEAP_ALLOCATOR(allocatorClass, bUseCustomHeap) \
|
|
HANDLE allocatorClass##Data::ms_hCustomHeap = NULL; \
|
|
LONG allocatorClass##Data::ms_dwRefs = 0; \
|
|
BOOL allocatorClass##Data::ms_bLFHEnabled = FALSE; \
|
|
BOOL allocatorClass##Data::ms_bUseCustomHeap = bUseCustomHeap; \
|
|
allocatorClass g_obj##allocatorClass;
|
|
|
|
//===========================================================================
|
|
// Summary:
|
|
// This template class used as a helper class to override new/delete
|
|
// operators and use custom heap allocators inside them.
|
|
// Parameters:
|
|
// _TObject - A base class;
|
|
// _TAllocator - An allocator class name;
|
|
//
|
|
// Example:
|
|
// <code>
|
|
//
|
|
// // *** Allocator must be declared (and implemented)
|
|
// // probably in header (*.h) file:
|
|
// XTP_DECLARE_HEAP_ALLOCATOR(CMyCustomHeapAllocator)
|
|
//
|
|
// // in implementation (*.cpp) file:
|
|
// XTP_IMPLEMENT_HEAP_ALLOCATOR(CMyCustomHeapAllocator, TRUE)
|
|
//
|
|
// // To enable custom heap allocations use second parameter in
|
|
// // XTP_IMPLEMENT_HEAP_ALLOCATOR macro or set corresponding flag
|
|
// // on initialization, before any allocations:
|
|
// //
|
|
// CMyCustomHeapAllocator::ms_bUseCustomHeap = TRUE;
|
|
//
|
|
// //*** One way to use:
|
|
// class CMyClass : public CXTPHeapObjectT<CMyClassBase, CMyCustomHeapAllocator>
|
|
// {
|
|
// // ...
|
|
// };
|
|
// CMyClass* pMyClassObj = new CMyClass();
|
|
//
|
|
//
|
|
// //*** Other way to use:
|
|
// class CMyClass : public CMyClassBase
|
|
// {
|
|
// // ...
|
|
// };
|
|
//
|
|
// class CMyClass_heap : public CXTPHeapObjectT<CMyClass, CMyCustomHeapAllocator>
|
|
// {
|
|
// };
|
|
// CMyClass* pMyClassObj = new CMyClass_heap();
|
|
// </code>
|
|
//
|
|
// See Also:
|
|
// XTP_DECLARE_HEAP_ALLOCATOR, XTP_IMPLEMENT_HEAP_ALLOCATOR,
|
|
//===========================================================================
|
|
template<class _TObject, class _TAllocator>
|
|
class CXTPHeapObjectT : public _TObject
|
|
{
|
|
public:
|
|
//{{AFX_CODEJOCK_PRIVATE
|
|
typedef _TObject TObject;
|
|
typedef _TAllocator TAllocator;
|
|
//}}AFX_CODEJOCK_PRIVATE
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Allocate memory block of nSize bytes.
|
|
// Returns:
|
|
// A pointer to allocated block or NULL.
|
|
// See Also:
|
|
// operator delete
|
|
//-----------------------------------------------------------------------
|
|
void* PASCAL operator new(size_t nSize)
|
|
{
|
|
if (TAllocator::ms_bUseCustomHeap)
|
|
return TAllocator::Alloc_mem(nSize);
|
|
else
|
|
{
|
|
InterlockedIncrement(&TAllocator::ms_dwRefs); //TAllocator::ms_dwRefs++;
|
|
return ::operator new(nSize);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Free memory block previously allocated by operator new.
|
|
// Parameters:
|
|
// p - [in] Pointer to a memory block.
|
|
// See Also:
|
|
// operator new
|
|
//-----------------------------------------------------------------------
|
|
void PASCAL operator delete(void* p)
|
|
{
|
|
if (TAllocator::ms_bUseCustomHeap)
|
|
TAllocator::Free_mem(p);
|
|
else
|
|
{
|
|
InterlockedDecrement(&TAllocator::ms_dwRefs); //TAllocator::ms_dwRefs--;
|
|
::operator delete(p);
|
|
}
|
|
}
|
|
|
|
//{{AFX_CODEJOCK_PRIVATE
|
|
|
|
//void* PASCAL operator new(size_t, void* p) {return p;} // default is fine as is
|
|
|
|
#if _MSC_VER >= 1200
|
|
void PASCAL operator delete(void* p, void* pPlace)
|
|
{
|
|
if (TAllocator::ms_bUseCustomHeap)
|
|
operator delete(p);
|
|
else
|
|
{
|
|
InterlockedDecrement(&TAllocator::ms_dwRefs); //TAllocator::ms_dwRefs--;
|
|
::operator delete(p, pPlace);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)
|
|
// for file name/line number tracking using DEBUG_NEW
|
|
void* PASCAL operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
|
|
{
|
|
if (TAllocator::ms_bUseCustomHeap)
|
|
return operator new(nSize);
|
|
else
|
|
{
|
|
InterlockedIncrement(&TAllocator::ms_dwRefs); //TAllocator::ms_dwRefs++;
|
|
return ::operator new(nSize, lpszFileName, nLine);
|
|
}
|
|
}
|
|
|
|
#if _MSC_VER >= 1200
|
|
void PASCAL operator delete(void *p, LPCSTR lpszFileName, int nLine)
|
|
{
|
|
if (TAllocator::ms_bUseCustomHeap)
|
|
operator delete(p);
|
|
else
|
|
{
|
|
InterlockedDecrement(&TAllocator::ms_dwRefs); //TAllocator::ms_dwRefs--;
|
|
::operator delete(p, lpszFileName, nLine);
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
//}}AFX_CODEJOCK_PRIVATE
|
|
};
|
|
|
|
//===========================================================================
|
|
// Summary:
|
|
// This class used to store strings. It automatically allocate/deallocate
|
|
// memory for string data.
|
|
// Remarks:
|
|
// Override _AllocStringData, _FreeStringData to change default memory allocation.
|
|
// See Also:
|
|
// CXTPHeapStringT, XTP_DECLARE_HEAP_ALLOCATOR, CXTPHeapAllocatorT
|
|
//===========================================================================
|
|
class _XTP_EXT_CLASS CXTPHeapString
|
|
{
|
|
public:
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Default object constructor.
|
|
// See Also:
|
|
// ~CXTPHeapString
|
|
//-----------------------------------------------------------------------
|
|
CXTPHeapString()
|
|
{
|
|
m_nStrLen = 0;
|
|
m_pcszString = NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Object constructor.
|
|
// Parameters:
|
|
// pcszString - [in] Pointer to a source string.
|
|
// See Also:
|
|
// ~CXTPHeapString
|
|
//-----------------------------------------------------------------------
|
|
CXTPHeapString(LPCTSTR pcszString)
|
|
{
|
|
m_nStrLen = 0;
|
|
m_pcszString = NULL;
|
|
|
|
SetString(pcszString);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Default object destructor.
|
|
// See Also:
|
|
// CXTPHeapString
|
|
//-----------------------------------------------------------------------
|
|
virtual ~CXTPHeapString()
|
|
{
|
|
_FreeStringData();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Use this function to determine is string empty.
|
|
// Returns:
|
|
// TRUE if stored string is empty, FALSE otherwise.
|
|
//-----------------------------------------------------------------------
|
|
virtual BOOL IsEmpty() const
|
|
{
|
|
return !m_pcszString || m_nStrLen == 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Assign new string value.
|
|
// Parameters:
|
|
// pcszString - [in] Pointer to a source string.
|
|
// Returns:
|
|
// Stored string value.
|
|
//-----------------------------------------------------------------------
|
|
LPCTSTR operator=(LPCTSTR pcszString)
|
|
{
|
|
SetString(pcszString);
|
|
return m_pcszString ? m_pcszString : _T("");
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Determine are strings equal.
|
|
// Parameters:
|
|
// pcszString - [in] Pointer to a string to compare.
|
|
// Returns:
|
|
// TRUE if strings are equal, FALSE otherwise.
|
|
//-----------------------------------------------------------------------
|
|
BOOL operator==(LPCTSTR pcszString) const
|
|
{
|
|
return 0 == _tcscmp((LPCTSTR)*this, pcszString);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Determine are strings different.
|
|
// Parameters:
|
|
// pcszString - [in] Pointer to a string to compare.
|
|
// Returns:
|
|
// TRUE if strings are different, FALSE otherwise.
|
|
//-----------------------------------------------------------------------
|
|
BOOL operator!=(LPCTSTR pcszString) const
|
|
{
|
|
return 0 != _tcscmp((LPCTSTR)*this, pcszString);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// operator LPCTSTR.
|
|
// Returns:
|
|
// Pointer to a stored string.
|
|
//-----------------------------------------------------------------------
|
|
operator LPCTSTR() const
|
|
{
|
|
return m_pcszString ? m_pcszString : _T("");
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// operator CString.
|
|
// Returns:
|
|
// A CString object which contains stored string.
|
|
//-----------------------------------------------------------------------
|
|
operator CString() const
|
|
{
|
|
return CString(m_pcszString ? m_pcszString : _T(""));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Allocates a BSTR from stored string data..
|
|
// Returns:
|
|
// The newly allocated string.
|
|
//-----------------------------------------------------------------------
|
|
virtual BSTR AllocSysString() const
|
|
{
|
|
CString str(m_pcszString ? m_pcszString : _T(""));
|
|
return str.AllocSysString();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Use this method to set new string value.
|
|
// Parameters:
|
|
// pcszString - [in] Pointer to a source string.
|
|
//-----------------------------------------------------------------------
|
|
virtual void SetString(LPCTSTR pcszString)
|
|
{
|
|
if (!pcszString || *pcszString == 0)
|
|
{
|
|
_FreeStringData();
|
|
return;
|
|
}
|
|
|
|
int nNewStrLen = (int)_tcslen(pcszString);
|
|
|
|
if (nNewStrLen <= m_nStrLen && m_pcszString)
|
|
{
|
|
STRCPY_S(m_pcszString, m_nStrLen + 1, pcszString);
|
|
}
|
|
else
|
|
{
|
|
_FreeStringData();
|
|
|
|
_AllocStringData(nNewStrLen);
|
|
|
|
if (m_pcszString)
|
|
STRCPY_S(m_pcszString, m_nStrLen + 1, pcszString);
|
|
}
|
|
}
|
|
|
|
protected:
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// This method is used to allocate string data buffer.
|
|
// Parameters:
|
|
// nNewStrLen - [in] New string length without null character.
|
|
//-----------------------------------------------------------------------
|
|
virtual void _AllocStringData(int nNewStrLen)
|
|
{
|
|
ASSERT(m_pcszString == NULL);
|
|
|
|
m_nStrLen = nNewStrLen;
|
|
m_pcszString = new TCHAR[nNewStrLen + 1];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// This method is used to free string data buffer previously allocated
|
|
// in _AllocStringData.
|
|
//-----------------------------------------------------------------------
|
|
virtual void _FreeStringData()
|
|
{
|
|
if (m_pcszString)
|
|
delete m_pcszString;
|
|
|
|
m_pcszString = NULL;
|
|
m_nStrLen = 0;
|
|
}
|
|
|
|
int m_nStrLen; // Stored string length (without null character).
|
|
LPTSTR m_pcszString; // Pointer to a stored string (or NULL).
|
|
};
|
|
|
|
//===========================================================================
|
|
// Summary:
|
|
// This template used to store strings using different allocators.
|
|
// Remarks:
|
|
// String data stored in default or separate (custom) heap.
|
|
// Specially useful for VC 6.0 instead of CString, because
|
|
// CString Release implementation allocates data using some cache
|
|
// and data is not deallocated when CString destroyed.
|
|
// See Also:
|
|
// CXTPHeapString, XTP_DECLARE_HEAP_ALLOCATOR, CXTPHeapAllocatorT
|
|
//===========================================================================
|
|
template<class _TAllocator>
|
|
class CXTPHeapStringT : public CXTPHeapString
|
|
{
|
|
public:
|
|
//{{AFX_CODEJOCK_PRIVATE
|
|
typedef _TAllocator TAllocator;
|
|
//}}AFX_CODEJOCK_PRIVATE
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Default object constructor.
|
|
// Parameters:
|
|
// pcszString - [in] Pointer to a source string.
|
|
// See Also:
|
|
// ~CXTPHeapStringT
|
|
//-----------------------------------------------------------------------
|
|
CXTPHeapStringT(LPCTSTR pcszString = _T(""))
|
|
{
|
|
SetString(pcszString);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Default object destructor.
|
|
// See Also:
|
|
// CXTPHeapString
|
|
//-----------------------------------------------------------------------
|
|
virtual ~CXTPHeapStringT()
|
|
{
|
|
_FreeStringData();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Assign new string value.
|
|
// Parameters:
|
|
// pcszString - [in] Pointer to a source string.
|
|
// Returns:
|
|
// Stored string value.
|
|
//-----------------------------------------------------------------------
|
|
LPCTSTR operator=(LPCTSTR pcszString)
|
|
{
|
|
SetString(pcszString);
|
|
return m_pcszString ? m_pcszString : _T("");
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Determine are strings equal.
|
|
// Parameters:
|
|
// pcszString - [in] Pointer to a string to compare.
|
|
// Returns:
|
|
// TRUE if strings are equal, FALSE otherwise.
|
|
//-----------------------------------------------------------------------
|
|
BOOL operator==(LPCTSTR pcszString) const
|
|
{
|
|
return 0 == _tcscmp((LPCTSTR)*this, pcszString);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Determine are strings different.
|
|
// Parameters:
|
|
// pcszString - [in] Pointer to a string to compare.
|
|
// Returns:
|
|
// TRUE if strings are different, FALSE otherwise.
|
|
//-----------------------------------------------------------------------
|
|
BOOL operator!=(LPCTSTR pcszString) const
|
|
{
|
|
return 0 != _tcscmp((LPCTSTR)*this, pcszString);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// operator LPCTSTR.
|
|
// Returns:
|
|
// Pointer to a stored string.
|
|
//-----------------------------------------------------------------------
|
|
operator LPCTSTR() const
|
|
{
|
|
return m_pcszString ? m_pcszString : _T("");
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// operator CString.
|
|
// Returns:
|
|
// A CString object which contains stored string.
|
|
//-----------------------------------------------------------------------
|
|
operator CString() const
|
|
{
|
|
return CString(m_pcszString ? m_pcszString : _T(""));
|
|
}
|
|
|
|
protected:
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// This method is used to allocate string data buffer.
|
|
// Parameters:
|
|
// nNewStrLen - [in] New string length without null character.
|
|
//-----------------------------------------------------------------------
|
|
virtual void _AllocStringData(int nNewStrLen)
|
|
{
|
|
ASSERT(m_pcszString == NULL);
|
|
|
|
m_nStrLen = nNewStrLen;
|
|
m_pcszString = (LPTSTR)TAllocator::Alloc_mem((nNewStrLen + 1) * sizeof(TCHAR));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// This method is used to free string data buffer previously allocated
|
|
// in _AllocStringData.
|
|
//-----------------------------------------------------------------------
|
|
virtual void _FreeStringData()
|
|
{
|
|
if (m_pcszString)
|
|
TAllocator::Free_mem(m_pcszString);
|
|
|
|
m_pcszString = NULL;
|
|
m_nStrLen = 0;
|
|
}
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//{{AFX_CODEJOCK_PRIVATE
|
|
struct XTP_BATCHALLOC_OBJ_HEADER;
|
|
|
|
struct XTP_BATCHALLOC_BLOCK_HEADER
|
|
{
|
|
LONG m_dwRefs;
|
|
|
|
#ifdef _DEBUG
|
|
DWORD m_dwObjCount;
|
|
DWORD m_dwObjSize; // for debug
|
|
#endif
|
|
XTP_BATCHALLOC_OBJ_HEADER* pFreeList;
|
|
|
|
XTP_BATCHALLOC_BLOCK_HEADER* pPrev;
|
|
XTP_BATCHALLOC_BLOCK_HEADER* pNext;
|
|
};
|
|
|
|
struct XTP_BATCHALLOC_OBJ_HEADER
|
|
{
|
|
XTP_BATCHALLOC_BLOCK_HEADER* pBlockHeader;
|
|
|
|
XTP_BATCHALLOC_OBJ_HEADER* pNextFree;
|
|
|
|
void* GetData()
|
|
{
|
|
BYTE* pData = (BYTE*)this;
|
|
pData += sizeof(XTP_BATCHALLOC_OBJ_HEADER);
|
|
return pData;
|
|
}
|
|
|
|
static XTP_BATCHALLOC_OBJ_HEADER* GetHeader(void* pData)
|
|
{
|
|
BYTE* pBlockData = (BYTE*)pData;
|
|
pBlockData -= sizeof(XTP_BATCHALLOC_OBJ_HEADER);
|
|
return (XTP_BATCHALLOC_OBJ_HEADER*)pBlockData;
|
|
}
|
|
};
|
|
|
|
template<class _TAllocator, class _TBatchAllocData>
|
|
class CXTPBatchAllocManagerT : public _TBatchAllocData
|
|
{
|
|
public:
|
|
//{{ AFX_CODEJOCK_PRIVATE
|
|
typedef _TBatchAllocData TBatchAllocData;
|
|
typedef _TAllocator TAllocator;
|
|
//}} AFX_CODEJOCK_PRIVATE
|
|
|
|
virtual ~CXTPBatchAllocManagerT()
|
|
{
|
|
// all data must be deallocated before
|
|
ASSERT(m_pBusyBlocks == NULL);
|
|
|
|
FreeExtraData();
|
|
|
|
ASSERT(m_pFreeBlocks == NULL);
|
|
|
|
// This static object destructor may be called later than allocator destructor.
|
|
if (TAllocator::ms_dwRefs == 0)
|
|
TAllocator::ClearHeap();
|
|
}
|
|
|
|
AFX_INLINE static int AFX_CDECL _Round4(int nSize)
|
|
{
|
|
int nDiv = nSize / 4;
|
|
int nMod = nSize % 4;
|
|
int nSizeQ4 = (nDiv + (nMod ? 1 : 0)) * 4;
|
|
return nSizeQ4;
|
|
}
|
|
|
|
static void* AFX_CDECL AllocData(size_t nSize)
|
|
{
|
|
if (!m_pFreeBlocks)
|
|
{
|
|
int nObjSize = _Round4((int)nSize + sizeof(XTP_BATCHALLOC_OBJ_HEADER));
|
|
int nBlockDataSize = sizeof(XTP_BATCHALLOC_BLOCK_HEADER) +
|
|
m_nBlockSize * nObjSize;
|
|
|
|
BYTE* pBlockData = (BYTE*)_TAllocator::Alloc_mem(nBlockDataSize);
|
|
|
|
if (!pBlockData)
|
|
return NULL;
|
|
|
|
XTP_BATCHALLOC_BLOCK_HEADER* pBlockHdr = (XTP_BATCHALLOC_BLOCK_HEADER*)pBlockData;
|
|
ZeroMemory(pBlockHdr, sizeof(XTP_BATCHALLOC_BLOCK_HEADER));
|
|
pBlockHdr->m_dwRefs = 0;
|
|
#ifdef _DEBUG
|
|
pBlockHdr->m_dwObjCount = m_nBlockSize;
|
|
pBlockHdr->m_dwObjSize = (DWORD)nSize;
|
|
#endif
|
|
//---------
|
|
m_pFreeBlocks = pBlockHdr;
|
|
|
|
XTP_BATCHALLOC_OBJ_HEADER* pObjHdr = NULL;
|
|
pBlockData = pBlockData + sizeof(XTP_BATCHALLOC_BLOCK_HEADER);
|
|
pBlockHdr->pFreeList = (XTP_BATCHALLOC_OBJ_HEADER*)pBlockData;
|
|
|
|
for (int i = 0; i < m_nBlockSize; i++)
|
|
{
|
|
pObjHdr = (XTP_BATCHALLOC_OBJ_HEADER*)pBlockData;
|
|
//ZeroMemory(pObjHdr, sizeof(XTP_BATCHALLOC_OBJ_HEADER));
|
|
|
|
pBlockData += nObjSize;
|
|
|
|
pObjHdr->pBlockHeader = pBlockHdr;
|
|
pObjHdr->pNextFree = (XTP_BATCHALLOC_OBJ_HEADER*)pBlockData;
|
|
}
|
|
if (pObjHdr) pObjHdr->pNextFree = NULL;
|
|
}
|
|
|
|
ASSERT(m_pFreeBlocks && m_pFreeBlocks->pFreeList);
|
|
if (!m_pFreeBlocks || !m_pFreeBlocks->pFreeList)
|
|
return NULL;
|
|
|
|
ASSERT(m_pFreeBlocks->m_dwObjSize == (DWORD)nSize);
|
|
|
|
void* pData = m_pFreeBlocks->pFreeList->GetData();
|
|
|
|
m_pFreeBlocks->m_dwRefs++;
|
|
m_dwAllocatedObjects++;
|
|
|
|
XTP_BATCHALLOC_OBJ_HEADER* pNextFree = m_pFreeBlocks->pFreeList->pNextFree;
|
|
m_pFreeBlocks->pFreeList->pNextFree = NULL;
|
|
m_pFreeBlocks->pFreeList = pNextFree;
|
|
|
|
// no more free objects, move to busy blocks
|
|
if (!pNextFree)
|
|
{
|
|
XTP_BATCHALLOC_BLOCK_HEADER* pNewBusyBlock = m_pFreeBlocks;
|
|
m_pFreeBlocks = m_pFreeBlocks->pPrev ? m_pFreeBlocks->pPrev : m_pFreeBlocks->pNext;
|
|
if (m_pFreeBlocks)
|
|
m_pFreeBlocks->pPrev = pNewBusyBlock->pPrev;
|
|
|
|
pNewBusyBlock->pNext = m_pBusyBlocks;
|
|
pNewBusyBlock->pPrev = m_pBusyBlocks ? m_pBusyBlocks->pPrev : NULL;
|
|
if (m_pBusyBlocks)
|
|
m_pBusyBlocks->pPrev = pNewBusyBlock;
|
|
m_pBusyBlocks = pNewBusyBlock;
|
|
}
|
|
|
|
return pData;
|
|
}
|
|
|
|
static void AFX_CDECL FreeData(void* pObj)
|
|
{
|
|
if (!pObj)
|
|
return;
|
|
|
|
XTP_BATCHALLOC_OBJ_HEADER* pObjHdr = XTP_BATCHALLOC_OBJ_HEADER::GetHeader(pObj);
|
|
pObjHdr->pNextFree = pObjHdr->pBlockHeader->pFreeList;
|
|
pObjHdr->pBlockHeader->pFreeList = pObjHdr;
|
|
|
|
pObjHdr->pBlockHeader->m_dwRefs--;
|
|
m_dwAllocatedObjects--;
|
|
|
|
// was busy block, move to free list
|
|
if (pObjHdr->pNextFree == NULL)
|
|
{
|
|
XTP_BATCHALLOC_BLOCK_HEADER* pNewFreeBlock = pObjHdr->pBlockHeader;
|
|
if (pNewFreeBlock->pPrev)
|
|
pNewFreeBlock->pPrev->pNext = pNewFreeBlock->pNext;
|
|
|
|
if (pNewFreeBlock->pNext)
|
|
pNewFreeBlock->pNext->pPrev = pNewFreeBlock->pPrev;
|
|
|
|
if (m_pBusyBlocks == pNewFreeBlock)
|
|
m_pBusyBlocks = pNewFreeBlock->pPrev ? pNewFreeBlock->pPrev : pNewFreeBlock->pNext;
|
|
|
|
pNewFreeBlock->pNext = m_pFreeBlocks;
|
|
pNewFreeBlock->pPrev = m_pFreeBlocks ? m_pFreeBlocks->pPrev : NULL;
|
|
if (m_pFreeBlocks)
|
|
m_pFreeBlocks->pPrev = pNewFreeBlock;
|
|
m_pFreeBlocks = pNewFreeBlock;
|
|
}
|
|
|
|
// block is totally free, destroy block
|
|
if (pObjHdr->pBlockHeader->m_dwRefs == 0 && m_bDestroyEmptyBlocksOnFree)
|
|
{
|
|
XTP_BATCHALLOC_BLOCK_HEADER* pEmptyBlock = pObjHdr->pBlockHeader;
|
|
|
|
XTP_BATCHALLOC_BLOCK_HEADER* pIsNextFree = pEmptyBlock->pPrev ? pEmptyBlock->pPrev : pEmptyBlock->pNext;
|
|
BOOL bLast = (m_pFreeBlocks == pEmptyBlock) && pIsNextFree;
|
|
|
|
// do not destroy last free block
|
|
if (!bLast || m_bDestroyLastEmptyBlockOnFree)
|
|
{
|
|
if (pEmptyBlock->pPrev)
|
|
pEmptyBlock->pPrev->pNext = pEmptyBlock->pNext;
|
|
if (pEmptyBlock->pNext)
|
|
pEmptyBlock->pNext->pPrev = pEmptyBlock->pPrev;
|
|
|
|
if (m_pFreeBlocks == pEmptyBlock)
|
|
m_pFreeBlocks = pEmptyBlock->pPrev ? pEmptyBlock->pPrev : pEmptyBlock->pNext;
|
|
|
|
_TAllocator::Free_mem(pEmptyBlock);
|
|
}
|
|
}
|
|
|
|
// if (m_dwAllocatedObjects == 0)
|
|
// FreeExtraData();
|
|
}
|
|
|
|
public:
|
|
static void AFX_CDECL FreeExtraData()
|
|
{
|
|
XTP_BATCHALLOC_BLOCK_HEADER* pBlock = m_pFreeBlocks;
|
|
while (pBlock && pBlock->pPrev)
|
|
{
|
|
pBlock = pBlock->pPrev;
|
|
}
|
|
|
|
while (pBlock)
|
|
{
|
|
// block is totally free, destroy block
|
|
if (pBlock->m_dwRefs == 0)
|
|
{
|
|
XTP_BATCHALLOC_BLOCK_HEADER* pEmptyBlock = pBlock;
|
|
|
|
if (pEmptyBlock->pPrev)
|
|
pEmptyBlock->pPrev->pNext = pEmptyBlock->pNext;
|
|
|
|
if (pEmptyBlock->pNext)
|
|
pEmptyBlock->pNext->pPrev = pEmptyBlock->pPrev;
|
|
|
|
if (m_pFreeBlocks == pEmptyBlock)
|
|
m_pFreeBlocks = pEmptyBlock->pPrev ? pEmptyBlock->pPrev : pEmptyBlock->pNext;
|
|
|
|
pBlock = pBlock->pNext;
|
|
|
|
TAllocator::Free_mem(pEmptyBlock);
|
|
}
|
|
else
|
|
{
|
|
pBlock = pBlock->pNext;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
//}}AFX_CODEJOCK_PRIVATE
|
|
|
|
//===========================================================================
|
|
// Summary:
|
|
// This template class used as a helper class to override new/delete
|
|
// operators and use batch allocation inside them.
|
|
// Batch allocation means that memory allocated not for one object only,
|
|
// but for many objects at one time (for 1024 objects by default).
|
|
// Next allocations take memory from this big block. New blocks allocated
|
|
// when necessary. This increase performance and reduce heap fragmentation.
|
|
// Batch allocation mechanism responsible for allocation/deallocation
|
|
// blocks of memory from heap and internally organize free/busy lists of
|
|
// memory pieces. When object deleted, its memory stored in free list and
|
|
// used for new objects.
|
|
// When all memory pieces from block free, it may be deallocated from
|
|
// heap automatically (this depends on options in _TBatchAllocData)
|
|
// or by FreeExtraData call,
|
|
//
|
|
// Parameters:
|
|
// _TObject - A base class;
|
|
// _TAllocator - An allocator class name; by default _TObject::TAllocator is used.
|
|
// _TBatchAllocData - This class must contain following static members for allocator:
|
|
//
|
|
// struct BatchAllocData
|
|
// {
|
|
// static BOOL m_bEnableBatchAllocation; // Define is Batch Allocation enabled;
|
|
// static LONG m_dwAllocatedObjects; // allocated blocks count;
|
|
//
|
|
// static BOOL m_bDestroyEmptyBlocksOnFree; // if TRUE - completely free blocks will be deallocated on free objects, otherwise they will stay in free list.
|
|
// static BOOL m_bDestroyLastEmptyBlockOnFree; // if TRUE - last completely free block will be deallocated on free objects, otherwise it will stay in free list.
|
|
//
|
|
// static int m_nBlockSize; // Count of objects in block.
|
|
// protected:
|
|
// static XTP_BATCHALLOC_BLOCK_HEADER* m_pFreeBlocks; // List of blocks which have free pieces.
|
|
// static XTP_BATCHALLOC_BLOCK_HEADER* m_pBusyBlocks; // List of blocks which have not free pieces.
|
|
// };
|
|
//
|
|
// Example:
|
|
// <code>
|
|
//
|
|
// // *** Batch data must be declared (and implemented)
|
|
// // probably in header (*.h) file:
|
|
// XTP_DECLARE_BATCH_ALLOC_OBJ_DATA(CBatchReportRecord_Data);
|
|
// class CBatchReportRecord : public CXTPBatchAllocObjT<CXTPReportRecord, CBatchReportRecord_Data>
|
|
// {
|
|
// // ...
|
|
// };
|
|
//
|
|
// // in implementation (*.cpp) file:
|
|
// XTP_IMPLEMENT_BATCH_ALLOC_OBJ_DATA(CBatchReportRecord_Data, CBatchReportRecord, TRUE);
|
|
//
|
|
// // To enable Batch allocations use second parameter in
|
|
// // XTP_IMPLEMENT_BATCH_ALLOC_OBJ_DATA macro or set corresponding flag
|
|
// // on initialization, before any allocations:
|
|
// //
|
|
// CMyCustomHeapAllocator::ms_bUseCustomHeap = TRUE;
|
|
//
|
|
// //*** How to use:
|
|
// CBatchReportRecord* pMyClassObj = new CBatchReportRecord();
|
|
//
|
|
//</code>
|
|
//
|
|
// See Also:
|
|
// XTP_DECLARE_BATCH_ALLOC_OBJ_DATA, XTP_IMPLEMENT_BATCH_ALLOC_OBJ_DATA,
|
|
//===========================================================================
|
|
template<class _TObject, class _TBatchAllocData, class _TAllocator = _TObject::TAllocator >
|
|
class CXTPBatchAllocObjT : public _TObject
|
|
{
|
|
public:
|
|
//{{AFX_CODEJOCK_PRIVATE
|
|
typedef _TObject TObject;
|
|
typedef _TBatchAllocData TBatchAllocData;
|
|
typedef _TAllocator TAllocator;
|
|
|
|
typedef CXTPBatchAllocManagerT<_TAllocator, _TBatchAllocData > TBlockMan;
|
|
//}}AFX_CODEJOCK_PRIVATE
|
|
|
|
public:
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// This member function check all blocks and deallocate which are
|
|
// completely free.
|
|
// See Also:
|
|
// _TBatchAllocData
|
|
//-----------------------------------------------------------------------
|
|
static void AFX_CDECL FreeExtraData() {
|
|
TBlockMan::FreeExtraData();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Allocate memory block of nSize bytes.
|
|
// Returns:
|
|
// A pointer to allocated block or NULL.
|
|
// See Also:
|
|
// operator delete
|
|
//-----------------------------------------------------------------------
|
|
void* PASCAL operator new(size_t nSize)
|
|
{
|
|
if (TBlockMan::m_bBatchAllocationEnabled)
|
|
return TBlockMan::AllocData(nSize);
|
|
else
|
|
return _TObject::operator new(nSize);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Summary:
|
|
// Free memory block previously allocated by operator new.
|
|
// Parameters:
|
|
// p - [in] Pointer to a memory block.
|
|
// See Also:
|
|
// operator new
|
|
//-----------------------------------------------------------------------
|
|
void PASCAL operator delete(void* p)
|
|
{
|
|
if (TBlockMan::m_bBatchAllocationEnabled)
|
|
TBlockMan::FreeData(p);
|
|
else
|
|
_TObject::operator delete(p);
|
|
}
|
|
|
|
|
|
//{{AFX_CODEJOCK_PRIVATE
|
|
//void* PASCAL operator new(size_t, void* p) {return p;} // default is fine as is
|
|
|
|
#if _MSC_VER >= 1200
|
|
void PASCAL operator delete(void* p, void* pPlace)
|
|
{
|
|
if (TBlockMan::m_bBatchAllocationEnabled)
|
|
TBlockMan::FreeData(p);
|
|
else
|
|
_TObject::operator delete(p, pPlace);
|
|
}
|
|
#endif
|
|
|
|
#if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)
|
|
// for file name/line number tracking using DEBUG_NEW
|
|
void* PASCAL operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
|
|
{
|
|
if (TBlockMan::m_bBatchAllocationEnabled)
|
|
return operator new(nSize);
|
|
else
|
|
return _TObject::operator new(nSize, lpszFileName, nLine);
|
|
}
|
|
|
|
#if _MSC_VER >= 1200
|
|
void PASCAL operator delete(void *p, LPCSTR lpszFileName, int nLine)
|
|
{
|
|
if (TBlockMan::m_bBatchAllocationEnabled)
|
|
operator delete(p);
|
|
else
|
|
_TObject::operator delete(p, lpszFileName, nLine);
|
|
}
|
|
#endif
|
|
#endif
|
|
//}}AFX_CODEJOCK_PRIVATE
|
|
};
|
|
|
|
//{{AFX_CODEJOCK_PRIVATE
|
|
#define XTP_DECLARE_BATCH_ALLOC_OBJ_DATA_(dataClass, EXPORT_PARAMS) \
|
|
struct EXPORT_PARAMS dataClass \
|
|
{ \
|
|
static BOOL m_bBatchAllocationEnabled; \
|
|
static LONG m_dwAllocatedObjects; \
|
|
static BOOL m_bDestroyEmptyBlocksOnFree; \
|
|
static BOOL m_bDestroyLastEmptyBlockOnFree; \
|
|
static int m_nBlockSize; \
|
|
\
|
|
static BOOL AFX_CDECL IsDataEmpty() { return !m_pFreeBlocks && !m_pBusyBlocks; }; \
|
|
protected: \
|
|
static XTP_BATCHALLOC_BLOCK_HEADER* m_pFreeBlocks; \
|
|
static XTP_BATCHALLOC_BLOCK_HEADER* m_pBusyBlocks; \
|
|
};
|
|
//}}AFX_CODEJOCK_PRIVATE
|
|
|
|
//===========================================================================
|
|
// Summary:
|
|
// This macros used to declare Batch allocation data which used with
|
|
// CXTPBatchAllocObjT template.
|
|
// Parameters:
|
|
// dataClass - [in] Name of the Batch allocation data class.
|
|
// Remarks:
|
|
// Used together with XTP_IMPLEMENT_BATCH_ALLOC_OBJ_DATA macro.
|
|
// Example:
|
|
// <code>
|
|
//
|
|
// XTP_DECLARE_BATCH_ALLOC_OBJ_DATA(CBatchReportRecord_Data);
|
|
// class CBatchReportRecord : public CXTPBatchAllocObjT<CXTPReportRecord, CBatchReportRecord_Data>
|
|
// {
|
|
// // ...
|
|
// };
|
|
//
|
|
// // in implementation (*.cpp) file:
|
|
// XTP_IMPLEMENT_BATCH_ALLOC_OBJ_DATA(CBatchReportRecord_Data, CBatchReportRecord, TRUE);
|
|
//
|
|
// </code>
|
|
// See Also:
|
|
// XTP_IMPLEMENT_HEAP_ALLOCATOR, CXTPHeapAllocatorT, CXTPBatchAllocObjT
|
|
//===========================================================================
|
|
#define XTP_DECLARE_BATCH_ALLOC_OBJ_DATA(dataClass) XTP_DECLARE_BATCH_ALLOC_OBJ_DATA_(dataClass, XTP_EXPORT_PARAMS_NO)
|
|
|
|
//===========================================================================
|
|
// Summary:
|
|
// This macros used to declare Batch allocation data which used with
|
|
// CXTPBatchAllocObjT template.
|
|
// Parameters:
|
|
// dataClass - [in] Name of the Batch allocation data class.
|
|
// objClass - [in] Name of the object class for Batch allocation.
|
|
// batchAllocEnabled - [in] Set as TRUE to enable Batch allocation by default for this object and FALSE to disable.
|
|
// Remarks:
|
|
// Used together with XTP_DECLARE_BATCH_ALLOC_OBJ_DATA macro.
|
|
// Example:
|
|
// <code>
|
|
//
|
|
// XTP_DECLARE_BATCH_ALLOC_OBJ_DATA(CBatchReportRecord_Data);
|
|
// class CBatchReportRecord : public CXTPBatchAllocObjT<CXTPReportRecord, CBatchReportRecord_Data>
|
|
// {
|
|
// // ...
|
|
// };
|
|
//
|
|
// // in implementation (*.cpp) file:
|
|
// XTP_IMPLEMENT_BATCH_ALLOC_OBJ_DATA(CBatchReportRecord_Data, CBatchReportRecord, TRUE);
|
|
//
|
|
// </code>
|
|
// See Also:
|
|
// XTP_DECLARE_BATCH_ALLOC_OBJ_DATA, CXTPHeapAllocatorT, CXTPBatchAllocObjT
|
|
//===========================================================================
|
|
#define XTP_IMPLEMENT_BATCH_ALLOC_OBJ_DATA(dataClass, objClass, batchAllocEnabled) \
|
|
BOOL dataClass::m_bBatchAllocationEnabled = batchAllocEnabled; \
|
|
LONG dataClass::m_dwAllocatedObjects = 0; \
|
|
int dataClass::m_nBlockSize = 1024; \
|
|
BOOL dataClass::m_bDestroyEmptyBlocksOnFree = FALSE; \
|
|
BOOL dataClass::m_bDestroyLastEmptyBlockOnFree = FALSE; \
|
|
XTP_BATCHALLOC_BLOCK_HEADER* dataClass::m_pFreeBlocks = NULL; \
|
|
XTP_BATCHALLOC_BLOCK_HEADER* dataClass::m_pBusyBlocks = NULL; \
|
|
objClass::TBlockMan gs_##objClass##_BlocksManager;
|
|
|
|
#endif // !defined(_XTPCUSTOMHEAP_H__)
|