加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
CentralCache.cpp 3.61 KB
一键复制 编辑 原始数据 按行查看 历史
mabay 提交于 2023-03-26 19:36 . 调整
#include "CentralCache.h"
#include "PageCache.h"
// 初始化CentralCache
CentralCache CentralCache::_sInst;
// 将_freeList中的小块内存归还给span
void CentralCache::ReleaseListToSpan(void* start, size_t size)
{
// 先找到size对应的桶下标
size_t index = SizeClass::GetBucketIndex(size);
// 要对CentralCache中的桶进行操作,所以需要加锁
_spanLists[index].GetMutex().lock();
while (start)
{
void* next = NextObj(start);
// span每次都更新了吗?频繁调用效率下降
// Span* span = PageCache::GetInstance()->MapObjectToSpan(start);
Span* span = PageCache::GetInstance()->MapObjectToSpan(start);
// 头插过程
NextObj(start) = span->_freeList;
span->_freeList = start;
span->_useCount--;
// 说明span切分出的所有小块内存都回来了
if (span->_useCount == 0)
{
_spanLists[index].Erase(span);
span->_freeList = nullptr;
span->_next = nullptr;
span->_prev = nullptr;
// 释放span还给page,使用PageCache的锁即可
// 解掉桶锁
_spanLists[index].GetMutex().unlock();
PageCache::GetInstance()->GetMutex().lock();
PageCache::GetInstance()->ReleaseSpanToPageCache(span);
PageCache::GetInstance()->GetMutex().unlock();
_spanLists[index].GetMutex().lock();
}
start = next;
}
_spanLists[index].GetMutex().unlock();
}
// 获得一个非空的Span
Span* CentralCache::GetOneSpan(SpanList& list, size_t size) // 获得span
{
// 查看当前的spanlist中是否还有未分配的span
Span* it = list.Begin();
// 如果还有未分配的span
while (it != list.End())
{
if (it->_freeList != nullptr)
{
return it;
}
else
{
it = it->_next;
}
}
// 这里先解掉桶锁
list.GetMutex().unlock();
// 没有未分配的span了,只能找PageCache要
PageCache::GetInstance()->GetMutex().lock();
Span* span = PageCache::GetInstance()->NewSpan(SizeClass::NumMovePage(size));
span->_isUse = true;
span->_objSize = size;
PageCache::GetInstance()->GetMutex().unlock();
list.GetMutex().lock();
// 将要的span进行分割
// 得到页的起始地址
char* start = (char*)(span->_pageId << PAGE_SHIFT);
// 得到大块内存的字节数
size_t bytes = span->_pageNum << PAGE_SHIFT;
char* end = start + bytes;
// 把大块内存切成小块内存,用自由链表连接起来
// 因为_freeList为空,给它一个初始值
span->_freeList = start;
if (start == nullptr)
{
std::cout << "GetSpan error!" << std::endl;
}
// 通过size来控制每一个小块内存的范围
start += size;
// 注意这里的tail
void* tail = span->_freeList;
// size_t k = 0; 统计尾插次数
while (start < end)
{
// tail的下一个为start
NextObj(tail) = start;
// 将tail更新为新的尾
tail = NextObj(tail);
// 调整小块内存
start += size;
// ++k;
}
NextObj(tail) = nullptr;
// 切好span之后,将span挂到桶里去,然后进行加锁
// 头插span
list.PushFront(span);
//list.GetMutex().lock(); //锁要加到上面
return span;
}
size_t CentralCache::FetchRangeObj(void*& start, void*& end, size_t batchNum, size_t size)
{
size_t index = SizeClass::GetBucketIndex(size);
// 加桶锁
_spanLists[index].GetMutex().lock();
Span* span = GetOneSpan(_spanLists[index], size);
assert(span);
assert(span->_freeList);
start = span->_freeList;
end = start;
size_t actualNum = 1;
size_t i = 0;
// 头删,如果不够有多少拿多少
while (actualNum < batchNum && NextObj(end) != nullptr)
{
end = NextObj(end);
++actualNum;
}
span->_freeList = NextObj(end);
NextObj(end) = nullptr;
span->_useCount += actualNum;
_spanLists[index].GetMutex().unlock();
return actualNum;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化