Skip to content

Instantly share code, notes, and snippets.

@ikskuh
Last active September 18, 2019 13:06
Show Gist options
  • Save ikskuh/d7ba8bf83b53a1dc06bd86392a1ef744 to your computer and use it in GitHub Desktop.
Save ikskuh/d7ba8bf83b53a1dc06bd86392a1ef744 to your computer and use it in GitHub Desktop.
C++ simple block allocator
#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