1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-24 22:11:15 +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;
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:
LRUCache(size_t capacity)
@ -83,7 +95,9 @@ public:
/**
* Look up an item in the cache. If it exists, it becomes the most
* recently used item.
* */
*
* @returns corresponding cache entry, std::nullopt if it's not in the cache
*/
template<typename K>
std::optional<Value> get(const K & key)
{
@ -91,20 +105,30 @@ public:
if (i == data.end())
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;
lru.splice(/*pos=*/lru.end(), /*other=*/lru, it.it);
promote(it.it);
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
{
return data.size();