源码分享:C++高性能的内存池实现。内存预分配,非复制构造,全局内存池。

10 篇文章 1 订阅
9 篇文章 0 订阅
为了实现面向对象编程,对于的复杂型结构快速构造与释放,写了个内存池管理模板。他特点是允许用户放弃内存池生成对象使用权,而不是执行析构。实现对象的复用。
  1. 实现同类型对象的全局化管理。无需显示构造内存池。采用newOne宏申请对象。
  2. 内存块的大小可调。内存池状态可输出显示。
  3. 采用内存预分配方式。对象构造采用原始构造,非动态申请和复制构造,提高速度。
  4. 加锁,实现多线程支持。(加锁会额外耗费cpu时间,可设置宏CLMP_USE_LOCK_TYPE ,决定采用哪种方案)
#define CLMP_USE_LOCK_TYPE 0 // 0=无锁(快),1=用C++锁(慢),2=用windows临界区锁
  1. 通过giveUpOne()方法,放弃对象使用权,不需要释放对象,实现快速对象复用。

演示代码:应用案例: 【C++高速矩阵类实现】.

//定义任意类型,其构造含有动态内存的申请。
struct MyStruct
{
	int * c;
	string name;
	MyStruct(const char* lpName = "" )
		:c(new int[100]) , name(lpName)
	{	
		cout << "\nMyStruct 构造!: " << name << endl;
	}
	~MyStruct() {
		delete[] c;
		cout << "\nMyStruct 析构!  " << name << endl;
	}
};


int main() {

	auto p1 = newOne(MyStruct,"p1"); //申请一个对象,命名未p1

	giveUpOne(p1); //放弃使用权,不执行对象析构

	auto p2 = newOne(MyStruct,"p2"); //申请第二个对象,命名未p2

	if (p1 == p2) //由于giveUpOne调用,前后两次newOne产生复用
		cout << "\np2 获得了复用对象: " << p2->name << endl; 

	auto p3 = newOne(MyStruct, "p3"); //再申请一个对象
	
	// ...
	//使用完成后释放对象,归还到内存池
	deleteOne(p1); // 注意:此处应该避免继续使用p1,因为他意见显示放弃了使用权。
	deleteOne(p2); // 因为p2与p1保存同一个对象指针,不会重复释放。
	deleteOne(p3);

	getchar();
	return 1;

运行结果:
在这里插入图片描述
模板库头源码:
CLMemPool.h

//DESIGNED BY CAILUO @2020-02-10 
//MINI-SUPPORT @ C++14

#pragma once

#ifndef __CL_MEMPOOL_H__
#define __CL_MEMPOOL_H__

#include <cassert>
#include <map>
#include <string>
#include <stdexcept>

#define CLMP_USE_LOCK_TYPE 0 // 0=无锁(快),1=用C++锁(慢),2=用windows临界区锁

#if CLMP_USE_LOCK_TYPE == 2
#include "windows.h" //windows平台,临界区
class CLLock {
private:
	CRITICAL_SECTION cs;
public:
	CLLock() { InitializeCriticalSection(&cs); }
	~CLLock() { DeleteCriticalSection(&cs); }
	void lock() { EnterCriticalSection(&cs); }
	void unlock() { LeaveCriticalSection(&cs); }
};
#elif CLMP_USE_LOCK_TYPE == 1
#include <mutex> // C++ STL mutex
class CLLock {
private:
	std::mutex mt;
public:
	void lock() { mt.lock(); }
	void unlock() { mt.unlock(); }
};
#else
class CLLock {  //no use lock, it do nothing
public:
	void lock() {} 
	void unlock() {} 
};
#endif

#ifndef _CL_DIFVARS_SUPPORT_
#define _CL_DIFVARS_SUPPORT_
#ifdef UNICODE
typedef wchar_t Char;
#define tstring wstring
#ifndef _T
#define _T(x)  L ## x
#endif
#ifndef _tprintf_s
#define _tprintf_s wprintf_s
#define _stprintf_s swprintf_s
#define _tcscpy_s wcscpy_s
#endif
#else
typedef char Char;
#define tstring string
#ifndef _T
#define _T(x)  x
#endif
#ifndef _tprintf_s
#define _tprintf_s printf_s
#define _stprintf_s sprintf_s
#define _tcscpy_s strcpy_s
#endif
#endif
typedef const Char* PCStr;
typedef Char* PStr;
#ifndef BUFSIZE
#define BUFSIZE 256
#endif
#ifndef max
#define max(a,b) ((a) < (b) ? (b) : (a))
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
#endif

template <typename classTag>
class CLMemPoolBlock;

template <typename classTag>
class CLMemPool;

内存池表类型
class MemPoolsTable
	:public std::map< CLMemPool<void*>*, std::tstring>,
	public CLLock
{};
//取得内存池表
inline MemPoolsTable* getMemPoolsTable() {
	static MemPoolsTable _mplst;
	return &_mplst;
}
增加内存池到内存池表
inline void addMemPoolToTable(PCStr name, CLMemPool<void*>* pMemPool)
{
	getMemPoolsTable()->lock();
	(*getMemPoolsTable())[pMemPool] = (name == nullptr ? _T("") : name);
	getMemPoolsTable()->unlock();
}

//内存池对象单元模板类
template <typename classTag>
class CLMemPoolUnit {
	friend class CLMemPool<classTag>;
	friend class CLMemPoolBlock<classTag>;
public:
	struct DataHead {
		CLMemPoolUnit<classTag>* pPre;
		CLMemPoolUnit<classTag>* pNext;
		CLMemPoolBlock<classTag>* pThisBlock;
		bool bIsCreate;
		bool bIsUsed;
	};
private:
	DataHead hdr;
	classTag data;//包裹数据对象

	//在构造时候显示调用
	CLMemPoolUnit<classTag>* init(
		CLMemPoolBlock<classTag>* _pThisBlock = 0,
		CLMemPoolUnit<classTag>* _pPre = 0,
		CLMemPoolUnit<classTag>* _pNext = 0,
		bool _isCreate = false,
		bool _isUsed = false
	) { 
		hdr.pThisBlock = _pThisBlock;
		hdr.pPre = _pPre;
		hdr.pNext = _pNext;
		hdr.bIsCreate = _isCreate;
		hdr.bIsUsed = _isUsed;
		return this; 
	}
	//注意:构造和析构函数用于显示的调用来构造和析构内部包裹对象
	//他们不应该被系统调用,且内部不能有任何的数据处理过程;
	CLMemPoolUnit(){}
	template <typename... Args>
	CLMemPoolUnit(Args&&... args):data(std::forward<Args>(args)...){}
	~CLMemPoolUnit() {}
public:
	inline CLMemPoolBlock<classTag>* getOwnerBlock() {return hdr.pThisBlock;}
};

#define MUHEARDER( classTag, pData )  ((CLMemPoolUnit<classTag>*)(((char*)(pData))-(sizeof(CLMemPoolUnit<classTag>::DataHead))))

//内存池内存块对象模板类
template <typename classTag>
class CLMemPoolBlock {
	friend class CLMemPool<classTag>;
	friend class CLMemPoolUnit<classTag>;
private:
	explicit CLMemPoolBlock(size_t PerBlockMemCapacity_MB , CLMemPool<classTag>* _pOwnerMemPool)
	:pOwnerMemPool(_pOwnerMemPool)
	{
		init();
		alloc(PerBlockMemCapacity_MB * 1024 * 1024 / sizeof(CLMemPoolUnit<classTag>));
	}
	virtual ~CLMemPoolBlock() {
		releaseObjMenBlock();
	}
	//判断该内存块是否存在可用单元
	inline bool isUsable() {
		return pUsableLst ? true : false;
	}
	//将对象指针回收进入内存块单元,如果对象是已经构造过的就调用标准析构。
	CLMemPoolUnit<classTag>* freeOneData(CLMemPoolUnit<classTag>* pUnit) {
		assert(pUnit !=nullptr);
		//执行对象析构
		if (pUnit->hdr.bIsCreate) {
			pUnit->CLMemPoolUnit<classTag>::~CLMemPoolUnit();
			pUnit->hdr.bIsCreate = false;
			nHasCreatedCounts--;
		}
		return putToUsable(pUnit);
	}
	//将对象指针回收进入内存块单元,而不调用析构
	CLMemPoolUnit<classTag>* giveUpOneData(CLMemPoolUnit<classTag>* pUnit) {
		assert(pUnit != nullptr);
		//不执行对象析构,直接放入未用连条
		return putToUsable(pUnit);
	}
	//取出一个待命可用的对象单元,返回其构造后的对象指针。注意:若申请时的当前分配对象已构造,则忽略构造传参。
	template <typename... Args>
	classTag* getOneData(Args&&... args) {
		assert(pUsableLst != nullptr);
		if(!pUsableLst->hdr.bIsCreate) {
			//执行对象默认构造,这会构造内部包裹的数据类
			pUsableLst->CLMemPoolUnit<classTag>::CLMemPoolUnit(std::forward<Args>(args)...);
			pUsableLst->hdr.bIsCreate = true;
			nHasCreatedCounts++;
		}
		return putToUnusable(pUsableLst);
	}
	inline void init() {
		pUsableLst = 0;
		nMaxUsable = 0;
		pUnusableLst = 0;
		nMaxUnusable = 0;
		nHasCreatedCounts = 0;
		pPre = 0;
		pNext = 0;
		pMainDataLst = 0;
		nMaxDataCounts = 0;
	}
	//分配内存
	void alloc(size_t unitCounts = 1) {
		assert(pMainDataLst == 0 && pUsableLst == 0 && pUnusableLst == 0);
		if (pMainDataLst == 0) {
			//第一次申请内存空间
			pMainDataLst = (CLMemPoolUnit<classTag> *)malloc(sizeof(CLMemPoolUnit<classTag>)*(nMaxDataCounts = nMaxUsable = (unitCounts == 0 ? 1 : unitCounts)));
			//第一次执行可用队列的初始化连接工作
			pUsableLst = &pMainDataLst[0];
			pMainDataLst[0].init(this, 0, nMaxDataCounts <= 1 ? 0 : &pMainDataLst[1]);
			for (size_t i = 1; i < nMaxDataCounts-1; ++i) {
				pMainDataLst[i].init(this, &pMainDataLst[i-1], &pMainDataLst[i + 1]);
			}
			pMainDataLst[nMaxDataCounts - 1].init(this, nMaxDataCounts <= 1 ? 0 : &pMainDataLst[nMaxDataCounts - 2], 0);
		}
	};
	//析构所有已经构造过的对象,但没有使用的对象。
	void distructCreatedUsable() {
		if (nHasCreatedCounts == 0)
			return;
		//析构所有在可用连中的已构造
		for (CLMemPoolUnit<classTag>* pc = pUsableLst; pc != nullptr; ) {
			if (pc->hdr.bIsCreate) {
				pc->CLMemPoolUnit<classTag>::~CLMemPoolUnit();
				pc->hdr.bIsCreate = false;
				nHasCreatedCounts--;
			}
			pc = pc->hdr.pNext;
		}
	}
	//释放内存
	void releaseObjMenBlock() {
		if (pMainDataLst) {
			//析构所有已使用的对象
			for (CLMemPoolUnit<classTag>* pc = pUnusableLst; pc != nullptr; ) {			
				pUnusableLst = freeOneData(pc);
				pc->init();
				pc = pUnusableLst;
			}
			//释放动态内存
			free(pMainDataLst);
			pMainDataLst = 0;
		}		
	}
	//处理前后连接,隔离对象,返回原对象指针
#define _extruct_pUnitBlock(pUnit) \
		((((pUnit)->pPre) ? ((pUnit)->pPre->pNext = (pUnit)->pNext) : 0),(((pUnit)->pNext)?((pUnit)->pNext->pPre = (pUnit)->pPre):0),(pUnit))
#define _extruct_pUnit(pUnit) \
		((((pUnit)->hdr.pPre) ? ((pUnit)->hdr.pPre->hdr.pNext = (pUnit)->hdr.pNext) : 0),(((pUnit)->hdr.pNext)?((pUnit)->hdr.pNext->hdr.pPre = (pUnit)->hdr.pPre):0),(pUnit))
	//对象放入可用队列头,返回不可用队列头指针
	CLMemPoolUnit<classTag>*  putToUsable(CLMemPoolUnit<classTag>* pUnit) {
		assert(this == pUnit->hdr.pThisBlock);
		pUnit->hdr.bIsUsed = false;
		//处理不可用列表头
		if (pUnusableLst && pUnusableLst == pUnit)
			pUnusableLst = pUnit->hdr.pNext;

		//处理前后连接,隔离对象
		_extruct_pUnit(pUnit);

		//接入可用列表
		if (pUsableLst) {pUsableLst->hdr.pPre = pUnit;}
		pUnit->hdr.pNext = pUsableLst;
		pUnit->hdr.pPre = 0;
		pUsableLst = pUnit;
		nMaxUnusable -= 1;
		nMaxUsable += 1;
		return pUnusableLst;
	}

	//返回可用对象指针
	classTag*  putToUnusable(CLMemPoolUnit<classTag>* pUnit) {
		assert(this == pUnit->hdr.pThisBlock);
		pUnit->hdr.bIsUsed = true;
		//处理可用列表头
		if (pUsableLst && pUsableLst == pUnit)
			pUsableLst = pUnit->hdr.pNext;

		//处理前后连接,隔离对象
		_extruct_pUnit(pUnit);
		
		//接入不可用列表
		if (pUnusableLst) {	pUnusableLst->hdr.pPre = pUnit;}
		pUnit->hdr.pNext = pUnusableLst;
		pUnit->hdr.pPre = 0;
		pUnusableLst = pUnit;
		nMaxUnusable += 1;
		nMaxUsable -= 1;
		return &pUnit->data;
	}
	CLMemPool<classTag>* const pOwnerMemPool; //所属内存池
	CLMemPoolUnit<classTag>* pMainDataLst;//内存队列
	size_t nMaxDataCounts;
	CLMemPoolUnit<classTag>* pUsableLst;//可用列表
	size_t nMaxUsable;
	CLMemPoolUnit<classTag>* pUnusableLst;//不可用列表
	size_t nMaxUnusable;
	size_t nHasCreatedCounts;
	CLMemPoolBlock<classTag>* pPre;
	CLMemPoolBlock<classTag>* pNext;
public:
	inline CLMemPool<classTag>* getOwnerMemPool() {	return pOwnerMemPool;}
};

//标准化接口
class IMenPool{
public:
	virtual void arrangement(bool) = 0;
	virtual void deallocateOne(void*) = 0;
	virtual void giveUpOne(void*) = 0;
};

//内存池对象模板类。
 //请使用静态的getMemPool()方法获取唯一的内存池对象。
template <typename classTag> 
class CLMemPool :public IMenPool,public CLLock {
	friend class CLMemPoolBlock<classTag>; 
	friend class CLMemPoolUnit<classTag>;
private:
	//构造带名称标识的目标类型内存池,加入内存池表。请勿显示调用该构造方法。
	//请使用静态的getMemPool()方法获取唯一的内存池对象。
	CLMemPool(PCStr _lpTypeName, size_t PerBlockMemCapacity_MB = 5) :
		pEntry(nullptr),
		pCurrentUsingBlock(nullptr)
	{
		setPerBlockMemCapacity(PerBlockMemCapacity_MB);
		setMemPoolTypeName(_lpTypeName);
	}
	//构造目标类型内存池,加入内存池表。请勿显示调用该构造方法。
	//请使用静态的getMemPool()方法获取唯一的内存池对象。	
	CLMemPool(size_t PerBlockMemCapacity_MB = 5) :
		pEntry(nullptr),
		pCurrentUsingBlock(nullptr)
	{
		setPerBlockMemCapacity(PerBlockMemCapacity_MB);
		setMemPoolTypeName(nullptr);
	}
public:
	PCStr lpTypeName;	
	virtual ~CLMemPool() {
		//不要释放任何内存,而是做一次整理
		arrangement();
		getMemPoolsTable()->lock();
		for (auto  i = ::getMemPoolsTable()->find((CLMemPool<void*>*)this); 
			i != ::getMemPoolsTable()->end(); ){
			::getMemPoolsTable()->erase(i);
			break;
		} 
		getMemPoolsTable()->unlock();
	}
	void setMemPoolTypeName(PCStr _lpTypeName) {
		lpTypeName = _lpTypeName ;
		::addMemPoolToTable(lpTypeName, (CLMemPool<void*>*)this);//构造之后加入队列
	}
	//整理内存,释放当前没有使用的空间归还系统。该函数用于内存池反复使用后占用较大资源后做一次统一释放。
	//distructCreatedButNoUsed = true 表示析构未被使用但已构造的对象
	virtual void arrangement(bool distructCreatedButNoUsed = true) {
		lock();
		pCurrentUsingBlock = nullptr;	//	置0
		for (CLMemPoolBlock<classTag>* pi = pEntry; pi != nullptr; )
		{
			CLMemPoolBlock<classTag>* pib = pi->pNext;
			if (distructCreatedButNoUsed)//是否析构未用对象
				pi->distructCreatedUsable();
			if (pi->nMaxUnusable == 0 && pi->nHasCreatedCounts == 0) { //释放条件,没有被使用,没有已构造
				if (pEntry == pi)
					pEntry = pi->pNext;
				delete _extruct_pUnitBlock(pi);
			}
			pi = pib;
		}
		unlock();
	}
	//强行释放所有内存。
	virtual void releaseObjMenPool() {
		lock();
		for (CLMemPoolBlock<classTag>* pi = pEntry; pi != nullptr; )
		{
			pCurrentUsingBlock = pi->pNext;
			delete pi; // 释放块
			pi = pCurrentUsingBlock;
		}
		m_PerBlockMemCapacity = 0;
		pEntry = 0;
		pCurrentUsingBlock = 0;
		unlock();
	}
	//向内存池储备内存动态申请一个对象,若对象是已经构造过,就返回指针,如果未构造,先构造并返回其对象指针。
	//该方法接受可变参数构造方式传参。
	//注意:若申请时的当前分配对象已构造过(比如:是由giveUpOne()放弃使用权而回收的对象),则忽略本次构造传参。
	template <typename... Args>
	classTag* allocateOne(Args&&... args) {
		lock();		
		classTag* rt = getAvailableBlock()->getOneData(std::forward<Args>(args)...);
		unlock();
		return rt;
	}
	//向内存池释放一个动态申请的对象,进行相关析构操作。
	virtual void deallocateOne(void* pDelete) {
		CLMemPoolUnit<classTag>* pUnit = MUHEARDER(classTag,pDelete);
		if(!checkPtrValidity(pUnit))return;//指针非法即返回或抛异常
		lock();
		pUnit->hdr.pThisBlock->freeOneData(pUnit);
		unlock();
	}
	//向内存池释放一个动态申请的对象,不析构。
	virtual void giveUpOne(void* pDelete) {
		CLMemPoolUnit<classTag>* pUnit = MUHEARDER(classTag, pDelete);
		if (!checkPtrValidity(pUnit))return;//指针非法即返回或抛异常
		lock();
		pUnit->hdr.pThisBlock->giveUpOneData(pUnit);
		unlock();
	}
	//判断指针是否属于本内存池构造
	bool checkPtrValidity(CLMemPoolUnit<classTag>* pUnit){
		if(pUnit->hdr.pThisBlock->pOwnerMemPool != this)
			throw std::runtime_error("Tag obj is not created by this mem pool!");
		//if(pUnit < pUnit->hdr.pThisBlock->pMainDataLst || pUnit > pUnit->hdr.pThisBlock->pMainDataLst + pUnit->hdr.pThisBlock->nMaxDataCounts - 1)
		//	throw std::runtime_error("Tag obj is not created by this mem pool!");
		if (!pUnit->hdr.bIsUsed) {			
#ifdef _DEBUG
			if(pUnit->hdr.bIsCreate)
				throw std::runtime_error("Tag obj has been give up!");
			else
				throw std::runtime_error("Tag obj has been distructed!");
#else
			return false;
#endif
		}
		return true;
	}
	//设置单个内存块的大小,单位MB,默认5MB
	virtual void setPerBlockMemCapacity(size_t PerBlockMemCapacity_MB = 5) {
		lock();
		m_PerBlockMemCapacity = PerBlockMemCapacity_MB == 0 ? 1 : PerBlockMemCapacity_MB;
		unlock();
	}
	//统计内存使用量,并控制向控台输出当前内存池的内存使用情况。
	//bLog = true表示输出信息到控制台否则只统计内存使用量,bDeTail = false表示采用简化输出,outInfoString动态信息字符串内容需要手动释放
	virtual size_t dumpInfo(bool bLog = true, bool bDeTail = false,PStr* outInfoString = nullptr) {
		std::tstring strAll;
#define dumpInfoMax 1000
		Char tem[dumpInfoMax];
		if (bLog || outInfoString) {
			if (bDeTail)
				_stprintf_s(tem, dumpInfoMax,_T("\r\n>>The MemmeryPool(=%s) Dumper Detail----------------------------------- \r\n>>MemBlock Info:\r\n"),(lpTypeName ? lpTypeName:_T("#UnkownTypeName")));
			else
				_stprintf_s(tem, dumpInfoMax,_T("\r\n>>The MemmeryPool(=%s) Dumper Simple----------------------------------- \r\n"), (lpTypeName ? lpTypeName : _T("#UnkownTypeName")));
			strAll += tem;
		}
		size_t si = 0;
		size_t siu = 0;
		size_t sit = 0;
		lock();
		for (const CLMemPoolBlock<classTag>* pc = pEntry; pc; )
		{
			si++;
			siu += pc->nMaxUnusable;
			sit += pc->nMaxDataCounts;
			size_t n = pc->nMaxDataCounts == 0 ? 0 : (pc->nMaxUnusable * 50) / pc->nMaxDataCounts;
			if ((bLog || outInfoString) && bDeTail) {
				_stprintf_s(tem, dumpInfoMax,_T(">>MemBlock(%zd): ["), si); strAll += tem;
				for (size_t i = 0; i < 50; ++i)
				{
					if (i < n)_stprintf_s(tem, dumpInfoMax,_T("*"));
					else _stprintf_s(tem, dumpInfoMax,_T("-"));
					strAll += tem;
				}
				_stprintf_s(tem, dumpInfoMax,_T("] <used=%zd%%>\r\n"), n * 2);
				strAll += tem;
			}
			pc = pc->pNext;
		}
		unlock();
		size_t perObj = sizeof(CLMemPoolUnit<classTag>);
		size_t mem = perObj*sit + si*sizeof(CLMemPoolBlock<classTag>);
		if (bLog || outInfoString) {
			size_t Tb = 0, Gb = 0, Mb = 0, Kb = 0, Byte = 0;
			Kb = mem / 1024; Byte = mem % 1024;
			Mb = Kb / 1024; Kb = Kb % 1024;
			Gb = Mb / 1024; Mb = Mb % 1024;
			Tb = Gb / 1024; Gb = Gb % 1024;
			if (Tb > 0)
				_stprintf_s(tem, dumpInfoMax,_T(">>Summary: mem= %zdT %zdG %zdM %zdK %zdB, blocks=%zd, total=%zd, used=%zd.\r\n\r\n"), Tb, Gb, Mb, Kb, Byte,  si, sit, siu);
			else if (Gb > 0)
				_stprintf_s(tem, dumpInfoMax,_T(">>Summary: mem= %zdG %zdM %zdK %zdB, blocks=%zd, total=%zd, used=%zd.\r\n\r\n"), Gb, Mb, Kb, Byte,  si, sit, siu);
			else if (Mb > 0)
				_stprintf_s(tem, dumpInfoMax,_T(">>Summary: mem= %zdM %zdK %zdB, blocks=%zd, total=%zd, used=%zd.\r\n\r\n"), Mb, Kb, Byte,  si, sit, siu);
			else if (Kb > 0)
				_stprintf_s(tem, dumpInfoMax,_T(">>Summary: mem= %zdK %zdB, blocks=%zd ,total=%zd, used=%zd.\r\n\r\n"), Kb, Byte,  si, sit, siu);
			else
				_stprintf_s(tem, dumpInfoMax,_T(">>Summary: mem= %zdB, blocks=%zd, total=%zd, used=%zd.\r\n\r\n"), Byte,  si, sit, siu);
			strAll += tem;
		}
		if (bLog)
			_tprintf_s(_T("%s"),strAll.c_str());
		if (outInfoString) {
			size_t nn = strAll.length() + 1;
			*outInfoString = new Char[nn];
			_tcscpy_s(*outInfoString, nn, strAll.c_str());
		}
		return mem;
	}
	//返回内存使用量bytes
	size_t getMemSize() const { return dumpInfo(false, false, nullptr); }
private:
	CLMemPoolBlock<classTag>* pEntry;
	CLMemPoolBlock<classTag>* pCurrentUsingBlock;
	size_t m_PerBlockMemCapacity;

	//检索列表取得可用的块,没有就创建
	CLMemPoolBlock<classTag>* getAvailableBlock() {
		if (pCurrentUsingBlock == nullptr) {
			if (pEntry == nullptr) {
				pCurrentUsingBlock = pEntry = new CLMemPoolBlock<classTag>(m_PerBlockMemCapacity, this);
			}
			else pCurrentUsingBlock = pEntry;
		}
		CLMemPoolBlock<classTag>* pStartBlock = pCurrentUsingBlock;
		//检索可用的块
		for (; pCurrentUsingBlock->isUsable() == false;)
		{
			if (pCurrentUsingBlock->pNext == nullptr) {
				if (pCurrentUsingBlock != pEntry) {
					pCurrentUsingBlock = pEntry;
				}
				else {
					pStartBlock = new CLMemPoolBlock<classTag>(m_PerBlockMemCapacity, this);
					if (pEntry->pNext)
						pEntry->pNext->pPre = pStartBlock;
					pStartBlock->pNext = pEntry->pNext;
					pEntry->pNext = pStartBlock;
					pCurrentUsingBlock = pStartBlock;
				}
			}
			else if (pCurrentUsingBlock->pNext == pStartBlock) {//插入新块,在队列中
				pStartBlock = new CLMemPoolBlock<classTag>(m_PerBlockMemCapacity, this);
				if (pCurrentUsingBlock->pNext)
					pCurrentUsingBlock->pNext->pPre = pStartBlock;
				pStartBlock->pNext = pCurrentUsingBlock->pNext;
				pCurrentUsingBlock->pNext = pStartBlock;
				pCurrentUsingBlock = pStartBlock;
			}
			else pCurrentUsingBlock = pCurrentUsingBlock->pNext;
		}
		return pCurrentUsingBlock;
	}
public:
	//取得类型对应的内存池对象
	static CLMemPool* getMenPool() {
		static CLMemPool _MenPool;
		return &_MenPool;
	}
	static CLMemPool* getMenPool(PCStr typeName) {
		CLMemPool* pc = getMenPool();
		if (pc->lpTypeName == nullptr && typeName != nullptr) {
			pc->setMemPoolTypeName(typeName);
		}
		return pc;
	}
	//向内存池动态申请一个对象,返回对象指针。对应的,该指针必须用deleteOne释放。也可用giveUpOne放弃使用权(该方式不执行对象析构)。
	//注意:若申请时的当前分配对象已构造过(比如:是由giveUpOne()放弃使用权而回收的对象),则忽略本次构造传参。
	template <typename... Args>
	static classTag* newOneFromCLMemPool(PCStr name = nullptr, Args&&... args) {
		return (classTag*)getMenPool(name)->allocateOne(std::forward<Args>(args)...);
	}	
	//设置内存池中内存块当个最大内存占用大小,单位MB
	static void setMemPoolBlockCapacity(size_t mb = 5) {
		assert(mb != 0);
		getMenPool()->setPerBlockMemCapacity(mb);
	}
};

//将由newOne获得的对象指针释放回内存池,会做相关析构操作。
inline void deleteOneBackToCLMemPool(void* pDelete) {
	assert(pDelete != nullptr);
	MUHEARDER(void*, pDelete)->getOwnerBlock()->getOwnerMemPool()->deallocateOne(pDelete);
}
//将由newOne获得的对象指针放弃操作权,归还放回内存池,但是不做析构操作。
inline void giveUpOneBackToCLMemPool(void* pDelete) {
	assert(pDelete != nullptr);
	MUHEARDER(void*, pDelete)->getOwnerBlock()->getOwnerMemPool()->giveUpOne(pDelete);
}

//目的:构造保存typeName类型的内存池(如果未构造过的话),并返回构造后的对象指针;
//作用:他向内存池动态申请一个对象(第一个参数是申请的类型,第二个参数可以是可变数量的构造参数),返回对象指针。
//方法:对应的,该方法返回的指针必须用deleteOne释放,也可用giveUpOne放弃使用权(giveUpOne方式不执行对象析构,只是把对象原样放回内存池)。
//注意:该内存池采用预分配机制,可以高速的完成读写,但无法分配连续数量的对象(对象队列),只能分配单个对象。
//注意:若申请时的当前分配对象已构造过(比如:是由giveUpOne()放弃使用权而回收的对象),则忽略本次构造传参。
#define newOne( typeName , ... ) (CLMemPool<typeName>::newOneFromCLMemPool(_T(#typeName) , __VA_ARGS__ ))
//生成代标号的内存池和对象指针的宏;并且指定内存池名称(若名称未被指定过的话)
#define newOneAndNamed( typeName, NameString , ... ) (CLMemPool<typeName>::newOneFromCLMemPool(_T(#NameString), __VA_ARGS__ ))
//删除对象,typeName是类型名,pObjToDelete是释放的对象指针
#define deleteOne( pObjToDelete ) (deleteOneBackToCLMemPool((pObjToDelete)))
//放弃对象使用权(不会析构对象),并放回内存池待用,typeName是类型名,pObjToDelete是释放的对象指针
#define giveUpOne( pObjToDelete ) (giveUpOneBackToCLMemPool((pObjToDelete)))

//整理所有内存池
inline void arrangeAllMemPools()
{
	getMemPoolsTable()->lock();
	for (auto& i : *getMemPoolsTable())
		i.first->arrangement();
	getMemPoolsTable()->unlock();
}
//输出内存池表所有对象
inline size_t dumpMemPoolsTable(bool bLog = true, bool bDeTail = false,  PStr* outInfoString = nullptr)
{
	size_t mem = 0;
	PStr lpT = 0;
	std::tstring str, strh;
	if (bLog || outInfoString) {
		if (bDeTail)strh = _T("\r\n>>>>The MemmeryPool Table Dumper Detail----------------------------------- \r\n");
		else strh = _T("\r\n>>>>The MemmeryPool Table Dumper Simple----------------------------------- \r\n");
	}
	size_t ic = 1;
	Char cts[BUFSIZE];
	getMemPoolsTable()->lock();
	for (auto i = getMemPoolsTable()->cbegin(); i != getMemPoolsTable()->cend(); ic++)
	{
		size_t memc = (i->first->dumpInfo(false, bDeTail, ((bLog || outInfoString) ? &lpT : nullptr)));
		mem += memc;
		if (bLog || outInfoString) {
			if (i->first->lpTypeName)_stprintf_s(cts, _T("<MemPool(%zd)>, mem= %zd Bytes, type= %s \r\n"), ic, memc, i->second.c_str());
			else _stprintf_s(cts, _T("<MemPool(%zd)>, mem= %zd Bytes, %s \r\n"), ic, memc, _T("#UnkownTypeName"));
			strh += cts;
		}
		if (bLog || outInfoString) {
			if (lpT) {
				str += lpT;
				delete[] lpT;
				lpT = 0;
			}
		}
		++i;
	}
	if (bLog || outInfoString) {
		_stprintf_s(cts, _T(">>>>Total Mem = %zd Bytes \r\n\r\n>>>>Per MemmeryPool Information: \r\n"), mem);
		strh += cts;
		strh += str;
	}
	if (bLog)
		_tprintf_s(_T("%s"), strh.c_str());
	getMemPoolsTable()->unlock();
	if (outInfoString) {
		*outInfoString = new Char[strh.length() + 1];
		_tcscpy_s(*outInfoString, strh.length() + 1, strh.c_str());
	}
	return mem;
}

#endif
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值