#pragma once
class MemoryBlock
{
private:
void* p_rawMem;
void* p_currentMemLocation;
size_t p_currentMemLocationOffset;
size_t p_totalMemSize;
size_t p_remainingMemSize;
size_t p_alignment;
void *p_lastMemByteLocation;
void p_addCurrentMemLocation(size_t delta);
public:
MemoryBlock(size_t size, size_t alignment);
void* getMemoryWith(size_t size, size_t alignemnt);
~MemoryBlock();
};
#include <memory>
#include <stdexcept>
#include <cmath>
#include <assert.h>
#include "MemoryBlock.h"
void MemoryBlock::p_addCurrentMemLocation(size_t delta)
{
if (delta == 0) {
return;
}
p_currentMemLocationOffset += delta;
assert((p_currentMemLocationOffset) <= p_totalMemSize);
p_remainingMemSize -= delta;
if (p_remainingMemSize == 0) {
p_currentMemLocation = p_lastMemByteLocation;
}
else {
p_currentMemLocation = static_cast<void*>(static_cast<char*>(p_currentMemLocation) + delta);
}
}
MemoryBlock::MemoryBlock(size_t size, size_t alignment):
p_rawMem(_aligned_malloc(size, alignment)),
p_currentMemLocation(p_rawMem),
p_currentMemLocationOffset(0),
p_totalMemSize(size),
p_remainingMemSize(size),
p_alignment(alignment),
p_lastMemByteLocation(static_cast<void*>(static_cast<char*>(p_rawMem) + (size - 1)))
{
}
void* MemoryBlock::getMemoryWith(size_t size, size_t alignment)
{
if (size > p_totalMemSize) {
throw std::bad_alloc();
}
if (size == 0) {
throw std::invalid_argument("size must be greater than 0");
}
if (alignment == 0 || (alignment &(alignment-1))!= 0) {//checks it alignment is power of 2
throw std::invalid_argument("alignment should be a power of 2.");
}
if (alignment > p_alignment) {
throw std::invalid_argument("alignment requirement is greater than the memory block alignment.");
}
if (size > p_remainingMemSize) {
return nullptr;
}
if (p_totalMemSize == p_remainingMemSize) {
p_addCurrentMemLocation(size);
return p_rawMem;
}
p_addCurrentMemLocation((std::ceil(p_currentMemLocationOffset/(double)alignment)*alignment)-p_currentMemLocationOffset);
void* retVal = p_currentMemLocation;
p_addCurrentMemLocation(size);
return retVal;
}
MemoryBlock::~MemoryBlock()
{
_aligned_free(p_rawMem);
}