Commit d6ab7bcd authored by Xiao Shi's avatar Xiao Shi Committed by Facebook Github Bot

document the non-standard compliance of `erase()`

Summary: See F14.md changes.

Reviewed By: nbronson

Differential Revision: D13722323

fbshipit-source-id: 70c68442cad56efc84bb29f0b694a7b71f837cbd
parent 541198dc
...@@ -265,6 +265,14 @@ factor iteration occurs in practice when erasing keys during iteration ...@@ -265,6 +265,14 @@ factor iteration occurs in practice when erasing keys during iteration
the weaker guarantee that iteration is O(size()) after erasing any prefix the weaker guarantee that iteration is O(size()) after erasing any prefix
of the iteration order. F14VectorMap doesn't have this problem. of the iteration order. F14VectorMap doesn't have this problem.
The standard requires that the order of the elements that are not erased be
preserved (since c++14). This is a stricter requirement than necessary to make
erasing individual elements while iterating through the container possible,
since all of the patterns we have seen for doing this don't care about order for
elements before the erased one. All F14 maps and sets support erase during
iteration, but F14Fast and F14Vector don't guarantee to preserve the relative
order of elements earlier in the iteration order than the erased element.
The standard requires that clear() be O(size()), which has the practical The standard requires that clear() be O(size()), which has the practical
effect of prohibiting a change to bucket_count. F14 deallocates effect of prohibiting a change to bucket_count. F14 deallocates
all memory during clear() if it has space for more than 100 keys, to all memory during clear() if it has space for more than 100 keys, to
......
...@@ -327,6 +327,32 @@ void runSimple() { ...@@ -327,6 +327,32 @@ void runSimple() {
F14TableStats::compute(h9); F14TableStats::compute(h9);
} }
template <typename T>
void runEraseWhileIterating() {
constexpr int kNumElements = 1000;
// mul and kNumElements should be relatively prime
for (int mul : {1, 3, 17, 137, kNumElements - 1}) {
for (int interval : {1, 3, 5, kNumElements / 2}) {
T h;
for (auto i = 0; i < kNumElements; ++i) {
EXPECT_TRUE(h.emplace((i * mul) % kNumElements, i).second);
}
int sum = 0;
for (auto it = h.begin(); it != h.end();) {
sum += it->second;
if (it->first % interval == 0) {
it = h.erase(it);
} else {
++it;
}
}
EXPECT_EQ(kNumElements * (kNumElements - 1) / 2, sum);
}
}
}
template <typename T> template <typename T>
void runRehash() { void runRehash() {
unsigned n = 10000; unsigned n = 10000;
...@@ -678,6 +704,18 @@ TEST(F14VectorMap, reverse_iterator) { ...@@ -678,6 +704,18 @@ TEST(F14VectorMap, reverse_iterator) {
} }
} }
TEST(F14ValueMap, eraseWhileIterating) {
runEraseWhileIterating<F14ValueMap<int, int>>();
}
TEST(F14NodeMap, eraseWhileIterating) {
runEraseWhileIterating<F14NodeMap<int, int>>();
}
TEST(F14VectorMap, eraseWhileIterating) {
runEraseWhileIterating<F14VectorMap<int, int>>();
}
TEST(F14ValueMap, rehash) { TEST(F14ValueMap, rehash) {
runRehash<F14ValueMap<std::string, std::string>>(); runRehash<F14ValueMap<std::string, std::string>>();
} }
......
...@@ -312,6 +312,32 @@ void runSimple() { ...@@ -312,6 +312,32 @@ void runSimple() {
F14TableStats::compute(h8); F14TableStats::compute(h8);
} }
template <typename T>
void runEraseWhileIterating() {
constexpr int kNumElements = 1000;
// mul and kNumElements should be relatively prime
for (int mul : {1, 3, 17, 137, kNumElements - 1}) {
for (int interval : {1, 3, 5, kNumElements / 2}) {
T h;
for (auto i = 0; i < kNumElements; ++i) {
EXPECT_TRUE(h.emplace((i * mul) % kNumElements).second);
}
int sum = 0;
for (auto it = h.begin(); it != h.end();) {
sum += *it;
if (*it % interval == 0) {
it = h.erase(it);
} else {
++it;
}
}
EXPECT_EQ(kNumElements * (kNumElements - 1) / 2, sum);
}
}
}
template <typename T> template <typename T>
void runRehash() { void runRehash() {
unsigned n = 10000; unsigned n = 10000;
...@@ -602,6 +628,18 @@ TEST(F14VectorMap, reverse_iterator) { ...@@ -602,6 +628,18 @@ TEST(F14VectorMap, reverse_iterator) {
} }
} }
TEST(F14ValueSet, eraseWhileIterating) {
runEraseWhileIterating<F14ValueSet<int>>();
}
TEST(F14NodeSet, eraseWhileIterating) {
runEraseWhileIterating<F14NodeSet<int>>();
}
TEST(F14VectorSet, eraseWhileIterating) {
runEraseWhileIterating<F14VectorSet<int>>();
}
TEST(F14ValueSet, rehash) { TEST(F14ValueSet, rehash) {
runRehash<F14ValueSet<std::string>>(); runRehash<F14ValueSet<std::string>>();
} }
......
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