Initial
This commit is contained in:
commit
d4c558a59a
34 changed files with 3850 additions and 0 deletions
132
private/PoolAllocator.cpp
Normal file
132
private/PoolAllocator.cpp
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
|
||||
/*
|
||||
*
|
||||
Implementation:
|
||||
* Adding chunk pointer to each chunk to form one-directional list that keeps track of free chunk
|
||||
* Storing ordered pointers to chunks in order to find desired chunk from delete pointer on deallocation in log time
|
||||
*
|
||||
* Allocations:
|
||||
* 1) allocate with chunk stored in list entry
|
||||
* 2) ...
|
||||
*
|
||||
* Deallocations:
|
||||
* 1) binary-search with delete pointer to find desired chunk
|
||||
* 2) ...
|
||||
*
|
||||
*/
|
||||
|
||||
#include "allocators.hpp"
|
||||
#include "PrivateConfig.hpp"
|
||||
|
||||
void tp::PoolAlloc::Chunks::add(Chunk* aChunk) {
|
||||
// ensure order
|
||||
auto smaller_address = findUtil(mBuff, mBuff + mUsedLen, aChunk);
|
||||
for (auto iter = mBuff + mUsedLen; iter != smaller_address; iter--) { *(iter + 1) = *iter; }
|
||||
|
||||
*(smaller_address + 1) = aChunk;
|
||||
mUsedLen++;
|
||||
|
||||
// check for buff overflow
|
||||
if (mUsedLen == mLen) {
|
||||
auto prevBuff = mBuff;
|
||||
mBuff = (Chunk**)HeapAllocGlobal::allocate(sizeof(Chunk*) * mLen * 2);
|
||||
memcp(mBuff, prevBuff, sizeof(Chunk*) * mUsedLen);
|
||||
mLen *= 2;
|
||||
HeapAllocGlobal::deallocate(prevBuff);
|
||||
}
|
||||
}
|
||||
|
||||
void tp::PoolAlloc::Chunks::remove(Chunk* aChunk) {
|
||||
// ensure order
|
||||
auto del_address = findUtil(mBuff, mBuff + mUsedLen, aChunk);
|
||||
for (auto iter = del_address; iter != mBuff + mUsedLen; iter++) { *iter = *(iter + 1); }
|
||||
|
||||
mUsedLen--;
|
||||
|
||||
// check for buff low usage
|
||||
if ((halnf)mUsedLen / mLen < 0.25f) {
|
||||
auto prevBuff = mBuff;
|
||||
mBuff = (Chunk**)HeapAllocGlobal::allocate(sizeof(Chunk*) * mLen / 2);
|
||||
memcp(mBuff, prevBuff, sizeof(Chunk*) * mUsedLen);
|
||||
mLen /= 2;
|
||||
HeapAllocGlobal::deallocate(prevBuff);
|
||||
}
|
||||
}
|
||||
|
||||
tp::PoolAlloc::Chunk* tp::PoolAlloc::Chunks::find(void* aPtr) {
|
||||
return *findUtil(mBuff, mBuff + mUsedLen, aPtr);
|
||||
}
|
||||
|
||||
tp::PoolAlloc::Chunk* tp::PoolAlloc::Chunks::findNotFull() {
|
||||
for (ualni idx = 0; idx < mUsedLen; idx++) {
|
||||
if (!mBuff[idx]->isFull()) {
|
||||
return mBuff[idx];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tp::PoolAlloc::Chunk** tp::PoolAlloc::Chunks::findUtil(Chunk** aLeft, Chunk** aRight, void* aPtr) {
|
||||
auto range = ualni(aRight - aLeft);
|
||||
if (range == 1) { return aLeft; }
|
||||
auto middle = aLeft + range / 2;
|
||||
return (aPtr > *middle) ? findUtil(middle, aRight, aPtr) : findUtil(aLeft, middle, aPtr);
|
||||
}
|
||||
|
||||
|
||||
tp::PoolAlloc::PoolAlloc(ualni aBlockSize, ualni aChunkSize) : mBlockSize(aBlockSize), mChunkSize(aChunkSize) {}
|
||||
|
||||
void* tp::PoolAlloc::allocate() {
|
||||
|
||||
if (!mFreeChunk || mFreeChunk->isFull()) {
|
||||
auto new_free_chunk = mChunks.findNotFull();
|
||||
|
||||
if (!new_free_chunk) {
|
||||
|
||||
new_free_chunk = new ((Chunk*)HeapAllocGlobal::allocate(sizeof(Chunk))) Chunk(mBlockSize, mChunkSize);
|
||||
RelAssert(new_free_chunk);
|
||||
mChunks.add(new_free_chunk);
|
||||
|
||||
if (mFreeChunk) {
|
||||
new_free_chunk->mNext = mFreeChunk->mNext;
|
||||
new_free_chunk->mPrev = mFreeChunk->mPrev;
|
||||
if (mFreeChunk->mNext) mFreeChunk->mNext->mPrev = new_free_chunk;
|
||||
if (mFreeChunk->mPrev) mFreeChunk->mPrev->mNext = new_free_chunk;
|
||||
}
|
||||
else {
|
||||
new_free_chunk->mNext = NULL;
|
||||
new_free_chunk->mPrev = NULL;
|
||||
}
|
||||
|
||||
mFreeChunk = new_free_chunk;
|
||||
}
|
||||
}
|
||||
|
||||
return mFreeChunk->allocate();
|
||||
}
|
||||
|
||||
void tp::PoolAlloc::deallocate(void* aPtr) {
|
||||
auto chunk = mChunks.find(aPtr);
|
||||
chunk->deallocate(aPtr);
|
||||
|
||||
if (mFreeChunk->isEmpty()) {
|
||||
|
||||
Chunk* new_chunk = NULL;
|
||||
for (ualni idx = 0; idx < mChunks.mUsedLen; idx++) {
|
||||
if (!mChunks.mBuff[idx]->isFull() && new_chunk != mFreeChunk) {
|
||||
new_chunk = mChunks.mBuff[idx];
|
||||
}
|
||||
}
|
||||
|
||||
if (new_chunk) {
|
||||
if (mFreeChunk->mNext) mFreeChunk->mNext->mPrev = mFreeChunk->mPrev;
|
||||
if (mFreeChunk->mPrev) mFreeChunk->mPrev->mNext = mFreeChunk->mNext;
|
||||
mChunks.remove(mFreeChunk);
|
||||
HeapAllocGlobal::deallocate(mFreeChunk);
|
||||
mFreeChunk = new_chunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tp::PoolAlloc::~PoolAlloc() {
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue