2013-08-26 19:02:46 +00:00
|
|
|
#ifndef MEMORY_ALLOCATOR_SMALL_BLOCK_H
|
|
|
|
#define MEMORY_ALLOCATOR_SMALL_BLOCK_H
|
|
|
|
|
|
|
|
/* Optimized memory allocator for small & frequent (de-)allocations.
|
|
|
|
* Low memory overhead. Used for Lua.
|
|
|
|
* Inspired by http://dns.achurch.org/cgi-bin/hg/aquaria-psp/file/tip/PSP/src/lalloc.c
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Originally made for LV3proj_ng (https://github.com/fgenesis/lv3proj_ng)
|
|
|
|
// Hacked in shape for use in Aquaria
|
|
|
|
// Public domain
|
|
|
|
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
class SmallBlockAllocator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
SmallBlockAllocator(unsigned int blockSizeMin, unsigned int blockSizeMax, unsigned int blockSizeIncr = 8,
|
|
|
|
unsigned int elemsPerBlockMin = 64, unsigned int elemsPerBlockMax = 2048);
|
|
|
|
|
|
|
|
~SmallBlockAllocator();
|
|
|
|
|
|
|
|
void *Alloc(void *ptr, size_t newsize, size_t oldsize);
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
void *_Alloc(unsigned int size);
|
|
|
|
void *_Realloc(void *ptr, unsigned int newsize, unsigned int oldsize);
|
|
|
|
void _Free(void* ptr, unsigned int size);
|
|
|
|
|
|
|
|
void *_FallbackAlloc(unsigned int size);
|
|
|
|
void _FallbackFree(void *ptr);
|
|
|
|
|
|
|
|
struct Block
|
|
|
|
{
|
|
|
|
// block header start
|
|
|
|
Block *next;
|
|
|
|
Block *prev;
|
|
|
|
unsigned short maxElems;
|
|
|
|
unsigned short freeElems;
|
|
|
|
unsigned short elemSize;
|
|
|
|
unsigned short bitmapInts;
|
|
|
|
// block header end
|
|
|
|
|
|
|
|
unsigned int bitmap[1]; // variable sized
|
|
|
|
// actual storage memory starts after bitmap[bitmapInts]
|
|
|
|
|
|
|
|
inline unsigned char *getPtr()
|
|
|
|
{
|
|
|
|
return (unsigned char*)&bitmap[bitmapInts];
|
|
|
|
}
|
|
|
|
inline const unsigned char *getPtr() const
|
|
|
|
{
|
|
|
|
return (unsigned char*)&bitmap[bitmapInts];
|
|
|
|
}
|
|
|
|
inline unsigned char *getEndPtr()
|
|
|
|
{
|
|
|
|
return getPtr() + (maxElems * elemSize);
|
|
|
|
}
|
|
|
|
inline const unsigned char *getEndPtr() const
|
|
|
|
{
|
|
|
|
return getPtr() + (maxElems * elemSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *allocElem();
|
|
|
|
void freeElem(unsigned char *ptr);
|
|
|
|
bool contains(unsigned char *ptr) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
Block *_AllocBlock(unsigned int elemCount, unsigned int elemSize);
|
|
|
|
void _FreeBlock(Block *blk);
|
|
|
|
Block *_AppendBlock(unsigned int elemSize);
|
|
|
|
Block *_GetFreeBlock(unsigned int elemSize); // NULL if none free
|
|
|
|
|
|
|
|
Block *_FindBlockContainingPtr(void *ptr);
|
|
|
|
|
|
|
|
inline unsigned int GetIndexForElemSize(unsigned int elemSize)
|
|
|
|
{
|
2016-05-05 17:40:28 +00:00
|
|
|
|
|
|
|
|
2013-08-26 19:02:46 +00:00
|
|
|
return ((elemSize + (_blockSizeIncr - 1)) / _blockSizeIncr) - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool Block_ptr_cmp(const Block *blk, const void *ptr);
|
|
|
|
|
|
|
|
Block **_blocks;
|
|
|
|
std::vector<Block*> _allblocks; // always sorted by pointer address
|
|
|
|
|
|
|
|
unsigned int _blockSizeMin;
|
|
|
|
unsigned int _blockSizeMax;
|
|
|
|
unsigned int _blockSizeIncr;
|
|
|
|
|
|
|
|
unsigned int _elemsPerBlockMin;
|
|
|
|
unsigned int _elemsPerBlockMax;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|