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