mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-05-14 19:31:25 +00:00
A container and allocator of objects of (or deriving from) the template type `T`. Objects are allocated by calling Create(), and are owned by the BlockAllocator. When the BlockAllocator is destructed, all constructed objects are automatically destructed and freed. Objects held by the BlockAllocator can be iterated over using a View or ConstView. Use this to hold the ast::Nodes in the ast::Module This is called BlockAllocator as it can be optimized to hold objects in contiguous memory blocks, which will improve cache coherencey. Currently BlockAllocator is a straight port of the vector-of-unique-ptr, taken from ast::Module. Change-Id: I4bf4d298aec3c70d2ddf833e2f168416cbb024c0 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/38001 Reviewed-by: dan sinclair <dsinclair@chromium.org> Commit-Queue: Ben Clayton <bclayton@google.com>
143 lines
3.2 KiB
C++
143 lines
3.2 KiB
C++
// Copyright 2021 The Tint Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "src/block_allocator.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace tint {
|
|
namespace {
|
|
|
|
struct LifetimeCounter {
|
|
explicit LifetimeCounter(size_t* count) : count_(count) { (*count)++; }
|
|
~LifetimeCounter() { (*count_)--; }
|
|
|
|
size_t* const count_;
|
|
};
|
|
|
|
using BlockAllocatorTest = testing::Test;
|
|
|
|
TEST_F(BlockAllocatorTest, Empty) {
|
|
using Allocator = BlockAllocator<int>;
|
|
|
|
Allocator allocator;
|
|
|
|
for (int* i : allocator.Objects()) {
|
|
(void)i;
|
|
if ((true)) { // Workaround for "error: loop will run at most once"
|
|
FAIL() << "BlockAllocator should be empty";
|
|
}
|
|
}
|
|
for (int* i : static_cast<const Allocator&>(allocator).Objects()) {
|
|
(void)i;
|
|
if ((true)) { // Workaround for "error: loop will run at most once"
|
|
FAIL() << "BlockAllocator should be empty";
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_F(BlockAllocatorTest, ObjectLifetime) {
|
|
using Allocator = BlockAllocator<LifetimeCounter>;
|
|
|
|
size_t count = 0;
|
|
{
|
|
Allocator allocator;
|
|
EXPECT_EQ(count, 0u);
|
|
allocator.Create(&count);
|
|
EXPECT_EQ(count, 1u);
|
|
allocator.Create(&count);
|
|
EXPECT_EQ(count, 2u);
|
|
allocator.Create(&count);
|
|
EXPECT_EQ(count, 3u);
|
|
}
|
|
EXPECT_EQ(count, 0u);
|
|
}
|
|
|
|
TEST_F(BlockAllocatorTest, MoveConstruct) {
|
|
using Allocator = BlockAllocator<LifetimeCounter>;
|
|
|
|
size_t count = 0;
|
|
|
|
{
|
|
Allocator allocator_a;
|
|
for (int i = 0; i < 10; i++) {
|
|
allocator_a.Create(&count);
|
|
}
|
|
EXPECT_EQ(count, 10u);
|
|
|
|
Allocator allocator_b{std::move(allocator_a)};
|
|
EXPECT_EQ(count, 10u);
|
|
}
|
|
|
|
EXPECT_EQ(count, 0u);
|
|
}
|
|
|
|
TEST_F(BlockAllocatorTest, MoveAssign) {
|
|
using Allocator = BlockAllocator<LifetimeCounter>;
|
|
|
|
size_t count_a = 0;
|
|
size_t count_b = 0;
|
|
|
|
{
|
|
Allocator allocator_a;
|
|
for (int i = 0; i < 10; i++) {
|
|
allocator_a.Create(&count_a);
|
|
}
|
|
EXPECT_EQ(count_a, 10u);
|
|
|
|
Allocator allocator_b;
|
|
for (int i = 0; i < 10; i++) {
|
|
allocator_b.Create(&count_b);
|
|
}
|
|
EXPECT_EQ(count_b, 10u);
|
|
|
|
allocator_b = std::move(allocator_a);
|
|
EXPECT_EQ(count_a, 10u);
|
|
EXPECT_EQ(count_b, 0u);
|
|
}
|
|
|
|
EXPECT_EQ(count_a, 0u);
|
|
EXPECT_EQ(count_b, 0u);
|
|
}
|
|
|
|
TEST_F(BlockAllocatorTest, ObjectOrder) {
|
|
using Allocator = BlockAllocator<int>;
|
|
|
|
Allocator allocator;
|
|
constexpr int N = 10000;
|
|
for (int i = 0; i < N; i++) {
|
|
allocator.Create(i);
|
|
}
|
|
|
|
{
|
|
int i = 0;
|
|
for (int* p : allocator.Objects()) {
|
|
EXPECT_EQ(*p, i);
|
|
i++;
|
|
}
|
|
EXPECT_EQ(i, N);
|
|
}
|
|
{
|
|
int i = 0;
|
|
for (int* p : static_cast<const Allocator&>(allocator).Objects()) {
|
|
EXPECT_EQ(*p, i);
|
|
i++;
|
|
}
|
|
EXPECT_EQ(i, N);
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace tint
|