c++メモリプールの実装(new複雑なオブジェクトが可能)
17789 ワード
/*
:
1>. Malloc()/Free()/Mempool_new()/Mempool_delete() malloc()/free() new()/delete()
2>. qt #define QT
3>. win32
4>. linux c/c++( ) pthread _Lock
:
1>. Mempool_new new , 0~4 , , .
2>. volatile/const , .
:
CMemoryPool<:list> myMemPool;
std::List* pLst = myMemPool.Mempool_new();// , .
struct mySimpleStruct* pStru = myMemPool.Malloc(sizeof(mySimpleStruct));// .
*/
#ifndef MEMORYPOOL_HPP
#define MEMORYPOOL_HPP
//#define QT // windows
#include
#include
#include
#ifndef QT
#include
#else
#include
#endif
using namespace std;
#define IN
#define OUT
#define MAX_BLOCK_TYPE 16
#define MAX_UNIT_NUM 1024
#ifndef QT
class _Lock
{
public:
_Lock(void)
{
InitializeCriticalSection(&m_csLock);
}
~_Lock(void)
{
DeleteCriticalSection(&m_csLock);
}
inline void Lock()
{
EnterCriticalSection(&m_csLock);
}
inline void UnLock()
{
LeaveCriticalSection(&m_csLock);
}
protected:
CRITICAL_SECTION m_csLock;
};
#else
class _Lock
{
public:
_Lock(void)
{
//do nothing
}
~_Lock(void)
{
//do nothing
}
inline void Lock()
{
m_mxLock.lock();
}
inline void UnLock()
{
m_mxLock.unlock();
}
protected:
QMutex m_mxLock;
};
#endif
typedef struct MEM_BLOCK
{
struct MEM_BLOCK *m_pNext;
_Lock m_csLock;
deque<char*> m_dqAddr;
int m_iUnitSize;
char *m_pBuffer;
MEM_BLOCK(IN const int iUnitSize)
{
m_pNext = NULL;
m_iUnitSize = iUnitSize;
m_pBuffer = new (std::nothrow)char[iUnitSize * MAX_UNIT_NUM];
for (int i = 0; i < MAX_UNIT_NUM; i ++)
m_dqAddr.push_back(m_pBuffer + i * iUnitSize);
return ;
}
~MEM_BLOCK()
{
m_pNext = NULL;
delete [] m_pBuffer;
m_dqAddr.clear();
return ;
}
} MEM_BLOCK, *LPMEM_BLOCK;
typedef struct MEM_POOL
{
_Lock m_csLock;
LPMEM_BLOCK m_pMemBlock[MAX_BLOCK_TYPE];
int m_iUnitSize[MAX_BLOCK_TYPE];
int m_iBlockNum[MAX_BLOCK_TYPE];
int m_iUsedMem;
MEM_POOL()
{
ZeroMemory(m_pMemBlock, sizeof(m_pMemBlock));
ZeroMemory(m_iUnitSize, sizeof(m_iUnitSize));
ZeroMemory(m_iBlockNum, sizeof(m_iBlockNum));
m_iUsedMem = 0;
}
} MEM_POOL, *LPMEM_POOL;
template <class T>
class CMemoryPool
{
public:
CMemoryPool(void);
virtual ~CMemoryPool(void);
void SetUseMemLimte(IN const int iMaxUseMem);
inline T* Mempool_new()
{
T* const p = (T*)Malloc(sizeof(T));
if (p == 0)
return p;
try
{
new (p)T();
}
catch (...)
{
(free)(p);
throw;
}
return p;
}
template <typename T0>
inline T* Mempool_new(IN const T0 & a0)
{
T* const p = (T*)Malloc(sizeof(T));
if (p == 0)
return p;
try
{
new (p)T(a0);
}
catch (...)
{
(free)(p);
throw;
}
return p;
}
template <typename T0, typename T1>
inline T* Mempool_new(IN const T0 & a0,IN const T1 & a1)
{
T* const p = (T*)Malloc(sizeof(T));
if (p == 0)
return p;
try
{
new (p)T(a0, a1);
}
catch (...)
{
(free)(p);
throw;
}
return p;
}
template <typename T0, typename T1, typename T2>
inline T* Mempool_new(IN const T0 & a0,IN const T1 & a1,IN const T2 & a2)
{
T* const p = (T*)Malloc(sizeof(T));
if (p == 0)
return p;
try
{
new (p)T(a0, a1, a2);
}
catch (...)
{
(free)(p);
throw;
}
return p;
}
template <typename T0, typename T1, typename T2, typename T3>
inline T* Mempool_new(IN const T0 & a0,IN const T1 & a1,IN const T2 & a2,IN const T3 & a3)
{
T* const p = (T*)Malloc(sizeof(T));
if (p == 0)
return p;
try
{
new (p)T(a0, a1, a2, a3);
}
catch (...)
{
(free)(p);
throw;
}
return p;
}
void Mempool_delete(IN T* p);
void* Malloc(IN const int iLen);
void Free(IN void* p);
bool IsEmpty();
protected:
MEM_POOL m_MemPool;
_Lock m_csMapLock;
map<void*, void*> m_mapMalloc;
int m_iMaxUseMem;
};
template<class T>
CMemoryPool::CMemoryPool(void)
{
m_iMaxUseMem = 0;
m_mapMalloc.clear();
for (int i = 0; i < MAX_BLOCK_TYPE; i++)
m_MemPool.m_iUnitSize[i] = 16 << i;
return;
}
template<class T>
CMemoryPool::~CMemoryPool(void)
{
//
for (int i = 0; i < MAX_BLOCK_TYPE; i++)
{
LPMEM_BLOCK p1 = NULL;
LPMEM_BLOCK p = m_MemPool.m_pMemBlock[i];
while (p)
{
p1 = p->m_pNext;
delete p;
p = p1;
}
}
return;
}
template<class T>
void CMemoryPool::SetUseMemLimte(IN int iMaxUseMem)
{
m_iMaxUseMem = iMaxUseMem;
return;
}
template <class T>
void CMemoryPool::Mempool_delete(IN T* p)
{
//
p->~T();
//
Free(p);
}
template<class T>
void* CMemoryPool::Malloc(IN int iLen)
{
void *p = NULL;
int i = 0;
for (; i < MAX_BLOCK_TYPE; i++)
{
if (iLen < m_MemPool.m_iUnitSize[i])
break;
}
//
if (i == MAX_BLOCK_TYPE)
return p;
//
m_MemPool.m_csLock.Lock();
if (!m_MemPool.m_pMemBlock[i])
{
m_MemPool.m_pMemBlock[i] = new (std::nothrow)MEM_BLOCK(m_MemPool.m_iUnitSize[i]);
if (m_MemPool.m_pMemBlock[i])
m_MemPool.m_iUsedMem += m_MemPool.m_iUnitSize[i] * MAX_UNIT_NUM;
}
m_MemPool.m_csLock.UnLock();
LPMEM_BLOCK pB = m_MemPool.m_pMemBlock[i];
if (!pB)
return p;
while (pB)
{
pB->m_csLock.Lock();
if (pB->m_dqAddr.size())
{
//
p = (void*)pB->m_dqAddr.front();
pB->m_dqAddr.pop_front();
pB->m_csLock.UnLock();
//
m_csMapLock.Lock();
m_mapMalloc[p] = (void*)pB;
m_csMapLock.UnLock();
break;
}
//
if (!pB->m_pNext)
{
//
if (m_iMaxUseMem && m_MemPool.m_iUsedMem + m_MemPool.m_iUnitSize[i] * MAX_UNIT_NUM > m_iMaxUseMem)
{
//
pB->m_csLock.UnLock();
break;
}
pB->m_pNext = new (std::nothrow)MEM_BLOCK(m_MemPool.m_iUnitSize[i]);
if (!pB->m_pNext)
{
//
pB->m_csLock.UnLock();
break;
}
m_MemPool.m_iUsedMem += m_MemPool.m_iUnitSize[i] * MAX_UNIT_NUM;
}
pB->m_csLock.UnLock();
pB = pB->m_pNext;
}
return p;
}
template<class T>
void CMemoryPool::Free(IN void *p)
{
LPMEM_BLOCK pB = NULL;
//
m_csMapLock.Lock();
map<void*, void*>::iterator it = m_mapMalloc.find(p);
if (it != m_mapMalloc.end())
{
pB = (LPMEM_BLOCK)it->second;
m_mapMalloc.erase(it);
}
m_csMapLock.UnLock();
if (!pB)
return;
pB->m_csLock.Lock();
memset(p, 0, pB->m_iUnitSize);
pB->m_dqAddr.push_back((char*)p);
pB->m_csLock.UnLock();
return;
}
template<class T>
bool CMemoryPool::IsEmpty()
{
return m_mapMalloc.size() == 0;
}
#endif //MEMORYPOOL_HPP