• [转]关于Memory Pool的一些想法及实现


    http://blog.csdn.net/xiaocai0001/archive/2006/04/14/663752.aspx

    在《Effective C++》(Second Edition)中Item 10 "Write operator delete if you write operator new"中提到一个Memory Pool技术, 并给出一个例子
    void *Airplane::operator new(size_t size)
    {
    if(size != sizeof(Airplane))
    return ::operator new(size);
    Airplane *p = headOfFreeList;
    if(p)
    headOfFreeList = p->next;
    else
    {
    Airplane * newBlock = static_cast<Airplane *>(::operator new(BLOCK_SIZE*sizeof(Airplane)));
    }
    for(int i=1; i<BLOCK_SIZE-1; ++i)
    newBlock[i].next = &newBlock[i+1];
    newBlock[BLOCK_SIZE-1].next = 0;
    p= newBlock;
    headOfFreeList = &newBlock[1];
    }
    书中提到, 用这种技术的好处有二: 一. 节省空间, 普通的new操作由于需要记住申请的大小, 一般需要更多的空间. 而应用这种技术则不需要额外的空间. 二. 操作速度快, 此种的new和delete操作只是对链表的添加和删除操作, 不需要做真正的系统空间分配, 速度更快.

    但明显, 例子中给出的操作只能针对Airplane类进行操作, 试想, 能不能扩展到对任何类进行这样的Memory Pool操作呢?

    第一想法就是用template.
    花了一中午的时间写了一个CMemoryPool模板类. 如下所示

    #ifndef __MEMORYPOOL_H__
    #define __MEMORYPOOL_H__

    #include <list>


    template <class _T>
    class CMemoryPool 
    {

    public:
    CMemoryPool(size_t init_size = 100) : INIT_SIZE(init_size), m_memoryHeadList(5)
    {
    headOfFreeList = NULL;
    }

    ~CMemoryPool()
    {
    std::list<Envelope *>::iterator iter;
    for(iter = m_memoryHeadList.begin(); iter != m_memoryHeadList.end(); ++iter)
    {
    Envelope *block = *iter;
    ::operator delete(block);
    }
    }

    _T *alloc()
    {
    Envelope *p = headOfFreeList;
    if(p)
    headOfFreeList = p->next;
    else
    {
    const size_t ObjectSize = (sizeof(_T) > sizeof(Envelope)) ? sizeof(_T) : sizeof(Envelope);
    // 申请空间
    Envelope *newBlock = static_cast<Envelope *>(::operator new(INIT_SIZE * ObjectSize));
    // 初始化空闲空间列表
    for(int i=1; i<INIT_SIZE; ++i)
    ((Envelope *)((char *)newBlock + i * ObjectSize))->next = (Envelope *)((char *)newBlock + (i+1) * ObjectSize);

    ((Envelope*)((char *)newBlock + (INIT_SIZE - 1) * ObjectSize))->next = NULL;
    // 保存首址
    m_memoryHeadList.push_back(newBlock);

    p = newBlock;
    headOfFreeList = (Envelope*)((char *)newBlock + ObjectSize);
    }
    return (_T *)p;
    }

    void free(_T *p)
    {
    if(p==NULL)
    return;

    Envelope *freeBlock = (Envelope *)p;
    freeBlock->next = headOfFreeList;
    headOfFreeList = freeBlock;
    }

    private:
    union Envelope
    {
    _T *object;
    union Envelope *next;
    };
    const size_t INIT_SIZE;// 默认每次分配多少初始大小的空间
    Envelope *headOfFreeList; // 当前自由空间首址
    std::list<Envelope *> m_memoryHeadList; // 申请空间首址向量
    };

    #endif // !defined __MEMORYPOOL_H__

    此模板类对于内建类型, 可做如下使用.
    #include <iostream>
    #include "MemoryPool.h"

    int main()
    {
    CMemoryPool<double> d_Pool;
    double *p[10];
    int i;
    for(i=0; i<10; ++i)
    {
    p[i] = d_Pool.alloc();
    std::cout<<p[i]<<std::endl;
    }
    for(i=0; i<5; ++i)
    d_Pool.free(p[i]);

    for(i=0; i<5; ++i)
    p[i] = d_Pool.alloc();

    for(i=0; i<10; ++i)
    std::cout<<p[i]<<std::endl;

    return 0;
    }

    如果仅仅这样使用, 还没有达到所要求的目的.
    关键是对于自己的自定义类, 通过重载operator new与operator delete来使用Memory Pool
    如下:
    #include <iostream>
    #include "MemoryPool.h"

    class MyClass
    {
    public:
    MyClass();
    ~MyClass();
    static void * operator new(size_t t);
    static void operator delete(void *p);

    private:
    static CMemoryPool<MyClass> st_objectPool;
    };

    CMemoryPool<MyClass> MyClass::st_objectPool(10);

    MyClass::MyClass()
    {
    std::cout<<"A() called"<<std::endl;
    }

    MyClass::~MyClass()
    {
    std::cout<<"~A() called"<<std::endl;
    }

    void * MyClass::operator new(size_t t)
    {
    if(t != sizeof(MyClass))
    return ::operator new(t);
    return MyClass::st_objectPool.alloc();
    }

    void MyClass::operator delete(void *p)
    {
    MyClass::st_objectPool.free((MyClass *)p);
    }


    int main()
    {
    MyClass *ptr;
    ptr = new MyClass;
    delete ptr;
    return 0;
    }

    至此, 已经完成了对于任何类的一个CMemoryPool类的写法, 自然会想到, 怎么样去写一个基类CMemoryPoolBaseClass, 让所有继承该类的子类都具有这种内存池的动态内存分配方式呢?

  • 相关阅读:
    设计模式之四(抽象工厂模式第二回合)
    C# try catch finally
    设计模式之三(工厂方法模式)
    C# XML与Json之间的相互转换
    Google免费的SVN服务器管理VS2010代码
    设计模式之四(抽象工厂模式第一回合)
    MVC项目开发中那些用到的知识点(Jquery ajax提交Json后台处理)
    设计模式之四(抽象工厂模式第三回合)
    设计模式之二(简单工厂模式)
    Jquery的$命名冲突
  • 原文地址:https://www.cnblogs.com/WuCountry/p/907046.html
Copyright © 2020-2023  润新知