blob: 3ce15fbec7e310539d271c3a4746607cde8f2865 [file] [log] [blame]
// SwiftShader Software Renderer
//
// Copyright(c) 2005-2011 TransGaming Inc.
//
// All rights reserved. No part of this software may be copied, distributed, transmitted,
// transcribed, stored in a retrieval system, translated into any human or computer
// language by any means, or disclosed to third parties without the explicit written
// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
// or implied, including but not limited to any patent rights, are granted to you.
//
#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] = 0;
ref[i] = &key[i];
}
}
template<class Key, class Data>
LRUCache<Key, Data>::~LRUCache()
{
delete[] key;
key = 0;
delete[] ref;
ref = 0;
for(int i = 0; i < size; i++)
{
if(data[i])
{
data[i]->unbind();
data[i] = 0;
}
}
delete[] data;
data = 0;
}
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 0; // 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