一个高效的内存池实现

在高效C++编程中看到一个不错的内存池实现方案,这里共享下,大家看看有什么不足。
代码很简单,如下:
template<typename T>
class CMemoryPool
{
     public:
         enum { EXPANSION_SIZE = 32};

        CMemoryPool(unsigned  int nItemCount = EXPANSION_SIZE)
        {
            ExpandFreeList(nItemCount);
        }
        
        ~CMemoryPool()
        {
             // free all memory in the list
            CMemoryPool<T>* pNext = NULL;
             for(pNext = m_pFreeList; pNext != NULL; pNext = m_pFreeList)
            {
                m_pFreeList = m_pFreeList->m_pFreeList;
                delete []( char*)pNext;
            }
        }

         void* Alloc(unsigned  int  /* size */)
        {
             if(m_pFreeList == NULL)
            {
                ExpandFreeList();
            }
            
             // get free memory from head
            CMemoryPool<T>* pHead = m_pFreeList;
            m_pFreeList = m_pFreeList->m_pFreeList;
             return pHead;
        }

         void Free( void* p)
        {
             // push the free memory back to list
            CMemoryPool<T>* pHead = static_cast<CMemoryPool<T>*>(p);
            pHead->m_pFreeList = m_pFreeList;
            m_pFreeList = pHead;
        }

     protected:
         // allocate memory and push to the list
         void ExpandFreeList(unsigned nItemCount = EXPANSION_SIZE)
        {
            unsigned  int nSize =  sizeof(T) >  sizeof(CMemoryPool<T>*) ?  sizeof(T) :  sizeof(CMemoryPool<T>*);
            CMemoryPool<T>* pLastItem = static_cast<CMemoryPool<T>*>(static_cast< void*>( new  char[nSize]));
            m_pFreeList = pLastItem;
             for( int i=0; i<nItemCount-1; ++i)
            {
                pLastItem->m_pFreeList = static_cast<CMemoryPool<T>*>(static_cast< void*>( new  char[nSize]));
                pLastItem = pLastItem->m_pFreeList;
            }

            pLastItem->m_pFreeList = NULL;
        }

     private:
        CMemoryPool<T>* m_pFreeList;
};

它的实现思想就是每次从List的头上取内存, 如果取不到则重新分配一定数量; 用完后把内存放回List头部,这样的话效率很高,因为每次List上可以取到的话,肯定是空闲的内存。

当然上面的代码只是针对单线程的,要支持多线程的话也很简单,外面加一层就可以了,
代码如下:
class CCriticalSection
{
public:
    CCriticalSection()
    {
        InitializeCriticalSection(&m_cs);
    }

    ~CCriticalSection()
    {
        DeleteCriticalSection(&m_cs);
    }

     void Lock()
    {
        EnterCriticalSection(&m_cs); 
    }

     void Unlock()
    {
        LeaveCriticalSection(&m_cs);
    }

protected:
    CRITICAL_SECTION m_cs;
};

template<typename POOLTYPE, typename LOCKTYPE>
class CMTMemoryPool
{
     public:
         void* Alloc(unsigned  int size)
        {
             void* p = NULL;
            m_lock.Lock();
            p = m_pool.Alloc(size);
            m_lock.Unlock();

             return p;
        }

         void Free( void* p)
        {
            m_lock.Lock();
            m_pool.Free(p);
            m_lock.Unlock();    
        }

     private:
        POOLTYPE m_pool;
        LOCKTYPE m_lock;
};

这是我的测试代码:
#include <iostream>
#include <windows.h>

using  namespace std;

#include "MemoryPool.h"
#include "MTMemoryPool.h"

class CTest
{
public:
     int m_n;
     int m_n1;

     voidoperator  new(size_t size)
    {
         void* p = s_pool->Alloc(size);
         return p;
    }

     void  operator delete( void* p, size_t size)
    {
        s_pool->Free(p);
    }

     static  void NewPool()
    {
         // s_pool = new CMemoryPool<CTest>;
        s_pool =  new CMTMemoryPool<CMemoryPool<CTest>, CCriticalSection>;
    }

     static  void DeletePool()
    {
        delete s_pool;
        s_pool = NULL;
    }
    
     // static CMemoryPool<CTest>* s_pool;
     static CMTMemoryPool<CMemoryPool<CTest>, CCriticalSection>* s_pool;
};

// CMemoryPool<CTest>* CTest::s_pool = NULL;
CMTMemoryPool<CMemoryPool<CTest>, CCriticalSection>* CTest::s_pool = NULL;

void testFun()
{
     int i;
     const  int nLoop = 10;
     const  int nCount = 10000;
    
     for( int j = 0; j<nLoop; ++j)
    {
        typedef CTest* LPTest;
        LPTest arData[nCount];
         for(i=0;i <nCount; ++i)
        {
            arData[i] =  new CTest;
        }

         for(i=0;i <nCount; ++i)
        {
            delete arData[i];
        }
    }
}

int main( int argc,  char* argv[])
{
    {
        unsigned  int dwStartTickCount = GetTickCount();

        CTest::NewPool();

        testFun();
        
        CTest::DeletePool();
        
        cout << "total cost" << GetTickCount() - dwStartTickCount << endl;
    }


    system("pause");

     return 0;
}
在我机器上测试结果比系统默认的CRT实现高效N倍。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
注:更多资料请根据压缩文件中的《更多资料.txt》文件的介绍免费获取 =====★★★★史上最全的IOCP资料大全★★★★============== 目的:研究和分享基于IOCP通讯模型的服务器端及即时通讯客户端相关技术 语言:Delphi\C++ 欢迎给位朋友加入 -------------------------前言------------------------ 最近在编写即时通讯工具,于是便参考和搜罗了网上大量的文章和源码, 对IOCP涉及的相关技术进行了广泛和深入的研究。 IOCP涉及的关键知识点有很多很多,这方面的文章也非常多, 但是很多讲述的都是某方面的,为了帮大家甄选资料,我决定分享给大家。 以下是我搜集的部分IOCP相关的资料目录,有需要的请加我QQ和QQ群,无偿分享: --------------------------IOCP部分相关知识点------------------ 线程池,Socket连接池、数据库连接池、内存池及内存管理 防DDos攻击、防只连接不发送消息及Setsockopt相关设置 WSAENOBUFS及0缓冲的WSARecive投递 优雅的链接关闭方法及shutdown、TIME_WAIT 及注册表设置:TcpNumConnections/MaxUserPort 多核多线程、生产消费者模型、读写者模型、多线程无锁环形队列及LockFreeList概念 Socket重用、端口重用 心跳、粘包、乱序 ------------------------我收集的文章及源码的部分目录---------------------- ------------------------供大家搜索资料时参考----------------------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值