Commit 376d6554 authored by Harrison Xu's avatar Harrison Xu Committed by Facebook GitHub Bot

introduce ConcurrentHashMap::erase_key_if

Summary:
Adding a new method `ConcurrentHashMap::erase_key_if`. This is a more general form of `erase_if_equal`, which allows arbitrary predicates to be evaluated against the existing value type, rather than simple equality.

`erase_key_if` was chosen as a name to avoid confusion with `std::erase_if`.

Reviewed By: magedm

Differential Revision: D22775217

fbshipit-source-id: 151975216d5d4288ec4e88b81f6a8d17a091e8f0
parent 93921194
......@@ -419,12 +419,19 @@ class ConcurrentHashMap {
// Erase if and only if key k is equal to expected
size_type erase_if_equal(const key_type& k, const ValueType& expected) {
return erase_key_if(
k, [&expected](const ValueType& v) { return v == expected; });
}
// Erase if predicate evaluates to true on the existing value
template <typename Predicate>
size_type erase_key_if(const key_type& k, Predicate&& predicate) {
auto segment = pickSegment(k);
auto seg = segments_[segment].load(std::memory_order_acquire);
if (!seg) {
return 0;
}
return seg->erase_if_equal(k, expected);
return seg->erase_key_if(k, std::forward<Predicate>(predicate));
}
// NOT noexcept, initializes new shard segments vs.
......
......@@ -1822,10 +1822,9 @@ class alignas(64) ConcurrentHashMapSegment {
return erase_internal(key, nullptr, [](const ValueType&) { return true; });
}
size_type erase_if_equal(const key_type& key, const ValueType& expected) {
return erase_internal(key, nullptr, [&expected](const ValueType& v) {
return v == expected;
});
template <typename Predicate>
size_type erase_key_if(const key_type& key, Predicate&& predicate) {
return erase_internal(key, nullptr, std::forward<Predicate>(predicate));
}
template <typename MatchFunc>
......
......@@ -328,6 +328,31 @@ TYPED_TEST_P(ConcurrentHashMapTest, EraseIfEqualTest) {
EXPECT_EQ(foomap.find(1), foomap.cend());
}
TYPED_TEST_P(ConcurrentHashMapTest, EraseIfTest) {
CHM<uint64_t, uint64_t> foomap(3);
foomap.insert(1, 0);
EXPECT_FALSE(
foomap.erase_key_if(1, [](const uint64_t& value) { return value == 1; }));
auto f1 = foomap.find(1);
EXPECT_EQ(0, f1->second);
EXPECT_TRUE(
foomap.erase_key_if(1, [](const uint64_t& value) { return value == 0; }));
EXPECT_EQ(foomap.find(1), foomap.cend());
CHM<std::string, std::weak_ptr<uint64_t>> barmap(3);
auto shared = std::make_shared<uint64_t>(123);
barmap.insert("test", shared);
EXPECT_FALSE(barmap.erase_key_if(
"test",
[](const std::weak_ptr<uint64_t>& ptr) { return ptr.expired(); }));
EXPECT_EQ(*barmap.find("test")->second.lock(), 123);
shared.reset();
EXPECT_TRUE(barmap.erase_key_if(
"test",
[](const std::weak_ptr<uint64_t>& ptr) { return ptr.expired(); }));
EXPECT_EQ(barmap.find("test"), barmap.cend());
}
TYPED_TEST_P(ConcurrentHashMapTest, CopyIterator) {
CHM<int, int> map;
map.insert(0, 0);
......@@ -850,6 +875,7 @@ REGISTER_TYPED_TEST_CASE_P(
DeletionWithForLoop,
DeletionWithIterator,
EraseIfEqualTest,
EraseIfTest,
EraseInIterateTest,
EraseStressTest,
EraseTest,
......
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