Skip to content

Commit

Permalink
Moved LRU cache implementation to separate files (#30218)
Browse files Browse the repository at this point in the history
* Move lru_cache implementation to separate files

* Updated tests
  • Loading branch information
kevingranade authored May 4, 2019
2 parents 9d39b31 + 0a0532b commit 2e4aa2a
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 100 deletions.
72 changes: 72 additions & 0 deletions src/lru_cache.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include "lru_cache.h"

#include <stddef.h>
#include <iterator>

#include "map_memory.h"

template<typename Key, typename Value>
Value lru_cache<Key, Value>::get( const Key &pos, const Value &default_ ) const
{
auto found = map.find( pos );
if( found != map.end() ) {
return found->second->second;
}
return default_;
}

template<typename Key, typename Value>
void lru_cache<Key, Value>::remove( const Key &pos )
{
auto found = map.find( pos );
if( found != map.end() ) {
ordered_list.erase( found->second );
map.erase( found );
}
}

template<typename Key, typename Value>
void lru_cache<Key, Value>::insert( int limit, const Key &pos, const Value &t )
{
auto found = map.find( pos );

if( found == map.end() ) {
// Need new entry in map. Make the new list entry and point to it.
ordered_list.emplace_back( pos, t );
map[pos] = std::prev( ordered_list.end() );
trim( limit );
} else {
// Splice existing entry to the back. Does not invalidate the
// iterator, so no need to change the map.
auto list_iterator = found->second;
ordered_list.splice( ordered_list.end(), ordered_list, list_iterator );
// Update the moved item
list_iterator->second = t;
}
}

template<typename Key, typename Value>
void lru_cache<Key, Value>::trim( int limit )
{
while( map.size() > static_cast<size_t>( limit ) ) {
map.erase( ordered_list.front().first );
ordered_list.pop_front();
}
}

template<typename Key, typename Value>
void lru_cache<Key, Value>::clear()
{
map.clear();
ordered_list.clear();
}

template<typename Key, typename Value>
const std::list<typename lru_cache<Key, Value>::Pair> &lru_cache<Key, Value>::list() const
{
return ordered_list;
}

// explicit template initialization for lru_cache of all types
template class lru_cache<tripoint, memorized_terrain_tile>;
template class lru_cache<tripoint, long>;
30 changes: 30 additions & 0 deletions src/lru_cache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once
#ifndef LRU_CACHE_H
#define LRU_CACHE_H

#include <list>
#include <string>
#include <unordered_map>
#include <utility>

#include "enums.h" // IWYU pragma: keep

template<typename Key, typename Value>
class lru_cache
{
public:
using Pair = std::pair<Key, Value>;

void insert( int limit, const Key &, const Value & );
Value get( const Key &, const Value &default_ ) const;
void remove( const Key & );

void clear();
const std::list<Pair> &list() const;
private:
void trim( int limit );
std::list<Pair> ordered_list;
std::unordered_map<Key, typename std::list<Pair>::iterator> map;
};

#endif
68 changes: 0 additions & 68 deletions src/map_memory.cpp
Original file line number Diff line number Diff line change
@@ -1,73 +1,5 @@
#include "map_memory.h"

#include <stddef.h>
#include <iterator>

template<typename T>
T lru_cache<T>::get( const tripoint &pos, const T &default_ ) const
{
auto found = map.find( pos );
if( found != map.end() ) {
return found->second->second;
}
return default_;
}

template<typename T>
void lru_cache<T>::remove( const tripoint &pos )
{
auto found = map.find( pos );
if( found != map.end() ) {
ordered_list.erase( found->second );
map.erase( found );
}
}

template<typename T>
void lru_cache<T>::insert( int limit, const tripoint &pos, const T &t )
{
auto found = map.find( pos );

if( found == map.end() ) {
// Need new entry in map. Make the new list entry and point to it.
ordered_list.emplace_back( pos, t );
map[pos] = std::prev( ordered_list.end() );
trim( limit );
} else {
// Splice existing entry to the back. Does not invalidate the
// iterator, so no need to change the map.
auto list_iterator = found->second;
ordered_list.splice( ordered_list.end(), ordered_list, list_iterator );
// Update the moved item
list_iterator->second = t;
}
}

template<typename T>
void lru_cache<T>::trim( int limit )
{
while( map.size() > static_cast<size_t>( limit ) ) {
map.erase( ordered_list.front().first );
ordered_list.pop_front();
}
}

template<typename T>
void lru_cache<T>::clear()
{
map.clear();
ordered_list.clear();
}

template<typename T>
const std::list<typename lru_cache<T>::Pair> &lru_cache<T>::list() const
{
return ordered_list;
}

template class lru_cache<memorized_terrain_tile>;
template class lru_cache<long>;

static const memorized_terrain_tile default_tile{ "", 0, 0 };

memorized_terrain_tile map_memory::get_tile( const tripoint &pos ) const
Expand Down
32 changes: 3 additions & 29 deletions src/map_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@
#ifndef MAP_MEMORY_H
#define MAP_MEMORY_H

#include <list>
#include <string>
#include <unordered_map>
#include <utility>

#include "enums.h" // IWYU pragma: keep
#include "lru_cache.h"

class JsonOut;
class JsonObject;
Expand All @@ -19,27 +14,6 @@ struct memorized_terrain_tile {
int rotation;
};

template<typename T>
class lru_cache
{
public:
using Pair = std::pair<tripoint, T>;

void insert( int limit, const tripoint &, const T & );
T get( const tripoint &, const T &default_ ) const;
void remove( const tripoint & );

void clear();
const std::list<Pair> &list() const;
private:
void trim( int limit );
std::list<Pair> ordered_list;
std::unordered_map<tripoint, typename std::list<Pair>::iterator> map;
};

extern template class lru_cache<memorized_terrain_tile>;
extern template class lru_cache<long>;

class map_memory
{
public:
Expand All @@ -58,8 +32,8 @@ class map_memory

void clear_memorized_tile( const tripoint &pos );
private:
lru_cache<memorized_terrain_tile> tile_cache;
lru_cache<long> symbol_cache;
lru_cache<tripoint, memorized_terrain_tile> tile_cache;
lru_cache<tripoint, long> symbol_cache;
};

#endif
6 changes: 3 additions & 3 deletions tests/map_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ TEST_CASE( "map_memory_remembers", "[map_memory]" )

TEST_CASE( "map_memory_limited", "[map_memory]" )
{
lru_cache<long> symbol_cache;
lru_cache<tripoint, long> symbol_cache;
symbol_cache.insert( 2, p1, 1 );
symbol_cache.insert( 2, p2, 1 );
symbol_cache.insert( 2, p3, 1 );
Expand All @@ -54,7 +54,7 @@ TEST_CASE( "map_memory_overwrites", "[map_memory]" )

TEST_CASE( "map_memory_erases_lru", "[map_memory]" )
{
lru_cache<long> symbol_cache;
lru_cache<tripoint, long> symbol_cache;
symbol_cache.insert( 2, p1, 1 );
symbol_cache.insert( 2, p2, 2 );
symbol_cache.insert( 2, p1, 1 );
Expand Down Expand Up @@ -93,7 +93,7 @@ TEST_CASE( "map_memory_survives_save_lod", "[map_memory]" )
TEST_CASE( "lru_cache_perf", "[.]" )
{
constexpr int max_size = 1000000;
lru_cache<long> symbol_cache;
lru_cache<tripoint, long> symbol_cache;
const auto start1 = std::chrono::high_resolution_clock::now();
for( int i = 0; i < 1000000; ++i ) {
for( int j = -60; j <= 60; ++j ) {
Expand Down

0 comments on commit 2e4aa2a

Please sign in to comment.