1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 #ifndef INCLUDED_O3TL_LRU_MAP_HXX
12 #define INCLUDED_O3TL_LRU_MAP_HXX
15 #include <unordered_map>
22 * Similar to unordered_map (it actually uses it) with additionally functionality
23 * which removes the entries that have been "least recently used" when the size
24 * hits the specified capacity.
26 * It only implements the minimal methods needed and the implementation is NOT
29 * The implementation is as simple as possible but it still uses O(1) complexity
30 * for most of the operations with a combination unordered map and linked list.
33 template<typename Key
, typename Value
, class KeyHash
= std::hash
<Key
>>
37 typedef typename
std::pair
<Key
, Value
> key_value_pair_t
;
38 typedef std::list
<key_value_pair_t
> list_t
;
39 typedef typename
list_t::iterator list_iterator_t
;
40 typedef typename
list_t::const_iterator list_const_iterator_t
;
42 typedef std::unordered_map
<Key
, list_iterator_t
, KeyHash
> map_t
;
43 typedef typename
map_t::iterator map_iterator_t
;
44 typedef typename
map_t::const_iterator map_const_iterator_t
;
48 const size_t mMaxSize
;
52 if (mLruMap
.size() > mMaxSize
)
55 mLruMap
.erase(mLruList
.back().first
);
61 typedef list_iterator_t iterator
;
62 typedef list_const_iterator_t const_iterator
;
64 lru_map(size_t nMaxSize
)
68 void insert(key_value_pair_t
& rPair
)
70 map_iterator_t iterator
= mLruMap
.find(rPair
.first
);
72 if (iterator
== mLruMap
.end()) // doesn't exist -> add to queue and map
74 // add to front of the list
75 mLruList
.push_front(rPair
);
76 // add the list position (iterator) to the map
77 mLruMap
[rPair
.first
] = mLruList
.begin();
80 else // already exists -> replace value
83 iterator
->second
->second
= rPair
.second
;
84 // bring to front of the lru list
85 mLruList
.splice(mLruList
.begin(), mLruList
, iterator
->second
);
89 void insert(key_value_pair_t
&& rPair
)
91 map_iterator_t iterator
= mLruMap
.find(rPair
.first
);
93 if (iterator
== mLruMap
.end()) // doesn't exist -> add to list and map
95 // add to front of the list
96 mLruList
.push_front(std::move(rPair
));
97 // add the list position (iterator) to the map
98 mLruMap
[rPair
.first
] = mLruList
.begin();
101 else // already exists -> replace value
104 iterator
->second
->second
= std::move(rPair
.second
);
105 // push to back of the lru list
106 mLruList
.splice(mLruList
.begin(), mLruList
, iterator
->second
);
110 const list_const_iterator_t
find(const Key
& key
)
112 const map_iterator_t iterator
= mLruMap
.find(key
);
113 if (iterator
== mLruMap
.cend()) // can't find entry for the key
115 // return empty iterator
116 return mLruList
.cend();
120 // push to back of the lru list
121 mLruList
.splice(mLruList
.begin(), mLruList
, iterator
->second
);
122 return iterator
->second
;
126 const list_const_iterator_t
end() const
128 return mLruList
.end();
133 return mLruList
.size();
139 #endif /* INCLUDED_O3TL_LRU_MAP_HXX */
141 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */