deargui-vpl/ref/virtools/Includes/FixedSizeAllocator.h

192 lines
3.6 KiB
C++

#ifndef FIXEDSIZEALLOCATOR_H
#define FIXEDSIZEALLOCATOR_H
/////////////////////////////////////
// XFixedSizeAllocator
// created : AGoTH
// Date : 05/12/01
//
// This class os to allocate fixed size object
// with a constant time allocation and deallocation
#ifndef _WIN32_WCE
#include <limits.h>
#undef new
#undef delete
#include <new.h>
#endif
#include "XBitArray.h"
//
class XFixedSizeAllocator
{
public:
enum {
DEFAULT_CHUNK_SIZE = 4096
};
VX_EXPORT XFixedSizeAllocator(const int iBlockSize,const int iPageSize = DEFAULT_CHUNK_SIZE);
VX_EXPORT ~XFixedSizeAllocator();
// return the number of allocated chunks
int GetChunksCount()
{
return m_Chunks.Size();
}
// return the number of allocated chunks
VX_EXPORT int GetChunksTotalSize();
// return the number of allocated chunks
VX_EXPORT int GetChunksOccupation();
template <class T>
void CallDtor(T* iDummy)
{
// we clear all the chunks
for (Chunks::Iterator it = m_Chunks.Begin(); it != m_Chunks.End(); ++it) {
it->CallDtor(iDummy,m_BlockSize,m_BlockCount);
}
}
VX_EXPORT void Clear();
VX_EXPORT void* Allocate();
VX_EXPORT void Free(void* iP);
private:
class Chunk
{
public:
Chunk() {}
void Init(size_t iBlockSize, unsigned int iBlockCount);
template <class T>
void CallDtor(T* iDummy,size_t iBlockSize, unsigned int iBlockCount)
{
// everything is clear -> nothing to do
if (m_BlockAvailables == iBlockCount)
return;
// else we have some cleaning todo
if (!m_BlockAvailables) { // we need to clean everything
{ // we call the dtor of the used blocks
for (unsigned int i=0; i<iBlockCount; ++i) {
unsigned char* p = m_Data + i*iBlockSize;
((T*)p)->~T();
}
}
} else { // only some are used
XBitArray freeBlocks;
{ // we mark the objects used
int freeb = m_FirstAvailableBlock;
for (unsigned int i=0; i<m_BlockAvailables-1; ++i) {
freeBlocks.Set(freeb);
unsigned char* p = m_Data + freeb*iBlockSize;
freeb = *(int*)p;
}
freeBlocks.Set(freeb);
}
{ // we call the dtor of the used blocks
for (unsigned int i=0; i<iBlockCount; ++i) {
if (freeBlocks.IsSet(i))
continue;
unsigned char* p = m_Data + i*iBlockSize;
((T*)p)->~T();
}
}
}
}
void Destroy();
void* Allocate(size_t iBlockSize);
void Deallocate(void* iP, size_t iBlockSize);
unsigned char* m_Data;
unsigned int m_FirstAvailableBlock;
unsigned int m_BlockAvailables;
unsigned int m_BlockCount;
};
// types
typedef XArray<Chunk> Chunks;
// function to find the chunk containing the ptr
Chunk* FindChunk(void* iP);
// members
size_t m_PageSize;
// Block size
size_t m_BlockSize;
// Blocks Count (per Chunk)
unsigned int m_BlockCount;
// the chunks
Chunks m_Chunks;
// Allocating and deallocating chunks
Chunk* m_AChunk;
Chunk* m_DChunk;
};
//
template <class T>
class XObjectPool
{
public:
XObjectPool(XBOOL iCallDtor = TRUE):m_Allocator(sizeof(T)),m_CallDtor(iCallDtor) {}
T* Allocate()
{
return new (m_Allocator.Allocate()) T;
}
void Free(T* iP)
{
if (m_CallDtor)
iP->~T();
m_Allocator.Free(iP);
}
void Clear()
{
if (m_CallDtor)
m_Allocator.CallDtor((T*)NULL);
m_Allocator.Clear();
}
private:
XFixedSizeAllocator m_Allocator;
XBOOL m_CallDtor;
};
/*
#define new (m_setOwner (__FILE__,__LINE__,__FUNCTION__),false) ? NULL : new
#define delete (m_setOwner (__FILE__,__LINE__,__FUNCTION__),false) ? m_setOwner("",0,"") : delete
*/
#endif // FIXEDSIZEALLOCATOR_H