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