#include <algorithm>
#include <cassert>
#include <limits>
#include <memory>
#include <vector>
#include <cstdint>
// Cache that evicts old entries which have not been used recently. Implemented
// using array/linear search so this works well for small array sizes.
template<typename TKey, typename TValue>
struct LruCache
{
explicit LruCache(int max_entries);
// Fetches an entry for |key|. If it does not exist, |allocator| will be
// invoked to create one.
template<typename TAllocator>
TValue Get(TKey const& key, TAllocator allocator);
// Returns true if there is an entry for |key|.
bool Has(TKey const& key);
// Fetches the entry for |filename| and updates it's usage so it is less
// likely to be evicted.
bool TryGet(TKey const& key, TValue* dest);
// TryGetEntry, except the entry is removed from the cache.
bool TryTake(TKey const& key, TValue* dest);
// Inserts an entry. Evicts the oldest unused entry if there is no space.
void Insert(TKey const& key, TValue const& value);
// Call |func| on existing entries. If |func| returns false iteration
// terminates early.
template<typename TFunc>
void IterateValues(TFunc func);
// Empties the cache
void Clear(void);
private:
// There is a global score counter, when we access an element we increase
// its score to the current global value, so it has the highest overall
// score. This means that the oldest/least recently accessed value has the
// lowest score.
//
// There is a bit of special logic to handle score overlow.
struct Entry
{
uint32_t score = 0;
TKey key;
TValue value;
bool operator<(Entry const& other) const
{
return score < other.score;
}
};