Add Map/SetNode::copy_from.

This commit is contained in:
levlam 2022-02-20 23:03:34 +03:00
parent 983cc2c45c
commit 77ccc13181
3 changed files with 57 additions and 25 deletions

View File

@ -14,13 +14,13 @@
namespace td {
template <class KeyT, class ValueT, class HashT = std::hash<KeyT>, class EqT = std::equal_to<KeyT>>
//using FlatHashMap = FlatHashMapImpl<KeyT, ValueT, HashT, EqT>;
using FlatHashMap = FlatHashMapChunks<KeyT, ValueT, HashT, EqT>;
using FlatHashMap = FlatHashMapImpl<KeyT, ValueT, HashT, EqT>;
//using FlatHashMap = FlatHashMapChunks<KeyT, ValueT, HashT, EqT>;
//using FlatHashMap = std::unordered_map<KeyT, ValueT, HashT, EqT>;
template <class KeyT, class HashT = std::hash<KeyT>, class EqT = std::equal_to<KeyT>>
//using FlatHashSet = FlatHashSetImpl<KeyT, HashT, EqT>;
using FlatHashSet = FlatHashSetChunks<KeyT, HashT, EqT>;
using FlatHashSet = FlatHashSetImpl<KeyT, HashT, EqT>;
//using FlatHashSet = FlatHashSetChunks<KeyT, HashT, EqT>;
//using FlatHashSet = std::unordered_set<KeyT, HashT, EqT>;
} // namespace td

View File

@ -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<Node> 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 <class ItT>
FlatHashTable(ItT begin, ItT end) {
assign(begin, end);
}
size_t bucket_count() const {
return nodes_.size();
}
@ -434,12 +450,20 @@ class FlatHashTable {
fixed_vector<Node> nodes_;
size_t used_nodes_{};
template <class ItT>
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() {

View File

@ -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());