Skip to content

Commit 4711720

Browse files
committed
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.
1 parent 6753526 commit 4711720

File tree

1 file changed

+35
-11
lines changed

1 file changed

+35
-11
lines changed

src/libutil/include/nix/util/lru-cache.hh

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ private:
3333
Data data;
3434
LRU lru;
3535

36+
/**
37+
* Move this item to the back of the LRU list.
38+
*/
39+
void promote(LRU::iterator it)
40+
{
41+
/* Think of std::list iterators as stable pointers to the list node,
42+
* which never get invalidated. Thus, we can reuse the same lru list
43+
* element and just splice it to the back of the list without the need
44+
* to update its value in the key -> list iterator map. */
45+
lru.splice(/*pos=*/lru.end(), /*other=*/lru, it);
46+
}
47+
3648
public:
3749

3850
LRUCache(size_t capacity)
@@ -83,28 +95,40 @@ public:
8395
/**
8496
* Look up an item in the cache. If it exists, it becomes the most
8597
* recently used item.
86-
* */
98+
*
99+
* @returns corresponding cache entry, std::nullopt if it's not in the cache
100+
*/
87101
template<typename K>
88102
std::optional<Value> get(const K & key)
89103
{
90104
auto i = data.find(key);
91105
if (i == data.end())
92106
return {};
93107

94-
/**
95-
* Move this item to the back of the LRU list.
96-
*
97-
* Think of std::list iterators as stable pointers to the list node,
98-
* which never get invalidated. Thus, we can reuse the same lru list
99-
* element and just splice it to the back of the list without the need
100-
* to update its value in the key -> list iterator map.
101-
*/
102108
auto & [it, value] = i->second;
103-
lru.splice(/*pos=*/lru.end(), /*other=*/lru, it.it);
104-
109+
promote(it.it);
105110
return value;
106111
}
107112

113+
/**
114+
* Look up an item in the cache. If it exists, it becomes the most
115+
* recently used item.
116+
*
117+
* @returns mutable pointer to the corresponding cache entry, nullptr if
118+
* it's not in the cache
119+
*/
120+
template<typename K>
121+
Value * getOrNullptr(const K & key)
122+
{
123+
auto i = data.find(key);
124+
if (i == data.end())
125+
return nullptr;
126+
127+
auto & [it, value] = i->second;
128+
promote(it.it);
129+
return &value;
130+
}
131+
108132
size_t size() const noexcept
109133
{
110134
return data.size();

0 commit comments

Comments
 (0)