mirror of
https://github.com/greg7mdp/parallel-hashmap.git
synced 2026-08-29 16:40:39 +08:00
Add new API try_emplace_l (issue #60)
This commit is contained in:
Vendored
+31
-1
@@ -3424,16 +3424,46 @@ public:
|
||||
return Policy::value(&*it);
|
||||
}
|
||||
|
||||
// ----------- phmap extensions --------------------------
|
||||
|
||||
// if map contains key, lambda is called with the mapped value (under read lock protection),
|
||||
// and if_contains returns true. This is a const API and lambda should not modify the value
|
||||
// -----------------------------------------------------------------------------------------
|
||||
template <class K = key_type, class F>
|
||||
bool if_contains(const key_arg<K>& key, F&& f) const {
|
||||
return const_cast<parallel_hash_map*>(this)->template modify_if_impl<K, F, typename Lockable::SharedLock>(key, std::forward<F>(f));
|
||||
return const_cast<parallel_hash_map*>(this)->template
|
||||
modify_if_impl<K, F, typename Lockable::SharedLock>(key, std::forward<F>(f));
|
||||
}
|
||||
|
||||
// if map contains key, lambda is called with the mapped value (under write lock protection),
|
||||
// and modify_if returns true. This is a non-const API and lambda is allowed to modify the mapped value
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
template <class K = key_type, class F>
|
||||
bool modify_if(const key_arg<K>& key, F&& f) {
|
||||
return modify_if_impl<K, F, typename Lockable::UniqueLock>(key, std::forward<F>(f));
|
||||
}
|
||||
|
||||
// if map does not contains key, it is inserted and the mapped value is value-constructed
|
||||
// with the provided arguments (if any), as with try_emplace.
|
||||
// Then the lambda is called with the mapped value (under write lock protection) and can
|
||||
// update the mapped value.
|
||||
// ---------------------------------------------------------------------------------------
|
||||
template <class K = key_type, class F, class... Args>
|
||||
bool try_emplace_l(K&& k, F&& f, Args&&... args) {
|
||||
typename Lockable::UniqueLock m;
|
||||
auto res = this->find_or_prepare_insert(k, m);
|
||||
typename Base::Inner *inner = std::get<0>(res);
|
||||
if (std::get<2>(res))
|
||||
inner->set_.emplace_at(std::get<1>(res), std::piecewise_construct,
|
||||
std::forward_as_tuple(std::forward<K>(k)),
|
||||
std::forward_as_tuple(std::forward<Args>(args)...));
|
||||
auto it = this->iterator_at(inner, inner->set_.iterator_at(std::get<1>(res)));
|
||||
std::forward<F>(f)(Policy::value(&*it));
|
||||
return std::get<2>(res);
|
||||
}
|
||||
|
||||
// ----------- end of phmap extensions --------------------------
|
||||
|
||||
template <class K = key_type, class P = Policy, K* = nullptr>
|
||||
MappedReference<P> operator[](key_arg<K>&& key) {
|
||||
return Policy::value(&*try_emplace(std::forward<K>(key)).first);
|
||||
|
||||
@@ -22,11 +22,25 @@ TEST(THIS_TEST_NAME, ThreadSafeContains) {
|
||||
|
||||
EXPECT_FALSE(m.if_contains(3, get_value));
|
||||
|
||||
auto set_value = [&val](int& v) { v = 11; };
|
||||
EXPECT_TRUE(m. modify_if(2, set_value));
|
||||
auto set_value = [](int& v) { v = 11; };
|
||||
EXPECT_TRUE(m.modify_if(2, set_value));
|
||||
EXPECT_EQ(m[2], 11);
|
||||
|
||||
EXPECT_FALSE(m.modify_if(3, set_value));
|
||||
|
||||
// overwrite an existing value
|
||||
m.try_emplace_l(2, [](int& v) { v = 5; });
|
||||
EXPECT_EQ(m[2], 5);
|
||||
|
||||
// insert a valye that is not already present
|
||||
m.try_emplace_l(3, [](int& v) { assert(v == 0); v = 6; });
|
||||
EXPECT_EQ(m[3], 6);
|
||||
|
||||
// insert a valye that is not already present, provide argument to value-construct it
|
||||
m.try_emplace_l(4, [](int& v) { assert(v == 999); v = 5; }, 999);
|
||||
EXPECT_EQ(m[4], 5);
|
||||
|
||||
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user