Loading...
Searching...
No Matches
lruCache.h
Go to the documentation of this file.
1//
2// Copyright 2025 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_EXEC_VDF_LRU_CACHE_H
8#define PXR_EXEC_VDF_LRU_CACHE_H
9
11
12#include "pxr/pxr.h"
13
14#include <cstddef>
15#include <list>
16
17PXR_NAMESPACE_OPEN_SCOPE
18
26template < typename Key, typename Value, typename Hash >
28{
29public:
30 // Non-copyable
31 VdfLRUCache(const VdfLRUCache &) = delete;
32 VdfLRUCache &operator=(const VdfLRUCache &) = delete;
33
34 // Non-movable
35 VdfLRUCache(VdfLRUCache &&) = delete;
36 VdfLRUCache &operator=(VdfLRUCache &&) = delete;
37
40 explicit VdfLRUCache(size_t capacity) : _capacity(capacity) {}
41
51 bool Lookup(const Key &key, Value **value);
52
55 void Clear();
56
57private:
58 // The cache entry stores a hash to accelerate equality comparison, as well
59 // as the key and value for each entry.
60 struct _Entry {
61 _Entry(size_t h, const Key &k) : hash(h), key(k) {}
62
63 size_t hash;
64 Key key;
65 Value value;
66 };
67
68 // The sorted list of cache entries. The most recently used entry will
69 // always be at the head of the list.
70 using _List = std::list<_Entry>;
71 _List _list;
72
73 // The fixed cache capacity. The cache will never grow beyond this size.
74 const size_t _capacity;
75};
76
78
79template < typename Key, typename Value, typename Hash >
80bool
81VdfLRUCache<Key, Value, Hash>::Lookup(const Key &key, Value **value)
82{
83 // Hash the key. We will use this hash as an early out for
84 // equality comparison.
85 const size_t hash = Hash()(key);
86
87 // Iterate over all the recently used entries.
88 typename _List::iterator it = _list.begin();
89 for (; it != _list.end(); ++it) {
90 // If the hash and key compare equal, we have found a matching entry.
91 if (it->hash == hash && it->key == key) {
92 // If this entry isn't already at the head of the list, move it
93 // there. This way, the list always stays sorted in order of most
94 // recent usage.
95 if (it != _list.begin()) {
96 _list.splice(_list.begin(), _list, it);
97 }
98
99 // Return a pointer to the value at the current entry.
100 *value = &it->value;
101 return true;
102 }
103 }
104
105 // If we were unable to find a matching entry and the list is below
106 // capacity, let's insert a new entry.
107 if (_list.size() < _capacity) {
108 _list.emplace_front(hash, key);
109 }
110
111 // If the list has reached capacity, reuse the last entry by first moving
112 // it to the front.
113 else {
114 _list.splice(_list.begin(), _list, --_list.end());
115 _list.front().hash = hash;
116 _list.front().key = key;
117 }
118
119 // Return a pointer to the new value entry.
120 *value = &_list.front().value;
121 return false;
122}
123
124template < typename Key, typename Value, typename Hash >
125void
127{
128 _list.clear();
129}
130
131PXR_NAMESPACE_CLOSE_SCOPE
132
133#endif
A simple cache with a fixed capacity and a least-recently-used eviction policy.
Definition: lruCache.h:28
VdfLRUCache(size_t capacity)
Constructs a new cache with a fixed capacity.
Definition: lruCache.h:40
void Clear()
Removes all entries from the cache.
Definition: lruCache.h:126
bool Lookup(const Key &key, Value **value)
Performs a lookup into the cache and returns true if the cache contains an entry for the given key.
Definition: lruCache.h:81