一个内存池类

#ifndef  _INCLUDE_CXMEMPOOL_H_
#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()
{

}








猜你喜欢

转载自blog.csdn.net/XiaoWhy/article/details/76208984
今日推荐