為了實作面向對象程式設計,對于的複雜型結構快速構造與釋放,寫了個記憶體池管理模闆。他特點是允許使用者放棄記憶體池生成對象使用權,而不是執行析構。實作對象的複用。
- 實作同類型對象的全局化管理。無需顯示構造記憶體池。采用newOne宏申請對象。
- 記憶體塊的大小可調。記憶體池狀态可輸出顯示。
- 采用記憶體預配置設定方式。對象構造采用原始構造,非動态申請和複制構造,提高速度。
- 加鎖,實作多線程支援。(加鎖會額外耗費cpu時間,可設定宏
,決定采用哪種方案)CLMP_USE_LOCK_TYPE
- 通過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