#ifndef _INCLUDE_KNIGHT_KE_SECTOR_STACK_H_ #define _INCLUDE_KNIGHT_KE_SECTOR_STACK_H_ #include #include namespace Knight { template 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 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_