smart memory pool :内存池--智能内存池 新鲜大出炉啦

来源:互联网 发布:淘宝视频免费上传 编辑:程序博客网 时间:2024/06/01 12:24
转,可以,标明出处吧,呵呵。
/************************************************************************
* Smart Memory Pool
* author: kelvin
* date:    2007-11-29
* info: 最近一直想写一个智能内存池,该内存池只有取出操作,当用户不再使用到
        该指针,那么指针自动回到内存池中。这个很类似于智能指针的操作,只是
        智能指针是当没有引用的时候,自动销毁。
        使用者对取出的指针的使用,仅仅通过传递值或者引用来完成。
************************************************************************/

#pragma once

#include <assert.h>
#include <list>
#include <boost/thread/mutex.hpp>

using namespace std;

template <typename T>
class kelvin_SmartMemPool;

template<typename POINTERTYPE>
class kelvin_ptr
{
public:
    int        *m_pRef;
    POINTERTYPE    *m_pPtr;
    kelvin_SmartMemPool< POINTERTYPE > *m_MemPool;

private:
    boost::mutex m_mutexRef;

public:
    explicit kelvin_ptr()
        :m_pRef(NULL)
        ,m_pPtr(NULL)
        ,m_MemPool(NULL)
    {
    }
   
    // 构造一个智能指针
    explicit kelvin_ptr(POINTERTYPE *pPtr,  kelvin_SmartMemPool< POINTERTYPE >* MemPool)
        :m_MemPool(MemPool)
    {
        // 确认指针有效
        assert(pPtr);

        AddRef(NULL);
        m_pPtr = pPtr;
    }

    ~kelvin_ptr() { Release(); }

    // 重载拷贝构造,增加引用记数
    kelvin_ptr(const kelvin_ptr<POINTERTYPE> &obj)
    {
        AddRef(obj.m_pRef);
        m_pPtr = obj.m_pPtr;
        m_MemPool = obj.m_MemPool;
    }

    // 重载赋值操作,使得可以对智能指针之间赋值
    const kelvin_ptr<POINTERTYPE>& operator=(kelvin_ptr<POINTERTYPE> &obj)
    {
        // 首先要减少以前的对象的引用记数,然后在指向新的指针。
        Release();

        AddRef(obj.m_pRef);
        m_pPtr = obj.m_pPtr;
        m_MemPool = obj.m_MemPool;

        return *this;
    }

    // 重载*运算符
    POINTERTYPE& operator*()
    {
        assert(m_pPtr);
        return *m_pPtr;
    }

    // 重载->运算符
    POINTERTYPE* operator->()
    {
        assert(m_pPtr);
        return m_pPtr;
    }

protected:
    // 增加引用记数
    void AddRef(int *pRef)
    {
        if (pRef == NULL)
        {
            m_pRef = new int;
            *m_pRef = 0;
        }
        else
        {
            m_pRef = pRef;
        }

        {
            boost::mutex::scoped_lock lock(m_mutexRef);
            (*m_pRef)++;
        }
        //InterlockedIncrement((LONG*)m_pRef);
    }

    // 减少引用记数
    void Release()
    {
        if (m_pRef != NULL)
        {
            {
                boost::mutex::scoped_lock lock(m_mutexRef);
                (*m_pRef)--;
            }
            //InterlockedDecrement((LONG*)m_pRef);

            if ( (*m_pRef) == 1)
            {
                //SmartMemPool<POINTERTYPE>::T pObj = *this;
                //m_MemPool.freeMem( (SmartMemPool<POINTERTYPE>::T*)(this) );
                m_MemPool->freeMem( *this );
               
                /// 这里由于在放回内存池的时候多了次拷贝构造,引起了记数多1,但是不能继续放在那边去减少记数,
                /// 否则,则循环调用了freeMem.所以在这里对该对象引用记数-1
                {
                    boost::mutex::scoped_lock lock(m_mutexRef);
                    (*m_pRef)--;
                }

                return;
            }

            if ( (*m_pRef) == 0)
            {
                if (m_pPtr != NULL)
                {
                    delete m_pPtr;
                    m_pPtr = NULL;
                }               

                delete m_pRef;
                m_pRef = NULL;
            }
        }
    }
};

template <typename TT>
class kelvin_SmartMemPool
{
public:
    typedef kelvin_ptr<TT> T;

public:
    explicit kelvin_SmartMemPool()
        :m_iMemLength(10)
    {
        //MemPool(10); /** 这里千万不要这么调用,构造中重复调用构造,实际上是生成了临时对象**/
        for (int i = 0; i < m_iMemLength; i++)
        {
            T* pNode = new T(new TT, this);
            assert(pNode);
            m_listMem.push_back( pNode );
        }
    }

    explicit kelvin_SmartMemPool(int iLength)
        :m_iMemLength(iLength)
    {
        for (int i = 0; i < m_iMemLength; i++)
        {
            T* pNode = new T(new TT, this);
            assert(pNode);
            m_listMem.push_back( pNode );
        }
    }

    virtual ~kelvin_SmartMemPool()
    {
        for (list< T* >::iterator itr = m_listMem.begin(); itr != m_listMem.end(); /*itr++*/)
        {
            ((*itr))->~T();
            //delete (*itr);
            //(*itr)->Release();
            *itr = NULL;
            m_listMem.erase(itr++);
        }

        m_listMem.clear();

        m_iMemLength = 0;
    }

    T        getMem()
    {
        T *pNode = NULL;

        {
            boost::mutex::scoped_lock lock(m_mutexLockList);
            if (m_listMem.size() > 0)
            {
                list< T* >::iterator itr = m_listMem.begin();
                pNode = (*itr);
                m_listMem.erase(itr);

                m_iMemLength--;               
            }
            else
            {
                pNode = new T(new TT, this);
                assert(pNode);
                //m_iMemLength++; //这里是个bug,iMemLength应该记载还剩的空余内存
            }
        }

        return *pNode;

    }

    //void    freeMem(T* pNode)
    //{
    //    boost::mutex::scoped_lock lock(m_mutexLockList);
    //    m_listMem.push_back( pNode );
    //    m_iMemLength++;
    //}

    void    freeMem(T Node)
    {
        if (Node.m_MemPool == NULL)
        {
            return ;
        }

        boost::mutex::scoped_lock lock(m_mutexLockList);
        T* pNode = new T();
        *pNode = Node;
        m_listMem.push_back( pNode );
        m_iMemLength++;
    }

    int        getSize()
    {
        return m_iMemLength;
    }

private:
    list< T* >    m_listMem;
    int            m_iMemLength;

    boost::mutex    m_mutexLockList;
};


有兴趣可以跟我留言,共同讨论如何把内存池写的更好,呵呵。