Last active
September 18, 2019 13:06
-
-
Save ikskuh/d7ba8bf83b53a1dc06bd86392a1ef744 to your computer and use it in GitHub Desktop.
C++ simple block allocator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdint> | |
#include <cstddef> | |
#include <bitset> | |
// WARNING: Code untested! | |
/// @tparam LowAddress Inclusive lower address of allocation size | |
/// @tparam HighAddress Inclusive upper bound of allocation size | |
/// @tparam BlockSize Size of minimal allocation size | |
template<uintptr_t LowAddress, uintptr_t HighAddress, size_t BlockSize> | |
struct BlockAllocator | |
{ | |
static_assert((BlockSize & (BlockSize - 1)) == 0); | |
size_t static constexpr TotalBlockCount = (HighAddress - LowAddress + BlockSize) / BlockSize; | |
std::bitset<TotalBlockCount> allocations; | |
/// allocates at least `byteCount` number of bytes, | |
/// uses granularity of BlockSize. | |
void * alloc(size_t byteCount) | |
{ | |
size_t const blockCount = (byteCount + BlockSize + 1) / BlockSize; | |
if(blockCount == 0) | |
return nullptr; | |
size_t startBlock = 0; | |
size_t counter = 0; | |
// we don't need to search the last (blockCount - 1) blocks here! | |
for(size_t block = 0; block < TotalBlockCount - (blockCount - 1); block++) | |
{ | |
if(allocations[block]) { | |
// current block is already allocated, so we have to start | |
// at the next block. | |
// also, we have zero blocks counted | |
startBlock = block + 1; | |
counter = 0; | |
} else { | |
// increase counter of free blocks. | |
// if the number of free blocks is enough, allocate | |
counter += 1; | |
if(counter >= blockCount) { | |
// we found *counter* valid blocks, so we have enough memory free | |
// for our allocation. Mark all blocks as used and return startBlock address | |
for(size_t i = startBlock; i <= block; i++) | |
allocations[i] = true; | |
return reinterpret_cast<void*>(BlockSize * startBlock); | |
} | |
} | |
} | |
return nullptr; | |
} | |
void free(void * mem, size_t byteCount) | |
{ | |
size_t const startBlock = reinterpret_cast<uintptr_t>(mem) / BlockSize; | |
size_t const blockCount = (byteCount + BlockSize + 1) / BlockSize; | |
for(size_t i = 0; i < blockCount; i++) | |
allocations[startBlock + i] = false; | |
} | |
}; | |
template struct BlockAllocator<0x10000, 0x1FFFF, 16>; | |
// BlockAllocator<0x10000, 0x1FFFF, 16> allocator; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment