-
Notifications
You must be signed in to change notification settings - Fork 0
/
CentralCache.cpp
102 lines (81 loc) · 2.08 KB
/
CentralCache.cpp
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
#include "CentralCache.h"
#include "PageCache.h"
CentralCache CentralCache::_sInst;
Span* CentralCache::GetOneSpan(SpanList& list, size_t size)
{
// 现在spanlist中去找还有内存的span
Span* it = list.Begin();
while (it != list.End())
{
if (it->_list)
{
return it;
}
it = it->_next;
}
// 走到这里代表着span都没有内存了,只能找pageCache
Span* span = PageCache::GetInstance()->NewSpan(SizeClass::NumMovePage(size));
// 切分好挂在list中
char* start = (char*)(span->_pageId << PAGE_SHIFT);
char* end = start + (span->_n << PAGE_SHIFT);
while (start < end)
{
char* next = start + size;
// 头插
NextObj(start) = span->_list;
span->_list = start;
start = next;
}
span->_objsize = size;
list.PushFront(span);
return span;
}
size_t CentralCache::FetchRangeObj(void*& start, void*& end, size_t n, size_t size)
{
size_t i = SizeClass::Index(size);
//_spanLists[i].Lock();
std::lock_guard<std::mutex> lock(_spanLists[i]._mtx);
Span* span = GetOneSpan(_spanLists[i], size);
// 找到一个有对象的span,有多少给多少
// 有n个给n个,没有n个,有多少给多少
size_t j = 1;
start = span->_list;
void* cur = start;
void* prev = start;
while (j <= n && cur != nullptr)
{
prev = cur;
cur = NextObj(cur);
++j;
span->_usecount++;// 每在span中取走一个对象就++
}
span->_list = cur;
end = prev;
NextObj(prev) = nullptr;
//_spanLists[i].Unlock();
return j - 1;
}
void CentralCache::ReleaseListToSpans(void* start, size_t byte_size)
{
size_t i = SizeClass::Index(byte_size);// 一定属于_spanLists[i],但不知道属于这个里面的哪一个span
std::lock_guard<std::mutex> lock(_spanLists[i]._mtx);
while (start)
{
void* next = NextObj(start);
// 找start内存块属于哪个span
Span* span = PageCache::GetInstance()->MapObjectToSpan(start);
// 把对象插入到span管理的list中
NextObj(start) = span->_list;
span->_list = start;
span->_usecount--;
// _usecount == 0说明这个span中切出去的大块内存
// 都换回来了
if (span->_usecount == 0)
{
_spanLists[i].Erase(span);
span->_list = nullptr;
PageCache::GetInstance()->ReleaseSpanToPageCache(span);
}
start = next;
}
}