#pragma once #include "deimos/core/base.h" #include "deimos/core/id_name.h" namespace deimos { struct MemoryScope { uint32 id; }; struct IAllocator { IAllocator() = default; deimos_NO_COPY_MOVE(IAllocator); virtual ~IAllocator() = default; [[nodiscard]] virtual void* Reallocate( void* old_ptr, int64 old_size, int64 new_size, MemoryScope scope, const SourceLocation& source_location = {}) = 0; }; class Allocator { IAllocator* m_allocator; const MemoryScope m_scope; public: constexpr explicit Allocator(IAllocator* allocator, MemoryScope scope) : m_allocator{allocator}, m_scope{scope} {} deimos_NO_COPY_MOVE(Allocator); ~Allocator() = default; [[nodiscard]] constexpr void* Allocate( int64 new_size, const SourceLocation& source_location = {}) { return m_allocator->Reallocate(nullptr, 0, new_size, m_scope, source_location); } [[nodiscard]] void* Reallocate( void* old_ptr, int64 old_size, int64 new_size, const SourceLocation& source_location = {}) { return m_allocator->Reallocate(old_ptr, old_size, new_size, m_scope, source_location); } constexpr void Free( void* old_ptr, int64 old_size, const SourceLocation& source_location = {}) { (void)m_allocator->Reallocate(old_ptr, old_size, 0, m_scope, source_location); } template T* NewInner( const SourceLocation& source_location, Args&&... args) { void* ptr = Allocate(sizeof(T), source_location); return new(ptr) T(std::forward(args)...); } template constexpr T* New(const SourceLocation& source_location = {}) { return NewInner(source_location); } template constexpr T* New(A0&& arg0, const SourceLocation& source_location = {}) { return NewInner(source_location, std::forward(arg0)); } template constexpr T* New( A0&& arg0, A1&& arg1, const SourceLocation& source_location = {}) { return NewInner(source_location, std::forward(arg0), std::forward(arg1)); } template constexpr T* New( A0&& arg0, A1&& arg1, A2&& arg2, const SourceLocation& source_location = {}) { return NewInner(source_location, std::forward(arg0), std::forward(arg1), std::forward(arg2)); } template constexpr T* New( A0&& arg0, A1&& arg1, A2&& arg2, A3&& arg3, const SourceLocation& source_location = {}) { return NewInner(source_location, std::forward(arg0), std::forward(arg1), std::forward(arg2), std::forward(arg3)); } template void Delete(T* t, const SourceLocation& source_location = {}) { if constexpr (!kIsTriviallyDestructible) { t->~T(); } Free(t, sizeof(T), source_location); } }; class AllocatorApi { public: static constexpr IdName kApiName{"deimos::AllocatorApi"}; Allocator* system{}; }; } // namespace deimos