.. _program_listing_file_Source_Common_Inc_Memory_Allocator.h: Program Listing for File Allocator.h ==================================== |exhale_lsh| :ref:`Return to documentation for file ` (``Source\Common\Inc\Memory\Allocator.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #pragma once #include #include "Types.h" #include "Utils/Macros.h" namespace Azura { namespace Memory { template using UniquePtr = std::unique_ptr>; template using UniqueArrayPtr = std::unique_ptr>; 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 UniquePtr New(Args ... args); template UniqueArrayPtr NewArray(U32 numElements, Args ... args); template UniquePtr RawNew(Args ... args); template UniqueArrayPtr 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 UniquePtr InternalAllocate(U32 size, U32 alignment, Args ... args); template UniqueArrayPtr InternalAllocateArray(U32 elementSize, U32 numElements, U32 alignment, Args ... args); AddressPtr m_basePtr; U32 m_size; }; template UniquePtr Allocator::New(Args ... args) { return InternalAllocate(sizeof(Type), alignof(Type), args...); } template UniqueArrayPtr Allocator::NewArray(U32 numElements, Args ... args) { return InternalAllocateArray(sizeof(Type), numElements, alignof(Type), args...); } template UniquePtr Allocator::RawNew(Args ... args) { return InternalAllocate(sizeof(Type), alignof(Type), args...); } template UniqueArrayPtr Allocator::RawNewArray(U32 numElements, Args ... args) { return InternalAllocateArray(sizeof(Type), numElements, alignof(Type), args...); } template UniquePtr Allocator::InternalAllocate(U32 size, U32 alignment, Args ... args) { Type* address = reinterpret_cast(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 result(address, customDeleter); return result; } template UniqueArrayPtr Allocator::InternalAllocateArray(U32 elementSize, U32 numElements, U32 alignment, Args ... args) { Type* address = reinterpret_cast(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 result(address, customDeleter); return result; } } // namespace Memory } // namespace Azura