| /* | |
| * 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 <typename K, typename V, typename KeyTraits, typename HashT = SkGoodHash> | |
| 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<K, V, HashT> fMap; | |
| mutable K fLastKey = KeyTraits::GetInvalidKey(); | |
| mutable V* fLastValue = nullptr; | |
| }; | |
| #endif |