11 线程资源层内存泄漏的BUG修复

        在之前的设计中,我没有考虑到当一个线程运行结束时,该线程的线程资源层内可能仍有残余资源的问题(残余内存块数量小于线程资源层的回收标准,没有在用户还回内存块的过程中自动归还给中心资源层),并且ThreadCache本身就是定长内存池ObjectPool开辟出来的空间,ThreadCache本身也应该在线程结束时,释放资源回定长内存池。

解决方法:

        通过ThreadCache的析构函数来回收资源,通过智能指针在线程运行结束时自动调用ThreadCache的析构函数。

步骤1:

        将原本每个线程独有的TLS ThreadCache指针变量改为unique_ptr智能指针类型,这样当某个线程运行结束时,就会自动调用ThreadCache的析构函数了。当然,由于ThreadCache的资源不是new出来的,而是向定长内存池ObjectPool申请的,因此必须设计unique_ptr的删除器,在删除器内调用ObjectPool的Delete接口。

#pragma once
#include "tool.hpp"
#include "CentreCache.h"
#include <thread>
class ThreadCache
{
public:
	~ThreadCache();//线程资源层是需要析构函数的,当某个线程运行完毕后,需要释放该线程的线程资源层资源
	void* Allocate(size_t n);
	void DeAllocate(void* ptr,size_t n);
	void* RequestFromCentralCache(size_t index, size_t alignedSize);//申请空间大于256KB时向中心资源曾申请空间,index为桶的编号,alignedsize为桶里所装内存块的大小
	void ThreadCacheListTooLong(FreeList&FList,size_t index,size_t alignedSize);//当线程资源层某个桶里的内存块过多(大于向线程资源层申请空间时一次性允许申请的最多块数时),将桶里目前所有内存块归还给中心资源层(不包括用户还未归还的部分)
private:
	FreeList freelists[BUCKETSIZE];
};
//以下是修改部分
class ThreadCachePool
{
public:
	ThreadCache* GetThreadCache()
	{
		return _ThreadCachePool.New();
	}
	void operator()(ThreadCache* ptr)//删除器
	{
		_ThreadCachePool.Delete(ptr);
	}
private:
	ObjectPool<ThreadCache> _ThreadCachePool;
};
//static _declspec(thread) ThreadCache* pTLSThreadCache = nullptr;//每个线程独有的变量
static _declspec(thread) std::unique_ptr<ThreadCache,ThreadCachePool> pTLSThreadCache;//每个线程独有的智能指针变量,当线程运行完毕后,自动释放该线程所独占的线程资源层资源,ThreadCachePool在这里为删除器,因为ThreadCache不是new出来的,它来自定长内存池,需要配置删除器

 原void* ThisThreadAllocate(size_t n)用户接口内自然也要做相应改动:

#pragma once
#include "ThreadCache.h"
#include "PageCache.h"
//这里函数的作用是对ThreadCache里的接口做封装,使得每个线程都拥有独有的ThreadCache,并使用本文件的函数从自己的ThreadCache里申请空间
void* ThisThreadAllocate(size_t n)
{	
	if (pTLSThreadCache.get() == nullptr)
	{	
		/*static ObjectPool<ThreadCache> ThreadCachePool;*/
		static ThreadCachePool threadCachePool;
		static mutex mt;
		mt.lock();
		/*pTLSThreadCache = ThreadCachePool.New();*/
		pTLSThreadCache = std::unique_ptr<ThreadCache,ThreadCachePool>(threadCachePool.GetThreadCache());
		mt.unlock();
	}
	//..............以下内容未做修改故省略
}

步骤2:设计ThreadCache的析构函数

这步很简单,依次将ThreadCache里的每个桶中的所有内存块归还给中心资源层CentreCache即可。

ThreadCache::~ThreadCache()
{	
	for (int i = 0; i < BUCKETSIZE; i++)//将线程资源层所有桶里的内存块都归还给中心资源层
	{	
		if (!freelists[i].empty())
		{	
			ThreadCacheListTooLong(freelists[i], i, SizeClass::IndexToAlignedSize(i));
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值