diff options
Diffstat (limited to 'source/core/memory-pool.cpp')
| -rw-r--r-- | source/core/memory-pool.cpp | 211 |
1 files changed, 104 insertions, 107 deletions
diff --git a/source/core/memory-pool.cpp b/source/core/memory-pool.cpp index f9d29636b..aec1efc37 100644 --- a/source/core/memory-pool.cpp +++ b/source/core/memory-pool.cpp @@ -1,135 +1,132 @@ #include "memory-pool.h" #include <cassert> -namespace CoreLib +namespace Slang { - namespace Basic + MemoryPool::MemoryPool(unsigned char * pBuffer, int pLog2BlockSize, int numBlocks) { - MemoryPool::MemoryPool(unsigned char * pBuffer, int pLog2BlockSize, int numBlocks) + Init(pBuffer, pLog2BlockSize, numBlocks); + } + void MemoryPool::Init(unsigned char * pBuffer, int pLog2BlockSize, int numBlocks) + { + assert(pLog2BlockSize >= 1 && pLog2BlockSize <= 30); + assert(numBlocks >= 4); + buffer = pBuffer; + blockSize = 1 << pLog2BlockSize; + log2BlockSize = pLog2BlockSize; + numLevels = Math::Log2Floor(numBlocks); + freeList[0] = (FreeListNode*)buffer; + freeList[0]->NextPtr = nullptr; + freeList[0]->PrevPtr = nullptr; + used.SetMax(1 << (numLevels)); + for (int i = 1; i < MaxLevels; i++) { - Init(pBuffer, pLog2BlockSize, numBlocks); + freeList[i] = nullptr; } - void MemoryPool::Init(unsigned char * pBuffer, int pLog2BlockSize, int numBlocks) - { - assert(pLog2BlockSize >= 1 && pLog2BlockSize <= 30); - assert(numBlocks >= 4); - buffer = pBuffer; - blockSize = 1 << pLog2BlockSize; - log2BlockSize = pLog2BlockSize; - numLevels = Math::Log2Floor(numBlocks); - freeList[0] = (FreeListNode*)buffer; - freeList[0]->NextPtr = nullptr; - freeList[0]->PrevPtr = nullptr; - used.SetMax(1 << (numLevels)); - for (int i = 1; i < MaxLevels; i++) - { - freeList[i] = nullptr; - } - } - int MemoryPool::AllocBlock(int level) + } + int MemoryPool::AllocBlock(int level) + { + if (level < 0) + return -1; + if (freeList[level] == nullptr) { - if (level < 0) - return -1; - if (freeList[level] == nullptr) + auto largeBlockAddr = AllocBlock(level - 1); + if (largeBlockAddr != -1) { - auto largeBlockAddr = AllocBlock(level - 1); - if (largeBlockAddr != -1) - { - auto block1 = (FreeListNode*)(buffer + ((largeBlockAddr ^ (1 << (numLevels - level))) << log2BlockSize)); - block1->NextPtr = nullptr; - block1->PrevPtr = nullptr; - freeList[level] = block1; + auto block1 = (FreeListNode*)(buffer + ((largeBlockAddr ^ (1 << (numLevels - level))) << log2BlockSize)); + block1->NextPtr = nullptr; + block1->PrevPtr = nullptr; + freeList[level] = block1; - int blockIndex = (1 << level) + (largeBlockAddr >> (numLevels-level)) - 1; - used.Add(blockIndex); - return largeBlockAddr; - } - else - return -1; + int blockIndex = (1 << level) + (largeBlockAddr >> (numLevels-level)) - 1; + used.Add(blockIndex); + return largeBlockAddr; } else + return -1; + } + else + { + auto node = freeList[level]; + if (node->NextPtr) { - auto node = freeList[level]; - if (node->NextPtr) - { - node->NextPtr->PrevPtr = node->PrevPtr; - } - freeList[level] = freeList[level]->NextPtr; - int rs = (int)((unsigned char *)node - buffer) >> log2BlockSize; - int blockIndex = (1 << level) + (rs >> (numLevels - level)) - 1; - used.Add(blockIndex); - return rs; + node->NextPtr->PrevPtr = node->PrevPtr; } + freeList[level] = freeList[level]->NextPtr; + int rs = (int)((unsigned char *)node - buffer) >> log2BlockSize; + int blockIndex = (1 << level) + (rs >> (numLevels - level)) - 1; + used.Add(blockIndex); + return rs; } - unsigned char * MemoryPool::Alloc(int size) - { - if (size == 0) - return nullptr; - int originalSize = size; - if (size < blockSize) - size = blockSize; - int order = numLevels - (Math::Log2Ceil(size) - log2BlockSize); - assert(order >= 0 && order < MaxLevels); + } + unsigned char * MemoryPool::Alloc(int size) + { + if (size == 0) + return nullptr; + int originalSize = size; + if (size < blockSize) + size = blockSize; + int order = numLevels - (Math::Log2Ceil(size) - log2BlockSize); + assert(order >= 0 && order < MaxLevels); - bytesAllocated += (1 << ((numLevels-order) + log2BlockSize)); - bytesWasted += (1 << ((numLevels - order) + log2BlockSize)) - originalSize; + bytesAllocated += (1 << ((numLevels-order) + log2BlockSize)); + bytesWasted += (1 << ((numLevels - order) + log2BlockSize)) - originalSize; - int blockId = AllocBlock(order); - if (blockId != -1) - return buffer + (blockId << log2BlockSize); - else - return nullptr; - } - void MemoryPool::FreeBlock(unsigned char * ptr, int level) + int blockId = AllocBlock(order); + if (blockId != -1) + return buffer + (blockId << log2BlockSize); + else + return nullptr; + } + void MemoryPool::FreeBlock(unsigned char * ptr, int level) + { + int indexInLevel = (int)(ptr - buffer) >> (numLevels - level + log2BlockSize); + int blockIndex = (1 << level) + indexInLevel - 1; + assert(used.Contains(blockIndex)); + int buddyIndex = (blockIndex & 1) ? blockIndex + 1 : blockIndex - 1; + used.Remove(blockIndex); + if (level > 0 && !used.Contains(buddyIndex)) { - int indexInLevel = (int)(ptr - buffer) >> (numLevels - level + log2BlockSize); - int blockIndex = (1 << level) + indexInLevel - 1; - assert(used.Contains(blockIndex)); - int buddyIndex = (blockIndex & 1) ? blockIndex + 1 : blockIndex - 1; - used.Remove(blockIndex); - if (level > 0 && !used.Contains(buddyIndex)) + auto buddyPtr = (FreeListNode *)(buffer + ((((int)(ptr - buffer) >> log2BlockSize) ^ (1 << (numLevels - level))) << log2BlockSize)); + if (buddyPtr->PrevPtr) { - auto buddyPtr = (FreeListNode *)(buffer + ((((int)(ptr - buffer) >> log2BlockSize) ^ (1 << (numLevels - level))) << log2BlockSize)); - if (buddyPtr->PrevPtr) - { - buddyPtr->PrevPtr->NextPtr = buddyPtr->NextPtr; - } - if (buddyPtr->NextPtr) - { - buddyPtr->NextPtr->PrevPtr = buddyPtr->PrevPtr; - } - if (freeList[level] == buddyPtr) - { - freeList[level] = buddyPtr->NextPtr; - } - // recursively free parent blocks - auto parentPtr = Math::Min(buddyPtr, (FreeListNode*)ptr); - if (level > 0) - FreeBlock((unsigned char*)parentPtr, level - 1); + buddyPtr->PrevPtr->NextPtr = buddyPtr->NextPtr; } - else + if (buddyPtr->NextPtr) + { + buddyPtr->NextPtr->PrevPtr = buddyPtr->PrevPtr; + } + if (freeList[level] == buddyPtr) { - // insert to freelist - auto freeNode = (FreeListNode *)ptr; - freeNode->NextPtr = freeList[level]; - freeNode->PrevPtr = nullptr; - if (freeList[level]) - freeList[level]->PrevPtr = freeNode; - freeList[level] = freeNode; + freeList[level] = buddyPtr->NextPtr; } + // recursively free parent blocks + auto parentPtr = Math::Min(buddyPtr, (FreeListNode*)ptr); + if (level > 0) + FreeBlock((unsigned char*)parentPtr, level - 1); } - void MemoryPool::Free(unsigned char * ptr, int size) + else { - if (size == 0) - return; - int originalSize = size; - if (size < blockSize) - size = blockSize; - int level = numLevels - (Math::Log2Ceil(size) - log2BlockSize); - bytesAllocated -= (1 << ((numLevels-level) + log2BlockSize)); - bytesWasted -= (1 << ((numLevels - level) + log2BlockSize)) - originalSize; - FreeBlock(ptr, level); + // insert to freelist + auto freeNode = (FreeListNode *)ptr; + freeNode->NextPtr = freeList[level]; + freeNode->PrevPtr = nullptr; + if (freeList[level]) + freeList[level]->PrevPtr = freeNode; + freeList[level] = freeNode; } } + void MemoryPool::Free(unsigned char * ptr, int size) + { + if (size == 0) + return; + int originalSize = size; + if (size < blockSize) + size = blockSize; + int level = numLevels - (Math::Log2Ceil(size) - log2BlockSize); + bytesAllocated -= (1 << ((numLevels-level) + log2BlockSize)); + bytesWasted -= (1 << ((numLevels - level) + log2BlockSize)) - originalSize; + FreeBlock(ptr, level); + } } |
