//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: This header should never be used directly from leaf code!!!
// Instead, just add the file memoverride.cpp into your project and all this
// will automagically be used
//
// $NoKeywords: $
//=============================================================================//

#ifndef TIER0_MEMALLOC_H
#define TIER0_MEMALLOC_H

#ifdef _WIN32
#pragma once
#endif

// These memory debugging switches aren't relevant under Linux builds since memoverride.cpp
// isn't built into Linux projects
#ifndef LINUX
// Define this in release to get memory tracking even in release builds
//#define USE_MEM_DEBUG 1

// Define this in release to get light memory debugging
//#define USE_LIGHT_MEM_DEBUG

// Define this to require -uselmd to turn light memory debugging on
//#define LIGHT_MEM_DEBUG_REQUIRES_CMD_LINE_SWITCH
#endif

#if defined( _MEMTEST )
#if defined( _WIN32 ) || defined( _PS3 )
#define USE_MEM_DEBUG 1
#endif
#endif


#if defined( _PS3 )
// Define STEAM_SHARES_GAME_ALLOCATOR to make Steam use the game's tier0 memory allocator.
// This adds some memory to the game's Small Block Heap and Medium Block Heap, to compensate.
// This configuration was disabled for Portal 2, as we could not sufficiently test it before ship.
//#define STEAM_SHARES_GAME_ALLOCATOR
#endif

#if defined( STEAM_SHARES_GAME_ALLOCATOR )
#define MBYTES_STEAM_SBH_USAGE 2
#define MBYTES_STEAM_MBH_USAGE 4
#else // STEAM_SHARES_GAME_ALLOCATOR
#define MBYTES_STEAM_SBH_USAGE 0
#define MBYTES_STEAM_MBH_USAGE 0
#endif // STEAM_SHARES_GAME_ALLOCATOR

// Undefine this if using a compiler lacking threadsafe RTTI (like vc6)
#define MEM_DEBUG_CLASSNAME 1

#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)

#include <stddef.h>
#ifdef LINUX
#undef offsetof
#define offsetof(s,m)	(size_t)&(((s *)0)->m)
#endif

#ifdef _PS3
#define MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS 1
#endif

#include "tier0/mem.h"

struct _CrtMemState;

#define MEMALLOC_VERSION 1

typedef size_t (*MemAllocFailHandler_t)( size_t );

struct GenericMemoryStat_t
{
	const char *name;
	int value;
};


// Virtual memory interface
#include "tier0/memvirt.h"


//-----------------------------------------------------------------------------
// NOTE! This should never be called directly from leaf code
// Just use new,delete,malloc,free etc. They will call into this eventually
//-----------------------------------------------------------------------------
abstract_class IMemAlloc
{
public:
	// Release versions
	virtual void *Alloc( size_t nSize ) = 0;
public:
	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;

	// Debug versions
    virtual void *Alloc( size_t nSize, const char *pFileName, int nLine ) = 0;
public:
    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;

#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
	virtual void *AllocAlign( size_t nSize, size_t align ) = 0;
	virtual void *AllocAlign( size_t nSize, size_t align, const char *pFileName, int nLine ) = 0;
	virtual void *ReallocAlign( void *pMem, size_t nSize, size_t align ) = 0;
#endif

	inline void *IndirectAlloc( size_t nSize )										{ return Alloc( nSize ); }
	inline void *IndirectAlloc( size_t nSize, const char *pFileName, int nLine )	{ return Alloc( nSize, pFileName, nLine ); }

	// Returns the size of a particular allocation (NOTE: may be larger than the size requested!)
	virtual size_t GetSize( void *pMem ) = 0;

    // Force file + line information for an allocation
    virtual void PushAllocDbgInfo( const char *pFileName, int nLine ) = 0;
    virtual void PopAllocDbgInfo() = 0;

	// FIXME: Remove when we have our own allocator
	// these methods of the Crt debug code is used in our codebase currently
	virtual int32 CrtSetBreakAlloc( int32 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;

	// FIXME: Make a better stats interface
	virtual void DumpStats() = 0;
	virtual void DumpStatsFileBase( char const *pchFileBase ) = 0;
	virtual size_t ComputeMemoryUsedBy( char const *pchSubStr ) = 0;

	// FIXME: Remove when we have our own allocator
	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, size_t nLogicalSize, size_t nActualSize, unsigned nTime ) = 0;
	virtual void RegisterDeallocation( const char *pFileName, int nLine, size_t nLogicalSize, size_t nActualSize, unsigned nTime ) = 0;

	virtual int GetVersion() = 0;

	virtual void CompactHeap() = 0;

	// Function called when malloc fails or memory limits hit to attempt to free up memory (can come in any thread)
	virtual MemAllocFailHandler_t SetAllocFailHandler( MemAllocFailHandler_t pfnMemAllocFailHandler ) = 0;

	virtual void DumpBlockStats( void * ) = 0;

	virtual void SetStatsExtraInfo( const char *pMapName, const char *pComment ) = 0;

	// Returns 0 if no failure, otherwise the size_t of the last requested chunk
	virtual size_t MemoryAllocFailed() = 0;

	virtual void CompactIncremental() = 0; 

	virtual void OutOfMemory( size_t nBytesAttempted = 0 ) = 0;

	// Region-based allocations
	virtual void *RegionAlloc( int region, size_t nSize ) = 0;
	virtual void *RegionAlloc( int region, size_t nSize, const char *pFileName, int nLine ) = 0;

	// Replacement for ::GlobalMemoryStatus which accounts for unused memory in our system
	virtual void GlobalMemoryStatus( size_t *pUsedMemory, size_t *pFreeMemory ) = 0;

	// Obtain virtual memory manager interface
	virtual IVirtualMemorySection * AllocateVirtualMemorySection( size_t numMaxBytes ) = 0;

	// Request 'generic' memory stats (returns a list of N named values; caller should assume this list will change over time)
	virtual int GetGenericMemoryStats( GenericMemoryStat_t **ppMemoryStats ) = 0;

	virtual ~IMemAlloc() { };

	// handles storing allocation info for coroutines
	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;
};

//-----------------------------------------------------------------------------
// Singleton interface
//-----------------------------------------------------------------------------
#ifdef _PS3

PLATFORM_INTERFACE IMemAlloc * g_pMemAllocInternalPS3;
#ifndef PLATFORM_INTERFACE_MEM_ALLOC_INTERNAL_PS3_OVERRIDE
#define g_pMemAlloc g_pMemAllocInternalPS3
#else
#define g_pMemAlloc PLATFORM_INTERFACE_MEM_ALLOC_INTERNAL_PS3_OVERRIDE
#endif

#else // !_PS3

MEM_INTERFACE IMemAlloc *g_pMemAlloc;

#endif

//-----------------------------------------------------------------------------

#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->IndirectAlloc( nSize );
}

inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName, int nLine )
{ 
	return g_pMemAlloc->IndirectAlloc( nSize, pFileName, nLine );
}
#endif

//-----------------------------------------------------------------------------

#ifdef MEMALLOC_REGIONS
#else
#endif


inline bool ValueIsPowerOfTwo( size_t value )			// don't clash with mathlib definition
{
	return (value & ( value - 1 )) == 0;
}


inline void *MemAlloc_AllocAlignedUnattributed( size_t size, size_t align )
{
#ifndef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS

	unsigned char *pAlloc, *pResult;

#endif

	if (!ValueIsPowerOfTwo(align))
		return NULL;

#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS

	return g_pMemAlloc->AllocAlign( size, align );

#else

	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;

#endif
}

inline void *MemAlloc_AllocAlignedFileLine( size_t size, size_t align, const char *pszFile, int nLine )
{
#ifndef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS

	unsigned char *pAlloc, *pResult;

#endif

	if (!ValueIsPowerOfTwo(align))
		return NULL;

#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS

	return g_pMemAlloc->AllocAlign( size, align, pszFile, nLine );

#else

	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;

#endif
}

#ifdef USE_MEM_DEBUG
#define MemAlloc_AllocAligned( s, a )	MemAlloc_AllocAlignedFileLine( s, a, __FILE__, __LINE__ )
#elif defined(USE_LIGHT_MEM_DEBUG)
extern const char *g_pszModule; 
#define MemAlloc_AllocAligned( s, a )	MemAlloc_AllocAlignedFileLine( s, a, g_pszModule, 0 )
#else
#define MemAlloc_AllocAligned( s, a )	MemAlloc_AllocAlignedUnattributed( s, a )
#endif


inline void *MemAlloc_ReallocAligned( void *ptr, size_t size, size_t align )
{
	if ( !ValueIsPowerOfTwo( align ) )
		return NULL;

	// Don't change alignment between allocation + reallocation.
	if ( ( (size_t)ptr & ( align - 1 ) ) != 0 )
		return NULL;

#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS

	return g_pMemAlloc->ReallocAlign( ptr, size, align );

#else

	if ( !ptr )
		return MemAlloc_AllocAligned( size, align );

	void *pAlloc, *pResult;

	// Figure out the actual allocation point
	pAlloc = ptr;
	pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
	pAlloc = *( (void **)pAlloc );

	// See if we have enough space
	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;

#endif
}

inline void MemAlloc_FreeAligned( void *pMemBlock )
{
#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS

	g_pMemAlloc->Free( pMemBlock );

#else

	void *pAlloc;

	if ( pMemBlock == NULL )
		return;

	pAlloc = pMemBlock;

	// pAlloc points to the pointer to starting of the memory block
	pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));

	// pAlloc is the pointer to the start of memory block
	pAlloc = *( (void **)pAlloc );

	g_pMemAlloc->Free( pAlloc );

#endif
}

inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pszFile, int nLine )
{
#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS

	g_pMemAlloc->Free( pMemBlock, pszFile, nLine );

#else

	void *pAlloc;

	if ( pMemBlock == NULL )
		return;

	pAlloc = pMemBlock;

	// pAlloc points to the pointer to starting of the memory block
	pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));

	// pAlloc is the pointer to the start of memory block
	pAlloc = *( (void **)pAlloc );
	g_pMemAlloc->Free( pAlloc, pszFile, nLine );

#endif
}

inline size_t MemAlloc_GetSizeAligned( void *pMemBlock )
{
#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS

	return g_pMemAlloc->GetSize( pMemBlock );

#else

	void *pAlloc;

	if ( pMemBlock == NULL )
		return 0;

	pAlloc = pMemBlock;

	// pAlloc points to the pointer to starting of the memory block
	pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));

	// pAlloc is the pointer to the start of memory block
	pAlloc = *((void **)pAlloc );
	return g_pMemAlloc->GetSize( pAlloc ) - ( (byte *)pMemBlock - (byte *)pAlloc );

#endif
}


struct aligned_tmp_t
{
	// empty base class
};

// template here to allow adding alignment at levels of hierarchy that aren't the base
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 );
		}
	}
};

//-----------------------------------------------------------------------------

#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

//-----------------------------------------------------------------------------

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(MSVC) && ( defined(_DEBUG) || defined(USE_MEM_DEBUG) )

	#pragma warning(disable:4290)
	#pragma warning(push)
	#include <typeinfo.h>

	// MEM_DEBUG_CLASSNAME is opt-in.
	// Note: typeid().name() is not threadsafe, so if the project needs to access it in multiple threads
	// simultaneously, it'll need a mutex.
	#if defined(_CPPRTTI) && defined(MEM_DEBUG_CLASSNAME)

		template <typename T> const char *MemAllocClassName( T *p )
		{
			static const char *pszName = typeid(*p).name(); // @TODO: support having debug heap ignore certain allocations, and ignore memory allocated here [5/7/2009 tom]
			return pszName;
		}

		#define MEM_ALLOC_CREDIT_CLASS()	MEM_ALLOC_CREDIT_( MemAllocClassName( this ) )
		#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

	// MEM_ALLOC_CREDIT_FUNCTION is used when no this pointer is available ( inside 'new' overloads, for example )
	#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> s_##tag##Allocs( DefLessFunc( void *) ); \
	CUtlMap<void *, MemAllocFileLine_t, int> * g_p##tag##Allocs = &s_##tag##Allocs; \
	static CThreadFastMutex s_##tag##AllocsMutex; \
	CThreadFastMutex * g_p##tag##AllocsMutex = &s_##tag##AllocsMutex; \
	const char * g_psz##tag##Alloc = strcpy( (char *)MemAlloc_Alloc( strlen( #tag "Alloc" ) + 1, "intentional leak", 0 ), #tag "Alloc" );

#define MEMALLOC_DECLARE_EXTERNAL_TRACKING( tag ) \
	extern CUtlMap<void *, MemAllocFileLine_t, int> * g_p##tag##Allocs; \
	extern CThreadFastMutex *g_p##tag##AllocsMutex; \
	extern const char * g_psz##tag##Alloc;

#define MemAlloc_RegisterExternalAllocation( tag, p, size ) \
	if ( !p ) \
		; \
	else \
	{ \
		AUTO_LOCK_FM( *g_p##tag##AllocsMutex ); \
		MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
		g_pMemAlloc->GetActualDbgInfo( fileLine.pszFile, fileLine.line ); \
		if ( fileLine.pszFile != g_psz##tag##Alloc ) \
		{ \
			g_p##tag##Allocs->Insert( p, fileLine ); \
		} \
		\
		MemAlloc_RegisterAllocation( fileLine.pszFile, fileLine.line, size, size, 0); \
	}

#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) \
	if ( !p ) \
		; \
	else \
	{ \
		AUTO_LOCK_FM( *g_p##tag##AllocsMutex ); \
		MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
		CUtlMap<void *, MemAllocFileLine_t, int>::IndexType_t iRecordedFileLine = g_p##tag##Allocs->Find( p ); \
		if ( iRecordedFileLine != g_p##tag##Allocs->InvalidIndex() ) \
		{ \
			fileLine = (*g_p##tag##Allocs)[iRecordedFileLine]; \
			g_p##tag##Allocs->RemoveAt( iRecordedFileLine ); \
		} \
		\
		MemAlloc_RegisterDeallocation( fileLine.pszFile, fileLine.line, size, size, 0); \
	}

#else

#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
#define MEMALLOC_DECLARE_EXTERNAL_TRACKING( tag )
#define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)

#endif

//-----------------------------------------------------------------------------

#endif // !STEAM && !NO_MALLOC_OVERRIDE

//-----------------------------------------------------------------------------

#if !defined(STEAM) && defined(NO_MALLOC_OVERRIDE)
#include <malloc.h>

#define MEM_ALLOC_CREDIT_(tag)	((void)0)
#define MEM_ALLOC_CREDIT()	MEM_ALLOC_CREDIT_(__FILE__)
#define MEM_ALLOC_CREDIT_CLASS()
#define MEM_ALLOC_CLASSNAME(type) NULL

#define MemAlloc_PushAllocDbgInfo( pszFile, line )
#define MemAlloc_PopAllocDbgInfo()

#define MemAlloc_RegisterAllocation( a,b,c,d,e ) ((void)0)
#define MemAlloc_RegisterDeallocation( a,b,c,d,e ) ((void)0)

#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
#define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)

inline void *MemAlloc_AllocAligned( size_t size, size_t align )
{
	return (void *)_aligned_malloc( size, align );
}
inline void *MemAlloc_AllocAligned( size_t size, size_t align, const char *pszFile, int nLine )
{
	pszFile = pszFile;
	nLine = nLine;
	return (void *)_aligned_malloc( size, align );
}

inline void MemAlloc_FreeAligned( void *pMemBlock )
{
	_aligned_free( pMemBlock );
}
inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pszFile, int nLine )
{
	pszFile = pszFile;
	nLine = nLine;
	_aligned_free( pMemBlock );
}

#endif // !STEAM && NO_MALLOC_OVERRIDE

//-----------------------------------------------------------------------------



// linux memory tracking via hooks.
#if defined( POSIX ) && !defined( _PS3 )
PLATFORM_INTERFACE void MemoryLogMessage( char const *s );						// throw a message into the memory log
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 );

// ApproximateProcessMemoryUsage returns the approximate memory footprint of this process.
PLATFORM_INTERFACE size_t ApproximateProcessMemoryUsage( void );
#else
inline void MemoryLogMessage( char const * )
{
}
inline void EnableMemoryLogging( bool )
{
}
inline void DumpMemoryLog( int )
{
}
inline void DumpMemorySummary( void )
{
}
inline void SetMemoryMark( void )
{
}
inline void DumpChangedMemory( int )
{
}
inline size_t ApproximateProcessMemoryUsage( void )
{
	return 0;
}
#endif


#endif /* TIER0_MEMALLOC_H */