Add new API try_emplace_l (issue #60)

This commit is contained in:
greg
2020-08-16 18:27:20 -04:00
parent 16a5e67b33
commit 0d229b1159
2 changed files with 47 additions and 3 deletions
+31 -1
View File
@@ -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);