#include "CentralCache.h"
#include "PageCache.h"
namespace MapleRuntime {
ImmortalWrapper<CentralCache> CentralCache::instance;
Span* CentralCache::GetOneSpan(SpanList& list, size_t alignBytes)
{
CHECK(alignBytes >= MIN_ALIGN_NUM);
Span* it = list.Begin();
while (it != list.End()) {
if (it->freeBlocks != nullptr) {
return it;
} else {
it = it->next;
}
}
Span* span = nullptr;
{
ScopedPageCacheMutex mtx;
span = PageCache::GetInstance()->NewSpan(SizeManager::CalculatePageNum(alignBytes));
span->isUse = true;
}
char* start = reinterpret_cast<char*>(span->pageId << PAGE_SHIFT);
size_t bytes = span->pageNum << PAGE_SHIFT;
char* end = start + bytes;
span->freeBlocks = start;
start += alignBytes;
void* tail = span->freeBlocks;
while (start < end) {
NextObj(tail) = start;
tail = start;
start += alignBytes;
}
NextObj(tail) = nullptr;
list.PushFront(span);
return span;
}
size_t CentralCache::FetchRangeObj(void*& start, void*& end, size_t batchNum, size_t alignBytes)
{
CHECK(batchNum > 0);
CHECK(alignBytes >= MIN_ALIGN_NUM);
size_t index = SizeManager::Index(alignBytes);
centralCacheSpans[index].GetSpanListMutex().lock();
Span* span = GetOneSpan(centralCacheSpans[index], alignBytes);
CHECK(span != nullptr);
CHECK(span->freeBlocks);
start = span->freeBlocks;
end = span->freeBlocks;
size_t actualNum = 1;
while (actualNum < batchNum && NextObj(end)) {
++actualNum;
end = NextObj(end);
}
span->freeBlocks = NextObj(end);
NextObj(end) = nullptr;
span->useCount += actualNum;
centralCacheSpans[index].GetSpanListMutex().unlock();
return actualNum;
}
void CentralCache::ReleaseListToSpans(void* start, size_t index)
{
CHECK(start != nullptr);
centralCacheSpans[index].GetSpanListMutex().lock();
while (start) {
void* next = NextObj(start);
Span* span = PageCache::GetInstance()->MapObjectToSpan(start);
if (span == nullptr) {
start = next;
continue;
}
NextObj(start) = span->freeBlocks;
span->freeBlocks = start;
--span->useCount;
if (span->useCount == 0) {
centralCacheSpans[index].Erase(span);
span->freeBlocks = nullptr;
span->next = nullptr;
span->prev = nullptr;
PageCache::GetInstance()->ReleaseSpanToPageCache(span);
}
start = next;
}
centralCacheSpans[index].GetSpanListMutex().unlock();
}
}