mirror of
https://github.com/thunderbrewhq/common.git
synced 2025-12-12 03:02:29 +00:00
160 lines
4.5 KiB
C++
160 lines
4.5 KiB
C++
#include "common/objectalloc/CObjectHeapList.hpp"
|
|
#include <storm/Error.hpp>
|
|
|
|
CObjectHeapList::CObjectHeapList(const CObjectHeapList& list) {
|
|
if (this == &list) {
|
|
return;
|
|
}
|
|
|
|
this->m_heaps.Set(list.m_heaps.Count(), list.m_heaps.Ptr());
|
|
|
|
this->m_objSize = list.m_objSize;
|
|
this->m_objsPerBlock = list.m_objsPerBlock;
|
|
this->m_numFullHeaps = list.m_numFullHeaps;
|
|
this->m_hasEmptyHeaps = list.m_hasEmptyHeaps;
|
|
this->uint20 = list.uint20;
|
|
this->m_fullestHeap = list.m_fullestHeap;
|
|
memcpy(this->m_heapName, list.m_heapName, sizeof(this->m_heapName));
|
|
this->uint78 = list.uint78;
|
|
this->uint7C = list.uint7C;
|
|
this->uint80 = list.uint80;
|
|
this->m_freeEmptyHeaps = list.m_freeEmptyHeaps;
|
|
}
|
|
|
|
int32_t CObjectHeapList::New(uint32_t* index, void** obj, bool zero) {
|
|
STORM_ASSERT(index);
|
|
|
|
CObjectHeap* heap = nullptr;
|
|
|
|
if (this->m_fullestHeap < this->m_heaps.Count()) {
|
|
heap = &this->m_heaps[this->m_fullestHeap];
|
|
}
|
|
|
|
if (!heap || heap->m_allocated == this->m_objsPerBlock || !heap->m_obj) {
|
|
if (this->m_heaps.Count() == this->m_numFullHeaps) {
|
|
this->m_fullestHeap = this->m_heaps.Count();
|
|
|
|
heap = this->m_heaps.New();
|
|
|
|
if (!heap->Allocate(this->m_objSize, this->m_objsPerBlock, this->m_heapName)) {
|
|
return 0;
|
|
}
|
|
} else {
|
|
for (uint32_t i = 0; i < this->m_heaps.Count(); ++i) {
|
|
auto currentHeap = &this->m_heaps[i];
|
|
if (currentHeap->m_allocated != this->m_objsPerBlock) {
|
|
this->m_fullestHeap = i;
|
|
heap = currentHeap;
|
|
if (currentHeap->m_obj) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!heap) {
|
|
return 0;
|
|
}
|
|
|
|
if (!heap->New(this->m_objSize, this->m_objsPerBlock, index, this->m_heapName, obj, zero)) {
|
|
return 0;
|
|
}
|
|
|
|
*index += this->m_fullestHeap * this->m_objsPerBlock;
|
|
|
|
if (heap->m_allocated == this->m_objsPerBlock) {
|
|
this->m_numFullHeaps++;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void* CObjectHeapList::Ptr(uint32_t index) {
|
|
uint32_t heapId = index / this->m_objsPerBlock;
|
|
uint32_t stackId = index % this->m_objsPerBlock;
|
|
|
|
STORM_ASSERT(heapId < this->m_heaps.Count());
|
|
return this->m_heaps[heapId].Ptr(stackId, this->m_objSize, this->m_objsPerBlock);
|
|
}
|
|
|
|
void CObjectHeapList::Delete(uint32_t index) {
|
|
uint32_t heapId = index / this->m_objsPerBlock;
|
|
uint32_t stackId = index % this->m_objsPerBlock;
|
|
|
|
STORM_ASSERT(heapId < this->m_heaps.Count());
|
|
auto& heap = this->m_heaps[heapId];
|
|
if (heap.m_allocated == this->m_objsPerBlock) {
|
|
this->m_numFullHeaps--;
|
|
}
|
|
|
|
heap.Delete(stackId, this->m_objSize, this->m_objsPerBlock);
|
|
|
|
if (this->m_freeEmptyHeaps) {
|
|
if (heap.m_obj && !heap.m_allocated) {
|
|
this->m_hasEmptyHeaps = 1;
|
|
}
|
|
|
|
if (this->m_hasEmptyHeaps) {
|
|
bool freeHeaps = (((this->m_objsPerBlock - 1) >> 2) & this->uint20) == 0;
|
|
this->uint20++;
|
|
if (freeHeaps) {
|
|
FreeEmptyHeaps();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CObjectHeapList::FreeEmptyHeaps() {
|
|
if (!this->m_heaps.Count()) {
|
|
this->m_hasEmptyHeaps = 0;
|
|
return;
|
|
}
|
|
|
|
uint32_t totalAllocated = 0;
|
|
uint32_t totalObjsPerBlock = 0;
|
|
uint32_t totalEmptyHeaps = 0;
|
|
|
|
for (uint32_t i = 0; i < this->m_heaps.Count(); ++i) {
|
|
auto& heap = this->m_heaps[i];
|
|
if (heap.m_obj) {
|
|
totalObjsPerBlock += this->m_objsPerBlock;
|
|
if (heap.m_allocated) {
|
|
totalAllocated += heap.m_allocated;
|
|
} else {
|
|
totalEmptyHeaps++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!totalEmptyHeaps) {
|
|
this->m_hasEmptyHeaps = 0;
|
|
return;
|
|
}
|
|
|
|
totalAllocated += ((3 * this->m_objsPerBlock) >> 1);
|
|
|
|
uint32_t count = this->m_heaps.Count();
|
|
|
|
while (count > 0 && totalAllocated < totalObjsPerBlock && !totalEmptyHeaps) {
|
|
auto& heap = this->m_heaps[count - 1];
|
|
if (heap.m_obj && !heap.m_allocated) {
|
|
heap.Free();
|
|
totalObjsPerBlock -= this->m_objsPerBlock;
|
|
totalEmptyHeaps--;
|
|
this->uint20 = 0;
|
|
}
|
|
count--;
|
|
}
|
|
|
|
this->m_hasEmptyHeaps = totalEmptyHeaps != 0;
|
|
}
|
|
|
|
uint32_t CObjectHeapList::BlocksAllocated() {
|
|
uint32_t result = 0;
|
|
for (uint32_t i = 0; i < this->m_heaps.Count(); ++i) {
|
|
result += this->m_heaps[i].m_allocated;
|
|
}
|
|
|
|
return result;
|
|
}
|