aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvadim-xd <vadim-xd@yandex-team.com>2023-09-13 12:00:12 +0300
committervadim-xd <vadim-xd@yandex-team.com>2023-09-13 12:31:05 +0300
commitfc3dd49af468e386f516606954df7339308ea86b (patch)
treea5f2ab0b1333ba61b83db57dc0f988bd9d4d698e
parent64a5ddcdef53b30c561b1e01d776993a6ac4e5d3 (diff)
downloadydb-fc3dd49af468e386f516606954df7339308ea86b.tar.gz
Optimize TConcurrentHashMap; add EmplaceIfAbsent
-rw-r--r--library/cpp/containers/concurrent_hash/concurrent_hash.h32
1 files changed, 28 insertions, 4 deletions
diff --git a/library/cpp/containers/concurrent_hash/concurrent_hash.h b/library/cpp/containers/concurrent_hash/concurrent_hash.h
index f15a1c3d6e..b11deb6254 100644
--- a/library/cpp/containers/concurrent_hash/concurrent_hash.h
+++ b/library/cpp/containers/concurrent_hash/concurrent_hash.h
@@ -54,6 +54,16 @@ public:
typename TActualMap::const_iterator it = Map.find(key);
return (it != Map.end());
}
+
+ const V* TryGetUnsafe(const K& key) const {
+ typename TActualMap::const_iterator it = Map.find(key);
+ return it == Map.end() ? nullptr : &it->second;
+ }
+
+ V* TryGetUnsafe(const K& key) {
+ typename TActualMap::iterator it = Map.find(key);
+ return it == Map.end() ? nullptr : &it->second;
+ }
};
std::array<TBucket, BucketCount> Buckets;
@@ -87,12 +97,26 @@ public:
return bucket.Map.insert(std::make_pair(key, value)).first->second;
}
+ template <typename TKey, typename... Args>
+ V& EmplaceIfAbsent(TKey&& key, Args&&... args) {
+ TBucket& bucket = GetBucketForKey(key);
+ TGuard<TLock> guard(bucket.Mutex);
+ if (V* value = bucket.TryGetUnsafe(key)) {
+ return *value;
+ }
+ return bucket.Map.emplace(
+ std::piecewise_construct,
+ std::forward_as_tuple(std::forward<TKey>(key)),
+ std::forward_as_tuple(std::forward<Args>(args)...)
+ ).first->second;
+ }
+
template <typename Callable>
V& InsertIfAbsentWithInit(const K& key, Callable initFunc) {
TBucket& bucket = GetBucketForKey(key);
TGuard<TLock> guard(bucket.Mutex);
- if (bucket.HasUnsafe(key)) {
- return bucket.GetUnsafe(key);
+ if (V* value = bucket.TryGetUnsafe(key)) {
+ return *value;
}
return bucket.Map.insert(std::make_pair(key, initFunc())).first->second;
@@ -107,8 +131,8 @@ public:
bool Get(const K& key, V& result) const {
const TBucket& bucket = GetBucketForKey(key);
TGuard<TLock> guard(bucket.Mutex);
- if (bucket.HasUnsafe(key)) {
- result = bucket.GetUnsafe(key);
+ if (const V* value = bucket.TryGetUnsafe(key)) {
+ result = *value;
return true;
}
return false;