Commit 8cb68e8d authored by Maged Michael's avatar Maged Michael Committed by Facebook Github Bot

ConcurrentHashMap: Make iterators not copyable

Summary: Disable unsafe iterator operations: copying and operator++ (because it copies the iterator). Copying is unsafe because starting to protect buckets and nodes after their removal is not guaranteed to be effective.

Reviewed By: yfeldblum, djwatson

Differential Revision: D8594743

fbshipit-source-id: 0990d8fe979a3217db855641d23e24cc853a25bf
parent 23817ea8
...@@ -405,17 +405,11 @@ class ConcurrentHashMap { ...@@ -405,17 +405,11 @@ class ConcurrentHashMap {
} }
ConstIterator& operator++() { ConstIterator& operator++() {
it_++; ++it_;
next(); next();
return *this; return *this;
} }
ConstIterator operator++(int) {
auto prev = *this;
++*this;
return prev;
}
bool operator==(const ConstIterator& o) const { bool operator==(const ConstIterator& o) const {
return it_ == o.it_ && segment_ == o.segment_; return it_ == o.it_ && segment_ == o.segment_;
} }
...@@ -424,12 +418,7 @@ class ConcurrentHashMap { ...@@ -424,12 +418,7 @@ class ConcurrentHashMap {
return !(*this == o); return !(*this == o);
} }
ConstIterator& operator=(const ConstIterator& o) { ConstIterator& operator=(const ConstIterator& o) = delete;
parent_ = o.parent_;
it_ = o.it_;
segment_ = o.segment_;
return *this;
}
ConstIterator& operator=(ConstIterator&& o) noexcept { ConstIterator& operator=(ConstIterator&& o) noexcept {
if (this != &o) { if (this != &o) {
...@@ -440,11 +429,7 @@ class ConcurrentHashMap { ...@@ -440,11 +429,7 @@ class ConcurrentHashMap {
return *this; return *this;
} }
ConstIterator(const ConstIterator& o) { ConstIterator(const ConstIterator& o) = delete;
parent_ = o.parent_;
it_ = o.it_;
segment_ = o.segment_;
}
ConstIterator(ConstIterator&& o) noexcept ConstIterator(ConstIterator&& o) noexcept
: it_(std::move(o.it_)), : it_(std::move(o.it_)),
......
...@@ -728,12 +728,6 @@ class alignas(64) ConcurrentHashMapSegment { ...@@ -728,12 +728,6 @@ class alignas(64) ConcurrentHashMapSegment {
} }
} }
Iterator operator++(int) {
auto prev = *this;
++*this;
return prev;
}
bool operator==(const Iterator& o) const { bool operator==(const Iterator& o) const {
return node_ == o.node_; return node_ == o.node_;
} }
...@@ -742,24 +736,20 @@ class alignas(64) ConcurrentHashMapSegment { ...@@ -742,24 +736,20 @@ class alignas(64) ConcurrentHashMapSegment {
return !(*this == o); return !(*this == o);
} }
Iterator& operator=(const Iterator& o) { Iterator& operator=(const Iterator& o) = delete;
node_ = o.node_;
hazptrs_[1].reset(node_); Iterator& operator=(Iterator&& o) noexcept {
idx_ = o.idx_; if (this != &o) {
buckets_ = o.buckets_; hazptrs_ = std::move(o.hazptrs_);
hazptrs_[0].reset(buckets_); node_ = std::exchange(o.node_, nullptr);
bucket_count_ = o.bucket_count_; buckets_ = std::exchange(o.buckets_, nullptr);
bucket_count_ = std::exchange(o.bucket_count_, 0);
idx_ = std::exchange(o.idx_, 0);
}
return *this; return *this;
} }
/* implicit */ Iterator(const Iterator& o) { Iterator(const Iterator& o) = delete;
node_ = o.node_;
hazptrs_[1].reset(node_);
idx_ = o.idx_;
buckets_ = o.buckets_;
hazptrs_[0].reset(buckets_);
bucket_count_ = o.bucket_count_;
}
Iterator(Iterator&& o) noexcept Iterator(Iterator&& o) noexcept
: hazptrs_(std::move(o.hazptrs_)), : hazptrs_(std::move(o.hazptrs_)),
......
...@@ -233,15 +233,15 @@ TEST(ConcurrentHashMap, MapIterateTest) { ...@@ -233,15 +233,15 @@ TEST(ConcurrentHashMap, MapIterateTest) {
EXPECT_NE(iter, foomap.cend()); EXPECT_NE(iter, foomap.cend());
EXPECT_EQ(iter->first, 1); EXPECT_EQ(iter->first, 1);
EXPECT_EQ(iter->second, 1); EXPECT_EQ(iter->second, 1);
iter++; ++iter;
EXPECT_NE(iter, foomap.cend()); EXPECT_NE(iter, foomap.cend());
EXPECT_EQ(iter->first, 2); EXPECT_EQ(iter->first, 2);
EXPECT_EQ(iter->second, 2); EXPECT_EQ(iter->second, 2);
iter++; ++iter;
EXPECT_EQ(iter, foomap.cend()); EXPECT_EQ(iter, foomap.cend());
int count = 0; int count = 0;
for (auto it = foomap.cbegin(); it != foomap.cend(); it++) { for (auto it = foomap.cbegin(); it != foomap.cend(); ++it) {
count++; count++;
} }
EXPECT_EQ(count, 2); EXPECT_EQ(count, 2);
...@@ -271,8 +271,7 @@ TEST(ConcurrentHashMap, EraseTest) { ...@@ -271,8 +271,7 @@ TEST(ConcurrentHashMap, EraseTest) {
TEST(ConcurrentHashMap, CopyIterator) { TEST(ConcurrentHashMap, CopyIterator) {
ConcurrentHashMap<int, int> map; ConcurrentHashMap<int, int> map;
map.insert(0, 0); map.insert(0, 0);
auto const cbegin = map.cbegin(); for (auto cit = map.cbegin(); cit != map.cend(); ++cit) {
for (auto cit = cbegin; cit != map.cend(); ++cit) {
std::pair<int const, int> const ckv{0, 0}; std::pair<int const, int> const ckv{0, 0};
EXPECT_EQ(*cit, ckv); EXPECT_EQ(*cit, ckv);
} }
...@@ -459,7 +458,7 @@ TEST(ConcurrentHashMap, IterateStressTest) { ...@@ -459,7 +458,7 @@ TEST(ConcurrentHashMap, IterateStressTest) {
EXPECT_TRUE(res); EXPECT_TRUE(res);
} }
int count = 0; int count = 0;
for (auto it = m.cbegin(); it != m.cend(); it++) { for (auto it = m.cbegin(); it != m.cend(); ++it) {
printf("Item is %li\n", it->first); printf("Item is %li\n", it->first);
if (it->first < 10) { if (it->first < 10) {
count++; count++;
......
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