/src/skia/src/gpu/GrHashMapWithCache.h
Line | Count | Source |
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 { |
17 | 1.27M | uint32_t operator()(uint32_t val) { |
18 | 1.27M | return SkChecksum::CheapMix(val); |
19 | 1.27M | } |
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? |
33 | | int count() const { return fMap.count(); } |
34 | | |
35 | | // Approximately how many bytes of memory do we use beyond sizeof(*this)? |
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. |
42 | 430k | const V* find(const K& key) const { |
43 | 430k | if (key != fLastKey) { |
44 | 300k | fLastKey = key; |
45 | 300k | fLastValue = fMap.find(key); |
46 | 300k | } |
47 | 430k | return fLastValue; |
48 | 430k | } |
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. |
52 | 100k | const V* set(K key, V val) { |
53 | 100k | if (fLastValue && key == fLastKey) { |
54 | 11.3k | *fLastValue = std::move(val); |
55 | 89.6k | } else { |
56 | 89.6k | fLastKey = key; |
57 | 89.6k | fLastValue = fMap.set(std::move(key), std::move(val)); |
58 | 89.6k | } |
59 | 100k | return fLastValue; |
60 | 100k | } |
61 | | |
62 | | // Remove the key/value entry in the table with this key. |
63 | 76.0k | void remove(K key) { |
64 | | // Match SkTHashMap requirement. The caller can find() if they're unsure. |
65 | 76.0k | SkASSERT(fMap.find(fLastKey)); |
66 | 76.0k | fLastKey = std::move(key); |
67 | 76.0k | fLastValue = nullptr; |
68 | 76.0k | fMap.remove(fLastKey); |
69 | 76.0k | } |
70 | | |
71 | | // Clear the map. |
72 | 21.9k | void reset() { |
73 | 21.9k | fLastKey = KeyTraits::GetInvalidKey(); |
74 | 21.9k | fLastValue = nullptr; |
75 | 21.9k | fMap.reset(); |
76 | 21.9k | } |
77 | | |
78 | | private: |
79 | | SkTHashMap<K, V, HashT> fMap; |
80 | | mutable K fLastKey = KeyTraits::GetInvalidKey(); |
81 | | mutable V* fLastValue = nullptr; |
82 | | }; |
83 | | |
84 | | #endif |