Let QuicLRUCache take explicit hasher. Also added various iterators, change Lookup to return iterator and add Erase function. PiperOrigin-RevId: 411112825
diff --git a/quic/core/crypto/quic_compressed_certs_cache.cc b/quic/core/crypto/quic_compressed_certs_cache.cc index fcc081f..6377a64 100644 --- a/quic/core/crypto/quic_compressed_certs_cache.cc +++ b/quic/core/crypto/quic_compressed_certs_cache.cc
@@ -81,7 +81,11 @@ uint64_t key = ComputeUncompressedCertsHash(uncompressed_certs); - CachedCerts* cached_value = certs_cache_.Lookup(key); + CachedCerts* cached_value = nullptr; + auto iter = certs_cache_.Lookup(key); + if (iter != certs_cache_.end()) { + cached_value = iter->second.get(); + } if (cached_value != nullptr && cached_value->MatchesUncompressedCerts(uncompressed_certs)) { return cached_value->compressed_cert();
diff --git a/quic/core/quic_lru_cache.h b/quic/core/quic_lru_cache.h index 67541ee..44024b6 100644 --- a/quic/core/quic_lru_cache.h +++ b/quic/core/quic_lru_cache.h
@@ -19,13 +19,36 @@ // This cache CANNOT be shared by multiple threads (even with locks) because // Value* returned by Lookup() can be invalid if the entry is evicted by other // threads. -template <class K, class V> +template <class K, class V, class Hash = std::hash<K>, + class Eq = std::equal_to<K>> class QUIC_NO_EXPORT QuicLRUCache { + private: + using HashMapType = + typename quiche::QuicheLinkedHashMap<K, std::unique_ptr<V>, Hash, Eq>; + public: + // The iterator, if valid, points to std::pair<K, std::unique_ptr<V>>. + using iterator = typename HashMapType::iterator; + using const_iterator = typename HashMapType::const_iterator; + using reverse_iterator = typename HashMapType::reverse_iterator; + using const_reverse_iterator = typename HashMapType::const_reverse_iterator; + explicit QuicLRUCache(size_t capacity) : capacity_(capacity) {} QuicLRUCache(const QuicLRUCache&) = delete; QuicLRUCache& operator=(const QuicLRUCache&) = delete; + iterator begin() { return cache_.begin(); } + const_iterator begin() const { return cache_.begin(); } + + iterator end() { return cache_.end(); } + const_iterator end() const { return cache_.end(); } + + reverse_iterator rbegin() { return cache_.rbegin(); } + const_reverse_iterator rbegin() const { return cache_.rbegin(); } + + reverse_iterator rend() { return cache_.rend(); } + const_reverse_iterator rend() const { return cache_.rend(); } + // Inserts one unit of |key|, |value| pair to the cache. Cache takes ownership // of inserted |value|. void Insert(const K& key, std::unique_ptr<V> value) { @@ -41,22 +64,21 @@ QUICHE_DCHECK_LE(cache_.size(), capacity_); } - // If cache contains an entry for |key|, return a pointer to it. This returned - // value is guaranteed to be valid until Insert or Clear. - // Else return nullptr. - V* Lookup(const K& key) { - auto it = cache_.find(key); - if (it == cache_.end()) { - return nullptr; + iterator Lookup(const K& key) { + auto iter = cache_.find(key); + if (iter == cache_.end()) { + return iter; } - std::unique_ptr<V> value = std::move(it->second); - cache_.erase(it); + std::unique_ptr<V> value = std::move(iter->second); + cache_.erase(iter); auto result = cache_.emplace(key, std::move(value)); QUICHE_DCHECK(result.second); - return result.first->second.get(); + return result.first; } + iterator Erase(iterator iter) { return cache_.erase(iter); } + // Removes all entries from the cache. void Clear() { cache_.clear(); } @@ -67,7 +89,7 @@ size_t Size() const { return cache_.size(); } private: - quiche::QuicheLinkedHashMap<K, std::unique_ptr<V>> cache_; + quiche::QuicheLinkedHashMap<K, std::unique_ptr<V>, Hash, Eq> cache_; const size_t capacity_; };
diff --git a/quic/core/quic_lru_cache_test.cc b/quic/core/quic_lru_cache_test.cc index d2c0505..8c6b5b8 100644 --- a/quic/core/quic_lru_cache_test.cc +++ b/quic/core/quic_lru_cache_test.cc
@@ -18,7 +18,7 @@ TEST(QuicLRUCacheTest, InsertAndLookup) { QuicLRUCache<int, CachedItem> cache(5); - EXPECT_EQ(nullptr, cache.Lookup(1)); + EXPECT_EQ(cache.end(), cache.Lookup(1)); EXPECT_EQ(0u, cache.Size()); EXPECT_EQ(5u, cache.MaxSize()); @@ -26,18 +26,23 @@ std::unique_ptr<CachedItem> item1(new CachedItem(11)); cache.Insert(1, std::move(item1)); EXPECT_EQ(1u, cache.Size()); - EXPECT_EQ(11u, cache.Lookup(1)->value); + EXPECT_EQ(11u, cache.Lookup(1)->second->value); // Check that item 2 overrides item 1. std::unique_ptr<CachedItem> item2(new CachedItem(12)); cache.Insert(1, std::move(item2)); EXPECT_EQ(1u, cache.Size()); - EXPECT_EQ(12u, cache.Lookup(1)->value); + EXPECT_EQ(12u, cache.Lookup(1)->second->value); std::unique_ptr<CachedItem> item3(new CachedItem(13)); cache.Insert(3, std::move(item3)); EXPECT_EQ(2u, cache.Size()); - EXPECT_EQ(13u, cache.Lookup(3)->value); + auto iter = cache.Lookup(3); + ASSERT_NE(cache.end(), iter); + EXPECT_EQ(13u, iter->second->value); + cache.Erase(iter); + ASSERT_EQ(cache.end(), cache.Lookup(3)); + EXPECT_EQ(1u, cache.Size()); // No memory leakage. cache.Clear(); @@ -56,15 +61,15 @@ EXPECT_EQ(3u, cache.MaxSize()); // Make sure item 1 is evicted. - EXPECT_EQ(nullptr, cache.Lookup(1)); - EXPECT_EQ(14u, cache.Lookup(4)->value); + EXPECT_EQ(cache.end(), cache.Lookup(1)); + EXPECT_EQ(14u, cache.Lookup(4)->second->value); - EXPECT_EQ(12u, cache.Lookup(2)->value); + EXPECT_EQ(12u, cache.Lookup(2)->second->value); std::unique_ptr<CachedItem> item5(new CachedItem(15)); cache.Insert(5, std::move(item5)); // Make sure item 3 is evicted. - EXPECT_EQ(nullptr, cache.Lookup(3)); - EXPECT_EQ(15u, cache.Lookup(5)->value); + EXPECT_EQ(cache.end(), cache.Lookup(3)); + EXPECT_EQ(15u, cache.Lookup(5)->second->value); // No memory leakage. cache.Clear();