/* * Copyright 2020 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrHashMapWithCache_DEFINED #define GrHashMapWithCache_DEFINED #include "include/private/base/SkNoncopyable.h" #include "src/core/SkChecksum.h" #include "src/core/SkTHash.h" // Cheaper than SkGoodHash and good enough for UniqueID tables. struct GrCheapHash { uint32_t operator()(uint32_t val) { return SkChecksum::CheapMix(val); } }; /** A hash map that caches the most recently accessed entry. The API is a subset of SkHashMap, and you must provide a sentinel key that will never be present, such as SK_InvalidUniqueID. KeyTraits must have: - static K GetInvalidKey() */ template class GrHashMapWithCache : public SkNoncopyable { public: // How many key/value pairs are in the table? int count() const { return fMap.count(); } // Approximately how many bytes of memory do we use beyond sizeof(*this)? size_t approxBytesUsed() const { return fMap.approxBytesUsed(); } // N.B. The pointers returned by set() and find() are valid only until the next call to set(). // If there is key/value entry in the table with this key, return a pointer to the value. // If not, return null. const V* find(const K& key) const { if (key != fLastKey) { fLastKey = key; fLastValue = fMap.find(key); } return fLastValue; } // Set key to val in the map, replacing any previous value with the same key. // We copy both key and val, and return a pointer to the value copy now in the map. const V* set(K key, V val) { if (fLastValue && key == fLastKey) { *fLastValue = std::move(val); } else { fLastKey = key; fLastValue = fMap.set(std::move(key), std::move(val)); } return fLastValue; } // Remove the key/value entry in the table with this key. void remove(K key) { // Match THashMap requirement. The caller can find() if they're unsure. SkASSERT(fMap.find(fLastKey)); fLastKey = std::move(key); fLastValue = nullptr; fMap.remove(fLastKey); } // Clear the map. void reset() { fLastKey = KeyTraits::GetInvalidKey(); fLastValue = nullptr; fMap.reset(); } private: skia_private::THashMap fMap; mutable K fLastKey = KeyTraits::GetInvalidKey(); mutable V* fLastValue = nullptr; }; #endif