1+ #ifndef PV_PCAPPP_LRU_LIST
2+ #define PV_PCAPPP_LRU_LIST
3+
4+ #include < list>
5+ #include < map>
6+
7+ #if __cplusplus > 199711L || _MSC_VER >= 1800
8+ #include < utility>
9+ #endif
10+
11+ // / @file
12+
13+ /* *
14+ * \namespace pcpp
15+ * \brief The main namespace for the PcapPlusPlus lib
16+ */
17+ namespace pcpp {
18+
19+ /* *
20+ * @class LRUList
21+ * A template class that implements a LRU cache with limited size. Each time the user puts an element it goes to head of the
22+ * list as the most recently used element (if the element was already in the list it advances to the head of the list).
23+ * 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
24+ * and a new element comes in. All actions on this LRU list are O(1)
25+ */
26+ template <typename T, typename V>
27+ class LRUList
28+ {
29+ public:
30+ typedef typename std::list<std::pair<T, V>>::iterator ListIterator;
31+ typedef typename std::map<T, ListIterator>::iterator MapIterator;
32+
33+ /* *
34+ * A c'tor for this class
35+ * @param[in] maxSize The max size this list can go
36+ */
37+
38+ LRUList (size_t maxSize)
39+ {
40+ m_MaxSize = maxSize;
41+ }
42+
43+ /* *
44+ * A c'tor for this class with unlimited size
45+ */
46+ LRUList ()
47+ {
48+ m_MaxSize = 0 ;
49+ }
50+
51+ /* *
52+ * Puts an element in the list. This element will be inserted (or advanced if it already exists) to the head of the
53+ * list as the most recently used element. If the list already reached its max size and the element is new this method
54+ * will remove the least recently used element and return a value in deletedValue. Method complexity is O(log(getSize())).
55+ * This is a optimized version of the method T* put(const T&).
56+ * @param[in] element The element to insert or to advance to the head of the list (if already exists)
57+ * @param[out] deletedValue The value of deleted element if a pointer is not NULL. This parameter is optional.
58+ * @return 0 if the list didn't reach its max size, 1 otherwise. In case the list already reached its max size
59+ * and deletedValue is not NULL the value of deleted element is copied into the place the deletedValue points to.
60+ */
61+ int put (const T &element, const V &value, std::pair<T, V> *deletedValue = NULL )
62+ {
63+ m_CacheItemsList.push_front (std::make_pair (element, value));
64+
65+ // 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
66+ std::pair<MapIterator, bool > pair = m_CacheItemsMap.insert (std::make_pair (element, m_CacheItemsList.begin ()));
67+ if (pair.second == false ) // already exists
68+ {
69+ m_CacheItemsList.erase (pair.first ->second );
70+ pair.first ->second = m_CacheItemsList.begin ();
71+ }
72+
73+ if (m_MaxSize && m_CacheItemsMap.size () > m_MaxSize) {
74+ ListIterator lruIter = m_CacheItemsList.end ();
75+ lruIter--;
76+
77+ if (deletedValue != NULL )
78+ #if __cplusplus > 199711L || _MSC_VER >= 1800
79+ *deletedValue = std::move (*lruIter);
80+ #else
81+ *deletedValue = *lruIter;
82+ #endif
83+ m_CacheItemsMap.erase (lruIter->first );
84+ m_CacheItemsList.erase (lruIter);
85+ return 1 ;
86+ }
87+
88+ return 0 ;
89+ }
90+
91+ /* *
92+ * Get the most recently used element (the one at the beginning of the list)
93+ * @return The most recently used element
94+ */
95+ inline const std::pair<T, V> &getMRUElement () const
96+ {
97+ return m_CacheItemsList.front ();
98+ }
99+
100+ /* *
101+ * Get the least recently used element (the one at the end of the list)
102+ * @return The least recently used element
103+ */
104+ inline const std::pair<T, V> &getLRUElement () const
105+ {
106+ return m_CacheItemsList.back ();
107+ }
108+
109+ /* *
110+ * Erase an element from the list. If element isn't found in the list nothing happens
111+ * @param[in] element The element to erase
112+ */
113+ inline void eraseElement (const T &element)
114+ {
115+ MapIterator iter = m_CacheItemsMap.find (element);
116+ if (iter == m_CacheItemsMap.end ())
117+ return ;
118+
119+ m_CacheItemsList.erase (iter->second );
120+ m_CacheItemsMap.erase (iter);
121+ }
122+
123+ /* *
124+ * @return The max size of this list as determined in the c'tor
125+ */
126+ inline size_t getMaxSize () const
127+ {
128+ return m_MaxSize;
129+ }
130+
131+ /* *
132+ * @return The number of elements currently in this list
133+ */
134+ inline size_t getSize () const
135+ {
136+ return m_CacheItemsMap.size ();
137+ }
138+
139+ private:
140+ std::list<std::pair<T, V>> m_CacheItemsList;
141+ std::map<T, ListIterator> m_CacheItemsMap;
142+ size_t m_MaxSize;
143+ };
144+
145+ } // namespace pcpp
146+
147+ #endif /* PV_PCAPPP_LRU_LIST */
0 commit comments