Skip to content
Snippets Groups Projects
Commit d54a7757 authored by Christian Engwer's avatar Christian Engwer
Browse files

New container type. Like map<...> ist stores key and data, but it

keeps a "least recently used" ordering.

[[Imported from SVN: r5015]]
parent 2ef95151
No related branches found
No related tags found
No related merge requests found
......@@ -21,7 +21,7 @@ commoninclude_HEADERS = dlist.cc stdstreams.cc alignment.hh \
gcd.hh lcm.hh configparser.hh propertymap.hh \
collectivecommunication.hh mpihelper.hh singleton.hh \
mpicollectivecommunication.hh geometrytype.hh utility.hh \
bartonnackmanifcheck.hh binaryfunctions.hh
bartonnackmanifcheck.hh binaryfunctions.hh lru.hh
if EXPRESSIONTEMPLATES
commoninclude_HEADERS += exprtmpl.hh exprtmpl/scalar.inc exprtmpl/exprexpr.inc
......
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_COMMON_LRU_HH
#define DUNE_COMMON_LRU_HH
#include <list>
#include <utility>
#include <map>
/** @file
@author Christian Engwer
@brief LRU Cache Container, using an STL like interface
Implementatation of an LRU (least recently used) cache
container. This implementation follows the approach presented in
\url
http://aim.adc.rmit.edu.au/phd/sgreuter/papers/graphite2003.pdf
*/
namespace Dune {
template <typename _Key, typename _Tp,
typename _Alloc = std::allocator<_Tp> >
struct _lru_default_traits
{
typedef _Key key_type;
typedef _Alloc allocator;
typedef std::list< std::pair<_Key, _Tp> > list_type;
typedef typename list_type::iterator iterator;
typedef typename std::less<key_type> cmp;
typedef std::map< key_type, iterator, cmp, allocator > map_type;
};
template <typename _Key, typename _Tp,
typename _Traits = _lru_default_traits<_Key, _Tp> >
class lru
{
typedef typename _Traits::list_type list_type;
typedef typename _Traits::map_type map_type;
typedef typename _Traits::allocator allocator;
typedef typename map_type::iterator map_iterator;
typedef typename map_type::const_iterator const_map_iterator;
public:
typedef typename _Traits::key_type key_type;
typedef typename allocator::value_type value_type;
typedef typename allocator::pointer pointer;
typedef typename allocator::const_pointer const_pointer;
typedef typename allocator::const_reference const_reference;
typedef typename allocator::reference reference;
typedef typename allocator::size_type size_type;
typedef typename list_type::iterator iterator;
typedef typename list_type::const_iterator const_iterator;
/**
* Returns a read/write reference to the data of the most
* recently used entry.
*/
reference front()
{
return _data.front().second;
}
/**
* Returns a read-only (constant) reference to the data of the
* most recently used entry.
*/
const_reference front() const
{
return _data.front().second;
}
/**
* Returns a read/write reference to the data of the least
* recently used entry.
*/
reference back()
{
return _data.back().second;
}
/**
* Returns a read-only (constant) reference to the data of the
* least recently used entry.
*/
const_reference back (int i) const
{
return _data.back().second;
}
/**
* @brief Removes the first element.
*/
const void pop_front()
{
key_type k = _data.front().first;
_data.pop_front();
_index.erase(k);
}
/**
* @brief Removes the last element.
*/
const void pop_back()
{
key_type k = _data.back().first;
_data.pop_back();
_index.erase(k);
}
/**
* @brief Finds the element whose key is k.
*
* @return iterator
*/
iterator find (const key_type & key)
{
const map_iterator it = _index.find(key);
if (it == _index.end()) return _data.end();
return it->second;
}
/**
* @brief Finds the element whose key is k.
*
* @return const_iterator
*/
const_iterator find (const key_type & key) const
{
const map_iterator it = _index.find(key);
if (it == _index.end()) return _data.end();
return it->second;
}
/**
* @brief Insert a value into the container
*
* Stores value under key and marks it as most recent.
*
* @param key associated with data
* @param data to store
*
* @return reference of stored data
*/
reference insert (const key_type & key, const_reference data)
{
std::pair<key_type, value_type> x(key, data);
/* insert item as mru */
iterator it = _data.insert(_data.begin(), x);
/* store index */
_index[key] = it;
return it->second;
}
/**
* @copydoc touch
*/
reference insert (const key_type & key)
{
return touch (key);
}
/**
* @brief mark data associateed with key as most recent
*
* @return reference of stored data
*/
reference touch (const key_type & key)
{
/* query _index for iterator */
iterator it = _index[key];
/* update _data
move it to the front
*/
_data.splice(_data.begin(), _data, it);
return it->second;
}
private:
list_type _data;
map_type _index;
};
} // namespace Dune
#endif // DUNE_COMMON_LRU_HH
......@@ -3,6 +3,7 @@ Makefile.in
.deps
.libs
semantic.cache
lrutest
parsetest
test-stack
arraylisttest
......
......@@ -4,7 +4,7 @@ TESTPROGS = parsetest test-stack arraylisttest smartpointertest \
sllisttest iteratorfacadetest tuplestest fvectortest fmatrixtest \
poolallocatortest settest gcdlcdtest streamtest \
bigunsignedinttest mpihelpertest singletontest mpicollcomm \
utilitytest
utilitytest lrutest
# which tests to run
TESTS = $(TESTPROGS)
......@@ -21,6 +21,9 @@ bigunsignedinttest_DEPENDENCIES = $(LOCAL_LIBS)
parsetest_SOURCES = parsetest.cc
parsetest_DEPENDENCIES = $(LOCAL_LIBS)
lrutest_SOURCES = lrutest.cc
lrutest_DEPENDENCIES = $(LOCAL_LIBS)
sllisttest_SOURCES = sllisttest.cc
sllisttest_DEPENDENCIES = $(LOCAL_LIBS)
......
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#include <assert.h>
#include <iostream>
#include <dune/common/lru.hh>
void lru_test()
{
std::cout << "testing Dune::lru<int,double>\n";
Dune::lru<int, double> lru;
lru.insert(10, 1.0);
assert(lru.front() == lru.back());
lru.insert(11, 2.0);
assert(lru.front() == 2.0 && lru.back() == 1.0);
lru.insert(12, 99);
lru.insert(13, 1.3);
lru.insert(14, 12345);
lru.insert(15, -17);
assert(lru.front() == -17 && lru.back() == 1.0);
// update
lru.insert(10);
assert(lru.front() == 1.0 && lru.back() == 2.0);
// update
lru.touch(13);
assert(lru.front() == 1.3 && lru.back() == 2.0);
// remove item
lru.pop_front();
assert(lru.front() == 1.0 && lru.back() == 2.0);
// remove item
lru.pop_back();
assert(lru.front() == 1.0 && lru.back() == 99);
std::cout << "... passed\n";
}
int main ()
{
lru_test();
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment