您的位置:首页 > 其它

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

2007-11-29 17:00 267 查看
转,可以,标明出处吧,呵呵。
/************************************************************************
* 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;
};

有兴趣可以跟我留言,共同讨论如何把内存池写的更好,呵呵。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: