1 /* 2 * Copyright 2020 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrHashMapWithCache_DEFINED 9 #define GrHashMapWithCache_DEFINED 10 11 #include "include/private/SkChecksum.h" 12 #include "include/private/base/SkNoncopyable.h" 13 #include "src/core/SkTHash.h" 14 15 // Cheaper than SkGoodHash and good enough for UniqueID tables. 16 struct GrCheapHash { operatorGrCheapHash17 uint32_t operator()(uint32_t val) { 18 return SkChecksum::CheapMix(val); 19 } 20 }; 21 22 /** A hash map that caches the most recently accessed entry. 23 The API is a subset of SkHashMap, and you must provide a 24 sentinel key that will never be present, such as SK_InvalidUniqueID. 25 26 KeyTraits must have: 27 - static K GetInvalidKey() 28 */ 29 template <typename K, typename V, typename KeyTraits, typename HashT = SkGoodHash> 30 class GrHashMapWithCache : public SkNoncopyable { 31 public: 32 // How many key/value pairs are in the table? count()33 int count() const { return fMap.count(); } 34 35 // Approximately how many bytes of memory do we use beyond sizeof(*this)? approxBytesUsed()36 size_t approxBytesUsed() const { return fMap.approxBytesUsed(); } 37 38 // N.B. The pointers returned by set() and find() are valid only until the next call to set(). 39 40 // If there is key/value entry in the table with this key, return a pointer to the value. 41 // If not, return null. find(const K & key)42 const V* find(const K& key) const { 43 if (key != fLastKey) { 44 fLastKey = key; 45 fLastValue = fMap.find(key); 46 } 47 return fLastValue; 48 } 49 50 // Set key to val in the map, replacing any previous value with the same key. 51 // We copy both key and val, and return a pointer to the value copy now in the map. set(K key,V val)52 const V* set(K key, V val) { 53 if (fLastValue && key == fLastKey) { 54 *fLastValue = std::move(val); 55 } else { 56 fLastKey = key; 57 fLastValue = fMap.set(std::move(key), std::move(val)); 58 } 59 return fLastValue; 60 } 61 62 // Remove the key/value entry in the table with this key. remove(K key)63 void remove(K key) { 64 // Match SkTHashMap requirement. The caller can find() if they're unsure. 65 SkASSERT(fMap.find(fLastKey)); 66 fLastKey = std::move(key); 67 fLastValue = nullptr; 68 fMap.remove(fLastKey); 69 } 70 71 // Clear the map. reset()72 void reset() { 73 fLastKey = KeyTraits::GetInvalidKey(); 74 fLastValue = nullptr; 75 fMap.reset(); 76 } 77 78 private: 79 SkTHashMap<K, V, HashT> fMap; 80 mutable K fLastKey = KeyTraits::GetInvalidKey(); 81 mutable V* fLastValue = nullptr; 82 }; 83 84 #endif 85