Created
February 29, 2020 14:06
-
-
Save dwilliamson/b3d54848a6cdff744d7a2d985f5e76fb to your computer and use it in GitHub Desktop.
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
struct GlobalHeapAllocator : public memAllocator | |
{ | |
void* malloc(size_t size) override | |
{ | |
return ::malloc(size); | |
} | |
void free(void* ptr) override | |
{ | |
return ::free(ptr); | |
} | |
void* realloc(void* ptr, size_t size) override | |
{ | |
return ::realloc(ptr, size); | |
} | |
}; | |
MEMORY_API memAllocator* memGlobalHeapAllocator() | |
{ | |
static GlobalHeapAllocator allocator; | |
return &allocator; | |
} | |
memDynamicBuffer::memDynamicBuffer(memAllocator* allocator) | |
: m_Allocator(allocator) | |
{ | |
if (m_Allocator == nullptr) | |
m_Allocator = memGlobalHeapAllocator(); | |
} | |
memDynamicBuffer::memDynamicBuffer(uint32_t size, memAllocator* allocator) | |
: memDynamicBuffer(allocator) | |
{ | |
resize(size); | |
} | |
memDynamicBuffer::memDynamicBuffer(const memDynamicBuffer& rhs) | |
: m_Allocator(rhs.m_Allocator) | |
, m_Capacity(rhs.m_Capacity) | |
, m_Size(rhs.m_Size) | |
{ | |
if (rhs.m_Data != nullptr) | |
{ | |
m_Data = (uint8_t*)m_Allocator->malloc(m_Capacity); | |
memcpy(m_Data, rhs.m_Data, m_Size); | |
} | |
} | |
memDynamicBuffer::memDynamicBuffer(memDynamicBuffer&& rhs) | |
: m_Allocator(rhs.m_Allocator) | |
, m_Data(rhs.m_Data) | |
, m_Capacity(rhs.m_Capacity) | |
, m_Size(rhs.m_Size) | |
{ | |
rhs.m_Allocator = nullptr; | |
rhs.m_Data = nullptr; | |
rhs.m_Capacity = 0; | |
rhs.m_Size = 0; | |
} | |
memDynamicBuffer::~memDynamicBuffer() | |
{ | |
if (m_Data != nullptr) | |
m_Allocator->free(m_Data); | |
} | |
void memDynamicBuffer::resize(uint32_t new_size, uint32_t alignment) | |
{ | |
if (new_size > m_Capacity) | |
{ | |
// Calculate size rounded up to the requested alignment | |
assert(alignment > 0); | |
m_Capacity = new_size + ((alignment - 1) - ((new_size - 1) % alignment)); | |
m_Data = m_Allocator->realloc(m_Data, m_Capacity); | |
} | |
m_Size = new_size; | |
} | |
void memDynamicBuffer::growSize(int32_t nb_bytes, uint32_t alignment) | |
{ | |
assert((int32_t)m_Size + nb_bytes >= 0); | |
resize(m_Size + nb_bytes, alignment); | |
} | |
void memDynamicBuffer::resetSize() | |
{ | |
m_Size = 0; | |
} |
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
// Optional runtime-swappable interface to allocators | |
// The implemented functions are optional to call but the cost of the vtable will stick be present in each allocator | |
struct clcpp_attr(reflect) memAllocator | |
{ | |
virtual void* malloc(size_t size) = 0; | |
virtual void free(void* ptr) = 0; | |
// Allocators are not obliged to implement this and some will assert if called | |
virtual void* realloc(void* ptr, size_t size) = 0; | |
}; | |
// Return pointer to the global heap allocator | |
MEMORY_API memAllocator* memGlobalHeapAllocator(); | |
// This dynamic buffer separates size from capacity so that buffer memory can be reused without | |
// needing to release the allocation; calling `resetSize` will merely set the size to zero. | |
class MEMORY_API memDynamicBuffer | |
{ | |
public: | |
// Empty memory buffer | |
explicit memDynamicBuffer(memAllocator* allocator = nullptr); | |
// Pre-allocate | |
explicit memDynamicBuffer(uint32_t size, memAllocator* allocator = nullptr); | |
// Make copy construction explicit | |
explicit memDynamicBuffer(const memDynamicBuffer& rhs); | |
// Moves for returning from creation functions | |
memDynamicBuffer(memDynamicBuffer&& rhs); | |
~memDynamicBuffer(); | |
// No assignment copies | |
memDynamicBuffer& operator = (memDynamicBuffer&) = delete; | |
void resize(uint32_t new_size, uint32_t alignment = MEMORY_NATURAL_ALIGNMENT); | |
void growSize(int32_t nb_bytes, uint32_t alignment = MEMORY_NATURAL_ALIGNMENT); | |
void resetSize(); | |
void* data() const { return m_Data; } | |
void* dataAtOffset(uint32_t offset) const { return (uint8_t*)m_Data + offset; } | |
void* dataAtEnd() const { return (uint8_t*)m_Data + m_Size; } | |
uint32_t size() const { return m_Size; } | |
private: | |
// Inputs | |
memAllocator* m_Allocator = nullptr; | |
// Allocated data | |
void* m_Data = nullptr; | |
// Allocated capacity and current size within that capacity | |
uint32_t m_Capacity = 0; | |
uint32_t m_Size = 0; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment