1237 lines
28 KiB
C++
1237 lines
28 KiB
C++
|
|
#include "fmod_settings.h"
|
||
|
|
|
||
|
|
#include "fmod.h"
|
||
|
|
#include "fmod_debug.h"
|
||
|
|
#include "fmod_memory.h"
|
||
|
|
#include "fmod_os_misc.h"
|
||
|
|
#include "fmod_string.h"
|
||
|
|
#include "fmod_types.h"
|
||
|
|
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
|
||
|
|
#ifdef DEBUG
|
||
|
|
#include <assert.h>
|
||
|
|
#endif
|
||
|
|
|
||
|
|
//#define FMOD_MEMORY_ALLOC_FAIL_RANDOM 30
|
||
|
|
//#define FMOD_MEMORY_ALLOC_FAIL_AFTER 822
|
||
|
|
#ifdef FMOD_MEMORY_ALLOC_FAIL_AFTER
|
||
|
|
static int FMOD_Memory_FailCount = 0;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef FMOD_MEMORY_ALLOC_FAIL_RANDOM
|
||
|
|
#include <time.h>
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#define FMOD_MEMORY_BYTESTOBLOCKS(_pool, _bytes) (((_bytes) + (mBlockSize - 1)) / mBlockSize)
|
||
|
|
|
||
|
|
|
||
|
|
extern "C"
|
||
|
|
{
|
||
|
|
void *FMOD_Memory_allocC(int len, const char *file, const int line)
|
||
|
|
{
|
||
|
|
return FMOD::gGlobal->gSystemPool->alloc(len, file, line);
|
||
|
|
}
|
||
|
|
void *FMOD_Memory_callocC(int len, const char *file, const int line)
|
||
|
|
{
|
||
|
|
return FMOD::gGlobal->gSystemPool->calloc(len, file, line);
|
||
|
|
}
|
||
|
|
|
||
|
|
void *FMOD_Memory_reallocC(void *ptr, int len, const char *file, const int line)
|
||
|
|
{
|
||
|
|
return FMOD::gGlobal->gSystemPool->realloc(ptr, len, file, line);
|
||
|
|
}
|
||
|
|
|
||
|
|
void FMOD_Memory_freeC(void *ptr, const char *file, const int line)
|
||
|
|
{
|
||
|
|
FMOD::gGlobal->gSystemPool->free(ptr, file, line);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
namespace FMOD
|
||
|
|
{
|
||
|
|
|
||
|
|
|
||
|
|
void *MemSingleton::alloc(int len, const char *file, const int line)
|
||
|
|
{
|
||
|
|
if (!mRefCount)
|
||
|
|
{
|
||
|
|
mBuffer = FMOD::gGlobal->gSystemPool->alloc(len, file, line);
|
||
|
|
FLOG((FMOD_DEBUG_TYPE_MEMORY, __FILE__, __LINE__, "MemSingleton::alloc", "Allocated a singleton memory buffer %d bytes\n", len));
|
||
|
|
}
|
||
|
|
mRefCount++;
|
||
|
|
|
||
|
|
return mBuffer;
|
||
|
|
}
|
||
|
|
|
||
|
|
void MemSingleton::free(const char *file, const int line)
|
||
|
|
{
|
||
|
|
if (mRefCount)
|
||
|
|
{
|
||
|
|
mRefCount--;
|
||
|
|
}
|
||
|
|
if (!mRefCount)
|
||
|
|
{
|
||
|
|
if (mBuffer)
|
||
|
|
{
|
||
|
|
FMOD::gGlobal->gSystemPool->free(mBuffer, file, line);
|
||
|
|
mBuffer = 0;
|
||
|
|
FLOG((FMOD_DEBUG_TYPE_MEMORY, __FILE__, __LINE__, "MemSingleton::free", "Freed singleton memory buffer\n"));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
The wrapper is needed to handle stdcall callbacks when malloc/free is normally cdecl
|
||
|
|
*/
|
||
|
|
void * F_CALLBACK Memory_DefaultMalloc(unsigned int size, FMOD_MEMORY_TYPE type)
|
||
|
|
{
|
||
|
|
return FMOD_OS_Memory_Alloc(size, type);
|
||
|
|
}
|
||
|
|
void * F_CALLBACK Memory_DefaultRealloc(void *data, unsigned int size, FMOD_MEMORY_TYPE type)
|
||
|
|
{
|
||
|
|
return FMOD_OS_Memory_Realloc(data, size, type);
|
||
|
|
}
|
||
|
|
void F_CALLBACK Memory_DefaultFree(void *ptr, FMOD_MEMORY_TYPE type)
|
||
|
|
{
|
||
|
|
FMOD_OS_Memory_Free(ptr, type);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
void
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
MemPool::MemPool()
|
||
|
|
{
|
||
|
|
int count;
|
||
|
|
|
||
|
|
mAlloc = Memory_DefaultMalloc;
|
||
|
|
mRealloc = Memory_DefaultRealloc;
|
||
|
|
mFree = Memory_DefaultFree;
|
||
|
|
#ifdef FMOD_MEMORY_THREADSAFE
|
||
|
|
mCrit = 0;
|
||
|
|
#endif
|
||
|
|
for (count = 0; count < FMOD_MEMORY_MAXTHREADS; count++)
|
||
|
|
{
|
||
|
|
mCurrentAllocated[count] = 0;
|
||
|
|
mCurrentAllocatedThreadID[count] = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
mCurrentAllocatedSecondary = 0;
|
||
|
|
mMaxAllocatedSecondary = 0;
|
||
|
|
|
||
|
|
#ifdef FMOD_SUPPORT_DLMALLOC
|
||
|
|
mDLMallocSpace = 0;
|
||
|
|
#endif
|
||
|
|
#ifdef FMOD_DEBUG
|
||
|
|
mAllocCount = 0;
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
void
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
MemPool::~MemPool()
|
||
|
|
{
|
||
|
|
close();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
void
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
FMOD_RESULT MemPool::init(void *poolmem, int poolsize, int blocksize)
|
||
|
|
{
|
||
|
|
FMOD_RESULT result;
|
||
|
|
void *oldpoolmem = poolmem;
|
||
|
|
int count;
|
||
|
|
|
||
|
|
if (!poolmem || !poolsize)
|
||
|
|
{
|
||
|
|
return FMOD_ERR_MEMORY;
|
||
|
|
}
|
||
|
|
|
||
|
|
close();
|
||
|
|
|
||
|
|
#define ALIGNMENT 256
|
||
|
|
|
||
|
|
/*
|
||
|
|
Align the pool memory and reduce the pool size by the number of bytes we had to align by.
|
||
|
|
*/
|
||
|
|
poolmem = (unsigned char *)FMOD_ALIGNPOINTER(poolmem, ALIGNMENT);
|
||
|
|
poolsize -= (int)((FMOD_SINT_NATIVE)poolmem - (FMOD_SINT_NATIVE)oldpoolmem);
|
||
|
|
poolsize &= ~((unsigned int)blocksize-1);
|
||
|
|
|
||
|
|
#ifdef FMOD_SUPPORT_DLMALLOC
|
||
|
|
mDLMallocSpace = create_mspace_with_base(poolmem, poolsize, 0);
|
||
|
|
if (!mDLMallocSpace)
|
||
|
|
{
|
||
|
|
return FMOD_ERR_MEMORY;
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
int bitmapsize;
|
||
|
|
|
||
|
|
mBlockSize = blocksize;
|
||
|
|
#ifdef FMOD_MEMORY_USEBITS
|
||
|
|
bitmapsize = FMOD_MEMORY_BYTESTOBLOCKS(pool, (poolsize + 7) / 8);
|
||
|
|
#else
|
||
|
|
bitmapsize = FMOD_MEMORY_BYTESTOBLOCKS(pool, poolsize);
|
||
|
|
#endif
|
||
|
|
bitmapsize += (blocksize-1);
|
||
|
|
bitmapsize &= ~(blocksize-1);
|
||
|
|
|
||
|
|
mSizeBlocks = FMOD_MEMORY_BYTESTOBLOCKS(pool, poolsize - bitmapsize);
|
||
|
|
mSizeBytes = mSizeBlocks * mBlockSize;
|
||
|
|
mBitmap = (unsigned char *)poolmem;
|
||
|
|
mData = mBitmap + bitmapsize;
|
||
|
|
|
||
|
|
set(0, 0, mSizeBlocks);
|
||
|
|
|
||
|
|
FMOD_memset(mData, 0, mSizeBytes);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
mNumBlocks = 0;
|
||
|
|
mMaxBlocks = 0;
|
||
|
|
mMaxAllocated = 0;
|
||
|
|
mMaxAllocatedSecondary = 0;
|
||
|
|
mActualMaxBytes = 0;
|
||
|
|
mWastage = 0;
|
||
|
|
mFirstFreeBlock = 0;
|
||
|
|
mCurrentAllocatedSecondary = 0;
|
||
|
|
for (count = 0; count < FMOD_MEMORY_MAXTHREADS; count++)
|
||
|
|
{
|
||
|
|
mCurrentAllocated[count] = 0;
|
||
|
|
mCurrentAllocatedThreadID[count] = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef FMOD_MEMORY_THREADSAFE
|
||
|
|
result = FMOD_OS_CriticalSection_Create(&mCrit, true);
|
||
|
|
if (result != FMOD_OK)
|
||
|
|
{
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return FMOD_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
void
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
FMOD_RESULT MemPool::initCustom(void *poolmem, int poolsize, int blocksize)
|
||
|
|
{
|
||
|
|
FMOD_RESULT result;
|
||
|
|
int bitmapsize, count;
|
||
|
|
|
||
|
|
if (!poolsize)
|
||
|
|
{
|
||
|
|
return FMOD_ERR_MEMORY;
|
||
|
|
}
|
||
|
|
|
||
|
|
close();
|
||
|
|
|
||
|
|
mBlockSize = blocksize;
|
||
|
|
mSizeBlocks = FMOD_MEMORY_BYTESTOBLOCKS(pool, poolsize);
|
||
|
|
mSizeBlocks = mSizeBlocks & 0xFFFFFFFC;
|
||
|
|
mSizeBytes = mSizeBlocks * mBlockSize;
|
||
|
|
|
||
|
|
#ifdef FMOD_MEMORY_USEBITS
|
||
|
|
bitmapsize = (mSizeBlocks + 7) / 8;
|
||
|
|
#else
|
||
|
|
bitmapsize = mSizeBlocks;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
mBitmap = (unsigned char *)FMOD_Memory_Alloc(bitmapsize);
|
||
|
|
if (!mBitmap)
|
||
|
|
{
|
||
|
|
return FMOD_ERR_MEMORY;
|
||
|
|
}
|
||
|
|
mData = (unsigned char *)poolmem;
|
||
|
|
|
||
|
|
set(0, 0, mSizeBlocks);
|
||
|
|
|
||
|
|
mNumBlocks = 0;
|
||
|
|
mMaxBlocks = 0;
|
||
|
|
mMaxAllocated = 0;
|
||
|
|
mActualMaxBytes = 0;
|
||
|
|
mWastage = 0;
|
||
|
|
mCustomPool = true;
|
||
|
|
mFirstFreeBlock = 0;
|
||
|
|
|
||
|
|
for (count = 0; count < FMOD_MEMORY_MAXTHREADS; count++)
|
||
|
|
{
|
||
|
|
mCurrentAllocated[count] = 0;
|
||
|
|
mCurrentAllocatedThreadID[count] = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
mAlloc = 0;
|
||
|
|
mRealloc = 0;
|
||
|
|
mFree = 0;
|
||
|
|
|
||
|
|
#ifdef FMOD_MEMORY_THREADSAFE
|
||
|
|
result = FMOD_OS_CriticalSection_Create(&mCrit);
|
||
|
|
if (result != FMOD_OK)
|
||
|
|
{
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return FMOD_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
void
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
void MemPool::close()
|
||
|
|
{
|
||
|
|
int count;
|
||
|
|
|
||
|
|
if (mCustomPool && mBitmap)
|
||
|
|
{
|
||
|
|
FMOD_Memory_Free(mBitmap);
|
||
|
|
}
|
||
|
|
|
||
|
|
mBitmap = 0;
|
||
|
|
mData = 0;
|
||
|
|
mSizeBytes = 0;
|
||
|
|
mSizeBlocks = 0;
|
||
|
|
mNumBlocks = 0;
|
||
|
|
mMaxBlocks = 0;
|
||
|
|
mMaxAllocated = 0;
|
||
|
|
|
||
|
|
for (count = 0; count < FMOD_MEMORY_MAXTHREADS; count++)
|
||
|
|
{
|
||
|
|
mCurrentAllocated[count] = 0;
|
||
|
|
mCurrentAllocatedThreadID[count] = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
mAlloc = Memory_DefaultMalloc;
|
||
|
|
mRealloc = Memory_DefaultRealloc;
|
||
|
|
mFree = Memory_DefaultFree;
|
||
|
|
mCustomPool = false;
|
||
|
|
|
||
|
|
#ifdef FMOD_MEMORY_THREADSAFE
|
||
|
|
if (mCrit)
|
||
|
|
{
|
||
|
|
FMOD_OS_CriticalSection_Free(mCrit, true);
|
||
|
|
mCrit = 0;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
void MemPool::set(int blockoffset, int value, int numblocks)
|
||
|
|
{
|
||
|
|
#ifdef FMOD_MEMORY_USEBITS
|
||
|
|
int byteoffset;
|
||
|
|
int bitoffset;
|
||
|
|
int count;
|
||
|
|
int blocksleft;
|
||
|
|
|
||
|
|
blocksleft = numblocks;
|
||
|
|
byteoffset = blockoffset / 8;
|
||
|
|
bitoffset = blockoffset & 7;
|
||
|
|
|
||
|
|
/*
|
||
|
|
First align the blocks to a 32 block boundary, so we can then do a dword at a time.
|
||
|
|
*/
|
||
|
|
count = 0;
|
||
|
|
if (blockoffset & 31)
|
||
|
|
{
|
||
|
|
count = 32 - (blockoffset & 31);
|
||
|
|
if (count > numblocks)
|
||
|
|
{
|
||
|
|
count = numblocks;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
while (count)
|
||
|
|
{
|
||
|
|
if (value)
|
||
|
|
{
|
||
|
|
mBitmap[byteoffset] |= (1<<bitoffset);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
mBitmap[byteoffset] &= ~(1<<bitoffset);
|
||
|
|
}
|
||
|
|
|
||
|
|
bitoffset++;
|
||
|
|
if (bitoffset >= 8)
|
||
|
|
{
|
||
|
|
bitoffset = 0;
|
||
|
|
byteoffset++;
|
||
|
|
}
|
||
|
|
count--;
|
||
|
|
blocksleft--;
|
||
|
|
}
|
||
|
|
|
||
|
|
count = blocksleft / 8;
|
||
|
|
if (count)
|
||
|
|
{
|
||
|
|
FMOD_memset(&mBitmap[byteoffset], value ? 0xFF : 0, count);
|
||
|
|
|
||
|
|
byteoffset += count;
|
||
|
|
blocksleft -= count * 8;
|
||
|
|
}
|
||
|
|
|
||
|
|
count = blocksleft & 31;
|
||
|
|
while (count)
|
||
|
|
{
|
||
|
|
if (value)
|
||
|
|
{
|
||
|
|
mBitmap[byteoffset] |= (1<<bitoffset);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
mBitmap[byteoffset] &= ~(1<<bitoffset);
|
||
|
|
}
|
||
|
|
|
||
|
|
bitoffset++;
|
||
|
|
if (bitoffset >= 8)
|
||
|
|
{
|
||
|
|
bitoffset = 0;
|
||
|
|
byteoffset++;
|
||
|
|
}
|
||
|
|
count--;
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
FMOD_memset(&mBitmap[blockoffset], value, numblocks);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (value)
|
||
|
|
{
|
||
|
|
if (blockoffset == mFirstFreeBlock) /* Only move firstfree forward if it is the firstfree block that is being used. */
|
||
|
|
{
|
||
|
|
mFirstFreeBlock = blockoffset + numblocks;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
If mFirstFreeBlock is now pointing to a used block because we just filled in a hole. Scan it forward.
|
||
|
|
*/
|
||
|
|
#ifdef FMOD_MEMORY_USEBITS
|
||
|
|
byteoffset = mFirstFreeBlock / 8;
|
||
|
|
bitoffset = mFirstFreeBlock & 7;
|
||
|
|
if (mBitmap[byteoffset] & (1 << bitoffset))
|
||
|
|
#else
|
||
|
|
if (mBitmap[mFirstFreeBlock])
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
mFirstFreeBlock = findFreeBlocks(mFirstFreeBlock, mSizeBlocks, 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (blockoffset < mFirstFreeBlock)
|
||
|
|
{
|
||
|
|
mFirstFreeBlock = blockoffset;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
int MemPool::findFreeBlocks(int offset, int to, int numblocks)
|
||
|
|
{
|
||
|
|
int found = 0;
|
||
|
|
#ifdef FMOD_MEMORY_USEBITS
|
||
|
|
int one_ls_bitoffset, byteoffset;
|
||
|
|
|
||
|
|
byteoffset = offset >> 3;
|
||
|
|
one_ls_bitoffset = (1 << (offset & 7));
|
||
|
|
|
||
|
|
while (found < numblocks && offset < to && offset < mSizeBlocks)
|
||
|
|
{
|
||
|
|
if (mBitmap[byteoffset] & one_ls_bitoffset || (!(offset & 31) && *((unsigned int *)&mBitmap[byteoffset]) == 0xFFFFFFFF))
|
||
|
|
{
|
||
|
|
found = 0;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
found++;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(offset & 31) && *((unsigned int *)&mBitmap[byteoffset]) == 0xFFFFFFFF)
|
||
|
|
{
|
||
|
|
byteoffset += 4;
|
||
|
|
offset += 32;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
offset++;
|
||
|
|
|
||
|
|
one_ls_bitoffset *= 2;
|
||
|
|
if (!(offset & 7))
|
||
|
|
{
|
||
|
|
one_ls_bitoffset = 1;
|
||
|
|
byteoffset++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#else
|
||
|
|
|
||
|
|
while (found < numblocks && offset < to && offset < mSizeBlocks)
|
||
|
|
{
|
||
|
|
if (mBitmap[offset])
|
||
|
|
{
|
||
|
|
found = 0;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
found++;
|
||
|
|
}
|
||
|
|
|
||
|
|
offset++;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (found == numblocks)
|
||
|
|
{
|
||
|
|
offset -= numblocks;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
offset = -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
return offset;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
void *MemPool::alloc(int len, const char *file, const int line, FMOD_MEMORY_TYPE type, bool clear)
|
||
|
|
{
|
||
|
|
#ifdef FMOD_DEBUG
|
||
|
|
++mAllocCount;
|
||
|
|
#endif
|
||
|
|
MemBlockHeader *block = 0;
|
||
|
|
int numblocks = 0, reallen = len;
|
||
|
|
|
||
|
|
{
|
||
|
|
#ifdef FMOD_MEMORY_ALLOC_FAIL_RANDOM
|
||
|
|
srand(clock());
|
||
|
|
if (
|
||
|
|
#ifdef FMOD_MEMORY_ALLOC_FAIL_AFTER
|
||
|
|
FMOD_Memory_FailCount >= FMOD_MEMORY_ALLOC_FAIL_AFTER &&
|
||
|
|
#endif
|
||
|
|
!(FMOD_RAND() % FMOD_MEMORY_ALLOC_FAIL_RANDOM))
|
||
|
|
{
|
||
|
|
FLOG(((FMOD_DEBUGLEVEL)(FMOD_DEBUG_TYPE_MEMORY | FMOD_DEBUG_LEVEL_ERROR), __FILE__, __LINE__, "MemPool::alloc", "Failed allocating %-45s line %5d. Wanted %d bytes, current %d/%d (rounding wastage = %d bytes)\n", file, line, len, mCurrentAllocated[0], mSizeBytes, mWastage));
|
||
|
|
|
||
|
|
if (FMOD::gGlobal->gSystemCallback)
|
||
|
|
{
|
||
|
|
char fileLine[256];
|
||
|
|
sprintf(fileLine, "%s (%d)", file, line);
|
||
|
|
|
||
|
|
FMOD::gGlobal->gSystemCallback(NULL, FMOD_SYSTEM_CALLBACKTYPE_MEMORYALLOCATIONFAILED, (void*)fileLine, (void*)len);
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
#elif defined(FMOD_MEMORY_ALLOC_FAIL_AFTER)
|
||
|
|
if (FMOD_Memory_FailCount >= FMOD_MEMORY_ALLOC_FAIL_AFTER)
|
||
|
|
{
|
||
|
|
FLOG(((FMOD_DEBUGLEVEL)(FMOD_DEBUG_TYPE_MEMORY | FMOD_DEBUG_LEVEL_ERROR), __FILE__, __LINE__, "MemPool::alloc", "Failed allocating %-45s line %5d. Wanted %d bytes, current %d/%d (rounding wastage = %d bytes)\n", file, line, len, mCurrentAllocated[0], mSizeBytes, mWastage));
|
||
|
|
|
||
|
|
if (FMOD::gGlobal->gSystemCallback)
|
||
|
|
{
|
||
|
|
char fileLine[256];
|
||
|
|
sprintf(fileLine, "%s (%d)", file, line);
|
||
|
|
|
||
|
|
FMOD::gGlobal->gSystemCallback(NULL, FMOD_SYSTEM_CALLBACKTYPE_MEMORYALLOCATIONFAILED, (void*)fileLine, (void*)len);
|
||
|
|
}
|
||
|
|
|
||
|
|
FMOD_Memory_FailCount = 0;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
#ifdef FMOD_MEMORY_ALLOC_FAIL_AFTER
|
||
|
|
FMOD_Memory_FailCount++;
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef FMOD_MEMORY_THREADSAFE
|
||
|
|
if (!mCrit)
|
||
|
|
{
|
||
|
|
FMOD_RESULT result = FMOD_OS_CriticalSection_Create(&mCrit, true);
|
||
|
|
if (result != FMOD_OK)
|
||
|
|
{
|
||
|
|
FLOG((FMOD_DEBUG_LEVEL_ERROR, __FILE__, __LINE__, "MemPool::alloc", "Error creating critical section!\n"));
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
FMOD_OS_CriticalSection_Enter(mCrit);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (!mCustomPool)
|
||
|
|
{
|
||
|
|
reallen += sizeof(MemBlockHeader);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (mAlloc)
|
||
|
|
{
|
||
|
|
/*
|
||
|
|
Only want the flags that have been specified.
|
||
|
|
*/
|
||
|
|
type &= FMOD::gGlobal->gMemoryTypeFlags;
|
||
|
|
|
||
|
|
block = (MemBlockHeader *)mAlloc(reallen, type);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
#ifdef FMOD_SUPPORT_DLMALLOC
|
||
|
|
if (!mCustomPool)
|
||
|
|
{
|
||
|
|
block = (MemBlockHeader *)FMOD::mspace_malloc(mDLMallocSpace, reallen);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
numblocks = FMOD_MEMORY_BYTESTOBLOCKS(pool, reallen);
|
||
|
|
|
||
|
|
/*
|
||
|
|
Simple search for a free block in our memory pool. First fit.
|
||
|
|
*/
|
||
|
|
{
|
||
|
|
int offset;
|
||
|
|
|
||
|
|
offset = findFreeBlocks(mFirstFreeBlock, mSizeBlocks, numblocks);
|
||
|
|
if (offset >= 0)
|
||
|
|
{
|
||
|
|
set(offset, 1, numblocks);
|
||
|
|
|
||
|
|
if (mCustomPool)
|
||
|
|
{
|
||
|
|
block = (MemBlockHeader *)FMOD_Memory_Alloc(sizeof(MemBlockHeader));
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
block = (MemBlockHeader *)(mData + (offset * mBlockSize));
|
||
|
|
}
|
||
|
|
block->mBlockOffset = offset;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!block)
|
||
|
|
{
|
||
|
|
FLOG(((FMOD_DEBUGLEVEL)(FMOD_DEBUG_TYPE_MEMORY | FMOD_DEBUG_LEVEL_ERROR), __FILE__, __LINE__, "MemPool::alloc", "Failed allocating %-45s line %5d. Wanted %d bytes, current %d/%d (rounding wastage = %d bytes)\n", file, line, len, mCurrentAllocated[0], mSizeBytes, mWastage));
|
||
|
|
|
||
|
|
#ifdef FMOD_MEMORY_THREADSAFE
|
||
|
|
FMOD_OS_CriticalSection_Leave(mCrit);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (FMOD::gGlobal->gSystemCallback)
|
||
|
|
{
|
||
|
|
char fileLine[256];
|
||
|
|
sprintf(fileLine, "%s (%d)", file, line);
|
||
|
|
|
||
|
|
FMOD::gGlobal->gSystemCallback(NULL, FMOD_SYSTEM_CALLBACKTYPE_MEMORYALLOCATIONFAILED, (void*)fileLine, (void*)len);
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
block->mSize = len;
|
||
|
|
block->mNumBlocks = numblocks;
|
||
|
|
block->mThreadID = getCurrentThreadID();
|
||
|
|
|
||
|
|
if (type & FMOD_MEMORY_SECONDARY)
|
||
|
|
{
|
||
|
|
mCurrentAllocatedSecondary += block->mSize;
|
||
|
|
|
||
|
|
if (mCurrentAllocatedSecondary > mMaxAllocatedSecondary)
|
||
|
|
{
|
||
|
|
mMaxAllocatedSecondary = mCurrentAllocatedSecondary;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
mCurrentAllocated[0] += block->mSize; /* All threads. */
|
||
|
|
mCurrentAllocated[block->mThreadID] += block->mSize;
|
||
|
|
|
||
|
|
if (mCurrentAllocated[0] > mMaxAllocated)
|
||
|
|
{
|
||
|
|
mMaxAllocated = mCurrentAllocated[0];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
mNumBlocks += block->mNumBlocks;
|
||
|
|
if (mNumBlocks > mMaxBlocks)
|
||
|
|
{
|
||
|
|
mMaxBlocks = mNumBlocks;
|
||
|
|
mActualMaxBytes = mMaxBlocks * mBlockSize;
|
||
|
|
mWastage = mActualMaxBytes - mMaxAllocated;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!mCustomPool)
|
||
|
|
{
|
||
|
|
block++; /* return pointer to actual data, not our memory block header */
|
||
|
|
|
||
|
|
if (clear && block)
|
||
|
|
{
|
||
|
|
FMOD_memset(block, 0, len);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef FMOD_MEMORY_THREADSAFE
|
||
|
|
FMOD_OS_CriticalSection_Leave(mCrit);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
FLOG((FMOD_DEBUG_TYPE_MEMORY, file, line, "MemPool::alloc", "%6d bytes (%p) (alloc %d)\n", len, block, mAllocCount));
|
||
|
|
|
||
|
|
return block;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
void MemPool::free(void *ptr, const char *file, const int line, FMOD_MEMORY_TYPE type)
|
||
|
|
{
|
||
|
|
MemBlockHeader *block = (MemBlockHeader *)ptr;
|
||
|
|
|
||
|
|
#ifdef FMOD_MEMORY_THREADSAFE
|
||
|
|
if (!mCrit)
|
||
|
|
{
|
||
|
|
FMOD_RESULT result = FMOD_OS_CriticalSection_Create(&mCrit, true);
|
||
|
|
if (result != FMOD_OK)
|
||
|
|
{
|
||
|
|
FLOG((FMOD_DEBUG_LEVEL_ERROR, __FILE__, __LINE__, "MemPool::free", "Error creating critical section!\n"));
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
FMOD_OS_CriticalSection_Enter(mCrit);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (!mCustomPool)
|
||
|
|
{
|
||
|
|
block--; /* Find the actual block header */
|
||
|
|
}
|
||
|
|
|
||
|
|
FLOG((FMOD_DEBUG_TYPE_MEMORY, file, line, "MemPool::free", "%6d bytes (%p)\n", block->mSize, ptr));
|
||
|
|
|
||
|
|
#ifdef DEBUG
|
||
|
|
assert(block->mThreadID); /* If this is 0, it must have already been freed? */
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (type & FMOD_MEMORY_SECONDARY)
|
||
|
|
{
|
||
|
|
mCurrentAllocatedSecondary -= block->mSize;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
mCurrentAllocated[0] -= block->mSize;
|
||
|
|
mCurrentAllocated[block->mThreadID] -= block->mSize;
|
||
|
|
}
|
||
|
|
|
||
|
|
mNumBlocks -= block->mNumBlocks;
|
||
|
|
block->mThreadID = 0;
|
||
|
|
|
||
|
|
if (mFree)
|
||
|
|
{
|
||
|
|
/*
|
||
|
|
Only want the flags that have been specified.
|
||
|
|
*/
|
||
|
|
type &= FMOD::gGlobal->gMemoryTypeFlags;
|
||
|
|
|
||
|
|
mFree(block, type);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
#ifdef FMOD_SUPPORT_DLMALLOC
|
||
|
|
if (!mCustomPool)
|
||
|
|
{
|
||
|
|
mspace_free(mDLMallocSpace, block);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
set(block->mBlockOffset, 0, block->mNumBlocks);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef FMOD_MEMORY_THREADSAFE
|
||
|
|
FMOD_OS_CriticalSection_Leave(mCrit);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (mCustomPool)
|
||
|
|
{
|
||
|
|
FMOD_Memory_Free(block);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
void *MemPool::calloc(int len, const char *file, const int line, FMOD_MEMORY_TYPE type)
|
||
|
|
{
|
||
|
|
void *ptr;
|
||
|
|
|
||
|
|
ptr = alloc(len, file, line, type, true);
|
||
|
|
|
||
|
|
return ptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
void *MemPool::realloc(void *ptr, int len, const char *file, const int line, FMOD_MEMORY_TYPE type)
|
||
|
|
{
|
||
|
|
MemBlockHeader *block = (MemBlockHeader *)ptr;
|
||
|
|
int reallen = len, numblocks = 0;
|
||
|
|
|
||
|
|
if (!ptr)
|
||
|
|
{
|
||
|
|
return MemPool::alloc(len, file, line);
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
#ifdef FMOD_MEMORY_ALLOC_FAIL_RANDOM
|
||
|
|
srand(clock());
|
||
|
|
if (
|
||
|
|
#ifdef FMOD_MEMORY_ALLOC_FAIL_AFTER
|
||
|
|
FMOD_Memory_FailCount >= FMOD_MEMORY_ALLOC_FAIL_AFTER &&
|
||
|
|
#endif
|
||
|
|
!(FMOD_RAND() % FMOD_MEMORY_ALLOC_FAIL_RANDOM))
|
||
|
|
{
|
||
|
|
FLOG(((FMOD_DEBUGLEVEL)(FMOD_DEBUG_TYPE_MEMORY | FMOD_DEBUG_LEVEL_ERROR), __FILE__, __LINE__, "MemPool::realloc", "Failed allocating %-45s line %5d. Wanted %d bytes, current %d/%d (rounding wastage = %d bytes)\n", file, line, len, mCurrentAllocated[0], mSizeBytes, mWastage));
|
||
|
|
|
||
|
|
if (FMOD::gGlobal->gSystemCallback)
|
||
|
|
{
|
||
|
|
char fileLine[256];
|
||
|
|
sprintf(fileLine, "%s (%d)", file, line);
|
||
|
|
|
||
|
|
FMOD::gGlobal->gSystemCallback(NULL, FMOD_SYSTEM_CALLBACKTYPE_MEMORYALLOCATIONFAILED, (void*)fileLine, (void*)len);
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
#elif defined(FMOD_MEMORY_ALLOC_FAIL_AFTER)
|
||
|
|
if (FMOD_Memory_FailCount >= FMOD_MEMORY_ALLOC_FAIL_AFTER)
|
||
|
|
{
|
||
|
|
FLOG(((FMOD_DEBUGLEVEL)(FMOD_DEBUG_TYPE_MEMORY | FMOD_DEBUG_LEVEL_ERROR), __FILE__, __LINE__, "MemPool::realloc", "Failed allocating %-45s line %5d. Wanted %d bytes, current %d/%d (rounding wastage = %d bytes)\n", file, line, len, mCurrentAllocated[0], mSizeBytes, mWastage));
|
||
|
|
|
||
|
|
if (FMOD::gGlobal->gSystemCallback)
|
||
|
|
{
|
||
|
|
char fileLine[256];
|
||
|
|
sprintf(fileLine, "%s (%d)", file, line);
|
||
|
|
|
||
|
|
FMOD::gGlobal->gSystemCallback(NULL, FMOD_SYSTEM_CALLBACKTYPE_MEMORYALLOCATIONFAILED, (void*)fileLine, (void*)len);
|
||
|
|
}
|
||
|
|
|
||
|
|
FMOD_Memory_FailCount = 0;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
#ifdef FMOD_MEMORY_ALLOC_FAIL_AFTER
|
||
|
|
FMOD_Memory_FailCount++;
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef FMOD_MEMORY_THREADSAFE
|
||
|
|
if (!mCrit)
|
||
|
|
{
|
||
|
|
FMOD_RESULT result = FMOD_OS_CriticalSection_Create(&mCrit, true);
|
||
|
|
if (result != FMOD_OK)
|
||
|
|
{
|
||
|
|
FLOG((FMOD_DEBUG_LEVEL_ERROR, __FILE__, __LINE__, "MemPool::realloc", "Error creating critical section!\n"));
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
FMOD_OS_CriticalSection_Enter(mCrit);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (!mCustomPool)
|
||
|
|
{
|
||
|
|
reallen += sizeof(MemBlockHeader);
|
||
|
|
block--;
|
||
|
|
}
|
||
|
|
|
||
|
|
FLOG((FMOD_DEBUG_TYPE_MEMORY, file, line, "MemPool::realloc", "from %6d to %6d bytes\n", block->mSize, len));
|
||
|
|
|
||
|
|
mCurrentAllocated[0] -= block->mSize; /* All threads. */
|
||
|
|
mCurrentAllocated[block->mThreadID] -= block->mSize;
|
||
|
|
mNumBlocks -= block->mNumBlocks;
|
||
|
|
|
||
|
|
if (mRealloc)
|
||
|
|
{
|
||
|
|
/*
|
||
|
|
Only want the flags that have been specified.
|
||
|
|
*/
|
||
|
|
type &= FMOD::gGlobal->gMemoryTypeFlags;
|
||
|
|
|
||
|
|
block = (MemBlockHeader *)mRealloc(block, reallen, type);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
#ifdef FMOD_SUPPORT_DLMALLOC
|
||
|
|
if (!mCustomPool)
|
||
|
|
{
|
||
|
|
block = (MemBlockHeader *)mspace_realloc(mDLMallocSpace, block, reallen);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
int offset;
|
||
|
|
|
||
|
|
numblocks = FMOD_MEMORY_BYTESTOBLOCKS(pool, reallen);
|
||
|
|
|
||
|
|
set(block->mBlockOffset, 0, block->mNumBlocks);
|
||
|
|
|
||
|
|
offset = findFreeBlocks(block->mBlockOffset, block->mBlockOffset + numblocks, numblocks);
|
||
|
|
|
||
|
|
if (offset >= 0)
|
||
|
|
{
|
||
|
|
/*
|
||
|
|
We are able to simply extend the block
|
||
|
|
*/
|
||
|
|
set(offset, 1, numblocks);
|
||
|
|
block = (MemBlockHeader *)(mData + (offset * mBlockSize));
|
||
|
|
block->mBlockOffset = offset;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/*
|
||
|
|
We have to find a new place and move the data
|
||
|
|
*/
|
||
|
|
offset = findFreeBlocks(mFirstFreeBlock, mSizeBlocks, numblocks);
|
||
|
|
if (offset >= 0)
|
||
|
|
{
|
||
|
|
MemBlockHeader *newblock;
|
||
|
|
|
||
|
|
set(offset, 1, numblocks);
|
||
|
|
|
||
|
|
if (mCustomPool)
|
||
|
|
{
|
||
|
|
newblock = block;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
newblock = (MemBlockHeader *)(mData + (offset * mBlockSize));
|
||
|
|
}
|
||
|
|
|
||
|
|
newblock->mBlockOffset = offset;
|
||
|
|
|
||
|
|
if (!mCustomPool)
|
||
|
|
{
|
||
|
|
FMOD_memmove(newblock + 1, block + 1, block->mSize);
|
||
|
|
}
|
||
|
|
|
||
|
|
block = newblock;
|
||
|
|
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
block = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!block)
|
||
|
|
{
|
||
|
|
FLOG(((FMOD_DEBUGLEVEL)(FMOD_DEBUG_TYPE_MEMORY | FMOD_DEBUG_LEVEL_ERROR), __FILE__, __LINE__, "MemPool::realloc", "Failed allocating %-45s line %5d. Wanted %d bytes, current %d/%d (rounding wastage = %d bytes)\n", file, line, len, mCurrentAllocated[0], mSizeBytes, mWastage));
|
||
|
|
|
||
|
|
#ifdef FMOD_MEMORY_THREADSAFE
|
||
|
|
FMOD_OS_CriticalSection_Leave(mCrit);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (FMOD::gGlobal->gSystemCallback)
|
||
|
|
{
|
||
|
|
char fileLine[256];
|
||
|
|
sprintf(fileLine, "%s (%d)", file, line);
|
||
|
|
|
||
|
|
FMOD::gGlobal->gSystemCallback(NULL, FMOD_SYSTEM_CALLBACKTYPE_MEMORYALLOCATIONFAILED, (void*)fileLine, (void*)len);
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
block->mSize = len;
|
||
|
|
block->mNumBlocks = numblocks;
|
||
|
|
block->mThreadID = getCurrentThreadID();
|
||
|
|
|
||
|
|
mCurrentAllocated[0] += block->mSize; /* All threads. */
|
||
|
|
mCurrentAllocated[block->mThreadID] += block->mSize;
|
||
|
|
|
||
|
|
if (mCurrentAllocated[0] > mMaxAllocated)
|
||
|
|
{
|
||
|
|
mMaxAllocated = mCurrentAllocated[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
mNumBlocks += block->mNumBlocks;
|
||
|
|
if (mNumBlocks > mMaxBlocks)
|
||
|
|
{
|
||
|
|
mMaxBlocks = mNumBlocks;
|
||
|
|
mActualMaxBytes = mMaxBlocks * mBlockSize;
|
||
|
|
mWastage = mActualMaxBytes - mMaxAllocated;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!mCustomPool)
|
||
|
|
{
|
||
|
|
block++; /* return pointer to actual data, not our memory block header */
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef FMOD_MEMORY_THREADSAFE
|
||
|
|
FMOD_OS_CriticalSection_Leave(mCrit);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return block;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
int MemPool::getSize(void *ptr, const char *file, const int line)
|
||
|
|
{
|
||
|
|
MemBlockHeader *block = (MemBlockHeader *)ptr;
|
||
|
|
|
||
|
|
if (!mCustomPool)
|
||
|
|
{
|
||
|
|
block--; /* Find the actual block header */
|
||
|
|
}
|
||
|
|
|
||
|
|
return block->mSize;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
[API]
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
Callback to allocate a block of memory.
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
'size' Size in bytes of the memory block to be allocated and returned.
|
||
|
|
'type' Type of memory allocation.
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
On success, a pointer to the newly allocated block of memory is returned.
|
||
|
|
On failure, NULL is returned.
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
Returning an aligned pointer, of 16 byte alignment is recommended for speed purposes.
|
||
|
|
|
||
|
|
[PLATFORMS]
|
||
|
|
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation 2, PlayStation Portable, PlayStation 3, Wii, Solaris, iPhone
|
||
|
|
|
||
|
|
[SEE_ALSO]
|
||
|
|
Memory_Initialize
|
||
|
|
Memory_GetStats
|
||
|
|
FMOD_MEMORY_REALLOCCALLBACK
|
||
|
|
FMOD_MEMORY_FREECALLBACK
|
||
|
|
FMOD_MEMORY_TYPE
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
/*
|
||
|
|
void * F_CALLBACK FMOD_MEMORY_ALLOCCALLBACK(unsigned int size, FMOD_MEMORY_TYPE type)
|
||
|
|
{
|
||
|
|
#if 0
|
||
|
|
// here purely for documentation purposes.
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
*/
|
||
|
|
|
||
|
|
/*
|
||
|
|
[API]
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
Callback to re-allocate a block of memory to a different size.
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
'ptr' Pointer to a block of memory to be resized. If this is NULL then a new block of memory is simply allocated.
|
||
|
|
'size' Size of the memory to be reallocated. The original memory must be preserved.
|
||
|
|
'type' Type of memory allocation.
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
On success, a pointer to the newly re-allocated block of memory is returned.
|
||
|
|
On failure, NULL is returned.
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
Returning an aligned pointer, of 16 byte alignment is recommended for speed purposes.
|
||
|
|
|
||
|
|
[PLATFORMS]
|
||
|
|
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation 2, PlayStation Portable, PlayStation 3, Wii, Solaris, iPhone
|
||
|
|
|
||
|
|
[SEE_ALSO]
|
||
|
|
Memory_Initialize
|
||
|
|
Memory_GetStats
|
||
|
|
FMOD_MEMORY_ALLOCCALLBACK
|
||
|
|
FMOD_MEMORY_FREECALLBACK
|
||
|
|
FMOD_MEMORY_TYPE
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
/*
|
||
|
|
void * F_CALLBACK FMOD_MEMORY_REALLOCCALLBACK(void *ptr, unsigned int size, FMOD_MEMORY_TYPE type)
|
||
|
|
{
|
||
|
|
#if 0
|
||
|
|
// here purely for documentation purposes.
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
*/
|
||
|
|
|
||
|
|
/*
|
||
|
|
[API]
|
||
|
|
[
|
||
|
|
[DESCRIPTION]
|
||
|
|
Callback to free a block of memory.
|
||
|
|
|
||
|
|
[PARAMETERS]
|
||
|
|
'ptr' Pointer to a pre-existing block of memory to be freed.
|
||
|
|
'type' Type of memory to be freed.
|
||
|
|
|
||
|
|
[RETURN_VALUE]
|
||
|
|
void
|
||
|
|
|
||
|
|
[REMARKS]
|
||
|
|
|
||
|
|
[PLATFORMS]
|
||
|
|
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation 2, PlayStation Portable, PlayStation 3, Wii, Solaris, iPhone
|
||
|
|
|
||
|
|
[SEE_ALSO]
|
||
|
|
Memory_Initialize
|
||
|
|
Memory_GetStats
|
||
|
|
FMOD_MEMORY_ALLOCCALLBACK
|
||
|
|
FMOD_MEMORY_REALLOCCALLBACK
|
||
|
|
FMOD_MEMORY_TYPE
|
||
|
|
]
|
||
|
|
*/
|
||
|
|
/*
|
||
|
|
void F_CALLBACK FMOD_MEMORY_FREECALLBACK(void *ptr, FMOD_MEMORY_TYPE type)
|
||
|
|
{
|
||
|
|
#if 0
|
||
|
|
// here purely for documentation purposes.
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
*/
|
||
|
|
|
||
|
|
|
||
|
|
|