sourcemod/knight/shared/KeSectorStack.h

163 lines
2.8 KiB
C
Raw Normal View History

#ifndef _INCLUDE_KNIGHT_KE_SECTOR_STACK_H_
#define _INCLUDE_KNIGHT_KE_SECTOR_STACK_H_
#include <KnightAllocator.h>
#include <KeVector.h>
namespace Knight
{
template <class T>
class KeSectorStack
{
public:
static const size_t DEFAULT_SECTOR_SIZE = 64;
KeSectorStack() : m_SectorSize(DEFAULT_SECTOR_SIZE), m_UsedSize(0), m_MaxUsedSize(0)
{
m_pAlloc = NULL;
}
KeSectorStack(size_t sectorSize) : m_SectorSize(sectorSize), m_UsedSize(0), m_MaxUsedSize(0)
{
m_pAlloc = NULL;
}
KeSectorStack(size_t sectorSize, ke_allocator_t *alloc) :
m_SectorSize(sectorSize), m_UsedSize(0), m_pAlloc(alloc), m_MaxUsedSize(0)
{
}
~KeSectorStack()
{
clear();
}
void clear()
{
T *sector;
size_t last_sector;
size_t last_sector_item;
if (m_MaxUsedSize == 0)
{
return;
}
last_sector = (m_MaxUsedSize - 1) / m_SectorSize;
last_sector_item = (m_MaxUsedSize - 1) % m_SectorSize;
for (size_t i = 0; i < last_sector; i++)
{
sector = m_Sectors[i];
for (size_t j = 0; j < m_SectorSize; j++)
{
sector[j].~T();
}
}
sector = m_Sectors[last_sector];
for (size_t i = 0; i <= last_sector_item; i++)
{
sector[i].~T();
}
clear_no_dtors();
}
void clear_no_dtors()
{
for (size_t i = 0; i < m_Sectors.size(); i++)
{
free_sector(m_Sectors[i]);
}
m_Sectors.clear();
}
bool empty()
{
return (m_UsedSize == 0) ? true : false;
}
void push(const T & val)
{
if ((m_UsedSize / m_SectorSize) >= m_Sectors.size())
{
/* Create a new sector */
T * sector;
if (m_pAlloc == NULL)
{
sector = (T *)malloc(sizeof(T) * m_SectorSize);
}
else
{
sector = (T *)m_pAlloc->alloc(m_pAlloc, sizeof(T) * m_SectorSize);
}
m_Sectors.push_back(sector);
}
at(m_UsedSize) = val;
m_UsedSize++;
/* Keep track of the maximum used size so we can defer the
* massive destruction job until the end.
*/
if (m_UsedSize > m_MaxUsedSize)
{
m_MaxUsedSize = m_UsedSize;
}
}
void pop()
{
m_UsedSize--;
}
void pop_all()
{
m_UsedSize = 0;
}
T & front()
{
return at(m_UsedSize - 1);
}
size_t size()
{
return m_UsedSize;
}
private:
T & at(size_t x)
{
return m_Sectors[x / m_SectorSize][x % m_SectorSize];
}
void free_sector(T * sector)
{
if (m_pAlloc == NULL)
{
free(sector);
}
else if (m_pAlloc->dealloc != NULL)
{
m_pAlloc->dealloc(m_pAlloc, sector);
}
}
private:
KeVector<T *> m_Sectors;
size_t m_SectorSize;
size_t m_UsedSize;
ke_allocator_t *m_pAlloc;
size_t m_MaxUsedSize;
};
}
#endif //_INCLUDE_KNIGHT_KE_SECTOR_STACK_H_