181 lines
6.6 KiB
C
181 lines
6.6 KiB
C
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
* Contains all memory macros.
|
|
* \file IceMemoryMacros.h
|
|
* \author Pierre Terdiman
|
|
* \date April, 4, 2000
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Include Guard
|
|
#ifndef ICEMEMORYMACROS_H
|
|
#define ICEMEMORYMACROS_H
|
|
|
|
#undef ZeroMemory
|
|
#undef CopyMemory
|
|
#undef MoveMemory
|
|
#undef FillMemory
|
|
|
|
//! Clears a buffer.
|
|
//! \param addr [in] buffer address
|
|
//! \param size [in] buffer length
|
|
//! \see FillMemory
|
|
//! \see StoreDwords
|
|
//! \see CopyMemory
|
|
//! \see MoveMemory
|
|
inline_ void ZeroMemory(void* addr, regsize size) { memset(addr, 0, size); }
|
|
|
|
//! Fills a buffer with a given byte.
|
|
//! \param addr [in] buffer address
|
|
//! \param size [in] buffer length
|
|
//! \param val [in] the byte value
|
|
//! \see StoreDwords
|
|
//! \see ZeroMemory
|
|
//! \see CopyMemory
|
|
//! \see MoveMemory
|
|
inline_ void FillMemory(void* dest, regsize size, ubyte val) { memset(dest, val, size); }
|
|
|
|
//! Fills a buffer with a given dword.
|
|
//! \param addr [in] buffer address
|
|
//! \param nb [in] number of dwords to write
|
|
//! \param value [in] the dword value
|
|
//! \see FillMemory
|
|
//! \see ZeroMemory
|
|
//! \see CopyMemory
|
|
//! \see MoveMemory
|
|
//! \warning writes nb*4 bytes !
|
|
inline_ void StoreDwords(udword* dest, udword nb, udword value)
|
|
{
|
|
// The asm code below **SHOULD** be equivalent to one of those C versions
|
|
// or the other if your compiled is good: (checked on VC++ 6.0)
|
|
//
|
|
// 1) while(nb--) *dest++ = value;
|
|
//
|
|
// 2) for(udword i=0;i<nb;i++) dest[i] = value;
|
|
//
|
|
_asm push eax
|
|
_asm push ecx
|
|
_asm push edi
|
|
_asm mov edi, dest
|
|
_asm mov ecx, nb
|
|
_asm mov eax, value
|
|
_asm rep stosd
|
|
_asm pop edi
|
|
_asm pop ecx
|
|
_asm pop eax
|
|
}
|
|
|
|
//! Copies a buffer.
|
|
//! \param addr [in] destination buffer address
|
|
//! \param addr [in] source buffer address
|
|
//! \param size [in] buffer length
|
|
//! \see ZeroMemory
|
|
//! \see FillMemory
|
|
//! \see StoreDwords
|
|
//! \see MoveMemory
|
|
inline_ void CopyMemory(void* dest, const void* src, regsize size) { memcpy(dest, src, size); }
|
|
|
|
//! Moves a buffer.
|
|
//! \param addr [in] destination buffer address
|
|
//! \param addr [in] source buffer address
|
|
//! \param size [in] buffer length
|
|
//! \see ZeroMemory
|
|
//! \see FillMemory
|
|
//! \see StoreDwords
|
|
//! \see CopyMemory
|
|
inline_ void MoveMemory(void* dest, const void* src, regsize size) { memmove(dest, src, size); }
|
|
|
|
//! Flexible buffer copy
|
|
//! \param src [in] source buffer address
|
|
//! \param dst [in] destination buffer address
|
|
//! \param nb_elem [in] number of elements to copy
|
|
//! \param elem_size [in] size of an element
|
|
//! \param stride [in] stride in bytes, including size of element
|
|
inline_ void FlexiCopy(const void* src, void* dst, udword nb_elem, regsize elem_size, udword stride)
|
|
{
|
|
ubyte* d = (ubyte*)dst;
|
|
const ubyte* s = (const ubyte*)src;
|
|
const ubyte* Last = s + stride*nb_elem;
|
|
while(s!=Last)
|
|
{
|
|
CopyMemory(d, s, elem_size);
|
|
d += elem_size;
|
|
s += stride;
|
|
}
|
|
}
|
|
|
|
//! Gives the size of current object. This avoids some mistakes (e.g. "sizeof(this)").
|
|
#define SIZEOFOBJECT sizeof(*this)
|
|
|
|
//! Clears current object. Laziness is my business! HANDLE WITH CARE. ### Removed, too dangerous, cleared too many v-tables
|
|
//#define CLEAROBJECT { memset(this, 0, SIZEOFOBJECT); }
|
|
|
|
// The two macros below are here for several reasons:
|
|
// - sometimes we write "delete x" instead of "delete []x" just because we don't pay attention. Using the macro forces you
|
|
// to think about what you're deleting, just because you have to write the macro's name (SINGLE or ARRAY).
|
|
// - always clearing the pointer afterwards prevents some double-deletion in various situations.
|
|
// - deleting null is a valid operation according to the standard, yet some lame memory managers don't like it. In sake of
|
|
// robustness, we avoid trying.
|
|
|
|
//! Deletes an instance of a class.
|
|
#define DELETESINGLE(x) if (x) { delete x; x = null; }
|
|
//! Deletes an array.
|
|
#define DELETEARRAY(x) if (x) { delete []x; x = null; }
|
|
|
|
//! Safe D3D-style release
|
|
#define SAFE_RELEASE(x) if (x) { (x)->Release(); (x) = null; }
|
|
|
|
//! Safe ICE-style release
|
|
#define SAFE_DESTRUCT(x) if (x) { (x)->SelfDestruct(); (x) = null; }
|
|
|
|
#ifdef ICEERROR_H
|
|
//! Standard alloc checking. HANDLE WITH CARE. Relies on strict coding rules. Probably shouldn't be used outside of ICE.
|
|
#define CHECKALLOC(x) if(!x) return SetIceError("Out of memory.", EC_OUT_OF_MEMORY);
|
|
#else
|
|
#define CHECKALLOC(x) if(!x) return false;
|
|
#endif
|
|
|
|
//! Standard allocation cycle
|
|
#define SAFE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = new type[count]; CHECKALLOC(ptr);
|
|
#define SAFE_ICE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = ICE_NEW(type)[count]; CHECKALLOC(ptr);
|
|
|
|
//! Don't use inline for alloca !!!
|
|
#ifdef WIN32
|
|
#define StackAlloc(x) _alloca(x)
|
|
#elif LINUX
|
|
#define StackAlloc(x) alloca(x)
|
|
#elif defined(__APPLE__)
|
|
#define StackAlloc(x) alloca(x)
|
|
#elif defined(_XBOX)
|
|
#define StackAlloc(x) _alloca(x)
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
// #define ICE_ALLOC_TMP(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #x, MEMORY_TEMP)
|
|
// #define ICE_ALLOC(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #x, MEMORY_PERSISTENT)
|
|
#define ICE_ALLOC_TMP(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, "(undefined)", MEMORY_TEMP)
|
|
#define ICE_ALLOC(x) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, "(undefined)", MEMORY_PERSISTENT)
|
|
#define ICE_ALLOC_TMP2(x, y) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #y, MEMORY_TEMP)
|
|
#define ICE_ALLOC2(x, y) GetAllocator()->mallocDebug(x, __FILE__, __LINE__, #y, MEMORY_PERSISTENT)
|
|
#else
|
|
#define ICE_ALLOC_TMP(x) GetAllocator()->malloc(x, MEMORY_TEMP)
|
|
#define ICE_ALLOC(x) GetAllocator()->malloc(x, MEMORY_PERSISTENT)
|
|
#endif
|
|
#define ICE_FREE(x) if(x) { GetAllocator()->free(x); x = null; }
|
|
|
|
#ifdef DONT_TRACK_MEMORY_LEAKS
|
|
#ifdef _DEBUG
|
|
#define ICE_NEW_TMP(x) new(__FILE__, __LINE__, #x, MEMORY_TEMP) x
|
|
#define ICE_NEW(x) new(__FILE__, __LINE__, #x, MEMORY_PERSISTENT) x
|
|
#else
|
|
#define ICE_NEW_TMP(x) new(MEMORY_TEMP) x
|
|
#define ICE_NEW(x) new(MEMORY_PERSISTENT) x
|
|
#endif
|
|
#else
|
|
#define ICE_NEW_TMP(x) new x
|
|
#define ICE_NEW(x) new x
|
|
#endif
|
|
|
|
#endif // ICEMEMORYMACROS_H
|