From 77ccc13181868ab8660162f76a9ed6a175d4c0d6 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 20 Feb 2022 23:03:34 +0300 Subject: [PATCH] Add Map/SetNode::copy_from. --- tdutils/td/utils/FlatHashMap.h | 8 ++-- tdutils/td/utils/FlatHashMapLinear.h | 60 +++++++++++++++++++--------- tdutils/test/HashSet.cpp | 14 +++++-- 3 files changed, 57 insertions(+), 25 deletions(-) diff --git a/tdutils/td/utils/FlatHashMap.h b/tdutils/td/utils/FlatHashMap.h index 097d02939..c1bd4ef47 100644 --- a/tdutils/td/utils/FlatHashMap.h +++ b/tdutils/td/utils/FlatHashMap.h @@ -14,13 +14,13 @@ namespace td { template , class EqT = std::equal_to> -//using FlatHashMap = FlatHashMapImpl; -using FlatHashMap = FlatHashMapChunks; +using FlatHashMap = FlatHashMapImpl; +//using FlatHashMap = FlatHashMapChunks; //using FlatHashMap = std::unordered_map; template , class EqT = std::equal_to> -//using FlatHashSet = FlatHashSetImpl; -using FlatHashSet = FlatHashSetChunks; +using FlatHashSet = FlatHashSetImpl; +//using FlatHashSet = FlatHashSetChunks; //using FlatHashSet = std::unordered_set; } // namespace td diff --git a/tdutils/td/utils/FlatHashMapLinear.h b/tdutils/td/utils/FlatHashMapLinear.h index 8127b3005..4dcd6788b 100644 --- a/tdutils/td/utils/FlatHashMapLinear.h +++ b/tdutils/td/utils/FlatHashMapLinear.h @@ -71,6 +71,13 @@ struct MapNode { } } + void copy_from(const MapNode &other) { + DCHECK(empty()); + DCHECK(!other.empty()); + first = other.first; + new (&second) ValueT(other.second); + } + bool empty() const { return is_key_empty(key()); } @@ -97,7 +104,9 @@ struct SetNode { using key_type = KeyT; using public_type = KeyT; using value_type = KeyT; + KeyT first{}; + const auto &key() const { return first; } @@ -125,6 +134,12 @@ struct SetNode { } ~SetNode() = default; + void copy_from(const SetNode &other) { + DCHECK(empty()); + DCHECK(!other.empty()); + first = other.first; + } + bool empty() const { return is_key_empty(key()); } @@ -236,27 +251,33 @@ class FlatHashTable { using const_iterator = ConstIterator; FlatHashTable() = default; - FlatHashTable(const FlatHashTable &other) : FlatHashTable(other.begin(), other.end()) { + FlatHashTable(const FlatHashTable &other) { + assign(other); } FlatHashTable &operator=(const FlatHashTable &other) { - assign(other.begin(), other.end()); + clear(); + assign(other); return *this; } FlatHashTable(std::initializer_list nodes) { + if (nodes.size() == 0) { + return; + } reserve(nodes.size()); for (auto &new_node : nodes) { CHECK(!new_node.empty()); - auto bucket = calc_bucket(new_node.first); + auto bucket = calc_bucket(new_node.key()); while (true) { auto &node = nodes_[bucket]; - if (node.key() == new_node.first) { - node.second = new_node.second; + if (node.empty()) { + node.copy_from(new_node); + used_nodes_++; break; } - if (node.empty()) { - node.emplace(new_node.first, new_node.second); - used_nodes_++; + if (EqT()(node.key(), new_node.key())) { + node.clear(); + node.copy_from(new_node); break; } next_bucket(bucket); @@ -280,11 +301,6 @@ class FlatHashTable { } ~FlatHashTable() = default; - template - FlatHashTable(ItT begin, ItT end) { - assign(begin, end); - } - size_t bucket_count() const { return nodes_.size(); } @@ -434,12 +450,20 @@ class FlatHashTable { fixed_vector nodes_; size_t used_nodes_{}; - template - void assign(ItT begin, ItT end) { - resize(std::distance(begin, end)); // TODO: should be conditional - for (; begin != end; ++begin) { - emplace(begin->first, begin->second); + void assign(const FlatHashTable &other) { + resize(other.size()); + for (const auto &new_node : other) { + auto bucket = calc_bucket(new_node.key()); + while (true) { + auto &node = nodes_[bucket]; + if (node.empty()) { + node.copy_from(new_node); + break; + } + next_bucket(bucket); + } } + used_nodes_ = other.size(); } void try_grow() { diff --git a/tdutils/test/HashSet.cpp b/tdutils/test/HashSet.cpp index 029a90fa7..949918bb4 100644 --- a/tdutils/test/HashSet.cpp +++ b/tdutils/test/HashSet.cpp @@ -129,7 +129,10 @@ TEST(FlatHashMap, basic) { { ASSERT_EQ(Data{}, extract_kv(KV())); } { - KV kv(data.begin(), data.end()); + KV kv; + for (auto &pair : data) { + kv.emplace(pair.first, pair.second); + } ASSERT_EQ(data, extract_kv(kv)); KV copied_kv(kv); @@ -153,7 +156,10 @@ TEST(FlatHashMap, basic) { ASSERT_TRUE(kv.empty()); kv = std::move(assign_moved_kv); - KV it_copy_kv(kv.begin(), kv.end()); + KV it_copy_kv; + for (auto &pair : kv) { + it_copy_kv.emplace(pair.first, pair.second); + } ASSERT_EQ(data, extract_kv(it_copy_kv)); } @@ -161,7 +167,9 @@ TEST(FlatHashMap, basic) { KV kv; ASSERT_TRUE(kv.empty()); ASSERT_EQ(0u, kv.size()); - kv = KV(data.begin(), data.end()); + for (auto &pair : data) { + kv.emplace(pair.first, pair.second); + } ASSERT_TRUE(!kv.empty()); ASSERT_EQ(2u, kv.size());