244 lines
6.4 KiB
C
244 lines
6.4 KiB
C
|
/*
|
||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||
|
*
|
||
|
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||
|
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU General Public License
|
||
|
* as published by the Free Software Foundation; either version 2
|
||
|
* of the License, or (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, you may find one here:
|
||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||
|
* or you may write to the Free Software Foundation, Inc.,
|
||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @file lru_cache.h
|
||
|
* @brief Template define a least-recently-used cache algo based on wxHashMap and wxString
|
||
|
* http://docs.wxwidgets.org/3.0/classwx_hash_map.html
|
||
|
*/
|
||
|
|
||
|
#ifndef LRU_CACHE_H
|
||
|
#define LRU_CACHE_H
|
||
|
|
||
|
|
||
|
#include <list>
|
||
|
#include <iterator>
|
||
|
#include <map>
|
||
|
#include <stdexcept>
|
||
|
#include <wx/string.h>
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Template LRU_WXSTR_CACHE
|
||
|
* template for a wxString key based LRU cache
|
||
|
*
|
||
|
* @code
|
||
|
* LRU_WXSTR_CACHE< int > cache;
|
||
|
*
|
||
|
* cache.Resize( 3 );
|
||
|
*
|
||
|
* cache.Insert( "First", 1 );
|
||
|
* cache.Insert( "Second", 2 );
|
||
|
*
|
||
|
* printf(" cache.Size() %d \n", cache.Size() ); // size == 2
|
||
|
* printf(" cache.MaxSize() %d \n", cache.MaxSize() ); // max size == 3
|
||
|
* @endcode
|
||
|
*/
|
||
|
template< typename t_value >
|
||
|
class LRU_WXSTR_CACHE
|
||
|
{
|
||
|
|
||
|
private:
|
||
|
|
||
|
/**
|
||
|
* Declares KEY_VALUE_PAIR
|
||
|
* Declares a pair with the key (wxString) and a value
|
||
|
*/
|
||
|
typedef std::pair< wxString, t_value > KEY_VALUE_PAIR;
|
||
|
|
||
|
/**
|
||
|
* Declares LIST_ITERATOR
|
||
|
* Declares a iterator type for a list of KEY_VALUE_PAIR
|
||
|
*/
|
||
|
typedef std::list< KEY_VALUE_PAIR > CACHED_LIST;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Declares LIST_ITERATOR
|
||
|
* Declares a iterator type for a list of KEY_VALUE_PAIR
|
||
|
*/
|
||
|
typedef typename CACHED_LIST::iterator LIST_ITERATOR;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Declares WXSTR_HASH_MAP
|
||
|
* Declares a map type of LIST_ITERATOR based on a wxString key
|
||
|
*/
|
||
|
typedef std::map< wxString, LIST_ITERATOR > WXSTR_HASH_MAP;
|
||
|
|
||
|
/**
|
||
|
* Declares MAP_ITERATOR
|
||
|
* Declares a iterator for the map
|
||
|
*/
|
||
|
typedef typename WXSTR_HASH_MAP::iterator MAP_ITERATOR;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* list of cached items
|
||
|
*/
|
||
|
CACHED_LIST m_cached_list;
|
||
|
|
||
|
/**
|
||
|
* Cache map with iterators of the list
|
||
|
*/
|
||
|
WXSTR_HASH_MAP m_map_iterators;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Max capacity of the cache
|
||
|
*/
|
||
|
size_t m_maxSize;
|
||
|
|
||
|
public:
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Constructor LRU_WXSTR_CACHE
|
||
|
* @param aMaxSize - initial max number of items of the cache
|
||
|
*/
|
||
|
LRU_WXSTR_CACHE( size_t aMaxSize = 1 ) : m_maxSize( aMaxSize ) {}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Function Insert
|
||
|
* @param aKey = the string key that is the reference of this entry
|
||
|
* @param aValue = the value to add
|
||
|
*/
|
||
|
void Insert( const wxString &aKey, const t_value &aValue )
|
||
|
{
|
||
|
MAP_ITERATOR it = m_map_iterators.find( aKey );
|
||
|
|
||
|
if( it != m_map_iterators.end() )
|
||
|
{
|
||
|
// It already exists, so must remove it from list and form the map
|
||
|
// it->second have a iterator from the list m_cached_list
|
||
|
m_cached_list.erase( it->second );
|
||
|
m_map_iterators.erase( it );
|
||
|
}
|
||
|
|
||
|
// Inserts a new element at the beginning of the list, a pair of <aKey, aValue>
|
||
|
m_cached_list.push_front( KEY_VALUE_PAIR( aKey, aValue) );
|
||
|
|
||
|
// Insert a new key and the added list iterator to the map
|
||
|
m_map_iterators[aKey] = m_cached_list.begin();
|
||
|
|
||
|
// Manage the size of the list
|
||
|
if( m_cached_list.size() > m_maxSize )
|
||
|
{
|
||
|
// Get an iterator to the end of the list
|
||
|
LIST_ITERATOR last_it = m_cached_list.end();
|
||
|
|
||
|
// This gets the real iterator that is the latest one
|
||
|
last_it--;
|
||
|
|
||
|
// Remove the key from the map
|
||
|
m_map_iterators.erase( last_it->first );
|
||
|
|
||
|
// Removes the last element in the list
|
||
|
m_cached_list.pop_back();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Function Get
|
||
|
* Returns an existent value from the given key.
|
||
|
* The key must exists, if not it will throw an error.
|
||
|
* Use function Exists to check first if you can get that key
|
||
|
* @param aKey = an existent key
|
||
|
* @return t_value
|
||
|
*/
|
||
|
const t_value& Get( const wxString &aKey )
|
||
|
{
|
||
|
MAP_ITERATOR map_it = m_map_iterators.find( aKey );
|
||
|
|
||
|
if( map_it == m_map_iterators.end() )
|
||
|
{
|
||
|
throw std::range_error( "Requested a key that dont exists" );
|
||
|
}
|
||
|
|
||
|
// This will update the list and put in the beginning the iterator that we are getting
|
||
|
m_cached_list.splice( m_cached_list.begin(), m_cached_list, map_it->second );
|
||
|
|
||
|
// Return the t_value from the <key, value> pair that was in the list
|
||
|
return map_it->second->second;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Function Exists
|
||
|
* @param aKey key to look for
|
||
|
* @return true if the aKey exists
|
||
|
*/
|
||
|
bool Exists( const wxString &aKey ) const
|
||
|
{
|
||
|
return ( m_map_iterators.find( aKey ) != m_map_iterators.end() );
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Function Resize
|
||
|
* If aNewSize is smaller than the current maxSize then the items back in the list are discarded
|
||
|
* This function can be used to empty the cache, setting the new size to 0
|
||
|
* @param aNewSize - resize the store capability of the list to aNewSize
|
||
|
*/
|
||
|
void Resize( size_t aNewSize )
|
||
|
{
|
||
|
m_maxSize = aNewSize;
|
||
|
|
||
|
while( m_map_iterators.size() > m_maxSize )
|
||
|
{
|
||
|
// Remove the key from the map
|
||
|
m_map_iterators.erase( m_cached_list.back().first );
|
||
|
|
||
|
// Remove the back of the list
|
||
|
m_cached_list.pop_back();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Function Size
|
||
|
* @return size_t current size of the cache
|
||
|
*/
|
||
|
size_t Size() const
|
||
|
{
|
||
|
return m_map_iterators.size();
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Function MaxSize
|
||
|
* @return size_t current max size of the cache
|
||
|
*/
|
||
|
size_t MaxSize() const
|
||
|
{
|
||
|
return m_maxSize;
|
||
|
}
|
||
|
|
||
|
|
||
|
};
|
||
|
|
||
|
#endif // LRU_CACHE_H
|