三层结构: PageCache: 内存的单位是页,一页的大小是4KB,从操作系统中最多申请128页,维护128个链表,每个链表的每个节点存放对应数量的页。 节点结构体: //记录页的内容 typedef size_t PageID; struct Span{ void *_objlist = nullptr;//分配的地址的头指针 因为分配内存返回的是void*头指针。 Span *_prev = nullptr; //指向前一个对象 Span *_next = nullptr;//指向后一个对象 size_t _pages = 0; //记录有几页 PageID _pageid = 0; //记录开始页号 size_t _objsize = 0; //记录centralCache中每一块的大小 size_t _usecount = 0;//记录被使用了多少块 }; class PageCache{ private : std::mutex _mtx; //多进程需要上锁 SpanList _spanlist[MAXPAGES + 1]; //链表数组,管理不同页数的Span对象 static PageCache _Inst; //创建单例模式所需 Radix<Span *> _page_id_span; //页号与Span对象对应的映射 public: PageCache() = default; //默认构造函数 PageCache(const PageCache&) = delete; //禁止拷贝 PageCache operator = (const PageCache&) = delete; //禁止赋值 static PageCache *GetInstance(){ return &_Inst; } Span *_NewSpan(size_t npage); //从操作系统获取内存,或者从数组链表中获取Span对象返回给NewSpan函数。 Span *NewSpan(size_t npage); //CentralCache从PageCache获取Span对象 void RealeaseSpanToPageCache(Span *span); //合并Span对象 Span *GetIdToSpan(size_t id); //根据页号获取Span对象 }; CentralCache: 从PageCache中获取Span对象,将Span对象连续的页给拆分成固定字节的块,这些块在Span对象里形成链表,给ThreadCache分配块。CentralCache维护Span对象。 内存的基本单位是块,128字节范围内8字节对齐,1024 字节范围内16字节对齐,8*1024字节范围内128字节对齐,64*1024字节范围内1024字节对齐。总共有240种。 CentralCache只是对对象链表上锁,多线程的时候就比全部上锁快。 class CentralCache{ private: static CentralCache _inst; SpanList _spanlists[MAXBLOCKS + 1]; //存放Span对象的链表 public: CentralCache() = default; //默认构造函数 CentralCache(CentralCache &) = delete; //禁止拷贝 CentralCache operator = (CentralCache &) = delete; //禁止赋值 static CentralCache* GetCentralInstance(){ //单例模式 return &_inst; } Span *GetOneSpan(size_t size); //从PageCache中或者CentralCache数组链表中获取Span对象,并且分块。 size_t FetchRangeObj(void *&start,void *&endd,size_t num,size_t size); //ThreadCache向CentralCache中请求num个size字节大小的块,分配来自GetOneSpan对象。 void ReleaseListToSpans(void *start,size_t size); //合并块 }; ThreadCache: 内存单位也是块,和CentralCache中分块范围是一样的。使用某种机制,一下子申请多个内存块。从CentralCache获取void*内存指针,数组链表将维护void*指针。 class ThreadCache{ private: FreeList _freelist[MAXBLOCKS + 1]; public: void *Allocate(size_t sizes); //用户向ThreadCache申请内存。 void *FetchFromCentralCache(size_t index,size_t sizes); //ThreadCache向CentralCache申请内存。 void Deallocte(void *ptr,size_t sizes); //用户释放内存放入FreeList中管理,达到一定条件调用ListTooLong释放内存。 void ListTooLong(FreeList &freelists,size_t num,size_t sizes); //释放内存。 }; 源文件:等找到一个地方放原码之后上传。