Commit 1f6bf6c8 authored by Maged Michael's avatar Maged Michael Committed by Facebook Github Bot

ConcurrentHashMap: Make iterators movable

Summary:
To reduce unnecessary copying for user code handling ConstIterator-s.

Added move test and change UpdateStressTest to use few concurrent iterators.

Reviewed By: yfeldblum

Differential Revision: D8587056

fbshipit-source-id: d6b592a3aa40ca8a7599b258b45a1d339088c978
parent 3af92dbe
main v2022.02.14.00 v2022.02.07.00 v2022.01.31.00 v2022.01.24.00 v2022.01.17.00 v2022.01.10.00 v2022.01.03.00 v2021.12.27.00 v2021.12.20.00 v2021.12.13.00 v2021.12.06.00 v2021.11.29.00 v2021.11.15.00 v2021.11.08.00 v2021.11.01.00 v2021.10.25.00 v2021.10.18.00 v2021.10.11.00 v2021.10.04.00 v2021.09.27.00 v2021.09.20.00 v2021.09.13.00 v2021.09.06.00 v2021.08.30.00 v2021.08.23.00 v2021.08.02.00 v2021.07.22.00 v2021.07.20.01 v2021.07.20.00 v2021.06.28.00 v2021.06.14.00 v2021.06.07.00 v2021.05.31.00 v2021.05.24.00 v2021.05.17.00 v2021.05.10.00 v2021.05.03.00 v2021.04.26.00 v2021.04.19.00 v2021.04.12.00 v2021.04.05.00 v2021.03.29.00 v2021.03.22.00 v2021.03.15.00 v2021.03.08.00 v2021.03.01.00 v2021.02.22.00 v2021.02.15.00 v2021.02.08.00 v2021.02.01.00 v2021.01.25.00 v2021.01.18.01 v2021.01.18.00 v2021.01.11.00 v2021.01.04.00 v2020.12.28.00 v2020.12.21.00 v2020.12.14.00 v2020.12.07.00 v2020.11.30.00 v2020.11.23.00 v2020.11.16.00 v2020.11.09.00 v2020.11.02.00 v2020.10.26.00 v2020.10.19.00 v2020.10.12.00 v2020.10.05.00 v2020.09.28.00 v2020.09.21.00 v2020.09.14.00 v2020.09.07.00 v2020.08.31.00 v2020.08.24.00 v2020.08.17.00 v2020.08.10.00 v2020.08.03.00 v2020.07.27.00 v2020.07.20.00 v2020.07.13.00 v2020.07.06.00 v2020.06.29.00 v2020.06.15.00 v2020.06.08.00 v2020.06.01.00 v2020.05.25.00 v2020.05.18.00 v2020.05.11.00 v2020.05.04.00 v2020.04.27.00 v2020.04.20.00 v2020.04.13.00 v2020.04.06.00 v2020.03.30.00 v2020.03.23.00 v2020.03.16.00 v2020.03.09.00 v2020.03.02.00 v2020.02.24.00 v2020.02.17.00 v2020.02.10.00 v2020.02.03.00 v2020.01.27.00 v2020.01.20.00 v2020.01.13.00 v2020.01.06.00 v2019.12.30.00 v2019.12.23.00 v2019.12.16.00 v2019.12.09.00 v2019.12.06.00 v2019.12.02.00 v2019.11.11.00 v2019.11.04.00 v2019.10.28.00 v2019.10.21.00 v2019.10.14.00 v2019.10.07.00 v2019.09.30.00 v2019.09.23.00 v2019.09.16.00 v2019.09.09.00 v2019.09.02.00 v2019.08.26.00 v2019.08.19.00 v2019.08.12.00 v2019.08.05.00 v2019.07.29.00 v2019.07.22.00 v2019.06.17.00 v2019.06.10.00 v2019.06.03.00 v2019.05.27.00 v2019.05.20.00 v2019.05.13.00 v2019.05.06.00 v2019.04.29.00 v2019.04.22.00 v2019.04.15.00 v2019.04.08.00 v2019.04.01.00 v2019.03.25.00 v2019.03.18.00 v2019.03.04.00 v2019.02.25.00 v2019.02.18.00 v2019.02.11.00 v2019.02.04.00 v2019.01.28.00 v2019.01.21.00 v2019.01.14.00 v2019.01.07.00 v2018.12.31.00 v2018.12.24.00 v2018.12.17.00 v2018.12.10.00 v2018.12.03.00 v2018.11.26.00 v2018.11.19.00 v2018.11.12.00 v2018.11.05.00 v2018.10.29.00 v2018.10.22.00 v2018.10.15.00 v2018.10.08.00 v2018.10.01.00 v2018.09.24.00 v2018.09.17.00 v2018.09.10.01 v2018.09.10.00 v2018.09.03.01 v2018.09.03.00 v2018.08.27.00 v2018.08.20.00 v2018.08.13.00 v2018.08.09.00 v2018.08.06.00 v2018.07.30.00 v2018.07.23.00 v2018.07.16.00 v2018.07.09.00 v2018.07.02.00
No related merge requests found
...@@ -431,12 +431,26 @@ class ConcurrentHashMap { ...@@ -431,12 +431,26 @@ class ConcurrentHashMap {
return *this; return *this;
} }
ConstIterator& operator=(ConstIterator&& o) noexcept {
if (this != &o) {
it_ = std::move(o.it_);
segment_ = std::exchange(o.segment_, uint64_t(NumShards));
parent_ = std::exchange(o.parent_, nullptr);
}
return *this;
}
ConstIterator(const ConstIterator& o) { ConstIterator(const ConstIterator& o) {
parent_ = o.parent_; parent_ = o.parent_;
it_ = o.it_; it_ = o.it_;
segment_ = o.segment_; segment_ = o.segment_;
} }
ConstIterator(ConstIterator&& o) noexcept
: it_(std::move(o.it_)),
segment_(std::exchange(o.segment_, uint64_t(NumShards))),
parent_(std::exchange(o.parent_, nullptr)) {}
ConstIterator(const ConcurrentHashMap* parent, uint64_t segment) ConstIterator(const ConcurrentHashMap* parent, uint64_t segment)
: segment_(segment), parent_(parent) {} : segment_(segment), parent_(parent) {}
......
...@@ -761,13 +761,12 @@ class alignas(64) ConcurrentHashMapSegment { ...@@ -761,13 +761,12 @@ class alignas(64) ConcurrentHashMapSegment {
bucket_count_ = o.bucket_count_; bucket_count_ = o.bucket_count_;
} }
/* implicit */ Iterator(Iterator&& o) noexcept Iterator(Iterator&& o) noexcept
: hazptrs_(std::move(o.hazptrs_)) { : hazptrs_(std::move(o.hazptrs_)),
node_ = o.node_; node_(std::exchange(o.node_, nullptr)),
buckets_ = o.buckets_; buckets_(std::exchange(o.buckets_, nullptr)),
idx_ = o.idx_; bucket_count_(std::exchange(o.bucket_count_, 0)),
bucket_count_ = o.bucket_count_; idx_(std::exchange(o.idx_, 0)) {}
}
// These are accessed directly from the functions above // These are accessed directly from the functions above
hazptr_array<3, Atom> hazptrs_; hazptr_array<3, Atom> hazptrs_;
......
...@@ -337,14 +337,18 @@ TEST(ConcurrentHashMap, UpdateStressTest) { ...@@ -337,14 +337,18 @@ TEST(ConcurrentHashMap, UpdateStressTest) {
unsigned long k = folly::hash::jenkins_rev_mix32((i + offset)); unsigned long k = folly::hash::jenkins_rev_mix32((i + offset));
k = k % (iters / num_threads) + offset; k = k % (iters / num_threads) + offset;
unsigned long val = 3; unsigned long val = 3;
auto res = m.find(k); {
EXPECT_NE(res, m.cend()); auto res = m.find(k);
EXPECT_EQ(k, res->second); EXPECT_NE(res, m.cend());
auto r = m.assign(k, res->second); EXPECT_EQ(k, res->second);
EXPECT_TRUE(r); auto r = m.assign(k, res->second);
res = m.find(k); EXPECT_TRUE(r);
EXPECT_NE(res, m.cend()); }
EXPECT_EQ(k, res->second); {
auto res = m.find(k);
EXPECT_NE(res, m.cend());
EXPECT_EQ(k, res->second);
}
// Another random insertion to force table resizes // Another random insertion to force table resizes
val = size + i + offset; val = size + i + offset;
EXPECT_TRUE(m.insert(val, val).second); EXPECT_TRUE(m.insert(val, val).second);
...@@ -722,3 +726,23 @@ TEST(ConcurrentHashMap, ForEachLoop) { ...@@ -722,3 +726,23 @@ TEST(ConcurrentHashMap, ForEachLoop) {
} }
EXPECT_EQ(iters, 1); EXPECT_EQ(iters, 1);
} }
TEST(ConcurrentHashMap, IteratorMove) {
using CHM = ConcurrentHashMap<int, int>;
using Iter = CHM::ConstIterator;
struct Foo {
Iter it;
explicit Foo(Iter&& it_) : it(std::move(it_)) {}
Foo(Foo&&) = default;
Foo& operator=(Foo&&) = default;
};
CHM map;
int k = 111;
int v = 999999;
map.insert(k, v);
Foo foo(map.find(k));
ASSERT_EQ(foo.it->second, v);
Foo foo2(map.find(0));
foo2 = std::move(foo);
ASSERT_EQ(foo2.it->second, v);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment