diff options
| author | vadim-xd <[email protected]> | 2023-09-13 12:00:12 +0300 | 
|---|---|---|
| committer | vadim-xd <[email protected]> | 2023-09-13 12:31:05 +0300 | 
| commit | fc3dd49af468e386f516606954df7339308ea86b (patch) | |
| tree | a5f2ab0b1333ba61b83db57dc0f988bd9d4d698e /library/cpp | |
| parent | 64a5ddcdef53b30c561b1e01d776993a6ac4e5d3 (diff) | |
Optimize TConcurrentHashMap; add EmplaceIfAbsent
Diffstat (limited to 'library/cpp')
| -rw-r--r-- | library/cpp/containers/concurrent_hash/concurrent_hash.h | 32 | 
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 f15a1c3d6ec..b11deb62544 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; | 
