xref: /aosp_15_r20/external/swiftshader/src/System/LRUCache.hpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2020 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker //    http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #ifndef sw_LRUCache_hpp
16*03ce13f7SAndroid Build Coastguard Worker #define sw_LRUCache_hpp
17*03ce13f7SAndroid Build Coastguard Worker 
18*03ce13f7SAndroid Build Coastguard Worker #include "System/Debug.hpp"
19*03ce13f7SAndroid Build Coastguard Worker 
20*03ce13f7SAndroid Build Coastguard Worker #include <cstddef>
21*03ce13f7SAndroid Build Coastguard Worker #include <cstdint>
22*03ce13f7SAndroid Build Coastguard Worker #include <functional>
23*03ce13f7SAndroid Build Coastguard Worker #include <unordered_set>
24*03ce13f7SAndroid Build Coastguard Worker #include <vector>
25*03ce13f7SAndroid Build Coastguard Worker 
26*03ce13f7SAndroid Build Coastguard Worker namespace sw {
27*03ce13f7SAndroid Build Coastguard Worker 
28*03ce13f7SAndroid Build Coastguard Worker // LRUCache is a least recently used cache of a fixed capacity.
29*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH = std::hash<KEY> >
30*03ce13f7SAndroid Build Coastguard Worker class LRUCache
31*03ce13f7SAndroid Build Coastguard Worker {
32*03ce13f7SAndroid Build Coastguard Worker 	struct Entry;
33*03ce13f7SAndroid Build Coastguard Worker 
34*03ce13f7SAndroid Build Coastguard Worker public:
35*03ce13f7SAndroid Build Coastguard Worker 	using Key = KEY;
36*03ce13f7SAndroid Build Coastguard Worker 	using Data = DATA;
37*03ce13f7SAndroid Build Coastguard Worker 	using Hash = HASH;
38*03ce13f7SAndroid Build Coastguard Worker 
39*03ce13f7SAndroid Build Coastguard Worker 	// view is a const accessor of a single cache entry.
40*03ce13f7SAndroid Build Coastguard Worker 	class view
41*03ce13f7SAndroid Build Coastguard Worker 	{
42*03ce13f7SAndroid Build Coastguard Worker 	public:
43*03ce13f7SAndroid Build Coastguard Worker 		inline view(Entry *);
44*03ce13f7SAndroid Build Coastguard Worker 
45*03ce13f7SAndroid Build Coastguard Worker 		inline const Key &key() const;
46*03ce13f7SAndroid Build Coastguard Worker 		inline const Data &data() const;
47*03ce13f7SAndroid Build Coastguard Worker 
48*03ce13f7SAndroid Build Coastguard Worker 	private:
49*03ce13f7SAndroid Build Coastguard Worker 		Entry *entry;
50*03ce13f7SAndroid Build Coastguard Worker 	};
51*03ce13f7SAndroid Build Coastguard Worker 
52*03ce13f7SAndroid Build Coastguard Worker 	class iterator
53*03ce13f7SAndroid Build Coastguard Worker 	{
54*03ce13f7SAndroid Build Coastguard Worker 	public:
55*03ce13f7SAndroid Build Coastguard Worker 		inline iterator(Entry *);
56*03ce13f7SAndroid Build Coastguard Worker 		inline view operator*() const;
57*03ce13f7SAndroid Build Coastguard Worker 		inline iterator &operator++();
58*03ce13f7SAndroid Build Coastguard Worker 		inline bool operator==(const iterator &) const;
59*03ce13f7SAndroid Build Coastguard Worker 		inline bool operator!=(const iterator &) const;
60*03ce13f7SAndroid Build Coastguard Worker 
61*03ce13f7SAndroid Build Coastguard Worker 	private:
62*03ce13f7SAndroid Build Coastguard Worker 		Entry *entry;
63*03ce13f7SAndroid Build Coastguard Worker 	};
64*03ce13f7SAndroid Build Coastguard Worker 
65*03ce13f7SAndroid Build Coastguard Worker 	// Construct a LRU cache with the given maximum number of entries.
66*03ce13f7SAndroid Build Coastguard Worker 	inline LRUCache(size_t capacity);
67*03ce13f7SAndroid Build Coastguard Worker 	inline ~LRUCache() = default;
68*03ce13f7SAndroid Build Coastguard Worker 
69*03ce13f7SAndroid Build Coastguard Worker 	// lookup() looks up the cache entry with the given key.
70*03ce13f7SAndroid Build Coastguard Worker 	// If the entry is found, this is moved to the most-recent position in the
71*03ce13f7SAndroid Build Coastguard Worker 	// cache, and its data is returned.
72*03ce13f7SAndroid Build Coastguard Worker 	// If the entry is not found, then a default initialized Data is returned.
73*03ce13f7SAndroid Build Coastguard Worker 	inline Data lookup(const Key &key);
74*03ce13f7SAndroid Build Coastguard Worker 
75*03ce13f7SAndroid Build Coastguard Worker 	// add() adds the data to the cache using the given key, placed at the
76*03ce13f7SAndroid Build Coastguard Worker 	// most-recent position in the cache.
77*03ce13f7SAndroid Build Coastguard Worker 	// If an existing entry exists in the cache with the given key, then this is
78*03ce13f7SAndroid Build Coastguard Worker 	// replaced with data.
79*03ce13f7SAndroid Build Coastguard Worker 	// If no existing entry exists in the cache, and the cache is already full
80*03ce13f7SAndroid Build Coastguard Worker 	// then the least recently used entry is evicted before adding the new
81*03ce13f7SAndroid Build Coastguard Worker 	// entry.
82*03ce13f7SAndroid Build Coastguard Worker 	inline void add(const Key &key, const Data &data);
83*03ce13f7SAndroid Build Coastguard Worker 
84*03ce13f7SAndroid Build Coastguard Worker 	// clear() clears the cache of all elements.
85*03ce13f7SAndroid Build Coastguard Worker 	inline void clear();
86*03ce13f7SAndroid Build Coastguard Worker 
87*03ce13f7SAndroid Build Coastguard Worker 	// Range based iterators.
88*03ce13f7SAndroid Build Coastguard Worker 	inline iterator begin() const;
89*03ce13f7SAndroid Build Coastguard Worker 	inline iterator end() const;
90*03ce13f7SAndroid Build Coastguard Worker 
91*03ce13f7SAndroid Build Coastguard Worker private:
92*03ce13f7SAndroid Build Coastguard Worker 	LRUCache(const LRUCache &) = delete;
93*03ce13f7SAndroid Build Coastguard Worker 	LRUCache(LRUCache &&) = delete;
94*03ce13f7SAndroid Build Coastguard Worker 	LRUCache &operator=(const LRUCache &) = delete;
95*03ce13f7SAndroid Build Coastguard Worker 	LRUCache &operator=(LRUCache &&) = delete;
96*03ce13f7SAndroid Build Coastguard Worker 
97*03ce13f7SAndroid Build Coastguard Worker 	// Keyed holds a key. See find() for more information.
98*03ce13f7SAndroid Build Coastguard Worker 	struct Keyed
99*03ce13f7SAndroid Build Coastguard Worker 	{
100*03ce13f7SAndroid Build Coastguard Worker 		Key key = {};
101*03ce13f7SAndroid Build Coastguard Worker 	};
102*03ce13f7SAndroid Build Coastguard Worker 
103*03ce13f7SAndroid Build Coastguard Worker 	// Cache entry structure.
104*03ce13f7SAndroid Build Coastguard Worker 	// Holds the unique copy of the key and data, along with pointers for
105*03ce13f7SAndroid Build Coastguard Worker 	// maintaining the linked list.
106*03ce13f7SAndroid Build Coastguard Worker 	struct Entry : Keyed
107*03ce13f7SAndroid Build Coastguard Worker 	{
108*03ce13f7SAndroid Build Coastguard Worker 		Data data = {};
109*03ce13f7SAndroid Build Coastguard Worker 		Entry *next = nullptr;
110*03ce13f7SAndroid Build Coastguard Worker 		Entry *prev = nullptr;
111*03ce13f7SAndroid Build Coastguard Worker 	};
112*03ce13f7SAndroid Build Coastguard Worker 
113*03ce13f7SAndroid Build Coastguard Worker 	// KeyedComparator is a custom hasher and equality helper for Keyed.
114*03ce13f7SAndroid Build Coastguard Worker 	struct KeyedComparator
115*03ce13f7SAndroid Build Coastguard Worker 	{
116*03ce13f7SAndroid Build Coastguard Worker 		// Hash function.
117*03ce13f7SAndroid Build Coastguard Worker 		inline uint64_t operator()(const Keyed *k) const;
118*03ce13f7SAndroid Build Coastguard Worker 
119*03ce13f7SAndroid Build Coastguard Worker 		// Equality function.
120*03ce13f7SAndroid Build Coastguard Worker 		inline uint64_t operator()(const Keyed *a, const Keyed *b) const;
121*03ce13f7SAndroid Build Coastguard Worker 	};
122*03ce13f7SAndroid Build Coastguard Worker 
123*03ce13f7SAndroid Build Coastguard Worker 	// find() returns the Entry* for the given key, or nullptr.
124*03ce13f7SAndroid Build Coastguard Worker 	// find() performs this by casting the Key pointer to a Keyed pointer for
125*03ce13f7SAndroid Build Coastguard Worker 	// searching the std::unordered_set.
126*03ce13f7SAndroid Build Coastguard Worker 	//
127*03ce13f7SAndroid Build Coastguard Worker 	// This is to avoid having a duplicate Key held by both an
128*03ce13f7SAndroid Build Coastguard Worker 	// unordered_map<Key, Entry*> and the Entry itself, as the Key type may be
129*03ce13f7SAndroid Build Coastguard Worker 	// large.
130*03ce13f7SAndroid Build Coastguard Worker 	//
131*03ce13f7SAndroid Build Coastguard Worker 	// While we could use an unordered_set<Entry*>, this then requires the
132*03ce13f7SAndroid Build Coastguard Worker 	// construction of a temporary Entry to perform the call to
133*03ce13f7SAndroid Build Coastguard Worker 	// unordered_set<Entry*>::find(). This is undesirable as the Data type might
134*03ce13f7SAndroid Build Coastguard Worker 	// be large or have an expensive constructor.
135*03ce13f7SAndroid Build Coastguard Worker 	//
136*03ce13f7SAndroid Build Coastguard Worker 	// C++20 gains a new templated overload for unordered_set<Entry*>::find()
137*03ce13f7SAndroid Build Coastguard Worker 	// which would allow us to use unordered_set<Entry*>::find(Key*).
138*03ce13f7SAndroid Build Coastguard Worker 	// Until we can use C++20, keep this casting nastiness hidden away in this
139*03ce13f7SAndroid Build Coastguard Worker 	// one function.
140*03ce13f7SAndroid Build Coastguard Worker 	inline Entry *find(const Key &key);
141*03ce13f7SAndroid Build Coastguard Worker 
142*03ce13f7SAndroid Build Coastguard Worker 	// unlinks the entry from the list it is linked in.
143*03ce13f7SAndroid Build Coastguard Worker 	inline void unlink(Entry *);
144*03ce13f7SAndroid Build Coastguard Worker 
145*03ce13f7SAndroid Build Coastguard Worker 	// links the entry to the head of the LRU.
146*03ce13f7SAndroid Build Coastguard Worker 	inline void link(Entry *);
147*03ce13f7SAndroid Build Coastguard Worker 
148*03ce13f7SAndroid Build Coastguard Worker 	// storage holds the allocations of all the entries.
149*03ce13f7SAndroid Build Coastguard Worker 	// This vector must not change size for the lifetime of the cache.
150*03ce13f7SAndroid Build Coastguard Worker 	std::vector<Entry> storage;
151*03ce13f7SAndroid Build Coastguard Worker 
152*03ce13f7SAndroid Build Coastguard Worker 	// set is an unordered set of Keyed*, using the KeyedComparator for hash and
153*03ce13f7SAndroid Build Coastguard Worker 	// equality testing.
154*03ce13f7SAndroid Build Coastguard Worker 	std::unordered_set<const Keyed *, KeyedComparator, KeyedComparator> set;
155*03ce13f7SAndroid Build Coastguard Worker 
156*03ce13f7SAndroid Build Coastguard Worker 	Entry *free = nullptr;  // Singly-linked (prev is nullptr) list of free entries.
157*03ce13f7SAndroid Build Coastguard Worker 	Entry *head = nullptr;  // Pointer to the most recently used entry in the LRU.
158*03ce13f7SAndroid Build Coastguard Worker 	Entry *tail = nullptr;  // Pointer to the least recently used entry in the LRU.
159*03ce13f7SAndroid Build Coastguard Worker };
160*03ce13f7SAndroid Build Coastguard Worker 
161*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
162*03ce13f7SAndroid Build Coastguard Worker // LRUCache<>::view
163*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
164*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
view(Entry * entry)165*03ce13f7SAndroid Build Coastguard Worker LRUCache<KEY, DATA, HASH>::view::view(Entry *entry)
166*03ce13f7SAndroid Build Coastguard Worker     : entry(entry)
167*03ce13f7SAndroid Build Coastguard Worker {}
168*03ce13f7SAndroid Build Coastguard Worker 
169*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
key() const170*03ce13f7SAndroid Build Coastguard Worker const KEY &LRUCache<KEY, DATA, HASH>::view::key() const
171*03ce13f7SAndroid Build Coastguard Worker {
172*03ce13f7SAndroid Build Coastguard Worker 	return entry->key;
173*03ce13f7SAndroid Build Coastguard Worker }
174*03ce13f7SAndroid Build Coastguard Worker 
175*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
data() const176*03ce13f7SAndroid Build Coastguard Worker const DATA &LRUCache<KEY, DATA, HASH>::view::data() const
177*03ce13f7SAndroid Build Coastguard Worker {
178*03ce13f7SAndroid Build Coastguard Worker 	return entry->data;
179*03ce13f7SAndroid Build Coastguard Worker }
180*03ce13f7SAndroid Build Coastguard Worker 
181*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
182*03ce13f7SAndroid Build Coastguard Worker // LRUCache<>::iterator
183*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
184*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
iterator(Entry * entry)185*03ce13f7SAndroid Build Coastguard Worker LRUCache<KEY, DATA, HASH>::iterator::iterator(Entry *entry)
186*03ce13f7SAndroid Build Coastguard Worker     : entry(entry)
187*03ce13f7SAndroid Build Coastguard Worker {}
188*03ce13f7SAndroid Build Coastguard Worker 
189*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
operator *() const190*03ce13f7SAndroid Build Coastguard Worker typename LRUCache<KEY, DATA, HASH>::view LRUCache<KEY, DATA, HASH>::iterator::operator*() const
191*03ce13f7SAndroid Build Coastguard Worker {
192*03ce13f7SAndroid Build Coastguard Worker 	return view{ entry };
193*03ce13f7SAndroid Build Coastguard Worker }
194*03ce13f7SAndroid Build Coastguard Worker 
195*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
operator ++()196*03ce13f7SAndroid Build Coastguard Worker typename LRUCache<KEY, DATA, HASH>::iterator &LRUCache<KEY, DATA, HASH>::iterator::operator++()
197*03ce13f7SAndroid Build Coastguard Worker {
198*03ce13f7SAndroid Build Coastguard Worker 	entry = entry->next;
199*03ce13f7SAndroid Build Coastguard Worker 	return *this;
200*03ce13f7SAndroid Build Coastguard Worker }
201*03ce13f7SAndroid Build Coastguard Worker 
202*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
operator ==(const iterator & rhs) const203*03ce13f7SAndroid Build Coastguard Worker bool LRUCache<KEY, DATA, HASH>::iterator::operator==(const iterator &rhs) const
204*03ce13f7SAndroid Build Coastguard Worker {
205*03ce13f7SAndroid Build Coastguard Worker 	return entry == rhs.entry;
206*03ce13f7SAndroid Build Coastguard Worker }
207*03ce13f7SAndroid Build Coastguard Worker 
208*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
operator !=(const iterator & rhs) const209*03ce13f7SAndroid Build Coastguard Worker bool LRUCache<KEY, DATA, HASH>::iterator::operator!=(const iterator &rhs) const
210*03ce13f7SAndroid Build Coastguard Worker {
211*03ce13f7SAndroid Build Coastguard Worker 	return entry != rhs.entry;
212*03ce13f7SAndroid Build Coastguard Worker }
213*03ce13f7SAndroid Build Coastguard Worker 
214*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
215*03ce13f7SAndroid Build Coastguard Worker // LRUCache<>
216*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
217*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
LRUCache(size_t capacity)218*03ce13f7SAndroid Build Coastguard Worker LRUCache<KEY, DATA, HASH>::LRUCache(size_t capacity)
219*03ce13f7SAndroid Build Coastguard Worker     : storage(capacity)
220*03ce13f7SAndroid Build Coastguard Worker {
221*03ce13f7SAndroid Build Coastguard Worker 	for(size_t i = 0; i < capacity; i++)
222*03ce13f7SAndroid Build Coastguard Worker 	{
223*03ce13f7SAndroid Build Coastguard Worker 		Entry *entry = &storage[i];
224*03ce13f7SAndroid Build Coastguard Worker 		entry->next = free;  // No need for back link here.
225*03ce13f7SAndroid Build Coastguard Worker 		free = entry;
226*03ce13f7SAndroid Build Coastguard Worker 	}
227*03ce13f7SAndroid Build Coastguard Worker }
228*03ce13f7SAndroid Build Coastguard Worker 
229*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
lookup(const Key & key)230*03ce13f7SAndroid Build Coastguard Worker DATA LRUCache<KEY, DATA, HASH>::lookup(const Key &key)
231*03ce13f7SAndroid Build Coastguard Worker {
232*03ce13f7SAndroid Build Coastguard Worker 	if(Entry *entry = find(key))
233*03ce13f7SAndroid Build Coastguard Worker 	{
234*03ce13f7SAndroid Build Coastguard Worker 		unlink(entry);
235*03ce13f7SAndroid Build Coastguard Worker 		link(entry);
236*03ce13f7SAndroid Build Coastguard Worker 		return entry->data;
237*03ce13f7SAndroid Build Coastguard Worker 	}
238*03ce13f7SAndroid Build Coastguard Worker 	return {};
239*03ce13f7SAndroid Build Coastguard Worker }
240*03ce13f7SAndroid Build Coastguard Worker 
241*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
add(const Key & key,const Data & data)242*03ce13f7SAndroid Build Coastguard Worker void LRUCache<KEY, DATA, HASH>::add(const Key &key, const Data &data)
243*03ce13f7SAndroid Build Coastguard Worker {
244*03ce13f7SAndroid Build Coastguard Worker 	if(Entry *entry = find(key))
245*03ce13f7SAndroid Build Coastguard Worker 	{
246*03ce13f7SAndroid Build Coastguard Worker 		// Move entry to front.
247*03ce13f7SAndroid Build Coastguard Worker 		unlink(entry);
248*03ce13f7SAndroid Build Coastguard Worker 		link(entry);
249*03ce13f7SAndroid Build Coastguard Worker 		entry->data = data;
250*03ce13f7SAndroid Build Coastguard Worker 		return;
251*03ce13f7SAndroid Build Coastguard Worker 	}
252*03ce13f7SAndroid Build Coastguard Worker 
253*03ce13f7SAndroid Build Coastguard Worker 	Entry *entry = free;
254*03ce13f7SAndroid Build Coastguard Worker 	if(entry)
255*03ce13f7SAndroid Build Coastguard Worker 	{
256*03ce13f7SAndroid Build Coastguard Worker 		// Unlink from free.
257*03ce13f7SAndroid Build Coastguard Worker 		free = entry->next;
258*03ce13f7SAndroid Build Coastguard Worker 		entry->next = nullptr;
259*03ce13f7SAndroid Build Coastguard Worker 	}
260*03ce13f7SAndroid Build Coastguard Worker 	else
261*03ce13f7SAndroid Build Coastguard Worker 	{
262*03ce13f7SAndroid Build Coastguard Worker 		// Unlink least recently used.
263*03ce13f7SAndroid Build Coastguard Worker 		entry = tail;
264*03ce13f7SAndroid Build Coastguard Worker 		unlink(entry);
265*03ce13f7SAndroid Build Coastguard Worker 		set.erase(entry);
266*03ce13f7SAndroid Build Coastguard Worker 	}
267*03ce13f7SAndroid Build Coastguard Worker 
268*03ce13f7SAndroid Build Coastguard Worker 	// link as most recently used.
269*03ce13f7SAndroid Build Coastguard Worker 	link(entry);
270*03ce13f7SAndroid Build Coastguard Worker 	if(tail == nullptr)
271*03ce13f7SAndroid Build Coastguard Worker 	{
272*03ce13f7SAndroid Build Coastguard Worker 		tail = entry;
273*03ce13f7SAndroid Build Coastguard Worker 	}
274*03ce13f7SAndroid Build Coastguard Worker 
275*03ce13f7SAndroid Build Coastguard Worker 	entry->key = key;
276*03ce13f7SAndroid Build Coastguard Worker 	entry->data = data;
277*03ce13f7SAndroid Build Coastguard Worker 	set.emplace(entry);
278*03ce13f7SAndroid Build Coastguard Worker }
279*03ce13f7SAndroid Build Coastguard Worker 
280*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
clear()281*03ce13f7SAndroid Build Coastguard Worker void LRUCache<KEY, DATA, HASH>::clear()
282*03ce13f7SAndroid Build Coastguard Worker {
283*03ce13f7SAndroid Build Coastguard Worker 	while(Entry *entry = head)
284*03ce13f7SAndroid Build Coastguard Worker 	{
285*03ce13f7SAndroid Build Coastguard Worker 		unlink(entry);
286*03ce13f7SAndroid Build Coastguard Worker 		entry->next = free;  // No need for back link here.
287*03ce13f7SAndroid Build Coastguard Worker 		free = entry;
288*03ce13f7SAndroid Build Coastguard Worker 	}
289*03ce13f7SAndroid Build Coastguard Worker 	set.clear();
290*03ce13f7SAndroid Build Coastguard Worker }
291*03ce13f7SAndroid Build Coastguard Worker 
292*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
begin() const293*03ce13f7SAndroid Build Coastguard Worker typename LRUCache<KEY, DATA, HASH>::iterator LRUCache<KEY, DATA, HASH>::begin() const
294*03ce13f7SAndroid Build Coastguard Worker {
295*03ce13f7SAndroid Build Coastguard Worker 	return { head };
296*03ce13f7SAndroid Build Coastguard Worker }
297*03ce13f7SAndroid Build Coastguard Worker 
298*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
end() const299*03ce13f7SAndroid Build Coastguard Worker typename LRUCache<KEY, DATA, HASH>::iterator LRUCache<KEY, DATA, HASH>::end() const
300*03ce13f7SAndroid Build Coastguard Worker {
301*03ce13f7SAndroid Build Coastguard Worker 	return { nullptr };
302*03ce13f7SAndroid Build Coastguard Worker }
303*03ce13f7SAndroid Build Coastguard Worker 
304*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
unlink(Entry * entry)305*03ce13f7SAndroid Build Coastguard Worker void LRUCache<KEY, DATA, HASH>::unlink(Entry *entry)
306*03ce13f7SAndroid Build Coastguard Worker {
307*03ce13f7SAndroid Build Coastguard Worker 	if(head == entry) { head = entry->next; }
308*03ce13f7SAndroid Build Coastguard Worker 	if(tail == entry) { tail = entry->prev; }
309*03ce13f7SAndroid Build Coastguard Worker 	if(entry->prev) { entry->prev->next = entry->next; }
310*03ce13f7SAndroid Build Coastguard Worker 	if(entry->next) { entry->next->prev = entry->prev; }
311*03ce13f7SAndroid Build Coastguard Worker 	entry->prev = nullptr;
312*03ce13f7SAndroid Build Coastguard Worker 	entry->next = nullptr;
313*03ce13f7SAndroid Build Coastguard Worker }
314*03ce13f7SAndroid Build Coastguard Worker 
315*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
link(Entry * entry)316*03ce13f7SAndroid Build Coastguard Worker void LRUCache<KEY, DATA, HASH>::link(Entry *entry)
317*03ce13f7SAndroid Build Coastguard Worker {
318*03ce13f7SAndroid Build Coastguard Worker 	ASSERT_MSG(entry->next == nullptr, "link() called on entry already linked");
319*03ce13f7SAndroid Build Coastguard Worker 	ASSERT_MSG(entry->prev == nullptr, "link() called on entry already linked");
320*03ce13f7SAndroid Build Coastguard Worker 	if(head)
321*03ce13f7SAndroid Build Coastguard Worker 	{
322*03ce13f7SAndroid Build Coastguard Worker 		entry->next = head;
323*03ce13f7SAndroid Build Coastguard Worker 		head->prev = entry;
324*03ce13f7SAndroid Build Coastguard Worker 	}
325*03ce13f7SAndroid Build Coastguard Worker 	head = entry;
326*03ce13f7SAndroid Build Coastguard Worker 	if(!tail) { tail = entry; }
327*03ce13f7SAndroid Build Coastguard Worker }
328*03ce13f7SAndroid Build Coastguard Worker 
329*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
find(const Key & key)330*03ce13f7SAndroid Build Coastguard Worker typename LRUCache<KEY, DATA, HASH>::Entry *LRUCache<KEY, DATA, HASH>::find(const Key &key)
331*03ce13f7SAndroid Build Coastguard Worker {
332*03ce13f7SAndroid Build Coastguard Worker 	auto asKeyed = reinterpret_cast<const Keyed *>(&key);
333*03ce13f7SAndroid Build Coastguard Worker 	auto it = set.find(asKeyed);
334*03ce13f7SAndroid Build Coastguard Worker 	if(it == set.end())
335*03ce13f7SAndroid Build Coastguard Worker 	{
336*03ce13f7SAndroid Build Coastguard Worker 		return nullptr;
337*03ce13f7SAndroid Build Coastguard Worker 	}
338*03ce13f7SAndroid Build Coastguard Worker 	return const_cast<Entry *>(static_cast<const Entry *>(*it));
339*03ce13f7SAndroid Build Coastguard Worker }
340*03ce13f7SAndroid Build Coastguard Worker 
341*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
342*03ce13f7SAndroid Build Coastguard Worker // LRUCache<>::KeyedComparator
343*03ce13f7SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
344*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
operator ()(const Keyed * k) const345*03ce13f7SAndroid Build Coastguard Worker uint64_t LRUCache<KEY, DATA, HASH>::KeyedComparator::operator()(const Keyed *k) const
346*03ce13f7SAndroid Build Coastguard Worker {
347*03ce13f7SAndroid Build Coastguard Worker 	return Hash()(k->key);
348*03ce13f7SAndroid Build Coastguard Worker }
349*03ce13f7SAndroid Build Coastguard Worker 
350*03ce13f7SAndroid Build Coastguard Worker template<typename KEY, typename DATA, typename HASH>
operator ()(const Keyed * a,const Keyed * b) const351*03ce13f7SAndroid Build Coastguard Worker uint64_t LRUCache<KEY, DATA, HASH>::KeyedComparator::operator()(const Keyed *a, const Keyed *b) const
352*03ce13f7SAndroid Build Coastguard Worker {
353*03ce13f7SAndroid Build Coastguard Worker 	return a->key == b->key;
354*03ce13f7SAndroid Build Coastguard Worker }
355*03ce13f7SAndroid Build Coastguard Worker 
356*03ce13f7SAndroid Build Coastguard Worker }  // namespace sw
357*03ce13f7SAndroid Build Coastguard Worker 
358*03ce13f7SAndroid Build Coastguard Worker #endif  // sw_LRUCache_hpp
359