Files
Aerofoil/AerofoilPortable/GpAllocator_C.cpp
2021-04-28 01:46:07 -04:00

116 lines
3.7 KiB
C++

#include "GpAllocator_C.h"
#include "CoreDefs.h"
#include <string.h>
#include <stdlib.h>
#include <assert.h>
struct GpAllocator_C_MMBlock
{
uint8_t m_offsetFromAllocLocation;
static size_t AlignedSize();
};
size_t GpAllocator_C_MMBlock::AlignedSize()
{
const size_t paddedSize = sizeof(GpAllocator_C_MMBlock) + GP_SYSTEM_MEMORY_ALIGNMENT - 1;
const size_t paddedSizeTruncated = paddedSize - (paddedSize % GP_SYSTEM_MEMORY_ALIGNMENT);
return paddedSizeTruncated;
}
void *GpAllocator_C::Realloc(void *buf, size_t newSize)
{
if (buf == nullptr)
{
if (newSize == 0)
return nullptr;
return this->Alloc(newSize);
}
if (newSize == 0)
{
this->Free(buf);
return nullptr;
}
assert(buf != nullptr);
const size_t mmBlockSize = GpAllocator_C_MMBlock::AlignedSize();
uint8_t *oldBufBytes = static_cast<uint8_t*>(buf);
const GpAllocator_C_MMBlock *oldBufMMBlock = reinterpret_cast<const GpAllocator_C_MMBlock*>(oldBufBytes - GpAllocator_C_MMBlock::AlignedSize());
const size_t oldBufOffsetFromAlignLoc = oldBufMMBlock->m_offsetFromAllocLocation;
uint8_t *oldBufBase = oldBufBytes - GpAllocator_C_MMBlock::AlignedSize() - oldBufOffsetFromAlignLoc;
const size_t mmBlockSizeWithMaxPadding = GpAllocator_C_MMBlock::AlignedSize() + GP_SYSTEM_MEMORY_ALIGNMENT - 1;
if (SIZE_MAX - newSize < mmBlockSizeWithMaxPadding)
return nullptr;
const size_t newBufferSize = newSize + mmBlockSizeWithMaxPadding;
uint8_t *newBuffer = static_cast<uint8_t*>(realloc(oldBufBase, newSize + mmBlockSizeWithMaxPadding));
if (!newBuffer)
return nullptr;
const intptr_t offsetFromAlignPoint = reinterpret_cast<intptr_t>(newBuffer) & static_cast<intptr_t>(GP_SYSTEM_MEMORY_ALIGNMENT - 1);
intptr_t alignPadding = 0;
if (offsetFromAlignPoint != 0)
alignPadding = static_cast<intptr_t>(GP_SYSTEM_MEMORY_ALIGNMENT) - offsetFromAlignPoint;
// Check if the alignment changed, if so relocate
if (static_cast<size_t>(alignPadding) != oldBufOffsetFromAlignLoc)
memmove(newBuffer + alignPadding, newBuffer + oldBufOffsetFromAlignLoc, GpAllocator_C_MMBlock::AlignedSize() + newSize);
GpAllocator_C_MMBlock *newMMBlock = reinterpret_cast<GpAllocator_C_MMBlock*>(newBuffer + alignPadding);
newMMBlock->m_offsetFromAllocLocation = static_cast<uint8_t>(alignPadding);
return newBuffer + alignPadding + GpAllocator_C_MMBlock::AlignedSize();
}
void *GpAllocator_C::Alloc(size_t size)
{
if (size == 0)
return nullptr;
const size_t mmBlockSizeWithMaxPadding = GpAllocator_C_MMBlock::AlignedSize() + GP_SYSTEM_MEMORY_ALIGNMENT - 1;
if (SIZE_MAX - size < mmBlockSizeWithMaxPadding)
return nullptr;
uint8_t *buffer = static_cast<uint8_t*>(realloc(nullptr, size + mmBlockSizeWithMaxPadding));
if (!buffer)
return nullptr;
const intptr_t offsetFromAlignPoint = reinterpret_cast<intptr_t>(buffer) & static_cast<intptr_t>(GP_SYSTEM_MEMORY_ALIGNMENT - 1);
intptr_t alignPadding = 0;
if (offsetFromAlignPoint != 0)
alignPadding = static_cast<intptr_t>(GP_SYSTEM_MEMORY_ALIGNMENT) - offsetFromAlignPoint;
GpAllocator_C_MMBlock *mmBlock = reinterpret_cast<GpAllocator_C_MMBlock*>(buffer + alignPadding);
mmBlock->m_offsetFromAllocLocation = static_cast<uint8_t>(alignPadding);
return buffer + alignPadding + GpAllocator_C_MMBlock::AlignedSize();
}
void GpAllocator_C::Free(void *buf)
{
if (!buf)
return;
const size_t mmBlockSize = GpAllocator_C_MMBlock::AlignedSize();
uint8_t *bytes = static_cast<uint8_t*>(buf);
const GpAllocator_C_MMBlock *mmBlock = reinterpret_cast<const GpAllocator_C_MMBlock*>(bytes - GpAllocator_C_MMBlock::AlignedSize());
void *freeLoc = bytes - GpAllocator_C_MMBlock::AlignedSize() - mmBlock->m_offsetFromAllocLocation;
realloc(freeLoc, 0);
}
GpAllocator_C *GpAllocator_C::GetInstance()
{
return &ms_instance;
}
GpAllocator_C GpAllocator_C::ms_instance;