代码拉取完成,页面将自动刷新
#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;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。