mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-17 08:57:26 +00:00
tint/utils/UniqueVector: Use utils::Vector and utils::Hashset
For fewer heap allocations, faster lookups. Change-Id: I02da7c1a63608096ec898b0d89f9f97c6db8733f Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/98141 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: Dan Sinclair <dsinclair@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
b79238d7ec
commit
dce63f5717
@@ -21,17 +21,15 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "src/tint/utils/hashset.h"
|
||||
#include "src/tint/utils/vector.h"
|
||||
|
||||
namespace tint::utils {
|
||||
|
||||
/// UniqueVector is an ordered container that only contains unique items.
|
||||
/// Attempting to add a duplicate is a no-op.
|
||||
template <typename T, typename HASH = std::hash<T>, typename EQUAL = std::equal_to<T>>
|
||||
template <typename T, size_t N, typename HASH = std::hash<T>, typename EQUAL = std::equal_to<T>>
|
||||
struct UniqueVector {
|
||||
/// The iterator returned by begin() and end()
|
||||
using ConstIterator = typename std::vector<T>::const_iterator;
|
||||
/// The iterator returned by rbegin() and rend()
|
||||
using ConstReverseIterator = typename std::vector<T>::const_reverse_iterator;
|
||||
|
||||
/// Constructor
|
||||
UniqueVector() = default;
|
||||
|
||||
@@ -40,7 +38,7 @@ struct UniqueVector {
|
||||
/// elements will be removed.
|
||||
explicit UniqueVector(std::vector<T>&& v) {
|
||||
for (auto& el : v) {
|
||||
add(el);
|
||||
Add(el);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,10 +46,9 @@ struct UniqueVector {
|
||||
/// already contain the given item.
|
||||
/// @param item the item to append to the end of the vector
|
||||
/// @returns true if the item was added, otherwise false.
|
||||
bool add(const T& item) {
|
||||
if (set.count(item) == 0) {
|
||||
vector.emplace_back(item);
|
||||
set.emplace(item);
|
||||
bool Add(const T& item) {
|
||||
if (set.Add(item)) {
|
||||
vector.Push(item);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -59,7 +56,7 @@ struct UniqueVector {
|
||||
|
||||
/// @returns true if the vector contains `item`
|
||||
/// @param item the item
|
||||
bool contains(const T& item) const { return set.count(item); }
|
||||
bool Contains(const T& item) const { return set.Contains(item); }
|
||||
|
||||
/// @param i the index of the element to retrieve
|
||||
/// @returns the element at the index `i`
|
||||
@@ -70,48 +67,50 @@ struct UniqueVector {
|
||||
const T& operator[](size_t i) const { return vector[i]; }
|
||||
|
||||
/// @returns true if the vector is empty
|
||||
bool empty() const { return vector.empty(); }
|
||||
bool IsEmpty() const { return vector.IsEmpty(); }
|
||||
|
||||
/// @returns the number of items in the vector
|
||||
size_t size() const { return vector.size(); }
|
||||
size_t Length() const { return vector.Length(); }
|
||||
|
||||
/// @returns the pointer to the first element in the vector, or nullptr if the vector is empty.
|
||||
const T* data() const { return vector.empty() ? nullptr : vector.data(); }
|
||||
const T* Data() const { return vector.IsEmpty() ? nullptr : &vector[0]; }
|
||||
|
||||
/// @returns an iterator to the beginning of the vector
|
||||
ConstIterator begin() const { return vector.begin(); }
|
||||
auto begin() const { return vector.begin(); }
|
||||
|
||||
/// @returns an iterator to the end of the vector
|
||||
ConstIterator end() const { return vector.end(); }
|
||||
auto end() const { return vector.end(); }
|
||||
|
||||
/// @returns an iterator to the beginning of the reversed vector
|
||||
ConstReverseIterator rbegin() const { return vector.rbegin(); }
|
||||
auto rbegin() const { return vector.rbegin(); }
|
||||
|
||||
/// @returns an iterator to the end of the reversed vector
|
||||
ConstReverseIterator rend() const { return vector.rend(); }
|
||||
auto rend() const { return vector.rend(); }
|
||||
|
||||
/// @returns a const reference to the internal vector
|
||||
operator const std::vector<T>&() const { return vector; }
|
||||
operator const Vector<T, N>&() const { return vector; }
|
||||
|
||||
/// @returns the std::move()'d vector.
|
||||
/// @note The UniqueVector must not be used after calling this method
|
||||
VectorRef<T> Release() { return std::move(vector); }
|
||||
|
||||
/// Pre-allocates `count` elements in the vector and set
|
||||
/// @param count the number of elements to pre-allocate
|
||||
void reserve(size_t count) {
|
||||
vector.reserve(count);
|
||||
set.reserve(count);
|
||||
void Reserve(size_t count) {
|
||||
vector.Reserve(count);
|
||||
set.Reserve(count);
|
||||
}
|
||||
|
||||
/// Removes the last element from the vector
|
||||
/// @returns the popped element
|
||||
T pop_back() {
|
||||
auto el = std::move(vector.back());
|
||||
set.erase(el);
|
||||
vector.pop_back();
|
||||
return el;
|
||||
T Pop() {
|
||||
set.Remove(vector.Back());
|
||||
return vector.Pop();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<T> vector;
|
||||
std::unordered_set<T, HASH, EQUAL> set;
|
||||
Vector<T, N> vector;
|
||||
Hashset<T, N, HASH, EQUAL> set;
|
||||
};
|
||||
|
||||
} // namespace tint::utils
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/tint/utils/unique_vector.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "src/tint/utils/reverse.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
@@ -21,16 +24,16 @@ namespace tint::utils {
|
||||
namespace {
|
||||
|
||||
TEST(UniqueVectorTest, Empty) {
|
||||
UniqueVector<int> unique_vec;
|
||||
EXPECT_EQ(unique_vec.size(), 0u);
|
||||
EXPECT_EQ(unique_vec.empty(), true);
|
||||
UniqueVector<int, 4> unique_vec;
|
||||
EXPECT_EQ(unique_vec.Length(), 0u);
|
||||
EXPECT_EQ(unique_vec.IsEmpty(), true);
|
||||
EXPECT_EQ(unique_vec.begin(), unique_vec.end());
|
||||
}
|
||||
|
||||
TEST(UniqueVectorTest, MoveConstructor) {
|
||||
UniqueVector<int> unique_vec(std::vector<int>{0, 3, 2, 1, 2});
|
||||
EXPECT_EQ(unique_vec.size(), 4u);
|
||||
EXPECT_EQ(unique_vec.empty(), false);
|
||||
UniqueVector<int, 4> unique_vec(std::vector<int>{0, 3, 2, 1, 2});
|
||||
EXPECT_EQ(unique_vec.Length(), 4u);
|
||||
EXPECT_EQ(unique_vec.IsEmpty(), false);
|
||||
EXPECT_EQ(unique_vec[0], 0);
|
||||
EXPECT_EQ(unique_vec[1], 3);
|
||||
EXPECT_EQ(unique_vec[2], 2);
|
||||
@@ -38,12 +41,12 @@ TEST(UniqueVectorTest, MoveConstructor) {
|
||||
}
|
||||
|
||||
TEST(UniqueVectorTest, AddUnique) {
|
||||
UniqueVector<int> unique_vec;
|
||||
unique_vec.add(0);
|
||||
unique_vec.add(1);
|
||||
unique_vec.add(2);
|
||||
EXPECT_EQ(unique_vec.size(), 3u);
|
||||
EXPECT_EQ(unique_vec.empty(), false);
|
||||
UniqueVector<int, 4> unique_vec;
|
||||
unique_vec.Add(0);
|
||||
unique_vec.Add(1);
|
||||
unique_vec.Add(2);
|
||||
EXPECT_EQ(unique_vec.Length(), 3u);
|
||||
EXPECT_EQ(unique_vec.IsEmpty(), false);
|
||||
int i = 0;
|
||||
for (auto n : unique_vec) {
|
||||
EXPECT_EQ(n, i);
|
||||
@@ -59,15 +62,15 @@ TEST(UniqueVectorTest, AddUnique) {
|
||||
}
|
||||
|
||||
TEST(UniqueVectorTest, AddDuplicates) {
|
||||
UniqueVector<int> unique_vec;
|
||||
unique_vec.add(0);
|
||||
unique_vec.add(0);
|
||||
unique_vec.add(0);
|
||||
unique_vec.add(1);
|
||||
unique_vec.add(1);
|
||||
unique_vec.add(2);
|
||||
EXPECT_EQ(unique_vec.size(), 3u);
|
||||
EXPECT_EQ(unique_vec.empty(), false);
|
||||
UniqueVector<int, 4> unique_vec;
|
||||
unique_vec.Add(0);
|
||||
unique_vec.Add(0);
|
||||
unique_vec.Add(0);
|
||||
unique_vec.Add(1);
|
||||
unique_vec.Add(1);
|
||||
unique_vec.Add(2);
|
||||
EXPECT_EQ(unique_vec.Length(), 3u);
|
||||
EXPECT_EQ(unique_vec.IsEmpty(), false);
|
||||
int i = 0;
|
||||
for (auto n : unique_vec) {
|
||||
EXPECT_EQ(n, i);
|
||||
@@ -83,17 +86,17 @@ TEST(UniqueVectorTest, AddDuplicates) {
|
||||
}
|
||||
|
||||
TEST(UniqueVectorTest, AsVector) {
|
||||
UniqueVector<int> unique_vec;
|
||||
unique_vec.add(0);
|
||||
unique_vec.add(0);
|
||||
unique_vec.add(0);
|
||||
unique_vec.add(1);
|
||||
unique_vec.add(1);
|
||||
unique_vec.add(2);
|
||||
UniqueVector<int, 4> unique_vec;
|
||||
unique_vec.Add(0);
|
||||
unique_vec.Add(0);
|
||||
unique_vec.Add(0);
|
||||
unique_vec.Add(1);
|
||||
unique_vec.Add(1);
|
||||
unique_vec.Add(2);
|
||||
|
||||
const std::vector<int>& vec = unique_vec;
|
||||
EXPECT_EQ(vec.size(), 3u);
|
||||
EXPECT_EQ(unique_vec.empty(), false);
|
||||
const utils::Vector<int, 4>& vec = unique_vec;
|
||||
EXPECT_EQ(vec.Length(), 3u);
|
||||
EXPECT_EQ(unique_vec.IsEmpty(), false);
|
||||
int i = 0;
|
||||
for (auto n : vec) {
|
||||
EXPECT_EQ(n, i);
|
||||
@@ -106,46 +109,46 @@ TEST(UniqueVectorTest, AsVector) {
|
||||
}
|
||||
|
||||
TEST(UniqueVectorTest, PopBack) {
|
||||
UniqueVector<int> unique_vec;
|
||||
unique_vec.add(0);
|
||||
unique_vec.add(2);
|
||||
unique_vec.add(1);
|
||||
UniqueVector<int, 4> unique_vec;
|
||||
unique_vec.Add(0);
|
||||
unique_vec.Add(2);
|
||||
unique_vec.Add(1);
|
||||
|
||||
EXPECT_EQ(unique_vec.pop_back(), 1);
|
||||
EXPECT_EQ(unique_vec.size(), 2u);
|
||||
EXPECT_EQ(unique_vec.empty(), false);
|
||||
EXPECT_EQ(unique_vec.Pop(), 1);
|
||||
EXPECT_EQ(unique_vec.Length(), 2u);
|
||||
EXPECT_EQ(unique_vec.IsEmpty(), false);
|
||||
EXPECT_EQ(unique_vec[0], 0);
|
||||
EXPECT_EQ(unique_vec[1], 2);
|
||||
|
||||
EXPECT_EQ(unique_vec.pop_back(), 2);
|
||||
EXPECT_EQ(unique_vec.size(), 1u);
|
||||
EXPECT_EQ(unique_vec.empty(), false);
|
||||
EXPECT_EQ(unique_vec.Pop(), 2);
|
||||
EXPECT_EQ(unique_vec.Length(), 1u);
|
||||
EXPECT_EQ(unique_vec.IsEmpty(), false);
|
||||
EXPECT_EQ(unique_vec[0], 0);
|
||||
|
||||
unique_vec.add(1);
|
||||
unique_vec.Add(1);
|
||||
|
||||
EXPECT_EQ(unique_vec.size(), 2u);
|
||||
EXPECT_EQ(unique_vec.empty(), false);
|
||||
EXPECT_EQ(unique_vec.Length(), 2u);
|
||||
EXPECT_EQ(unique_vec.IsEmpty(), false);
|
||||
EXPECT_EQ(unique_vec[0], 0);
|
||||
EXPECT_EQ(unique_vec[1], 1);
|
||||
|
||||
EXPECT_EQ(unique_vec.pop_back(), 1);
|
||||
EXPECT_EQ(unique_vec.size(), 1u);
|
||||
EXPECT_EQ(unique_vec.empty(), false);
|
||||
EXPECT_EQ(unique_vec.Pop(), 1);
|
||||
EXPECT_EQ(unique_vec.Length(), 1u);
|
||||
EXPECT_EQ(unique_vec.IsEmpty(), false);
|
||||
EXPECT_EQ(unique_vec[0], 0);
|
||||
|
||||
EXPECT_EQ(unique_vec.pop_back(), 0);
|
||||
EXPECT_EQ(unique_vec.size(), 0u);
|
||||
EXPECT_EQ(unique_vec.empty(), true);
|
||||
EXPECT_EQ(unique_vec.Pop(), 0);
|
||||
EXPECT_EQ(unique_vec.Length(), 0u);
|
||||
EXPECT_EQ(unique_vec.IsEmpty(), true);
|
||||
}
|
||||
|
||||
TEST(UniqueVectorTest, Data) {
|
||||
UniqueVector<int> unique_vec;
|
||||
EXPECT_EQ(unique_vec.data(), nullptr);
|
||||
UniqueVector<int, 4> unique_vec;
|
||||
EXPECT_EQ(unique_vec.Data(), nullptr);
|
||||
|
||||
unique_vec.add(42);
|
||||
EXPECT_EQ(unique_vec.data(), &unique_vec[0]);
|
||||
EXPECT_EQ(*unique_vec.data(), 42);
|
||||
unique_vec.Add(42);
|
||||
EXPECT_EQ(unique_vec.Data(), &unique_vec[0]);
|
||||
EXPECT_EQ(*unique_vec.Data(), 42);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user