Added a max_size function to all AZStd container style allocator functions (#4106)

* Added a max_size function to all AZStd container style allocator
functions

The max_size functions returns the maximum value that a single contiguous
allocation value returns

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>

* Updated the BestFitExternalMapSchema and MallocSchema
GetMaxContiguousAllocationSize function

Those functions now return a Max allocation size of
AZ_CORE_MAX_ALLOCATOR size to indicate the maximum size for a single
allocation

Changed the IAllocatorAllocator::GetMaxContiguousAllocationSize function
from a pure virtual function to regular virtual function

Removed the left over String.cpp test to validate that the issue with
the allocator::max_size() function was occuring

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
This commit is contained in:
lumberyard-employee-dm
2021-09-14 16:15:46 -05:00
committed by GitHub
parent 2382b5cbd3
commit 4e8d4c0c51
43 changed files with 166 additions and 84 deletions
@@ -122,8 +122,15 @@ namespace UnitTest
TEST_F(AllocatorDefaultTest, AllocatorTraitsMaxSizeCompilesWithoutErrors)
{
using AZStdAllocatorTraits = AZStd::allocator_traits<AZStd::allocator>;
AZStd::allocator testAllocator("trait allocator");
struct AllocatorWithGetMaxSize
: AZStd::allocator
{
using AZStd::allocator::allocator;
size_t get_max_size() { return max_size(); }
};
using AZStdAllocatorTraits = AZStd::allocator_traits<AllocatorWithGetMaxSize>;
AllocatorWithGetMaxSize testAllocator("trait allocator");
typename AZStdAllocatorTraits::size_type maxSize = AZStdAllocatorTraits::max_size(testAllocator);
EXPECT_EQ(testAllocator.get_max_size(), maxSize);
}
@@ -149,32 +156,32 @@ namespace UnitTest
myalloc.set_name(newName);
AZ_TEST_ASSERT(strcmp(myalloc.get_name(), newName) == 0);
AZ_TEST_ASSERT(myalloc.get_max_size() == AZStd::size_t(bufferSize));
EXPECT_EQ(bufferSize, myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
buffer_alloc_type::pointer_type data = myalloc.allocate(100, 1);
AZ_TEST_ASSERT(data != nullptr);
AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize - 100);
EXPECT_EQ(bufferSize - 100, myalloc.max_size() - myalloc.get_allocated_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 100);
myalloc.deallocate(data, 100, 1); // we can free the last allocation only
AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize);
EXPECT_EQ(bufferSize, myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
data = myalloc.allocate(100, 1);
myalloc.allocate(3, 1);
myalloc.deallocate(data); // can't free allocation which is not the last.
AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize - 103);
EXPECT_EQ(bufferSize - 103, myalloc.max_size() - myalloc.get_allocated_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 103);
myalloc.reset();
AZ_TEST_ASSERT(myalloc.get_max_size() == AZStd::size_t(bufferSize));
EXPECT_EQ(bufferSize, myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
data = myalloc.allocate(50, 64);
AZ_TEST_ASSERT(data != nullptr);
AZ_TEST_ASSERT(((AZStd::size_t)data & 63) == 0);
AZ_TEST_ASSERT(myalloc.get_max_size() <= bufferSize - 50);
EXPECT_LE(myalloc.max_size() - myalloc.get_allocated_size(), bufferSize - 50);
AZ_TEST_ASSERT(myalloc.get_allocated_size() >= 50);
buffer_alloc_type myalloc2;
@@ -194,28 +201,28 @@ namespace UnitTest
myalloc.set_name(newName);
AZ_TEST_ASSERT(strcmp(myalloc.get_name(), newName) == 0);
AZ_TEST_ASSERT(myalloc.get_max_size() == sizeof(int) * numNodes);
EXPECT_EQ(numNodes * sizeof(int), myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
int* data = reinterpret_cast<int*>(myalloc.allocate(sizeof(int), 1));
AZ_TEST_ASSERT(data != nullptr);
AZ_TEST_ASSERT(myalloc.get_max_size() == (numNodes - 1) * sizeof(int));
EXPECT_EQ((numNodes - 1) * sizeof(int), myalloc.max_size() - myalloc.get_allocated_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == sizeof(int));
myalloc.deallocate(data, sizeof(int), 1);
AZ_TEST_ASSERT(myalloc.get_max_size() == sizeof(int) * numNodes);
EXPECT_EQ(numNodes * sizeof(int), myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
for (int i = 0; i < numNodes; ++i)
{
data = reinterpret_cast<int*>(myalloc.allocate(sizeof(int), 1));
AZ_TEST_ASSERT(data != nullptr);
AZ_TEST_ASSERT(myalloc.get_max_size() == (numNodes - (i + 1)) * sizeof(int));
EXPECT_EQ((numNodes - (i + 1)) * sizeof(int), myalloc.max_size() - myalloc.get_allocated_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == (i + 1) * sizeof(int));
}
myalloc.reset();
AZ_TEST_ASSERT(myalloc.get_max_size() == numNodes * sizeof(int));
EXPECT_EQ(numNodes * sizeof(int), myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
AZ_TEST_ASSERT(myalloc == myalloc);
@@ -233,7 +240,7 @@ namespace UnitTest
AZ_TEST_ASSERT(aligned_data != nullptr);
AZ_TEST_ASSERT(((AZStd::size_t)aligned_data & (dataAlignment - 1)) == 0);
AZ_TEST_ASSERT(myaligned_pool.get_max_size() == (numNodes - 1) * sizeof(aligned_int_type));
EXPECT_EQ((numNodes - 1) * sizeof(aligned_int_type), myaligned_pool.max_size() - myaligned_pool.get_allocated_size());
AZ_TEST_ASSERT(myaligned_pool.get_allocated_size() == sizeof(aligned_int_type));
myaligned_pool.deallocate(aligned_data, sizeof(aligned_int_type), dataAlignment); // Make sure we free what we have allocated.
@@ -268,32 +275,32 @@ namespace UnitTest
ref_allocator_type::pointer_type data1 = ref_allocator1.allocate(10, 1);
AZ_TEST_ASSERT(data1 != nullptr);
AZ_TEST_ASSERT(ref_allocator1.get_max_size() == bufferSize - 10);
EXPECT_EQ(bufferSize - 10, ref_allocator1.max_size() - ref_allocator1.get_allocated_size());
AZ_TEST_ASSERT(ref_allocator1.get_allocated_size() == 10);
AZ_TEST_ASSERT(shared_allocator.get_max_size() == bufferSize - 10);
EXPECT_EQ(bufferSize - 10, shared_allocator.max_size() - shared_allocator.get_allocated_size());
AZ_TEST_ASSERT(shared_allocator.get_allocated_size() == 10);
ref_allocator_type::pointer_type data2 = ref_allocator2.allocate(10, 1);
AZ_TEST_ASSERT(data2 != nullptr);
AZ_TEST_ASSERT(ref_allocator2.get_max_size() <= bufferSize - 20);
EXPECT_LE(ref_allocator2.max_size() - ref_allocator2.get_allocated_size(), bufferSize - 20);
AZ_TEST_ASSERT(ref_allocator2.get_allocated_size() >= 20);
AZ_TEST_ASSERT(shared_allocator.get_max_size() <= bufferSize - 20);
EXPECT_LE(shared_allocator.max_size() - shared_allocator.get_allocated_size(), bufferSize - 20);
AZ_TEST_ASSERT(shared_allocator.get_allocated_size() >= 20);
shared_allocator.reset();
data1 = ref_allocator1.allocate(10, 32);
AZ_TEST_ASSERT(data1 != nullptr);
AZ_TEST_ASSERT(ref_allocator1.get_max_size() <= bufferSize - 10);
EXPECT_LE(ref_allocator1.max_size() - ref_allocator1.get_allocated_size(), bufferSize - 10);
AZ_TEST_ASSERT(ref_allocator1.get_allocated_size() >= 10);
AZ_TEST_ASSERT(shared_allocator.get_max_size() <= bufferSize - 10);
EXPECT_LE(shared_allocator.max_size() - shared_allocator.get_allocated_size(), bufferSize - 10);
AZ_TEST_ASSERT(shared_allocator.get_allocated_size() >= 10);
data2 = ref_allocator2.allocate(10, 32);
AZ_TEST_ASSERT(data2 != nullptr);
AZ_TEST_ASSERT(ref_allocator1.get_max_size() <= bufferSize - 20);
EXPECT_LE(ref_allocator1.max_size() - ref_allocator1.get_allocated_size(), bufferSize - 20);
AZ_TEST_ASSERT(ref_allocator1.get_allocated_size() >= 20);
AZ_TEST_ASSERT(shared_allocator.get_max_size() <= bufferSize - 20);
EXPECT_LE(shared_allocator.max_size() - shared_allocator.get_allocated_size(), bufferSize - 20);
AZ_TEST_ASSERT(shared_allocator.get_allocated_size() >= 20);
AZ_TEST_ASSERT(ref_allocator1 == ref_allocator2);
@@ -312,31 +319,31 @@ namespace UnitTest
myalloc.set_name(newName);
AZ_TEST_ASSERT(strcmp(myalloc.get_name(), newName) == 0);
AZ_TEST_ASSERT(myalloc.get_max_size() == AZStd::size_t(bufferSize));
EXPECT_EQ(bufferSize, myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
stack_allocator::pointer_type data = myalloc.allocate(100, 1);
AZ_TEST_ASSERT(data != nullptr);
AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize - 100);
EXPECT_EQ(bufferSize - 100, myalloc.max_size() - myalloc.get_allocated_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 100);
myalloc.deallocate(data, 100, 1); // this allocator doesn't free data
AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize - 100);
EXPECT_EQ(bufferSize - 100, myalloc.max_size() - myalloc.get_allocated_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 100);
myalloc.reset();
AZ_TEST_ASSERT(myalloc.get_max_size() == AZStd::size_t(bufferSize));
EXPECT_EQ(bufferSize, myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
data = myalloc.allocate(50, 64);
AZ_TEST_ASSERT(data != nullptr);
AZ_TEST_ASSERT(((AZStd::size_t)data & 63) == 0);
AZ_TEST_ASSERT(myalloc.get_max_size() <= bufferSize - 50);
EXPECT_LE(myalloc.max_size() - myalloc.get_allocated_size(), bufferSize - 50);
AZ_TEST_ASSERT(myalloc.get_allocated_size() >= 50);
AZ_STACK_ALLOCATOR(myalloc2, 200); // test the macro declaration
AZ_TEST_ASSERT(myalloc2.get_max_size() == 200);
EXPECT_EQ(200, myalloc2.max_size() );
AZ_TEST_ASSERT(myalloc == myalloc);
AZ_TEST_ASSERT((myalloc2 != myalloc));
@@ -49,7 +49,7 @@ namespace UnitTest
const char newName[] = "My new test allocator";
myalloc.set_name(newName);
EXPECT_EQ(0, strcmp(myalloc.get_name(), newName));
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * s_allocatorCapacity, myalloc.get_max_size());
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * s_allocatorCapacity, myalloc.max_size());
}
}
@@ -61,10 +61,10 @@ namespace UnitTest
typename TestFixture::allocator_type::pointer_type data = myalloc.allocate();
EXPECT_NE(nullptr, data);
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type), myalloc.get_allocated_size());
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * (s_allocatorCapacity - 1), myalloc.get_max_size());
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * (s_allocatorCapacity - 1), myalloc.max_size() - myalloc.get_allocated_size());
myalloc.deallocate(data);
EXPECT_EQ(0, myalloc.get_allocated_size());
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * s_allocatorCapacity, myalloc.get_max_size());
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * s_allocatorCapacity, myalloc.max_size());
}
TYPED_TEST(ConcurrentAllocatorTestFixture, MultipleAllocateDeallocate)
@@ -84,19 +84,19 @@ namespace UnitTest
EXPECT_EQ(dataSize, dataSet.size());
dataSet.clear();
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * dataSize, myalloc.get_allocated_size());
EXPECT_EQ((s_allocatorCapacity - dataSize) * sizeof(typename TestFixture::allocator_type::value_type), myalloc.get_max_size());
EXPECT_EQ((s_allocatorCapacity - dataSize) * sizeof(typename TestFixture::allocator_type::value_type), myalloc.max_size() - myalloc.get_allocated_size());
for (size_t i = 0; i < dataSize; i += 2)
{
myalloc.deallocate(data[i]);
}
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * (dataSize / 2), myalloc.get_allocated_size());
EXPECT_EQ((s_allocatorCapacity - dataSize / 2) * sizeof(typename TestFixture::allocator_type::value_type), myalloc.get_max_size());
EXPECT_EQ((s_allocatorCapacity - dataSize / 2) * sizeof(typename TestFixture::allocator_type::value_type), myalloc.max_size() - myalloc.get_allocated_size());
for (size_t i = 1; i < dataSize; i += 2)
{
myalloc.deallocate(data[i]);
}
EXPECT_EQ(0, myalloc.get_allocated_size());
EXPECT_EQ(s_allocatorCapacity * sizeof(typename TestFixture::allocator_type::value_type), myalloc.get_max_size());
EXPECT_EQ(s_allocatorCapacity * sizeof(typename TestFixture::allocator_type::value_type), myalloc.max_size());
}
TYPED_TEST(ConcurrentAllocatorTestFixture, ConcurrentAllocateoDeallocate)
@@ -159,7 +159,7 @@ namespace UnitTest
EXPECT_NE(nullptr, aligned_data);
EXPECT_EQ(0, ((AZStd::size_t)aligned_data & (dataAlignment - 1)));
EXPECT_EQ((s_allocatorCapacity - 1) * sizeof(aligned_int_type), myaligned_pool.get_max_size());
EXPECT_EQ((s_allocatorCapacity - 1) * sizeof(aligned_int_type), myaligned_pool.max_size() - myaligned_pool.get_allocated_size());
EXPECT_EQ(sizeof(aligned_int_type), myaligned_pool.get_allocated_size());
myaligned_pool.deallocate(aligned_data, sizeof(aligned_int_type), dataAlignment); // Make sure we free what we have allocated.
+2
View File
@@ -1179,6 +1179,8 @@ namespace UnitTest
size_type Capacity() const override { return 1 * 1024 * 1024 * 1024; }
/// Returns max allocation size if possible. If not returned value is 0
size_type GetMaxAllocationSize() const override { return 1 * 1024 * 1024 * 1024; }
/// Returns max allocation size of a single contiguous allocation
size_type GetMaxContiguousAllocationSize() const override { return 1 * 1024 * 1024 * 1024; }
/// Returns a pointer to a sub-allocator or NULL.
IAllocatorAllocate* GetSubAllocator() override { return NULL; }
};