1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-25 02:21:16 +02:00

libutil: Add LRUCache::getOrNullptr

For heavier objects it doesn't make sense to return
a std::optional with the copy of the data, when it
can be used by const reference.
This commit is contained in:
Sergei Zimmerman 2025-05-15 22:28:41 +00:00
parent 67535263a5
commit 4711720efe
No known key found for this signature in database
GPG key ID: A9B0B557CA632325

View file

@ -33,6 +33,18 @@ private:
Data data; Data data;
LRU lru; LRU lru;
/**
* Move this item to the back of the LRU list.
*/
void promote(LRU::iterator it)
{
/* Think of std::list iterators as stable pointers to the list node,
* which never get invalidated. Thus, we can reuse the same lru list
* element and just splice it to the back of the list without the need
* to update its value in the key -> list iterator map. */
lru.splice(/*pos=*/lru.end(), /*other=*/lru, it);
}
public: public:
LRUCache(size_t capacity) LRUCache(size_t capacity)
@ -83,7 +95,9 @@ public:
/** /**
* Look up an item in the cache. If it exists, it becomes the most * Look up an item in the cache. If it exists, it becomes the most
* recently used item. * recently used item.
* */ *
* @returns corresponding cache entry, std::nullopt if it's not in the cache
*/
template<typename K> template<typename K>
std::optional<Value> get(const K & key) std::optional<Value> get(const K & key)
{ {
@ -91,20 +105,30 @@ public:
if (i == data.end()) if (i == data.end())
return {}; return {};
/**
* Move this item to the back of the LRU list.
*
* Think of std::list iterators as stable pointers to the list node,
* which never get invalidated. Thus, we can reuse the same lru list
* element and just splice it to the back of the list without the need
* to update its value in the key -> list iterator map.
*/
auto & [it, value] = i->second; auto & [it, value] = i->second;
lru.splice(/*pos=*/lru.end(), /*other=*/lru, it.it); promote(it.it);
return value; return value;
} }
/**
* Look up an item in the cache. If it exists, it becomes the most
* recently used item.
*
* @returns mutable pointer to the corresponding cache entry, nullptr if
* it's not in the cache
*/
template<typename K>
Value * getOrNullptr(const K & key)
{
auto i = data.find(key);
if (i == data.end())
return nullptr;
auto & [it, value] = i->second;
promote(it.it);
return &value;
}
size_t size() const noexcept size_t size() const noexcept
{ {
return data.size(); return data.size();