Skip to content

Commit

Permalink
Add template allocate() and deallocate() methods to MemoryAllocator s…
Browse files Browse the repository at this point in the history
…implying allocation and deallocation for given type
  • Loading branch information
danielkrupinski committed Aug 2, 2023
1 parent 2dff5cb commit 443ccf6
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 10 deletions.
2 changes: 1 addition & 1 deletion Source/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

#include <Platform/Macros/IsPlatform.h>

#if IS_WIN32()
#if IS_WIN32() || IS_WIN64()
#include <Windows.h>
#include <shellapi.h>
#include <ShlObj.h>
Expand Down
47 changes: 42 additions & 5 deletions Source/MemoryAllocation/MemoryAllocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,60 @@
#include "FreeMemoryRegionList.h"

struct MemoryAllocator {
[[nodiscard]] static std::byte* allocate(std::size_t size) noexcept;
static void deallocate(std::byte* memory, std::size_t size) noexcept;

template <typename T>
requires (!std::is_array_v<T>)
[[nodiscard]] static std::byte* allocate() noexcept
{
return allocate(memoryFor<T>());
}

template <typename T>
requires std::is_unbounded_array_v<T>
[[nodiscard]] static std::byte* allocate(std::size_t numberOfElements) noexcept
{
return allocate(memoryFor<T>(numberOfElements));
}

template <typename T, typename... Args>
requires std::is_bounded_array_v<T>
static void allocate(Args&&...) = delete;

template <typename T>
requires (!std::is_array_v<T>)
static void deallocate(T* memory) noexcept
{
deallocate(reinterpret_cast<std::byte*>(memory), memoryFor<T>());
}

template <typename T>
requires std::is_unbounded_array_v<T>
static void deallocate(std::remove_extent_t<T>* memory, std::size_t numberOfElements) noexcept
{
deallocate(reinterpret_cast<std::byte*>(memory), memoryFor<T>(numberOfElements));
}

template <typename T, typename... Args>
requires std::is_bounded_array_v<T>
static void deallocate(Args&&...) = delete;

private:
template <typename T>
requires (!std::is_array_v<T>)
[[nodiscard]] static auto memoryFor() noexcept
{
static_assert(!std::is_array_v<T>);
static_assert(alignof(T) <= FreeMemoryRegionList::minimumAlignment(), "Unsupported alignment");
return utils::align<sizeof(T), FreeMemoryRegionList::minimumAlignment()>();
}

template <typename T>
requires std::is_unbounded_array_v<T>
[[nodiscard]] static auto memoryFor(std::size_t numberOfElements) noexcept
{
static_assert(std::is_array_v<T>);
static_assert(alignof(T) <= FreeMemoryRegionList::minimumAlignment(), "Unsupported alignment");
assert(numberOfElements <= (std::numeric_limits<std::size_t>::max)() / sizeof(std::remove_extent_t<T>));
return utils::align(numberOfElements * sizeof(std::remove_extent_t<T>), FreeMemoryRegionList::minimumAlignment());
}

[[nodiscard]] static std::byte* allocate(std::size_t size) noexcept;
static void deallocate(std::byte* memory, std::size_t size) noexcept;
};
4 changes: 2 additions & 2 deletions Source/MemoryAllocation/MemoryDeleter.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct MemoryDeleter {
{
if (memory) {
std::destroy_at(memory);
MemoryAllocator::deallocate(reinterpret_cast<std::byte*>(memory), MemoryAllocator::memoryFor<T>());
MemoryAllocator::deallocate(memory);
}
}
};
Expand All @@ -29,7 +29,7 @@ struct MemoryDeleter<T[]> {
{
if (memory) {
std::destroy_n(memory, numberOfElements);
MemoryAllocator::deallocate(reinterpret_cast<std::byte*>(memory), MemoryAllocator::memoryFor<T[]>(numberOfElements));
MemoryAllocator::deallocate<T[]>(memory, numberOfElements);
}
}

Expand Down
4 changes: 2 additions & 2 deletions Source/MemoryAllocation/UniquePtr.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ template <typename T>
requires (!std::is_array_v<T>)
[[nodiscard]] auto makeUniqueForOverwrite() noexcept
{
return UniquePtr<T>{ new (MemoryAllocator::allocate(MemoryAllocator::memoryFor<T>())) T };
return UniquePtr<T>{ new (MemoryAllocator::allocate<T>()) T };
}

template <typename T>
requires std::is_unbounded_array_v<T>
[[nodiscard]] auto makeUniqueForOverwrite(std::size_t size) noexcept
{
return UniquePtr<T>{ new (MemoryAllocator::allocate(MemoryAllocator::memoryFor<T>(size))) std::remove_extent_t<T>[size], MemoryDeleter<T>{ size } };
return UniquePtr<T>{ new (MemoryAllocator::allocate<T>(size)) std::remove_extent_t<T>[size], MemoryDeleter<T>{ size } };
}

template <typename T, typename... Args>
Expand Down

0 comments on commit 443ccf6

Please sign in to comment.