MiniOB 1
MiniOB is one mini database, helping developers to learn how database works.
载入中...
搜索中...
未找到
lru_cache.h
1/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
2miniob is licensed under Mulan PSL v2.
3You can use this software according to the terms and conditions of the Mulan PSL v2.
4You may obtain a copy of Mulan PSL v2 at:
5 http://license.coscl.org.cn/MulanPSL2
6THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
7EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
8MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
9See the Mulan PSL v2 for more details. */
10
11//
12// Created by Wangyunlai on 2022.09.02
13//
14
15#pragma once
16
17#include "common/lang/functional.h"
18#include "common/lang/unordered_set.h"
19
20namespace common {
21
22template <typename Key, typename Value, typename Hash = hash<Key>, typename Pred = equal_to<Key>>
24{
25
27 {
28 public:
29 Key key_;
30 Value value_;
31
32 ListNode *prev_ = nullptr;
33 ListNode *next_ = nullptr;
34
35 public:
36 ListNode(const Key &key, const Value &value) : key_(key), value_(value) {}
37 };
38
40 {
41 public:
42 size_t operator()(ListNode *node) const
43 {
44 if (node == nullptr) {
45 return 0;
46 }
47 return hasher_(node->key_);
48 }
49
50 private:
51 Hash hasher_;
52 };
53
55 {
56 public:
57 bool operator()(ListNode *const node1, ListNode *const node2) const
58 {
59 if (node1 == node2) {
60 return true;
61 }
62
63 if (node1 == nullptr || node2 == nullptr) {
64 return false;
65 }
66
67 return pred_(node1->key_, node2->key_);
68 }
69
70 private:
71 Pred pred_;
72 };
73
74public:
75 LruCache(size_t reserve = 0)
76 {
77 if (reserve > 0) {
78 searcher_.reserve(reserve);
79 }
80 }
81
82 ~LruCache() { destroy(); }
83
84 void destroy()
85 {
86 for (ListNode *node : searcher_) {
87 delete node;
88 }
89 searcher_.clear();
90
91 lru_front_ = nullptr;
92 lru_tail_ = nullptr;
93 }
94
95 size_t count() const { return searcher_.size(); }
96
97 bool get(const Key &key, Value &value)
98 {
99 auto iter = searcher_.find((ListNode *)&key);
100 if (iter == searcher_.end()) {
101 return false;
102 }
103
104 lru_touch(*iter);
105 value = (*iter)->value_;
106 return true;
107 }
108
109 void put(const Key &key, const Value &value)
110 {
111 auto iter = searcher_.find((ListNode *)&key);
112 if (iter != searcher_.end()) {
113 ListNode *ln = *iter;
114 ln->value_ = value;
115 lru_touch(ln);
116 return;
117 }
118
119 ListNode *ln = new ListNode(key, value);
120 lru_push(ln);
121 }
122
123 void remove(const Key &key)
124 {
125 auto iter = searcher_.find((ListNode *)&key);
126 if (iter != searcher_.end()) {
127 lru_remove(*iter);
128 }
129 }
130
131 void pop(Value *&value)
132 {
133 // TODO
134 value = nullptr;
135 }
136
137 void foreach (function<bool(const Key &, const Value &)> func)
138 {
139 for (ListNode *node = lru_front_; node != nullptr; node = node->next_) {
140 bool ret = func(node->key_, node->value_);
141 if (!ret) {
142 break;
143 }
144 }
145 }
146
147 void foreach_reverse(function<bool(const Key &, const Value &)> func)
148 {
149 for (ListNode *node = lru_tail_; node != nullptr; node = node->prev_) {
150 bool ret = func(node->key_, node->value_);
151 if (!ret) {
152 break;
153 }
154 }
155 }
156
157private:
158 void lru_touch(ListNode *node)
159 {
160 // move node to front
161 if (nullptr == node->prev_) {
162 return;
163 }
164
165 node->prev_->next_ = node->next_;
166
167 if (node->next_ != nullptr) {
168 node->next_->prev_ = node->prev_;
169 } else {
170 lru_tail_ = node->prev_;
171 }
172
173 node->prev_ = nullptr;
174 node->next_ = lru_front_;
175 if (lru_front_ != nullptr) {
176 lru_front_->prev_ = node;
177 }
178 lru_front_ = node;
179 }
180
181 void lru_push(ListNode *node)
182 {
183 // push front
184 if (nullptr == lru_tail_) {
185 lru_tail_ = node;
186 }
187
188 node->prev_ = nullptr;
189 node->next_ = lru_front_;
190 if (lru_front_ != nullptr) {
191 lru_front_->prev_ = node;
192 }
193
194 lru_front_ = node;
195 searcher_.insert(node);
196 }
197
198 void lru_remove(ListNode *node)
199 {
200 if (node->prev_ != nullptr) {
201 node->prev_->next_ = node->next_;
202 }
203
204 if (node->next_ != nullptr) {
205 node->next_->prev_ = node->prev_;
206 }
207
208 if (lru_front_ == node) {
209 lru_front_ = node->next_;
210 }
211 if (lru_tail_ == node) {
212 lru_tail_ = node->prev_;
213 }
214
215 searcher_.erase(node);
216 delete node;
217 }
218
219private:
220 using SearchType = unordered_set<ListNode *, PListNodeHasher, PListNodePredicator>;
221 SearchType searcher_;
222 ListNode *lru_front_ = nullptr;
223 ListNode *lru_tail_ = nullptr;
224};
225
226} // namespace common
属性的值
Definition: value.h:30
Definition: lru_cache.h:27
Definition: lru_cache.h:40
Definition: lru_cache.h:55
Definition: lru_cache.h:24