Seaside/SpyCustom/sdk/memalloc.h
2021-06-16 18:48:15 +03:00

567 lines
17 KiB
C++

#ifndef TIER0_MEMALLOC_H
#define TIER0_MEMALLOC_H
#ifdef _WIN32
#pragma once
#endif
#ifndef POSIX
#endif
#if defined( _MEMTEST )
#ifdef _WIN32
#define USE_MEM_DEBUG 1
#endif
#endif
#define MEM_DEBUG_CLASSNAME 1
#include <stddef.h>
#if defined( OSX )
#include <malloc/malloc.h>
#endif
#include "mem.h"
#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)
struct _CrtMemState;
#define MEMALLOC_VERSION 1
typedef size_t(*MemAllocFailHandler_t)(size_t);
class IMemAlloc
{
public:
virtual void* Alloc(size_t nSize) = 0;
virtual void* Realloc(void* pMem, size_t nSize) = 0;
virtual void Free(void* pMem) = 0;
virtual void* Expand_NoLongerSupported(void* pMem, size_t nSize) = 0;
virtual void* Alloc(size_t nSize, const char* pFileName, int nLine) = 0;
virtual void* Realloc(void* pMem, size_t nSize, const char* pFileName, int nLine) = 0;
virtual void Free(void* pMem, const char* pFileName, int nLine) = 0;
virtual void* Expand_NoLongerSupported(void* pMem, size_t nSize, const char* pFileName, int nLine) = 0;
virtual size_t GetSize(void* pMem) = 0;
virtual void PushAllocDbgInfo(const char* pFileName, int nLine) = 0;
virtual void PopAllocDbgInfo() = 0;
virtual long CrtSetBreakAlloc(long lNewBreakAlloc) = 0;
virtual int CrtSetReportMode(int nReportType, int nReportMode) = 0;
virtual int CrtIsValidHeapPointer(const void* pMem) = 0;
virtual int CrtIsValidPointer(const void* pMem, unsigned int size, int access) = 0;
virtual int CrtCheckMemory(void) = 0;
virtual int CrtSetDbgFlag(int nNewFlag) = 0;
virtual void CrtMemCheckpoint(_CrtMemState* pState) = 0;
virtual void DumpStats() = 0;
virtual void DumpStatsFileBase(char const* pchFileBase) = 0;
virtual void* CrtSetReportFile(int nRptType, void* hFile) = 0;
virtual void* CrtSetReportHook(void* pfnNewHook) = 0;
virtual int CrtDbgReport(int nRptType, const char* szFile,
int nLine, const char* szModule, const char* pMsg) = 0;
virtual int heapchk() = 0;
virtual bool IsDebugHeap() = 0;
virtual void GetActualDbgInfo(const char*& pFileName, int& nLine) = 0;
virtual void RegisterAllocation(const char* pFileName, int nLine, int nLogicalSize, int nActualSize, unsigned nTime) = 0;
virtual void RegisterDeallocation(const char* pFileName, int nLine, int nLogicalSize, int nActualSize, unsigned nTime) = 0;
virtual int GetVersion() = 0;
virtual void CompactHeap() = 0;
virtual MemAllocFailHandler_t SetAllocFailHandler(MemAllocFailHandler_t pfnMemAllocFailHandler) = 0;
virtual void DumpBlockStats(void*) = 0;
#if defined( _MEMTEST )
virtual void SetStatsExtraInfo(const char* pMapName, const char* pComment) = 0;
#endif
virtual size_t MemoryAllocFailed() = 0;
virtual uint32 GetDebugInfoSize() = 0;
virtual void SaveDebugInfo(void* pvDebugInfo) = 0;
virtual void RestoreDebugInfo(const void* pvDebugInfo) = 0;
virtual void InitDebugInfo(void* pvDebugInfo, const char* pchRootFileName, int nLine) = 0;
virtual void GlobalMemoryStatus(size_t* pUsedMemory, size_t* pFreeMemory) = 0;
};
MEM_INTERFACE IMemAlloc* g_pMemAlloc;
#ifdef MEMALLOC_REGIONS
#ifndef MEMALLOC_REGION
#define MEMALLOC_REGION 0
#endif
inline void* MemAlloc_Alloc(size_t nSize)
{
return g_pMemAlloc->RegionAlloc(MEMALLOC_REGION, nSize);
}
inline void* MemAlloc_Alloc(size_t nSize, const char* pFileName, int nLine)
{
return g_pMemAlloc->RegionAlloc(MEMALLOC_REGION, nSize, pFileName, nLine);
}
#else
#undef MEMALLOC_REGION
inline void* MemAlloc_Alloc(size_t nSize)
{
return g_pMemAlloc->Alloc(nSize);
}
inline void* MemAlloc_Alloc(size_t nSize, const char* pFileName, int nLine)
{
return g_pMemAlloc->Alloc(nSize, pFileName, nLine);
}
#endif
inline void MemAlloc_Free(void* ptr)
{
g_pMemAlloc->Free(ptr);
}
inline void MemAlloc_Free(void* ptr, const char* pFileName, int nLine)
{
g_pMemAlloc->Free(ptr, pFileName, nLine);
}
inline bool ValueIsPowerOfTwo(size_t value)
{
return (value & (value - 1)) == 0;
}
inline void* MemAlloc_AllocAligned(size_t size, size_t align)
{
unsigned char* pAlloc, * pResult;
if (!IsPowerOfTwo(align))
return NULL;
align = (align > sizeof(void*) ? align : sizeof(void*)) - 1;
if ((pAlloc = (unsigned char*)g_pMemAlloc->Alloc(sizeof(void*) + align + size)) == (unsigned char*)NULL)
return NULL;
pResult = (unsigned char*)((size_t)(pAlloc + sizeof(void*) + align) & ~align);
((unsigned char**)(pResult))[-1] = pAlloc;
return (void*)pResult;
}
inline void* MemAlloc_AllocAligned(size_t size, size_t align, const char* pszFile, int nLine)
{
unsigned char* pAlloc, * pResult;
if (!IsPowerOfTwo(align))
return NULL;
align = (align > sizeof(void*) ? align : sizeof(void*)) - 1;
if ((pAlloc = (unsigned char*)g_pMemAlloc->Alloc(sizeof(void*) + align + size, pszFile, nLine)) == (unsigned char*)NULL)
return NULL;
pResult = (unsigned char*)((size_t)(pAlloc + sizeof(void*) + align) & ~align);
((unsigned char**)(pResult))[-1] = pAlloc;
return (void*)pResult;
}
inline void* MemAlloc_AllocAlignedUnattributed(size_t size, size_t align)
{
unsigned char* pAlloc, * pResult;
if (!ValueIsPowerOfTwo(align))
return NULL;
align = (align > sizeof(void*) ? align : sizeof(void*)) - 1;
if ((pAlloc = (unsigned char*)MemAlloc_Alloc(sizeof(void*) + align + size)) == (unsigned char*)NULL)
return NULL;
pResult = (unsigned char*)((size_t)(pAlloc + sizeof(void*) + align) & ~align);
((unsigned char**)(pResult))[-1] = pAlloc;
return (void*)pResult;
}
inline void* MemAlloc_AllocAlignedFileLine(size_t size, size_t align, const char* pszFile, int nLine)
{
unsigned char* pAlloc, * pResult;
if (!ValueIsPowerOfTwo(align))
return NULL;
align = (align > sizeof(void*) ? align : sizeof(void*)) - 1;
if ((pAlloc = (unsigned char*)MemAlloc_Alloc(sizeof(void*) + align + size, pszFile, nLine)) == (unsigned char*)NULL)
return NULL;
pResult = (unsigned char*)((size_t)(pAlloc + sizeof(void*) + align) & ~align);
((unsigned char**)(pResult))[-1] = pAlloc;
return (void*)pResult;
}
inline void* MemAlloc_ReallocAligned(void* ptr, size_t size, size_t align)
{
if (!IsPowerOfTwo(align))
return NULL;
if (((size_t)ptr & (align - 1)) != 0)
return NULL;
if (!ptr)
return MemAlloc_AllocAligned(size, align);
void* pAlloc, * pResult;
pAlloc = ptr;
pAlloc = (void*)(((size_t)pAlloc & ~(sizeof(void*) - 1)) - sizeof(void*));
pAlloc = *((void**)pAlloc);
size_t nOffset = (size_t)ptr - (size_t)pAlloc;
size_t nOldSize = g_pMemAlloc->GetSize(pAlloc);
if (nOldSize >= size + nOffset)
return ptr;
pResult = MemAlloc_AllocAligned(size, align);
memcpy(pResult, ptr, nOldSize - nOffset);
g_pMemAlloc->Free(pAlloc);
return pResult;
}
inline void MemAlloc_FreeAligned(void* pMemBlock)
{
void* pAlloc;
if (pMemBlock == NULL)
return;
pAlloc = pMemBlock;
pAlloc = (void*)(((size_t)pAlloc & ~(sizeof(void*) - 1)) - sizeof(void*));
pAlloc = *((void**)pAlloc);
g_pMemAlloc->Free(pAlloc);
}
inline void MemAlloc_FreeAligned(void* pMemBlock, const char* pFileName, int nLine)
{
void* pAlloc;
if (pMemBlock == NULL)
return;
pAlloc = pMemBlock;
pAlloc = (void*)(((size_t)pAlloc & ~(sizeof(void*) - 1)) - sizeof(void*));
pAlloc = *((void**)pAlloc);
g_pMemAlloc->Free(pAlloc, pFileName, nLine);
}
inline size_t MemAlloc_GetSizeAligned(void* pMemBlock)
{
void* pAlloc;
if (pMemBlock == NULL)
return 0;
pAlloc = pMemBlock;
pAlloc = (void*)(((size_t)pAlloc & ~(sizeof(void*) - 1)) - sizeof(void*));
pAlloc = *((void**)pAlloc);
return g_pMemAlloc->GetSize(pAlloc) - ((byte*)pMemBlock - (byte*)pAlloc);
}
#if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
#define MEM_ALLOC_CREDIT_(tag) CMemAllocAttributeAlloction memAllocAttributeAlloction( tag, __LINE__ )
#define MemAlloc_PushAllocDbgInfo( pszFile, line ) g_pMemAlloc->PushAllocDbgInfo( pszFile, line )
#define MemAlloc_PopAllocDbgInfo() g_pMemAlloc->PopAllocDbgInfo()
#define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime )
#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime )
#else
#define MEM_ALLOC_CREDIT_(tag) ((void)0)
#define MemAlloc_PushAllocDbgInfo( pszFile, line ) ((void)0)
#define MemAlloc_PopAllocDbgInfo() ((void)0)
#define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
#endif
#define MemAlloc_DumpStats() g_pMemAlloc->DumpStats()
#define MemAlloc_CompactHeap() g_pMemAlloc->CompactHeap()
#define MemAlloc_OutOfMemory() g_pMemAlloc->OutOfMemory()
#define MemAlloc_CompactIncremental() g_pMemAlloc->CompactIncremental()
#define MemAlloc_DumpStatsFileBase( _filename ) g_pMemAlloc->DumpStatsFileBase( _filename )
#define MemAlloc_CrtCheckMemory() g_pMemAlloc->CrtCheckMemory()
#define MemAlloc_GlobalMemoryStatus( _usedMemory, _freeMemory ) g_pMemAlloc->GlobalMemoryStatus( _usedMemory, _freeMemory )
#define MemAlloc_MemoryAllocFailed() g_pMemAlloc->MemoryAllocFailed()
#define MemAlloc_GetDebugInfoSize() g_pMemAlloc->GetDebugInfoSize()
#define MemAlloc_SaveDebugInfo( pvDebugInfo ) g_pMemAlloc->SaveDebugInfo( pvDebugInfo )
#define MemAlloc_RestoreDebugInfo( pvDebugInfo ) g_pMemAlloc->RestoreDebugInfo( pvDebugInfo )
#define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) g_pMemAlloc->InitDebugInfo( pvDebugInfo, pchRootFileName, nLine )
#define MemAlloc_GetSize( x ) g_pMemAlloc->GetSize( x );
class CMemAllocAttributeAlloction
{
public:
CMemAllocAttributeAlloction(const char* pszFile, int line)
{
MemAlloc_PushAllocDbgInfo(pszFile, line);
}
~CMemAllocAttributeAlloction()
{
MemAlloc_PopAllocDbgInfo();
}
};
#define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__)
#if defined(_WIN32) && ( defined(_DEBUG) || defined(USE_MEM_DEBUG) )
#pragma warning(disable:4290)
#pragma warning(push)
#include <typeinfo>
#if defined(_CPPRTTI) && defined(MEM_DEBUG_CLASSNAME)
#define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( typeid(*this).name() )
#define MEM_ALLOC_CLASSNAME(type) (typeid((type*)(0)).name())
#else
#define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( __FILE__ )
#define MEM_ALLOC_CLASSNAME(type) (__FILE__)
#endif
#ifdef _MSC_VER
#define MEM_ALLOC_CREDIT_FUNCTION() MEM_ALLOC_CREDIT_( __FUNCTION__ )
#else
#define MEM_ALLOC_CREDIT_FUNCTION() (__FILE__)
#endif
#pragma warning(pop)
#else
#define MEM_ALLOC_CREDIT_CLASS()
#define MEM_ALLOC_CLASSNAME(type) NULL
#define MEM_ALLOC_CREDIT_FUNCTION()
#endif
#if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
struct MemAllocFileLine_t
{
const char* pszFile;
int line;
};
#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag ) \
static CUtlMap<void *, MemAllocFileLine_t, int> g_##tag##Allocs( DefLessFunc( void *) ); \
static const char *g_psz##tag##Alloc = strcpy( (char *)g_pMemAlloc->Alloc( strlen( #tag "Alloc" ) + 1, "intentional leak", 0 ), #tag "Alloc" );
#define MemAlloc_RegisterExternalAllocation( tag, p, size ) \
if ( !p ) \
; \
else \
{ \
MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
g_pMemAlloc->GetActualDbgInfo( fileLine.pszFile, fileLine.line ); \
if ( fileLine.pszFile != g_psz##tag##Alloc ) \
{ \
g_##tag##Allocs.Insert( p, fileLine ); \
} \
\
MemAlloc_RegisterAllocation( fileLine.pszFile, fileLine.line, size, size, 0); \
}
#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) \
if ( !p ) \
; \
else \
{ \
MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
CUtlMap<void *, MemAllocFileLine_t, int>::IndexType_t iRecordedFileLine = g_##tag##Allocs.Find( p ); \
if ( iRecordedFileLine != g_##tag##Allocs.InvalidIndex() ) \
{ \
fileLine = g_##tag##Allocs[iRecordedFileLine]; \
g_##tag##Allocs.RemoveAt( iRecordedFileLine ); \
} \
\
MemAlloc_RegisterDeallocation( fileLine.pszFile, fileLine.line, size, size, 0); \
}
#else
#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
#define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)
#endif
#elif defined( POSIX )
#if defined( OSX )
inline void* memalign(size_t alignment, size_t size) { void* pTmp = NULL; pTmp = malloc(size); return pTmp; }
#endif
inline void* _aligned_malloc(size_t nSize, size_t align) { return memalign(align, nSize); }
inline void _aligned_free(void* ptr) { free(ptr); }
inline void* MemAlloc_Alloc(size_t nSize, const char* pFileName = NULL, int nLine = 0) { return malloc(nSize); }
inline void MemAlloc_Free(void* ptr, const char* pFileName = NULL, int nLine = 0) { free(ptr); }
inline void* MemAlloc_AllocAligned(size_t size, size_t align, const char* pszFile = NULL, int nLine = 0) { return memalign(align, size); }
inline void* MemAlloc_AllocAlignedFileLine(size_t size, size_t align, const char* pszFile = NULL, int nLine = 0) { return memalign(align, size); }
inline void MemAlloc_FreeAligned(void* pMemBlock, const char* pszFile = NULL, int nLine = 0) { free(pMemBlock); }
#if defined( OSX )
inline size_t _msize(void* ptr) { return malloc_size(ptr); }
#else
inline size_t _msize(void* ptr) { return malloc_usable_size(ptr); }
#endif
inline void* MemAlloc_ReallocAligned(void* ptr, size_t size, size_t align)
{
void* ptr_new_aligned = memalign(align, size);
if (ptr_new_aligned)
{
size_t old_size = _msize(ptr);
size_t copy_size = (size < old_size) ? size : old_size;
memcpy(ptr_new_aligned, ptr, copy_size);
free(ptr);
}
return ptr_new_aligned;
}
#else
#define MemAlloc_GetDebugInfoSize() g_pMemAlloc->GetDebugInfoSize()
#define MemAlloc_SaveDebugInfo( pvDebugInfo ) g_pMemAlloc->SaveDebugInfo( pvDebugInfo )
#define MemAlloc_RestoreDebugInfo( pvDebugInfo ) g_pMemAlloc->RestoreDebugInfo( pvDebugInfo )
#define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) g_pMemAlloc->InitDebugInfo( pvDebugInfo, pchRootFileName, nLine )
#endif
#if !defined(STEAM) && defined(NO_MALLOC_OVERRIDE)
#define MEM_ALLOC_CREDIT_(tag) ((void)0)
#define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__)
#define MEM_ALLOC_CREDIT_FUNCTION()
#define MEM_ALLOC_CREDIT_CLASS()
#define MEM_ALLOC_CLASSNAME(type) NULL
#define MemAlloc_PushAllocDbgInfo( pszFile, line )
#define MemAlloc_PopAllocDbgInfo()
#define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
#define MemAlloc_DumpStats() ((void)0)
#define MemAlloc_CompactHeap() ((void)0)
#define MemAlloc_OutOfMemory() ((void)0)
#define MemAlloc_CompactIncremental() ((void)0)
#define MemAlloc_DumpStatsFileBase( _filename ) ((void)0)
inline bool MemAlloc_CrtCheckMemory() { return true; }
inline void MemAlloc_GlobalMemoryStatus(size_t* pusedMemory, size_t* pfreeMemory)
{
*pusedMemory = 0;
*pfreeMemory = 0;
}
#define MemAlloc_MemoryAllocFailed() 0
#define MemAlloc_GetDebugInfoSize() 0
#define MemAlloc_SaveDebugInfo( pvDebugInfo ) ((void)0)
#define MemAlloc_RestoreDebugInfo( pvDebugInfo ) ((void)0)
#define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) ((void)0)
#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
#define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)
#endif
#if defined( POSIX ) && !defined( NO_HOOK_MALLOC )
PLATFORM_INTERFACE void MemoryLogMessage(char const* s);
PLATFORM_INTERFACE void EnableMemoryLogging(bool bOnOff);
PLATFORM_INTERFACE void DumpMemoryLog(int nThresh);
PLATFORM_INTERFACE void DumpMemorySummary(void);
PLATFORM_INTERFACE void SetMemoryMark(void);
PLATFORM_INTERFACE void DumpChangedMemory(int nThresh);
#else
FORCEINLINE void MemoryLogMessage(char const* s)
{
}
FORCEINLINE void EnableMemoryLogging(bool bOnOff)
{
}
FORCEINLINE void DumpMemoryLog(int nThresh)
{
}
FORCEINLINE void DumpMemorySummary(void)
{
}
FORCEINLINE void SetMemoryMark(void)
{
}
FORCEINLINE void DumpChangedMemory(int nThresh)
{
}
#endif
#ifdef POSIX
PLATFORM_INTERFACE size_t ApproximateProcessMemoryUsage(void);
#else
FORCEINLINE size_t ApproximateProcessMemoryUsage(void)
{
return 0;
}
#endif
struct aligned_tmp_t
{
};
template< int bytesAlignment = 16, class T = aligned_tmp_t >
class CAlignedNewDelete : public T
{
public:
void* operator new(size_t nSize)
{
return MemAlloc_AllocAligned(nSize, bytesAlignment);
}
void* operator new(size_t nSize, int nBlockUse, const char* pFileName, int nLine)
{
return MemAlloc_AllocAlignedFileLine(nSize, bytesAlignment, pFileName, nLine);
}
void operator delete(void* pData)
{
if (pData)
{
MemAlloc_FreeAligned(pData);
}
}
void operator delete(void* pData, int nBlockUse, const char* pFileName, int nLine)
{
if (pData)
{
MemAlloc_FreeAligned(pData, pFileName, nLine);
}
}
};
#endif