1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #ifndef sw_LRUCache_hpp
16 #define sw_LRUCache_hpp
18 #include "System/Math.hpp"
20 #include <type_traits>
21 #include <unordered_map>
25 template<class Key, class Data>
33 Data query(const Key &key) const;
34 virtual Data add(const Key &key, const Data &data);
36 int getSize() { return size; }
37 Key &getKey(int i) { return key[i]; }
50 // An LRU cache which can take a 'snapshot' of its current state. This is useful
51 // for allowing concurrent read access without requiring a mutex to be locked.
52 template<class Key, class Data, class Hasher = std::hash<Key>>
53 class LRUSnapshotCache : public LRUCache<Key, Data>
55 using LRUBase = LRUCache<Key, Data>;
58 LRUSnapshotCache(int n)
61 ~LRUSnapshotCache() { clearSnapshot(); }
63 Data add(const Key &key, const Data &data) override
65 snapshotNeedsUpdate = true;
66 return LRUBase::add(key, data);
69 void updateSnapshot();
70 const Data &querySnapshot(const Key &key) const;
74 bool snapshotNeedsUpdate = false;
75 std::unordered_map<Key, Data, Hasher> snapshot;
82 template<class Key, class Data>
83 LRUCache<Key, Data>::LRUCache(int n)
91 ref = new Key *[size];
92 data = new Data[size];
94 for(int i = 0; i < size; i++)
100 template<class Key, class Data>
101 LRUCache<Key, Data>::~LRUCache()
113 template<class Key, class Data>
114 Data LRUCache<Key, Data>::query(const Key &key) const
116 for(int i = top; i > top - fill; i--)
127 int k = (j + 1) & mask;
129 Data swapD = data[k];
142 return {}; // Not found
145 template<class Key, class Data>
146 Data LRUCache<Key, Data>::add(const Key &key, const Data &data)
148 top = (top + 1) & mask;
149 fill = fill + 1 < size ? fill + 1 : size;
152 this->data[top] = data;
157 template<class Key, class Data, class Hasher>
158 void LRUSnapshotCache<Key, Data, Hasher>::clearSnapshot()
163 template<class Key, class Data, class Hasher>
164 void LRUSnapshotCache<Key, Data, Hasher>::updateSnapshot()
166 if(snapshotNeedsUpdate)
170 for(int i = 0; i < LRUBase::size; i++)
174 snapshot[*LRUBase::ref[i]] = LRUBase::data[i];
178 snapshotNeedsUpdate = false;
182 template<class Key, class Data, class Hasher>
183 const Data &LRUSnapshotCache<Key, Data, Hasher>::querySnapshot(const Key &key) const
185 auto it = snapshot.find(key);
186 static Data null = {};
187 return (it != snapshot.end()) ? it->second : null;
192 #endif // sw_LRUCache_hpp