xref: /aosp_15_r20/external/ublksrv/qcow2/lrucache.hpp (revision 94c4a1e103eb1715230460aab379dff275992c20)
1*94c4a1e1SFrank Piva /*
2*94c4a1e1SFrank Piva  * File:   lrucache.hpp
3*94c4a1e1SFrank Piva  * Author: Alexander Ponomarev
4*94c4a1e1SFrank Piva  *
5*94c4a1e1SFrank Piva  * Created on June 20, 2013, 5:09 PM
6*94c4a1e1SFrank Piva  */
7*94c4a1e1SFrank Piva 
8*94c4a1e1SFrank Piva /*
9*94c4a1e1SFrank Piva  * Redistribution and use in source and binary forms, with or without
10*94c4a1e1SFrank Piva    modification, are permitted provided that the following conditions are met:
11*94c4a1e1SFrank Piva 
12*94c4a1e1SFrank Piva  * Redistributions of source code must retain the above copyright notice, this
13*94c4a1e1SFrank Piva    list of conditions and the following disclaimer.
14*94c4a1e1SFrank Piva 
15*94c4a1e1SFrank Piva  * Redistributions in binary form must reproduce the above copyright notice,
16*94c4a1e1SFrank Piva    this list of conditions and the following disclaimer in the documentation
17*94c4a1e1SFrank Piva    and/or other materials provided with the distribution.
18*94c4a1e1SFrank Piva 
19*94c4a1e1SFrank Piva  * Neither the name of lamerman nor the names of its
20*94c4a1e1SFrank Piva    contributors may be used to endorse or promote products derived from
21*94c4a1e1SFrank Piva    this software without specific prior written permission.
22*94c4a1e1SFrank Piva 
23*94c4a1e1SFrank Piva  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24*94c4a1e1SFrank Piva  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25*94c4a1e1SFrank Piva  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26*94c4a1e1SFrank Piva  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
27*94c4a1e1SFrank Piva  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28*94c4a1e1SFrank Piva  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29*94c4a1e1SFrank Piva  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30*94c4a1e1SFrank Piva  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31*94c4a1e1SFrank Piva  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32*94c4a1e1SFrank Piva  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*94c4a1e1SFrank Piva */
34*94c4a1e1SFrank Piva 
35*94c4a1e1SFrank Piva #ifndef _LRUCACHE_HPP_INCLUDED_
36*94c4a1e1SFrank Piva #define	_LRUCACHE_HPP_INCLUDED_
37*94c4a1e1SFrank Piva 
38*94c4a1e1SFrank Piva #include <unordered_map>
39*94c4a1e1SFrank Piva #include <list>
40*94c4a1e1SFrank Piva #include <cstddef>
41*94c4a1e1SFrank Piva #include <stdexcept>
42*94c4a1e1SFrank Piva 
43*94c4a1e1SFrank Piva namespace cache {
44*94c4a1e1SFrank Piva 
45*94c4a1e1SFrank Piva template<typename key_t, typename value_t>
46*94c4a1e1SFrank Piva class lru_cache {
47*94c4a1e1SFrank Piva public:
48*94c4a1e1SFrank Piva 	typedef typename std::pair<key_t, value_t> key_value_pair_t;
49*94c4a1e1SFrank Piva 	typedef typename std::list<key_value_pair_t>::iterator list_iterator_t;
50*94c4a1e1SFrank Piva 
lru_cache(size_t max_size)51*94c4a1e1SFrank Piva 	lru_cache(size_t max_size) :
52*94c4a1e1SFrank Piva 		_max_size(max_size) {
53*94c4a1e1SFrank Piva 	}
54*94c4a1e1SFrank Piva 
remove_last()55*94c4a1e1SFrank Piva 	value_t remove_last() {
56*94c4a1e1SFrank Piva 		auto last = _cache_items_list.end();
57*94c4a1e1SFrank Piva 		last--;
58*94c4a1e1SFrank Piva 		auto t = last->second;
59*94c4a1e1SFrank Piva 		_cache_items_map.erase(last->first);
60*94c4a1e1SFrank Piva 		_cache_items_list.pop_back();
61*94c4a1e1SFrank Piva 
62*94c4a1e1SFrank Piva 		return t;
63*94c4a1e1SFrank Piva 	}
64*94c4a1e1SFrank Piva 
put(const key_t & key,const value_t & value)65*94c4a1e1SFrank Piva 	value_t put(const key_t& key, const value_t& value) {
66*94c4a1e1SFrank Piva 		auto it = _cache_items_map.find(key);
67*94c4a1e1SFrank Piva 		_cache_items_list.push_front(key_value_pair_t(key, value));
68*94c4a1e1SFrank Piva 		if (it != _cache_items_map.end()) {
69*94c4a1e1SFrank Piva 			_cache_items_list.erase(it->second);
70*94c4a1e1SFrank Piva 			_cache_items_map.erase(it);
71*94c4a1e1SFrank Piva 		}
72*94c4a1e1SFrank Piva 		_cache_items_map[key] = _cache_items_list.begin();
73*94c4a1e1SFrank Piva 
74*94c4a1e1SFrank Piva 		if (_cache_items_map.size() > _max_size) {
75*94c4a1e1SFrank Piva 			auto t = remove_last();
76*94c4a1e1SFrank Piva 			return t;
77*94c4a1e1SFrank Piva 		} else {
78*94c4a1e1SFrank Piva 			//throw std::range_error("no cache dropped from put");
79*94c4a1e1SFrank Piva 			return nullptr;
80*94c4a1e1SFrank Piva 		}
81*94c4a1e1SFrank Piva 	}
82*94c4a1e1SFrank Piva 
83*94c4a1e1SFrank Piva 	//just retrieve value without updating position in the lru list
__get(const key_t & key)84*94c4a1e1SFrank Piva 	value_t __get(const key_t& key) {
85*94c4a1e1SFrank Piva 		auto it = _cache_items_map.find(key);
86*94c4a1e1SFrank Piva 		if (it == _cache_items_map.end())
87*94c4a1e1SFrank Piva 			return nullptr;
88*94c4a1e1SFrank Piva 		else
89*94c4a1e1SFrank Piva 			return it->second->second;
90*94c4a1e1SFrank Piva 	}
91*94c4a1e1SFrank Piva 
get(const key_t & key)92*94c4a1e1SFrank Piva 	value_t get(const key_t& key) {
93*94c4a1e1SFrank Piva 		auto it = _cache_items_map.find(key);
94*94c4a1e1SFrank Piva 		if (it == _cache_items_map.end()) {
95*94c4a1e1SFrank Piva 			//throw std::range_error("There is no such key in cache");
96*94c4a1e1SFrank Piva 			return nullptr;
97*94c4a1e1SFrank Piva 		} else {
98*94c4a1e1SFrank Piva 			_cache_items_list.splice(_cache_items_list.begin(), _cache_items_list, it->second);
99*94c4a1e1SFrank Piva 			return it->second->second;
100*94c4a1e1SFrank Piva 		}
101*94c4a1e1SFrank Piva 	}
102*94c4a1e1SFrank Piva 
exists(const key_t & key) const103*94c4a1e1SFrank Piva 	bool exists(const key_t& key) const {
104*94c4a1e1SFrank Piva 		return _cache_items_map.find(key) != _cache_items_map.end();
105*94c4a1e1SFrank Piva 	}
106*94c4a1e1SFrank Piva 
size() const107*94c4a1e1SFrank Piva 	size_t size() const {
108*94c4a1e1SFrank Piva 		return _cache_items_map.size();
109*94c4a1e1SFrank Piva 	}
110*94c4a1e1SFrank Piva 
get_lru_list_ro() const111*94c4a1e1SFrank Piva 	const std::list<key_value_pair_t>& get_lru_list_ro() const {
112*94c4a1e1SFrank Piva 		return _cache_items_list;
113*94c4a1e1SFrank Piva 	}
114*94c4a1e1SFrank Piva 
115*94c4a1e1SFrank Piva private:
116*94c4a1e1SFrank Piva 	std::list<key_value_pair_t> _cache_items_list;
117*94c4a1e1SFrank Piva 	std::unordered_map<key_t, list_iterator_t> _cache_items_map;
118*94c4a1e1SFrank Piva 	size_t _max_size;
119*94c4a1e1SFrank Piva };
120*94c4a1e1SFrank Piva 
121*94c4a1e1SFrank Piva } // namespace cache
122*94c4a1e1SFrank Piva 
123*94c4a1e1SFrank Piva #endif	/* _LRUCACHE_HPP_INCLUDED_ */
124*94c4a1e1SFrank Piva 
125