Replace `emplace` with `try_emplace` in QuicheLinkedHashMap and its callers. This should simplify the transition to StableBlockList. It's also more performant when key already exist in the map. We can add `emplace` back after the transition, if the need arises. PiperOrigin-RevId: 964131316
diff --git a/quiche/common/http/http_header_block.cc b/quiche/common/http/http_header_block.cc index f6c6169..914c0de 100644 --- a/quiche/common/http/http_header_block.cc +++ b/quiche/common/http/http_header_block.cc
@@ -156,9 +156,7 @@ if (lookup_result_ == block_->map_.end()) { QUICHE_DVLOG(1) << "Inserting: (" << key_ << ", " << value << ")"; lookup_result_ = - block_->map_ - .emplace(std::make_pair( - key_, HeaderValue(storage, key_, storage->Write(value)))) + block_->map_.try_emplace(key_, storage, key_, storage->Write(value)) .first; } else { QUICHE_DVLOG(1) << "Updating key: " << key_ << " with value: " << value; @@ -325,8 +323,7 @@ void HttpHeaderBlock::AppendHeader(const absl::string_view key, const absl::string_view value) { auto backed_key = WriteKey(key); - map_.emplace(std::make_pair( - backed_key, HeaderValue(&storage_, backed_key, storage_.Write(value)))); + map_.try_emplace(backed_key, &storage_, backed_key, storage_.Write(value)); } absl::string_view HttpHeaderBlock::WriteKey(const absl::string_view key) {
diff --git a/quiche/common/quiche_linked_hash_map.h b/quiche/common/quiche_linked_hash_map.h index 25c70fb..3932844 100644 --- a/quiche/common/quiche_linked_hash_map.h +++ b/quiche/common/quiche_linked_hash_map.h
@@ -188,17 +188,13 @@ size_type size() const { return map_.size(); } template <typename... Args> - std::pair<iterator, bool> emplace(Args&&... args) { - ListType node_donor; - auto node_pos = - node_donor.emplace(node_donor.end(), std::forward<Args>(args)...); - const auto& k = node_pos->first; - auto ins = map_.insert({k, node_pos}); - if (!ins.second) { - return {ins.first->second, false}; - } - list_.splice(list_.end(), node_donor, node_pos); - return {ins.first->second, true}; + std::pair<iterator, bool> try_emplace(const key_type& key, Args&&... args) { + return TryEmplaceInternal(key, std::forward<Args>(args)...); + } + + template <typename... Args> + std::pair<iterator, bool> try_emplace(key_type&& key, Args&&... args) { + return TryEmplaceInternal(std::move(key), std::forward<Args>(args)...); } void swap(QuicheLinkedHashMap& other) { @@ -225,6 +221,23 @@ return {list_iter, true}; } + template <typename K, typename... Args> + std::pair<iterator, bool> TryEmplaceInternal(K&& key, Args&&... args) { + auto insert_result = map_.try_emplace(std::forward<K>(key)); + + if (!insert_result.second) { + return {insert_result.first->second, false}; + } + + auto list_iter = + list_.emplace(list_.end(), std::piecewise_construct, + std::forward_as_tuple(std::forward<K>(key)), + std::forward_as_tuple(std::forward<Args>(args)...)); + + insert_result.first->second = list_iter; + return {list_iter, true}; + } + // The map component, used for speedy lookups MapType map_;
diff --git a/quiche/common/quiche_linked_hash_map_test.cc b/quiche/common/quiche_linked_hash_map_test.cc index 1a3aa79..98a731a 100644 --- a/quiche/common/quiche_linked_hash_map_test.cc +++ b/quiche/common/quiche_linked_hash_map_test.cc
@@ -30,15 +30,14 @@ UnorderedElementsAre(Pair(2, Pointee(12)), Pair(3, Pointee(13)))); } -TEST(LinkedHashMapTest, CanEmplaceMoveOnly) { +TEST(LinkedHashMapTest, CanTryEmplaceMoveOnly) { QuicheLinkedHashMap<int, std::unique_ptr<int>> m; struct Data { int k, v; }; const Data data[] = {{1, 123}, {3, 345}, {2, 234}, {4, 456}}; for (const auto& kv : data) { - m.emplace(std::piecewise_construct, std::make_tuple(kv.k), - std::make_tuple(new int{kv.v})); + m.try_emplace(kv.k, std::make_unique<int>(kv.v)); } EXPECT_TRUE(m.contains(2)); auto found = m.find(2); @@ -55,15 +54,14 @@ int x; }; -TEST(LinkedHashMapTest, CanEmplaceNoMoveNoCopy) { +TEST(LinkedHashMapTest, CanTryEmplaceNoMoveNoCopy) { QuicheLinkedHashMap<int, NoCopy> m; struct Data { int k, v; }; const Data data[] = {{1, 123}, {3, 345}, {2, 234}, {4, 456}}; for (const auto& kv : data) { - m.emplace(std::piecewise_construct, std::make_tuple(kv.k), - std::make_tuple(kv.v)); + m.try_emplace(kv.k, kv.v); } EXPECT_TRUE(m.contains(2)); auto found = m.find(2);
diff --git a/quiche/quic/core/quic_lru_cache.h b/quiche/quic/core/quic_lru_cache.h index eb9c553..b85944d 100644 --- a/quiche/quic/core/quic_lru_cache.h +++ b/quiche/quic/core/quic_lru_cache.h
@@ -56,7 +56,7 @@ if (it != cache_.end()) { cache_.erase(it); } - cache_.emplace(key, std::move(value)); + cache_.try_emplace(key, std::move(value)); if (cache_.size() > capacity_) { cache_.pop_front(); @@ -72,7 +72,7 @@ std::unique_ptr<V> value = std::move(iter->second); cache_.erase(iter); - auto result = cache_.emplace(key, std::move(value)); + auto result = cache_.try_emplace(key, std::move(value)); QUICHE_DCHECK(result.second); return result.first; }