// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
|
//
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
// you may not use this file except in compliance with the License.
|
// You may obtain a copy of the License at
|
//
|
// http://www.apache.org/licenses/LICENSE-2.0
|
//
|
// Unless required by applicable law or agreed to in writing, software
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// See the License for the specific language governing permissions and
|
// limitations under the License.
|
|
#ifndef sw_LRUCache_hpp
|
#define sw_LRUCache_hpp
|
|
#include "Common/Math.hpp"
|
|
namespace sw
|
{
|
template<class Key, class Data>
|
class LRUCache
|
{
|
public:
|
LRUCache(int n);
|
|
~LRUCache();
|
|
Data *query(const Key &key) const;
|
Data *add(const Key &key, Data *data);
|
|
int getSize() {return size;}
|
Key &getKey(int i) {return key[i];}
|
|
private:
|
int size;
|
int mask;
|
int top;
|
int fill;
|
|
Key *key;
|
Key **ref;
|
Data **data;
|
};
|
}
|
|
namespace sw
|
{
|
template<class Key, class Data>
|
LRUCache<Key, Data>::LRUCache(int n)
|
{
|
size = ceilPow2(n);
|
mask = size - 1;
|
top = 0;
|
fill = 0;
|
|
key = new Key[size];
|
ref = new Key*[size];
|
data = new Data*[size];
|
|
for(int i = 0; i < size; i++)
|
{
|
data[i] = nullptr;
|
|
ref[i] = &key[i];
|
}
|
}
|
|
template<class Key, class Data>
|
LRUCache<Key, Data>::~LRUCache()
|
{
|
delete[] key;
|
key = nullptr;
|
|
delete[] ref;
|
ref = nullptr;
|
|
for(int i = 0; i < size; i++)
|
{
|
if(data[i])
|
{
|
data[i]->unbind();
|
data[i] = nullptr;
|
}
|
}
|
|
delete[] data;
|
data = nullptr;
|
}
|
|
template<class Key, class Data>
|
Data *LRUCache<Key, Data>::query(const Key &key) const
|
{
|
for(int i = top; i > top - fill; i--)
|
{
|
int j = i & mask;
|
|
if(key == *ref[j])
|
{
|
Data *hit = data[j];
|
|
if(i != top)
|
{
|
// Move one up
|
int k = (j + 1) & mask;
|
|
Data *swapD = data[k];
|
data[k] = data[j];
|
data[j] = swapD;
|
|
Key *swapK = ref[k];
|
ref[k] = ref[j];
|
ref[j] = swapK;
|
}
|
|
return hit;
|
}
|
}
|
|
return nullptr; // Not found
|
}
|
|
template<class Key, class Data>
|
Data *LRUCache<Key, Data>::add(const Key &key, Data *data)
|
{
|
top = (top + 1) & mask;
|
fill = fill + 1 < size ? fill + 1 : size;
|
|
*ref[top] = key;
|
|
data->bind();
|
|
if(this->data[top])
|
{
|
this->data[top]->unbind();
|
}
|
|
this->data[top] = data;
|
|
return data;
|
}
|
}
|
|
#endif // sw_LRUCache_hpp
|