Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / include / o3tl / lru_map.hxx
blobc1bfff733f5bf0a6287180737e35078bc95ae334
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
9 */
11 #ifndef INCLUDED_O3TL_LRU_MAP_HXX
12 #define INCLUDED_O3TL_LRU_MAP_HXX
14 #include <list>
15 #include <unordered_map>
17 namespace o3tl
20 /** LRU 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
27 * thread safe.
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.
32 **/
33 template<typename Key, typename Value, class KeyHash = std::hash<Key>>
34 class lru_map final
36 private:
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;
46 list_t mLruList;
47 map_t mLruMap;
48 const size_t mMaxSize;
50 void checkLRU()
52 if (mLruMap.size() > mMaxSize)
54 // remove from map
55 mLruMap.erase(mLruList.back().first);
56 // remove from list
57 mLruList.pop_back();
60 public:
61 typedef list_iterator_t iterator;
62 typedef list_const_iterator_t const_iterator;
64 lru_map(size_t nMaxSize)
65 : mMaxSize(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();
78 checkLRU();
80 else // already exists -> replace value
82 // 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();
99 checkLRU();
101 else // already exists -> replace value
103 // 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();
118 else
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();
131 size_t size() const
133 return mLruList.size();
139 #endif /* INCLUDED_O3TL_LRU_MAP_HXX */
141 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */