From febffc453a37f6e68c5524b7afeddff416f9a966 Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Tue, 24 Jan 2023 18:57:45 +0800 Subject: [PATCH] feat(memory): add FAllocatorInterface and FHeapAllocator --- .../Source/Public/Memory/AllocatorInterface.h | 58 ++++++++++++++ .../Source/Public/Memory/DefaultAllocator.h | 15 ++++ .../Source/Public/Memory/HeapAllocator.h | 76 +++++++++++++++++++ .../Source/Public/Templates/TypeHash.h | 1 + 4 files changed, 150 insertions(+) create mode 100644 Redcraft.Utility/Source/Public/Memory/AllocatorInterface.h create mode 100644 Redcraft.Utility/Source/Public/Memory/DefaultAllocator.h create mode 100644 Redcraft.Utility/Source/Public/Memory/HeapAllocator.h diff --git a/Redcraft.Utility/Source/Public/Memory/AllocatorInterface.h b/Redcraft.Utility/Source/Public/Memory/AllocatorInterface.h new file mode 100644 index 0000000..a3bbc39 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Memory/AllocatorInterface.h @@ -0,0 +1,58 @@ +#pragma once + +#include "CoreTypes.h" +#include "Memory/Memory.h" +#include "Templates/Noncopyable.h" +#include "TypeTraits/TypeTraits.h" +#include "Miscellaneous/AssertionMacros.h" + +NAMESPACE_REDCRAFT_BEGIN +NAMESPACE_MODULE_BEGIN(Redcraft) +NAMESPACE_MODULE_BEGIN(Utility) + +struct FAllocatorInterface; + +template +concept CInstantiableAllocator = CDerivedFrom && !CSameAs; + +/** + * This is the allocator interface, the allocator does not use virtual, this contains the default of + * the allocator interface functions. Unlike std::allocator, IAllocator should be bound to only a object, + * such as a container, because there may be side effects between multiple allocations, for example, + * inline storage cannot be allocated multiple times in TInlineAllocator. + */ +struct FAllocatorInterface +{ + template + struct ForElementType : private FSingleton + { + /** + * Allocates uninitialized storage. + * Should be allocated according to the results given by the CalculateSlackReserve() family, + * without needing to allocate memory of the same size as the allocated memory, + * this is to support special allocators such as TInlineAllocator. + * If 'InNum' is zero, return nullptr. + */ + NODISCARD FORCEINLINE T* Allocate(size_t InNum) = delete; + + /** Deallocates storage. */ + FORCEINLINE void Deallocate(T* InPtr) = delete; + + /** @return true if allocation can be deallocated by another allocator, otherwise false. */ + NODISCARD FORCEINLINE bool IsTransferable(T* InPtr) { return true; } + + /** Calculates the amount of slack to allocate for an array that has just grown to a given number of elements. */ + NODISCARD FORCEINLINE constexpr size_t CalculateSlackGrow(size_t Num, size_t NumAllocated) const = delete; + + /** Calculates the amount of slack to allocate for an array that has just shrunk to a given number of elements. */ + NODISCARD FORCEINLINE constexpr size_t CalculateSlackShrink(size_t Num, size_t NumAllocated) const = delete; + + /** Calculates the amount of slack to allocate for an array that has just grown or shrunk to a given number of elements. */ + NODISCARD FORCEINLINE constexpr size_t CalculateSlackReserve(size_t Num) const = delete; + + }; +}; + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Memory/DefaultAllocator.h b/Redcraft.Utility/Source/Public/Memory/DefaultAllocator.h new file mode 100644 index 0000000..994d52c --- /dev/null +++ b/Redcraft.Utility/Source/Public/Memory/DefaultAllocator.h @@ -0,0 +1,15 @@ +#pragma once + +#include "CoreTypes.h" +#include "Memory/Memory.h" +#include "Memory/HeapAllocator.h" + +NAMESPACE_REDCRAFT_BEGIN +NAMESPACE_MODULE_BEGIN(Redcraft) +NAMESPACE_MODULE_BEGIN(Utility) + +using FDefaultAllocator = FHeapAllocator; + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Memory/HeapAllocator.h b/Redcraft.Utility/Source/Public/Memory/HeapAllocator.h new file mode 100644 index 0000000..2f4ef80 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Memory/HeapAllocator.h @@ -0,0 +1,76 @@ +#pragma once + +#include "CoreTypes.h" +#include "Memory/Memory.h" +#include "Memory/AllocatorInterface.h" + +NAMESPACE_REDCRAFT_BEGIN +NAMESPACE_MODULE_BEGIN(Redcraft) +NAMESPACE_MODULE_BEGIN(Utility) + +/** This is heap allocator that calls Memory::Malloc() directly for memory allocation. */ +struct FHeapAllocator : public FAllocatorInterface +{ + template + struct ForElementType : public FAllocatorInterface::ForElementType + { + NODISCARD FORCEINLINE T* Allocate(size_t InNum) + { + return InNum != 0 ? static_cast(Memory::Malloc(Memory::QuantizeSize(InNum * sizeof(T)), alignof(T))) : nullptr; + } + + FORCEINLINE void Deallocate(T* InPtr) + { + Memory::Free(InPtr); + } + + NODISCARD FORCEINLINE constexpr size_t CalculateSlackGrow(size_t Num, size_t NumAllocated) const + { + const size_t FirstGrow = 4; + const size_t ConstantGrow = 16; + + size_t Result; + + check(Num > NumAllocated); + + Result = (NumAllocated != 0) ? (Num + 3 * Num / 8 + ConstantGrow) : (Num > FirstGrow ? Num : FirstGrow); + + Result = Memory::QuantizeSize(Result * sizeof(T), alignof(T)) / sizeof(T); + + return Result; + } + + NODISCARD FORCEINLINE constexpr size_t CalculateSlackShrink(size_t Num, size_t NumAllocated) const + { + size_t Result; + + check(Num < NumAllocated); + + const bool bTooManySlackBytes = (NumAllocated - Num) * sizeof(T) >= 16 * 1024; + const bool bTooManySlackElements = 3 * Num < 2 * NumAllocated; + + const bool bNeedToShrink = (bTooManySlackBytes || bTooManySlackElements) && (NumAllocated - Num > 64 || Num == 0); + + if (bNeedToShrink) + { + Result = Num != 0 ? Memory::QuantizeSize(Num * sizeof(T), alignof(T)) / sizeof(T) : 0; + } + else + { + Result = NumAllocated; + } + + return Result; + } + + NODISCARD FORCEINLINE constexpr size_t CalculateSlackReserve(size_t Num) const + { + return Num != 0 ? Memory::QuantizeSize(Num * sizeof(T), alignof(T)) / sizeof(T) : 0; + } + + }; +}; + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Templates/TypeHash.h b/Redcraft.Utility/Source/Public/Templates/TypeHash.h index 549b0d3..6b2a08f 100644 --- a/Redcraft.Utility/Source/Public/Templates/TypeHash.h +++ b/Redcraft.Utility/Source/Public/Templates/TypeHash.h @@ -4,6 +4,7 @@ #include "Templates/Utility.h" #include "TypeTraits/PrimaryType.h" #include "TypeTraits/Miscellaneous.h" +#include "Miscellaneous/AssertionMacros.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft)