]> git.proxmox.com Git - ceph.git/blame - ceph/src/crimson/common/simple_lru.h
import 15.2.0 Octopus source
[ceph.git] / ceph / src / crimson / common / simple_lru.h
CommitLineData
11fdf7f2
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#pragma once
5
6#include <list>
7#include <map>
8#include <optional>
9#include <type_traits>
10#include <unordered_map>
11
12template <class Key, class Value, bool Ordered>
13class SimpleLRU {
14 static_assert(std::is_default_constructible_v<Value>);
15 using list_type = std::list<Key>;
16 template<class K, class V>
17 using map_t = std::conditional_t<Ordered,
18 std::map<K, V>,
19 std::unordered_map<K, V>>;
20 using map_type = map_t<Key, std::pair<Value, typename list_type::iterator>>;
21 list_type lru;
22 map_type cache;
23 const size_t max_size;
24
25public:
26 SimpleLRU(size_t size = 20)
27 : cache(size),
28 max_size(size)
29 {}
30 size_t size() const {
31 return cache.size();
32 }
33 size_t capacity() const {
34 return max_size;
35 }
36 using insert_return_type = std::pair<Value, bool>;
37 insert_return_type insert(const Key& key, Value value);
38 std::optional<Value> find(const Key& key);
39 std::optional<std::enable_if<Ordered, Value>> lower_bound(const Key& key);
40 void erase(const Key& key);
41 void clear();
42private:
43 // bump the item to the front of the lru list
44 Value _lru_add(typename map_type::iterator found);
45 // evict the last element of most recently used list
46 void _evict();
47};
48
49template <class Key, class Value, bool Ordered>
50typename SimpleLRU<Key,Value,Ordered>::insert_return_type
51SimpleLRU<Key,Value,Ordered>::insert(const Key& key, Value value)
52{
53 if constexpr(Ordered) {
54 auto found = cache.lower_bound(key);
55 if (found != cache.end() && found->first == key) {
56 // already exists
57 return {found->second.first, true};
58 } else {
59 if (size() >= capacity()) {
60 _evict();
61 }
62 lru.push_front(key);
63 // use lower_bound as hint to save the lookup
64 cache.emplace_hint(found, key, std::make_pair(value, lru.begin()));
65 return {std::move(value), false};
66 }
67 } else {
68 // cache is not ordered
69 auto found = cache.find(key);
70 if (found != cache.end()) {
71 // already exists
72 return {found->second.first, true};
73 } else {
74 if (size() >= capacity()) {
75 _evict();
76 }
77 lru.push_front(key);
78 cache.emplace(key, std::make_pair(value, lru.begin()));
79 return {std::move(value), false};
80 }
81 }
82}
83
84template <class Key, class Value, bool Ordered>
85std::optional<Value> SimpleLRU<Key,Value,Ordered>::find(const Key& key)
86{
87 if (auto found = cache.find(key); found != cache.end()){
88 return _lru_add(found);
89 } else {
90 return {};
91 }
92}
93
94template <class Key, class Value, bool Ordered>
95std::optional<std::enable_if<Ordered, Value>>
96SimpleLRU<Key,Value,Ordered>::lower_bound(const Key& key)
97{
98 if (auto found = cache.lower_bound(key); found != cache.end()) {
99 return _lru_add(found);
100 } else {
101 return {};
102 }
103}
104
105template <class Key, class Value, bool Ordered>
106void SimpleLRU<Key,Value,Ordered>::clear()
107{
108 lru.clear();
109 cache.clear();
110}
111
112template <class Key, class Value, bool Ordered>
113void SimpleLRU<Key,Value,Ordered>::erase(const Key& key)
114{
115 if (auto found = cache.find(key); found != cache.end()) {
9f95a23c 116 lru.erase(found->second.second);
11fdf7f2
TL
117 cache.erase(found);
118 }
119}
120
121template <class Key, class Value, bool Ordered>
122Value SimpleLRU<Key,Value,Ordered>::_lru_add(
123 typename SimpleLRU<Key,Value,Ordered>::map_type::iterator found)
124{
125 auto& [value, in_lru] = found->second;
126 if (in_lru != lru.begin()){
127 // move item to the front
128 lru.splice(lru.begin(), lru, in_lru);
129 }
130 // the item is already at the front
131 return value;
132}
133
134template <class Key, class Value, bool Ordered>
135void SimpleLRU<Key,Value,Ordered>::_evict()
136{
137 // evict the last element of most recently used list
138 auto last = --lru.end();
139 cache.erase(*last);
140 lru.erase(last);
141}