You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

77 lines
1.7 KiB

#pragma once
#ifndef CACHE_H
#define CACHE_H
#include <unordered_map>
#include <list>
#include <utility>
#include <iostream>
#include <memory>
#include <mutex>
template<class K, class V>
class LRUCache {
using Key_list = std::list<std::pair<K, std::shared_ptr<V>>>;
Key_list key_values;
std::unordered_map<K, typename Key_list::iterator> positions;
size_t max_values;
std::mutex cache_mutex;
void remove_oldest() {
while (positions.size() >= max_values) {
positions.erase(key_values.back().first);
key_values.pop_back();
}
}
public:
LRUCache(const size_t max_values) : max_values(max_values) {
}
void insert(const K& key, std::shared_ptr<V> value) {
std::lock_guard<std::mutex> lock(cache_mutex);
remove_oldest();
key_values.emplace_front(key, value);
positions[key] = key_values.begin();
}
void insert(const K& key, V* value) {
insert(key, std::shared_ptr<V>(value));
}
void insert(const K& key, V&& value) {
insert(key, std::make_shared<V>(std::move(value)));
}
void insert(const K& key, V& value) {
insert(key, std::make_shared<V>(value));
}
std::shared_ptr<V> find(const K& key) {
std::lock_guard<std::mutex> lock(cache_mutex);
auto p = positions.find(key);
if (p == positions.end())
return {};
auto iter = p->second;
auto& value = iter->second;
// If the iterator is not at the front of the list, move it there.
if (iter != key_values.begin()) {
key_values.splice(
key_values.begin(),
key_values,
iter,
std::next(iter));
}
positions[key] = key_values.begin();
return iter->second;
}
void debug_cache() {
std::lock_guard<std::mutex> lock(cache_mutex);
for (auto& p : key_values) {
std::cout << p.first << ":" << *p.second << std::endl;
}
}
};
#endif