From ff155e23de5f3314659e081c39a956ac4c496934 Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Wed, 22 Mar 2023 19:35:42 +0800 Subject: [PATCH] feat(memory): add CMultipleAllocator for non-contiguous containers --- .../Source/Public/Containers/Array.h | 2 +- .../Source/Public/Containers/ArrayView.h | 2 +- .../Source/Public/Containers/Bitset.h | 2 +- .../Source/Public/Memory/Allocator.h | 29 +++++++++++++------ 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/Redcraft.Utility/Source/Public/Containers/Array.h b/Redcraft.Utility/Source/Public/Containers/Array.h index ddabc08..b89f2d0 100644 --- a/Redcraft.Utility/Source/Public/Containers/Array.h +++ b/Redcraft.Utility/Source/Public/Containers/Array.h @@ -17,7 +17,7 @@ NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) /** Dynamic array. The elements are stored contiguously, which means that elements can be accessed not only through iterators, but also using offsets to regular pointers to elements. */ -template requires (!CConst) +template Allocator = FHeapAllocator> requires (!CConst) class TArray final { private: diff --git a/Redcraft.Utility/Source/Public/Containers/ArrayView.h b/Redcraft.Utility/Source/Public/Containers/ArrayView.h index 5806511..f6b41e9 100644 --- a/Redcraft.Utility/Source/Public/Containers/ArrayView.h +++ b/Redcraft.Utility/Source/Public/Containers/ArrayView.h @@ -17,7 +17,7 @@ NAMESPACE_MODULE_BEGIN(Utility) template struct TStaticArray; -template requires (!CConst) +template A> requires (!CConst) class TArray; inline constexpr size_t DynamicExtent = INDEX_NONE; diff --git a/Redcraft.Utility/Source/Public/Containers/Bitset.h b/Redcraft.Utility/Source/Public/Containers/Bitset.h index 02d1d9a..05f1560 100644 --- a/Redcraft.Utility/Source/Public/Containers/Bitset.h +++ b/Redcraft.Utility/Source/Public/Containers/Bitset.h @@ -24,7 +24,7 @@ using TDefaultBitsetAllocator = TInlineAllocator<(40 - 3 * sizeof(size_t)) / siz NAMESPACE_PRIVATE_END -template > requires (!CSameAs) +template Allocator = NAMESPACE_PRIVATE::TDefaultBitsetAllocator> requires (!CSameAs) class TBitset final { private: diff --git a/Redcraft.Utility/Source/Public/Memory/Allocator.h b/Redcraft.Utility/Source/Public/Memory/Allocator.h index 19cc606..3f5a7ae 100644 --- a/Redcraft.Utility/Source/Public/Memory/Allocator.h +++ b/Redcraft.Utility/Source/Public/Memory/Allocator.h @@ -13,7 +13,7 @@ NAMESPACE_MODULE_BEGIN(Utility) struct FAllocatorInterface; template -concept CInstantiableAllocator = !CSameAs +concept CAllocator = !CSameAs && requires (typename A::template ForElementType& Allocator, T* InPtr, size_t Num, size_t NumAllocated) { { Allocator.Allocate(Num) } -> CSameAs; @@ -24,6 +24,9 @@ concept CInstantiableAllocator = !CSameAs { AsConst(Allocator).CalculateSlackReserve(Num) } -> CSameAs; }; +template +concept CMultipleAllocator = CAllocator && A::bSupportsMultipleAllocation; + /** * 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, @@ -32,6 +35,14 @@ concept CInstantiableAllocator = !CSameAs */ struct FAllocatorInterface { + /** + * If this flag is false, it is possible to allocate an address that has already been allocated. + * 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. + */ + static constexpr bool bSupportsMultipleAllocation = true; + template class ForElementType /*: private FSingleton*/ { @@ -43,13 +54,7 @@ struct FAllocatorInterface ForElementType& operator=(const ForElementType&) = delete; ForElementType& operator=(ForElementType&&) = delete; - /** - * 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. - */ + /** Allocates uninitialized storage. If 'InNum' is zero, return nullptr. */ NODISCARD FORCEINLINE T* Allocate(size_t InNum) = delete; /** Deallocates storage. */ @@ -107,6 +112,8 @@ struct FAllocatorInterface /** This is heap allocator that calls Memory::Malloc() directly for memory allocation. */ struct FHeapAllocator { + static constexpr bool bSupportsMultipleAllocation = true; + template class ForElementType { @@ -181,9 +188,11 @@ struct FHeapAllocator * The inline allocator allocates up to a specified number of elements in the same allocation as the container. * Any allocation needed beyond that causes all data to be moved into an indirect allocation. */ -template +template struct TInlineAllocator { + static constexpr bool bSupportsMultipleAllocation = false; + template class ForElementType { @@ -264,6 +273,8 @@ struct TInlineAllocator /** This is a null allocator for which all operations are illegal. */ struct FNullAllocator { + static constexpr bool bSupportsMultipleAllocation = true; + template class ForElementType {