#define _INCLUDE_CXMEMPOOL_H_
#include <string>
#include "backcom/lock.h"
#include <list>
#include <map>
using namespace BackCom;
using namespace std;
多线程使用 一个线程申请 一个线程释放
class CXFixMemPoolLock
{
public:
struct CMemItem
{
char* m_pNextAddr;//下一块指针
};
CXFixMemPoolLock(int nFixLen);
void SetPoolName(const char* pName);
char* GetCacheMem(unsigned int& nRealLen);
void PutCacheMem(char* &pMem,int nRealLen);
unsigned int GetMemInfo(string& strMemInfo);
static unsigned int CalcuateFixLen(unsigned int nRealLen)
{
return nRealLen>sizeof(CMemItem)?nRealLen:sizeof(CMemItem);
}
private:
char* _getCacheMem(int nRealLen);
void _putCacheMem(char* &pMem,int nRealLen);
private:
void _allocMem();
char* _newMemItem();
void _moveMemItem();
void _freeMemItem(char* pMemItem);
protected:
string m_strName; //名称
const unsigned int m_nFixLen;
list<char*> m_cacheList;//总缓存块
unsigned int m_nBigNum; //大缓存块数目
unsigned int m_ntotalNum;
unsigned int m_nSumMemLen;
unsigned int m_nGetNum;
unsigned int m_nPutNum;
CLock m_GetLock;
char* m_pGetMemHead;//Get头
char* m_pGetMemTail;//Get尾
CLock m_MemLock;
char* m_pPutMemHead;
char* m_pPutMemTail;
};
//缓存池
template<class CFixPool>
class CXMulItemMemPool
{
public:
//512 1024 2*1024 3*1024 4*1024 5*1024 6*1024 7*1024 8*1024
enum{MINMEMSIZE=512,MEMARRSIZE=9};
CXMulItemMemPool()
{
_initLockPool();
}
char* GetMemByLen(unsigned int& nMemLen)//按长度获取一块内存
{
int nIndex = _lookIndex(nMemLen);//根据长度查找Index
if(nIndex>=0)
{
return m_pLockPool[nIndex]->GetCacheMem(nMemLen);//获取一块内存
}
return new char[nMemLen];//要是没找到,就new一块,归还的时候另外释放
}
void PutMemByLen(char* &pMem,const unsigned int nMemLen)//按长度归还一块内存
{
int nIndex = _lookIndex(nMemLen);
if(nIndex>=0)
{
m_pLockPool[nIndex]->PutCacheMem(pMem,nMemLen);
}
else
{
delete[] pMem;
pMem = NULL;
}
}
void GetMemInfo(string& strMemInfo)//统计内存信息
{
strMemInfo = m_strName;
strMemInfo += ":\n";
unsigned int nSumMemLen = 0;
for (int i=0;i<MEMARRSIZE;++i)
{
string strItem;
if (m_pLockPool[i])
{
nSumMemLen += m_pLockPool[i]->GetMemInfo(strItem);
strMemInfo += strItem;
}
}
char ptotalMemLen[128];
sprintf(ptotalMemLen,"SumMemLen=%-9u\n",nSumMemLen);
strMemInfo += ptotalMemLen;
}
void SetPoolName(const char* pName)
{
m_strName = pName;
}
void Clear()
{
for(int i=0;i<MEMARRSIZE;++i)
{
if (m_pLockPool[i])
{
m_pLockPool[i]->ClearMem();
}
}
}
private:
int _lookIndex(unsigned int nMemLen)
{
for(int i=0;i<MEMARRSIZE;++i)
{
if(m_nPoolNum[i]>=nMemLen)
{
return i;
}
}
return -1;
}
void _initLockPool()//初始化内存池
{
unsigned int nJeCheng = MINMEMSIZE;//最小内存大小512
for(int i=0;i<MEMARRSIZE;++i)//数组9
{
m_nPoolNum[i] = nJeCheng;//int数组标记对应内存池存放的内存大小
m_pLockPool[i] = new CFixPool(nJeCheng);//new CXFixMemPoolLock
if (nJeCheng<1024)//按1024倍数放大内存
{
nJeCheng *= 2;
}
else
{
nJeCheng += 1024;
}
}
}
private:
string m_strName;
unsigned int m_nPoolNum[MEMARRSIZE];
CFixPool* m_pLockPool[MEMARRSIZE];//内存池数组
};
#endif
#include "CXMemPool.h"
#include <assert.h>
CXFixMemPoolLock::CXFixMemPoolLock( int nFixLen ) :m_nFixLen(nFixLen>sizeof(CMemItem)?nFixLen:sizeof(CMemItem))
{
static int s_PoolID = 0;
char pName[64];
sprintf(pName,"lockpool_%02d<%04u>",s_PoolID++,m_nFixLen);
m_strName = pName;
m_nBigNum = 0;
m_ntotalNum = 0;
m_nSumMemLen = 0;
m_nGetNum = 0;
m_nPutNum = 0;
m_pGetMemHead = NULL;
m_pGetMemTail = NULL;
m_pPutMemHead = NULL;
m_pPutMemTail = NULL;
}
void CXFixMemPoolLock::SetPoolName( const char* pName )
{
m_strName = pName;
}
char* CXFixMemPoolLock::GetCacheMem(unsigned int& nRealLen )//获取一块内存
{
nRealLen = m_nFixLen;//获取内存固定大小的内存
return _getCacheMem(nRealLen);
}
void CXFixMemPoolLock::PutCacheMem( char* &pMem,int nRealLen )
{
_putCacheMem(pMem,nRealLen);
}
unsigned int CXFixMemPoolLock::GetMemInfo( string& strMemInfo )
{
char memBuffer[128];
sprintf(memBuffer,"<%06u> sumMemLen=%-9u totalNum=%-6u useNum=%-6u\n",m_nFixLen,m_nSumMemLen,m_ntotalNum,m_ntotalNum-m_nGetNum-m_nPutNum);
strMemInfo = memBuffer;
return m_nSumMemLen;
}
char* CXFixMemPoolLock::_getCacheMem( int nRealLen )
{
CAutoLock LocalLock(m_GetLock);
if (m_pGetMemHead == m_pGetMemTail)//头与尾相等
{
_moveMemItem();
if (m_pGetMemHead == m_pGetMemTail)//如果仍然相等,重新分配内存
{
_allocMem();
}
}
return _newMemItem();
}
void CXFixMemPoolLock::_putCacheMem( char* &pMem,int nRealLen )
{
_freeMemItem(pMem);
pMem = NULL;
}
void CXFixMemPoolLock::_allocMem()//分配内存
{
int nMemLen = 0;
if (m_nFixLen>=1024)
{
nMemLen = 100*m_nFixLen;
}
else
{
nMemLen = 1024* m_nFixLen;
}//1024的倍数
m_nSumMemLen+=nMemLen;//记录总大小
char* pMem = new char[nMemLen];
m_cacheList.push_back(pMem);//放进list
++m_nBigNum;
if (m_pGetMemHead == NULL || m_pGetMemTail == NULL)// 如果有为NULL,都指向pMem
{
m_pGetMemHead = pMem;
m_pGetMemTail = pMem;
}
for (int i=0;i<nMemLen/m_nFixLen;++i)//把大块内存均等划分
{
CMemItem* pCurItem = (CMemItem*)m_pGetMemTail;
m_pGetMemTail = pMem + i*m_nFixLen;//下一个
pCurItem->m_pNextAddr = m_pGetMemTail;//当前的next指向下一个
}
m_ntotalNum += nMemLen/m_nFixLen;
m_nGetNum += nMemLen/m_nFixLen;
}
char* CXFixMemPoolLock::_newMemItem()
{
assert(m_pGetMemHead!=m_pGetMemTail);
--m_nGetNum;
CMemItem* pCutItem = (CMemItem*)m_pGetMemHead;//当前头
m_pGetMemHead = pCutItem->m_pNextAddr;//指向下一个
return (char*)pCutItem;//返回头指向的内存
}
void CXFixMemPoolLock::_moveMemItem()
{
CAutoLock localLock(m_MemLock);
if (m_pPutMemHead && m_pPutMemTail)//把put的内存放到get中来
{ //有空间重复利用
CMemItem* pCurTail = (CMemItem*)m_pGetMemTail;//指向尾节点
pCurTail->m_pNextAddr = m_pPutMemHead;//next指向put的头
m_pGetMemTail = m_pPutMemTail;//get尾指向put的尾
m_pPutMemHead = NULL;
m_pPutMemTail = NULL;
m_nGetNum += m_nPutNum;
m_nPutNum = 0;
}
}
void CXFixMemPoolLock::_freeMemItem( char* pMemItem )//归还内存
{
CAutoLock localLock(m_MemLock);
++m_nPutNum;
if (m_pPutMemTail == NULL)
{
m_pPutMemHead = pMemItem;
m_pPutMemTail = pMemItem;
}
else
{
CMemItem* pCurTail = (CMemItem*)m_pPutMemTail;
m_pPutMemTail = pMemItem;//尾节点指向mem
pCurTail->m_pNextAddr = m_pPutMemTail;//之前尾节点next指向归还内存,归还内存放在末尾
}
}
使用
class CDataBlockPool
{
public:
enum
{
MAXNUMPERBLOCK = 100
};
//块结点
struct CBlockNode
{
unsigned int m_nMemLen;//缓存总大小
CBlockNode* m_pNextNode;
unsigned int m_nRecSize;//记录大小
unsigned int m_nMaxNum; //总数目
unsigned int m_nUseNum; //当前使用数目
unsigned int m_nUsePos; //使用位置
char m_pData[0];
void Init(unsigned int nMemLen,unsigned int nRecSize);
const char* operator[](unsigned int index) const;
unsigned int GetDataNum();
unsigned int GetSpaceSize() const;
//返回插入记录数目
int AddData(const void* pData,unsigned int nDataLen,unsigned int nRecNum);
void UpdateData(const void* pData,unsigned int nDataLen);
};
CDataBlockPool();
CBlockNode* GetOneBlock(unsigned int nRecSize);
void FreeOneBlock(CBlockNode* pBlock);
protected:
static unsigned int GetBlockLen(unsigned nRecSize);
CXMulItemMemPool<CXFixMemPoolLock> m_MemPool;
};
void CDataBlockPool::CBlockNode::Init(unsigned int nMemLen,unsigned int nRecSize)
{
m_nMemLen = nMemLen;
m_pNextNode = NULL;
m_nRecSize = nRecSize;
m_nMaxNum = (nMemLen-sizeof(CBlockNode))/nRecSize;
m_nUseNum = 0;
m_nUsePos = 0;
}
const char* CDataBlockPool::CBlockNode::operator[]( unsigned int index ) const
{
if (index>=m_nUseNum)
{
return NULL;
}
return m_pData + index*m_nRecSize;
}
unsigned int CDataBlockPool::CBlockNode::GetDataNum()
{
return m_nUseNum;
}
unsigned int CDataBlockPool::CBlockNode::GetSpaceSize() const
{
return m_nMaxNum - m_nUseNum;
}
int CDataBlockPool::CBlockNode::AddData( const void* pData,unsigned int nDataLen,unsigned int nRecNum )
{
if (pData == NULL || nDataLen==0 || nRecNum==0)
{
return 0;
}
if (nDataLen/nRecNum!=m_nRecSize)//固定大小
{
return 0;
}
unsigned int nCpyNum = nRecNum;
if (GetSpaceSize()<nCpyNum)
{
nCpyNum = GetSpaceSize();
}
unsigned int nCpySize = nCpyNum * m_nRecSize;
memcpy(m_pData+m_nUsePos,pData,nCpySize);
m_nUsePos += nCpySize;
m_nUseNum += nCpyNum;
return nCpyNum;
}
void CDataBlockPool::CBlockNode::UpdateData( const void* pData,unsigned int nDataLen )
{
if (nDataLen!=m_nRecSize)
{
return;
}
memcpy(m_pData+m_nUsePos-nDataLen,pData,nDataLen);
}
CDataBlockPool::CBlockNode* CDataBlockPool::GetOneBlock( unsigned int nRecSize )
{
unsigned int nLen = GetBlockLen(nRecSize);
CBlockNode* pBlock = (CBlockNode*) m_MemPool.GetMemByLen(nLen);
pBlock->Init(nLen,nRecSize);
return pBlock;
}
void CDataBlockPool::FreeOneBlock( CBlockNode* pBlock )
{
char* pMem = (char*)pBlock;
m_MemPool.PutMemByLen(pMem,pBlock->m_nMemLen);
pBlock = NULL;
}
unsigned int CDataBlockPool::GetBlockLen( unsigned int nRecSize )
{
return sizeof(CBlockNode) + nRecSize*MAXNUMPERBLOCK;
}
CDataBlockPool::CDataBlockPool()
{
}