forked from HONGYU-LEE/Window-TinyLFU-Cache
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSegmentLRUCache.hpp
121 lines (91 loc) · 2.89 KB
/
SegmentLRUCache.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#pragma once
#include "LRU.hpp"
template<typename T>
class SegmentLRUCache
{
public:
typedef LRUNode<T> LRUNode;
explicit SegmentLRUCache(size_t probationCapacity, size_t protectionCapacity)
: _probationCapacity(probationCapacity)
, _protectionCapacity(protectionCapacity)
, _hashmap(probationCapacity + protectionCapacity)
{}
std::pair<LRUNode, bool> get(LRUNode& node)
{
//找不到则返回空
auto res = _hashmap.find(node._key);
if (res == _hashmap.end())
{
return std::make_pair(LRUNode(), false);
}
//获取数据的位置
typename std::list<LRUNode>::iterator pos = res->second;
//如果查找的值在PROTECTION区中,则直接移动到首部
if (node._flag == PROTECTION)
{
_protectionList.erase(pos);
_protectionList.push_front(node);
res->second = _protectionList.begin();
return std::make_pair(node, true);
}
//如果是PROBATION区的数据,如果PROTECTION还有空位,则将其移过去
if (_protectionList.size() < _probationCapacity)
{
node._flag = PROTECTION;
_probationList.erase(pos);
_protectionList.push_front(node);
res->second = _protectionList.begin();
return std::make_pair(node, true);
}
//如果PROTECTION没有空位,此时就将其最后一个与PROBATION当前元素进行交换位置
LRUNode backNode = _protectionList.back();
std::swap(backNode._flag, node._flag);
_probationList.erase(_hashmap[node._key]);
_protectionList.erase(_hashmap[backNode._key]);
_probationList.push_front(backNode);
_protectionList.push_front(node);
_hashmap[backNode._key] = _probationList.begin();
_hashmap[node._key] = _protectionList.begin();
return std::make_pair(node, true);
}
std::pair<LRUNode, bool> put(LRUNode& newNode)
{
//新节点放入PROBATION段中
newNode._flag = PROBATION;
LRUNode delNode;
//如果还有剩余空间就直接插入
if (_probationList.size() < _probationCapacity || size() < _probationCapacity + _protectionCapacity)
{
_probationList.push_front(newNode);
_hashmap.insert(make_pair(newNode._key, _probationList.begin()));
return std::make_pair(delNode, false);
}
//如果没有剩余空间,就需要淘汰掉末尾元素,然后再将元素插入首部
delNode = _probationList.back();
_hashmap.erase(delNode._key);
_probationList.pop_back();
_probationList.push_front(newNode);
_hashmap.insert(make_pair(newNode._key, _probationList.begin()));
return std::make_pair(delNode, true);
}
std::pair<LRUNode, bool> victim()
{
//如果还有剩余的空间,就不需要淘汰
if (_probationCapacity + _protectionCapacity > size())
{
return std::make_pair(LRUNode(), false);
}
//否则淘汰_probationList的最后一个元素
return std::make_pair(_probationList.back(), true);
}
int size() const
{
return _protectionList.size() + _probationList.size();
}
private:
size_t _probationCapacity;
size_t _protectionCapacity;
std::unordered_map<int, typename std::list<LRUNode>::iterator> _hashmap;
std::list<LRUNode> _probationList;
std::list<LRUNode> _protectionList;
};