Program Listing for File Allocator.h¶
↰ Return to documentation for file (Source\Common\Inc\Memory\Allocator.h
)
#pragma once
#include <functional>
#include "Types.h"
#include "Utils/Macros.h"
namespace Azura {
namespace Memory {
template <typename T>
using UniquePtr = std::unique_ptr<T, std::function<void(T*)>>;
template <typename T>
using UniqueArrayPtr = std::unique_ptr<T[], std::function<void(T*)>>;
struct MemoryRange {
U32 m_offset;
U32 m_size;
MemoryRange(U32 offset, U32 size);
};
class Allocator {
public:
Allocator(void* resource, U32 size);
Allocator(AddressPtr resource, U32 size);
virtual ~Allocator();
// Disable Copy
Allocator(const Allocator& other) = delete;
Allocator& operator=(const Allocator& other) = delete;
// Enable Move
Allocator(Allocator&& other) noexcept = default;
Allocator& operator=(Allocator&& other) noexcept = default;
template <typename Type, typename... Args>
UniquePtr<Type> New(Args ... args);
template <typename Type, typename... Args>
UniqueArrayPtr<Type> NewArray(U32 numElements, Args ... args);
template <typename Type, typename... Args>
UniquePtr<Type> RawNew(Args ... args);
template <typename Type, typename... Args>
UniqueArrayPtr<Type> RawNewArray(U32 numElements, Args ... args);
#ifdef BUILD_UNIT_TEST
AddressPtr GetBasePtr() const {
return BasePtr();
};
AddressPtr GetSize() const {
return Size();
};
#endif
protected:
U32 Size() const;
AddressPtr BasePtr() const;
virtual void* Allocate(U32 size, U32 alignment) = 0;
virtual void Deallocate(void* address) = 0;
virtual void Reset();
private:
template <typename Type, bool Construct, typename... Args>
UniquePtr<Type> InternalAllocate(U32 size, U32 alignment, Args ... args);
template <class Type, bool Construct, class... Args>
UniqueArrayPtr<Type> InternalAllocateArray(U32 elementSize, U32 numElements, U32 alignment, Args ... args);
AddressPtr m_basePtr;
U32 m_size;
};
template <typename Type, typename... Args>
UniquePtr<Type> Allocator::New(Args ... args) {
return InternalAllocate<Type, true, Args...>(sizeof(Type), alignof(Type), args...);
}
template <typename Type, typename... Args>
UniqueArrayPtr<Type> Allocator::NewArray(U32 numElements, Args ... args) {
return InternalAllocateArray<Type, true, Args...>(sizeof(Type), numElements, alignof(Type), args...);
}
template <typename Type, typename... Args>
UniquePtr<Type> Allocator::RawNew(Args ... args) {
return InternalAllocate<Type, false, Args...>(sizeof(Type), alignof(Type), args...);
}
template <typename Type, typename... Args>
UniqueArrayPtr<Type> Allocator::RawNewArray(U32 numElements, Args ... args) {
return InternalAllocateArray<Type, false, Args...>(sizeof(Type), numElements, alignof(Type), args...);
}
template <typename Type, bool Construct, typename... Args>
UniquePtr<Type> Allocator::InternalAllocate(U32 size, U32 alignment, Args ... args) {
Type* address = reinterpret_cast<Type*>(Allocate(size, alignment));
// Allocator couldn't allocate
if (address == nullptr) {
return nullptr;
}
if constexpr (Construct) {
new(address) Type(args...);
}
const auto customDeleter = [this](Type* data)
{
data->~Type();
Deallocate(data);
};
UniquePtr<Type> result(address, customDeleter);
return result;
}
template <typename Type, bool Construct, typename... Args>
UniqueArrayPtr<Type> Allocator::InternalAllocateArray(U32 elementSize, U32 numElements, U32 alignment, Args ... args) {
Type* address = reinterpret_cast<Type*>(Allocate(elementSize * numElements, alignment));
// Allocator couldn't allocate
if (address == nullptr) {
return nullptr;
}
if constexpr (Construct) {
for (U32 idx = 0; idx < numElements; ++idx) {
new(address + (idx * elementSize)) Type(args...);
}
}
const auto customDeleter = [this, numElements](Type* data)
{
if constexpr (Construct) {
Type* ptr = data;
for (U32 idx = 0; idx < numElements; ++idx) {
UNUSED(ptr->~Type());
++ptr;
}
}
Deallocate(data);
};
UniqueArrayPtr<Type> result(address, customDeleter);
return result;
}
} // namespace Memory
} // namespace Azura