#include <boost/unordered_map.hpp>
#define DEFAULT_LRU_CAPACITY 10000
template<class K, class V>
class LRUCache
{
struct Node
{
K key;
V value;
Node *prev, *next;
Node(const K& key, const V& value)
: key(key)
, value(value)
{
prev = next = NULL;
}
Node()
{
}
};
public:
LRUCache(std::size_t size = DEFAULT_LRU_CAPACITY)
: size_(size)
{
// Mutex::Lock autolock(lock);
assert(size > 0);
head_ = new Node;
head_->next = head_;
head_->prev = head_;//circle
}
int get(const K& k, V& v)
{
// Mutex::Lock autolock(lock);
boost::unordered_map<K, Node*>::const_iterator iter = elems_.find(k);
if (iter == elems_.end()) {
cout << "get, cannot find:" << k << endl;
return -1; //can't find
}
Node* node = iter->second;
if (head_->next != node) {
detatch(node);
attach(node);
}
v = node->value;
return 0;
}
int put(const K key, const V& value)
{
// Mutex::Lock autolock(lock);
if (elems_.find(key) != elems_.end()) {
return -1; //not unique
}
if (elems_.size() >= size_)
{
drop_oldest();
}
Node* node = new Node(key, value);
elems_[key] = node;
attach(node);
return 0;
}
void dump()
{
std::cout << "dump-----------------------" << endl;
Node* node = head_->next;
while (node && node != head_) {
std::cout << "------------\t" << node->key << "\t" << node->value << endl;
node = node->next;
}
}
protected:
void detatch(Node* node)
{
node->prev->next = node->next;
node->next->prev = node->prev;
}
void attach(Node* node)
{
node->next = head_->next;
node->prev = head_;
head_->next->prev = node;
head_->next = node;
}
void drop_oldest()
{
Node* node = head_->prev;// last node
assert(node != head_);// not empty
if (node == head_) {
return;// empty
}
K key = node->key;
elems_.erase(key);
head_->prev = node->prev;
node->prev->next = head_;
delete node;
}
protected:
boost::unordered_map<K, Node*> elems_;
Node* head_;
std::size_t size_;
// Mutex lock;
};