mirror of
https://github.com/greg7mdp/parallel-hashmap.git
synced 2026-08-29 16:40:39 +08:00
Add lazy_emplace_l which is similar to try_emplace_l
lazy_emplace returns an iterator that is not thread-safe
This commit is contained in:
Vendored
+23
-6
@@ -1424,9 +1424,7 @@ public:
|
||||
iterator lazy_emplace(const key_arg<K>& key, F&& f) {
|
||||
auto res = find_or_prepare_insert(key);
|
||||
if (res.second) {
|
||||
slot_type* slot = slots_ + res.first;
|
||||
std::forward<F>(f)(constructor(&alloc_ref(), &slot));
|
||||
assert(!slot);
|
||||
lazy_emplace_at(res.first, std::forward<F>(f));
|
||||
}
|
||||
return iterator_at(res.first);
|
||||
}
|
||||
@@ -1435,13 +1433,18 @@ public:
|
||||
iterator lazy_emplace_with_hash(const key_arg<K>& key, size_t &hash, F&& f) {
|
||||
auto res = find_or_prepare_insert(key, hash);
|
||||
if (res.second) {
|
||||
slot_type* slot = slots_ + res.first;
|
||||
std::forward<F>(f)(constructor(&alloc_ref(), &slot));
|
||||
assert(!slot);
|
||||
lazy_emplace_at(res.first, std::forward<F>(f));
|
||||
}
|
||||
return iterator_at(res.first);
|
||||
}
|
||||
|
||||
template <class K = key_type, class F>
|
||||
void lazy_emplace_at(size_t& idx, F&& f) {
|
||||
slot_type* slot = slots_ + idx;
|
||||
std::forward<F>(f)(constructor(&alloc_ref(), &slot));
|
||||
assert(!slot);
|
||||
}
|
||||
|
||||
|
||||
// Extension API: support for heterogeneous keys.
|
||||
//
|
||||
@@ -2930,6 +2933,20 @@ public:
|
||||
return make_iterator(&inner, set.lazy_emplace_with_hash(key, hashval, std::forward<F>(f)));
|
||||
}
|
||||
|
||||
template <class K = key_type, class FExists, class FEmplace>
|
||||
bool lazy_emplace_l(const key_arg<K>& key, FExists&& fExists, FEmplace&& fEmplace) {
|
||||
typename Lockable::UniqueLock m;
|
||||
auto res = this->find_or_prepare_insert(key, m);
|
||||
typename Inner* inner = std::get<0>(res);
|
||||
if (std::get<2>(res))
|
||||
inner->set_.lazy_emplace_at(std::get<1>(res), std::forward<FEmplace>(fEmplace));
|
||||
else {
|
||||
auto it = this->iterator_at(inner, inner->set_.iterator_at(std::get<1>(res)));
|
||||
std::forward<FExists>(fExists)(Policy::value(&*it));
|
||||
}
|
||||
return std::get<2>(res);
|
||||
}
|
||||
|
||||
// Extension API: support for heterogeneous keys.
|
||||
//
|
||||
// std::unordered_set<std::string> s;
|
||||
|
||||
@@ -32,13 +32,21 @@ TEST(THIS_TEST_NAME, ThreadSafeContains) {
|
||||
m.try_emplace_l(2, [](int& v) { v = 5; });
|
||||
EXPECT_EQ(m[2], 5);
|
||||
|
||||
// insert a valye that is not already present. Will be default initialised to 0 and lambda not called
|
||||
// insert a value that is not already present. Will be default initialised to 0 and lambda not called
|
||||
m.try_emplace_l(3, [](int& v) { assert(v == 0); /* should not be called when value constructed */ v = 6; });
|
||||
EXPECT_EQ(m[3], 0);
|
||||
|
||||
// insert a valye that is not already present, provide argument to value-construct it
|
||||
// insert a value that is not already present, provide argument to value-construct it
|
||||
m.try_emplace_l(4, [](int& ) { assert(0); /* should not be called when value constructed */ }, 999);
|
||||
EXPECT_EQ(m[4], 999);
|
||||
|
||||
// insert a value that is not already present.
|
||||
m.lazy_emplace_l(5, [](int& v) { assert(0); /* should not be called when value constructed */ v = 6; }, [](const auto& ctor) { ctor(5, 13); });
|
||||
EXPECT_EQ(m[5], 13);
|
||||
|
||||
// change a value that is present
|
||||
m.lazy_emplace_l(5, [](int& v) { v = 6; }, [](const auto& ctor) { assert(0); /* should not be called when value exists */ctor(5, 13); });
|
||||
EXPECT_EQ(m[5], 6);
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user