libraries/pcappp/include/pcapplusplus/LRUList.h

136 lines
4.0 KiB
C++

#ifndef PCAPPP_LRU_LIST
#define PCAPPP_LRU_LIST
#include <map>
#include <list>
#if __cplusplus > 199711L || _MSC_VER >= 1800
#include <utility>
#endif
/// @file
/**
* \namespace pcpp
* \brief The main namespace for the PcapPlusPlus lib
*/
namespace pcpp
{
/**
* @class LRUList
* A template class that implements a LRU cache with limited size. Each time the user puts an element it goes to head of the
* list as the most recently used element (if the element was already in the list it advances to the head of the list).
* The last element in the list is the one least recently used and will be pulled out of the list if it reaches its max size
* and a new element comes in. All actions on this LRU list are O(1)
*/
template<typename T>
class LRUList
{
public:
typedef typename std::list<T>::iterator ListIterator;
typedef typename std::map<T, ListIterator>::iterator MapIterator;
/**
* A c'tor for this class
* @param[in] maxSize The max size this list can go
*/
LRUList(size_t maxSize)
{
m_MaxSize = maxSize;
}
/**
* Puts an element in the list. This element will be inserted (or advanced if it already exists) to the head of the
* list as the most recently used element. If the list already reached its max size and the element is new this method
* will remove the least recently used element and return a value in deletedValue. Method complexity is O(log(getSize())).
* This is a optimized version of the method T* put(const T&).
* @param[in] element The element to insert or to advance to the head of the list (if already exists)
* @param[out] deletedValue The value of deleted element if a pointer is not NULL. This parameter is optional.
* @return 0 if the list didn't reach its max size, 1 otherwise. In case the list already reached its max size
* and deletedValue is not NULL the value of deleted element is copied into the place the deletedValue points to.
*/
int put(const T& element, T* deletedValue = NULL)
{
m_CacheItemsList.push_front(element);
// Inserting a new element. If an element with an equivalent key already exists the method returns an iterator to the element that prevented the insertion
std::pair<MapIterator, bool> pair = m_CacheItemsMap.insert(std::make_pair(element, m_CacheItemsList.begin()));
if (pair.second == false) // already exists
{
m_CacheItemsList.erase(pair.first->second);
pair.first->second = m_CacheItemsList.begin();
}
if (m_CacheItemsMap.size() > m_MaxSize)
{
ListIterator lruIter = m_CacheItemsList.end();
lruIter--;
if (deletedValue != NULL)
#if __cplusplus > 199711L || _MSC_VER >= 1800
*deletedValue = std::move(*lruIter);
#else
*deletedValue = *lruIter;
#endif
m_CacheItemsMap.erase(*lruIter);
m_CacheItemsList.erase(lruIter);
return 1;
}
return 0;
}
/**
* Get the most recently used element (the one at the beginning of the list)
* @return The most recently used element
*/
const T& getMRUElement() const
{
return m_CacheItemsList.front();
}
/**
* Get the least recently used element (the one at the end of the list)
* @return The least recently used element
*/
const T& getLRUElement() const
{
return m_CacheItemsList.back();
}
/**
* Erase an element from the list. If element isn't found in the list nothing happens
* @param[in] element The element to erase
*/
void eraseElement(const T& element)
{
MapIterator iter = m_CacheItemsMap.find(element);
if (iter == m_CacheItemsMap.end())
return;
m_CacheItemsList.erase(iter->second);
m_CacheItemsMap.erase(iter);
}
/**
* @return The max size of this list as determined in the c'tor
*/
size_t getMaxSize() const { return m_MaxSize; }
/**
* @return The number of elements currently in this list
*/
size_t getSize() const { return m_CacheItemsMap.size(); }
private:
std::list<T> m_CacheItemsList;
std::map<T, ListIterator> m_CacheItemsMap;
size_t m_MaxSize;
};
} // namespace pcpp
#endif /* PCAPPP_LRU_LIST */