blob: 37b62e85a773c7d990259f457a92ff6133358163 [file] [log] [blame]
/*
* 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