• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/SkNoncopyable.h"
13 #include "include/private/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