最近做服务器,需要把数千个客户端上发的数据保存起来;保存数据所使用的缓冲区,是从一个内存池里面取得的;客户端上发的数据,长度从几十字节至三四 k 不等(按照协议,数据长度最大为4k);如果内存池中的每片缓冲区的长度大小都使用4k,会造成空间浪费,因为客户端就算只上发几个字节的数据,也会占用一片4k的缓冲区;想了一下,就做了下面这个内存池来避免空间浪费;里面使用了8块大内存,每块内存依次按照 32字节 至 4k 为单位长度,细分为若干个区域,并使用8个堆栈来保存这些区域的地址;收到客户端数据以后,根据数据长度从内存池里面取一片合适长度的缓冲区来保存数据。。。。。。
MemoryPool.h
#ifndef __MEMORYPOOL_H__
#define __MEMORYPOOL_H__
#include <Windows.h>
#include "stack.h" //代码见 http://blog.csdn.net/firebird321/archive/2010/04/27/5532985.aspx
class CMemoryPool
{
CStack< char* >* m_pStackBufferPool;
DWORD m_dwPerSize; //内存池的元素大小
DWORD m_dwCount; //内存池的元素个数
char* m_pBuffer; //内存池起始地址
VOID AllocBuffer( VOID );
VOID FreeBuffer( VOID );
public:
CMemoryPool( DWORD dwCount, DWORD dwPerSize );
virtual ~CMemoryPool( VOID );
// 从相应的内存池中取得一片内存
char* GetBufferNode( VOID );
// 将使用的内存片放回内存池
BOOL AddBufferNode( char* pBuf );
};
#endif
MemoryPool.cpp
#include "MemoryPool.h"
class CMemoryBadInit
{
public:
CMemoryBadInit() {}
};
CMemoryPool::CMemoryPool( DWORD dwCount, DWORD dwPerSize )
{
m_pBuffer = NULL;
m_pStackBufferPool = NULL;
m_dwCount = dwCount;
m_dwPerSize = dwPerSize;
AllocBuffer();
}
CMemoryPool::~CMemoryPool( VOID )
{
FreeBuffer();
}
VOID CMemoryPool::AllocBuffer( VOID )
{
m_pBuffer = new char[ m_dwCount * m_dwPerSize ];
if ( NULL == m_pBuffer )
{
throw CMemoryBadInit();
return;
}
m_pStackBufferPool = new CStack<char*>( m_dwCount );
if ( NULL == m_pStackBufferPool )
{
throw CMemoryBadInit();
return;
}
for ( DWORD i=0; i<m_dwCount; i++ )
{
m_pStackBufferPool->push( m_pBuffer + i * m_dwPerSize );
}
}
VOID CMemoryPool::FreeBuffer( VOID )
{
if ( NULL != m_pStackBufferPool )
{
delete m_pStackBufferPool;
}
if ( NULL != m_pBuffer )
{
delete [] m_pBuffer;
}
}
char* CMemoryPool::GetBufferNode( VOID )
{
char* p = NULL;
if ( 0 == m_pStackBufferPool->size() )
{
return p;
}
p = m_pStackBufferPool->top();
m_pStackBufferPool->pop();
return p;
}
BOOL CMemoryPool::AddBufferNode( char* pBuf )
{
if ( NULL==m_pBuffer || NULL==m_pStackBufferPool || NULL==pBuf )
{
return FALSE;
}
if ( ( pBuf < m_pBuffer ) && ( pBuf > ( m_pBuffer + m_dwCount * m_dwPerSize ) ) )
{
return FALSE;
}
m_pStackBufferPool->push( pBuf );
return TRUE;
}
MemoryManager.h
#ifndef __MEMORYMANAGER_H__
#define __MEMORYMANAGER_H__
#include <Windows.h>
#include "MemoryPool.h"
enum BUFFER_LENGTH_TYPE { DATA_LENGTH_32, DATA_LENGTH_64, DATA_LENGTH_128, DATA_LENGTH_256, DATA_LENGTH_512,
DATA_LENGTH_1024, DATA_LENGTH_2048, DATA_LENGTH_4096, DATA_LENGTH_ERROR };
class CMemoryManager
{
protected:
CMemoryPool* m_pMemoryPool_32;
CMemoryPool* m_pMemoryPool_64;
CMemoryPool* m_pMemoryPool_128;
CMemoryPool* m_pMemoryPool_256;
CMemoryPool* m_pMemoryPool_512;
CMemoryPool* m_pMemoryPool_1024;
CMemoryPool* m_pMemoryPool_2048;
CMemoryPool* m_pMemoryPool_4096;
VOID AllocBuffer( VOID );
VOID FreeBuffer( VOID );
// 从相应的内存池中取得一片内存
char* GetBuffer( DWORD dwType );
public:
CMemoryManager( VOID );
virtual ~CMemoryManager( VOID );
char* GetBuffNode( DWORD dwDataLen );
BOOL AddBuffNode( char* pBuf, DWORD dwLenType );
// 根据传入的数据长度,确定相关的内存池
BUFFER_LENGTH_TYPE GetBufLenType( DWORD dwDataLen );
};
#endif
MemoryManager.cpp
#include "MemoryManager.h"
#include <assert.h>
class CMemoryManagerBadInit
{
public:
CMemoryManagerBadInit() {}
};
CMemoryManager::CMemoryManager( VOID )
{
m_pMemoryPool_32 = NULL;
m_pMemoryPool_64 = NULL;
m_pMemoryPool_128 = NULL;
m_pMemoryPool_256 = NULL;
m_pMemoryPool_512 = NULL;
m_pMemoryPool_1024 = NULL;
m_pMemoryPool_2048 = NULL;
m_pMemoryPool_4096 = NULL;
AllocBuffer();
}
CMemoryManager::~CMemoryManager( VOID )
{
FreeBuffer();
}
VOID CMemoryManager::AllocBuffer( VOID )
{
//1000000; // 32M
m_pMemoryPool_32 = new CMemoryPool( 10000, 32 );
if ( NULL == m_pMemoryPool_32 )
{
throw CMemoryManagerBadInit();
}
//1000000; // 61M
m_pMemoryPool_64 = new CMemoryPool( 10000, 64 );
if ( NULL == m_pMemoryPool_64 )
{
throw CMemoryManagerBadInit();
}
//1000000; // 122M
m_pMemoryPool_128 = new CMemoryPool( 10000, 128 );
if ( NULL == m_pMemoryPool_128 )
{
throw CMemoryManagerBadInit();
}
//500000; // 122M
m_pMemoryPool_256 = new CMemoryPool( 10000, 256 );
if ( NULL == m_pMemoryPool_256 )
{
throw CMemoryManagerBadInit();
}
//500000; // 244M
m_pMemoryPool_512 = new CMemoryPool( 10000, 512 );
if ( NULL == m_pMemoryPool_512 )
{
throw CMemoryManagerBadInit();
}
//30000; // 29M
m_pMemoryPool_1024 = new CMemoryPool( 10000, 1024 );
if ( NULL == m_pMemoryPool_1024 )
{
throw CMemoryManagerBadInit();
}
//30000; // 58M
m_pMemoryPool_2048 = new CMemoryPool( 10000, 2048 );
if ( NULL == m_pMemoryPool_2048 )
{
throw CMemoryManagerBadInit();
}
//30000; // 116M
m_pMemoryPool_4096 = new CMemoryPool( 10000, 4096 );
if ( NULL == m_pMemoryPool_4096 )
{
throw CMemoryManagerBadInit();
}
}
VOID CMemoryManager::FreeBuffer( VOID )
{
if ( NULL == m_pMemoryPool_32 )
{
delete m_pMemoryPool_32;
m_pMemoryPool_32 = NULL;
}
if ( NULL == m_pMemoryPool_64 )
{
delete m_pMemoryPool_64;
m_pMemoryPool_64 = NULL;
}
if ( NULL == m_pMemoryPool_128 )
{
delete m_pMemoryPool_128;
m_pMemoryPool_128 = NULL;
}
if ( NULL == m_pMemoryPool_256 )
{
delete m_pMemoryPool_256;
m_pMemoryPool_256 = NULL;
}
if ( NULL == m_pMemoryPool_512 )
{
delete m_pMemoryPool_512;
m_pMemoryPool_512 = NULL;
}
if ( NULL == m_pMemoryPool_1024 )
{
delete m_pMemoryPool_1024;
m_pMemoryPool_1024 = NULL;
}
if ( NULL == m_pMemoryPool_2048 )
{
delete m_pMemoryPool_2048;
m_pMemoryPool_2048 = NULL;
}
if ( NULL == m_pMemoryPool_4096 )
{
delete m_pMemoryPool_4096;
m_pMemoryPool_4096 = NULL;
}
}
char* CMemoryManager::GetBuffNode( DWORD dwDataLen )
{
DWORD dwType = ( DWORD )GetBufLenType( dwDataLen );
char *p = NULL;
p = GetBuffer( dwType );
return p;
}
BUFFER_LENGTH_TYPE CMemoryManager::GetBufLenType( DWORD dwDataLen )
{
if ( 4096 < dwDataLen )
{
return DATA_LENGTH_ERROR;
}
if ( dwDataLen <= 32 )
{
return DATA_LENGTH_32;
}
if ( ( dwDataLen > 32 ) && ( dwDataLen <= 64 ) )
{
return DATA_LENGTH_64;
}
if ( ( dwDataLen > 64 ) && ( dwDataLen <= 128 ) )
{
return DATA_LENGTH_128;
}
if ( ( dwDataLen > 128 ) && ( dwDataLen <= 256 ) )
{
return DATA_LENGTH_256;
}
if ( ( dwDataLen > 256 ) && ( dwDataLen <= 512 ) )
{
return DATA_LENGTH_512;
}
if ( ( dwDataLen > 512 ) && ( dwDataLen <= 1024 ) )
{
return DATA_LENGTH_1024;
}
if ( ( dwDataLen > 1024 ) && ( dwDataLen <= 2048 ) )
{
return DATA_LENGTH_2048;
}
if ( ( dwDataLen > 2048 ) && ( dwDataLen <= 4096 ) )
{
return DATA_LENGTH_4096;
}
return DATA_LENGTH_ERROR;
}
char* CMemoryManager::GetBuffer( DWORD dwType )
{
char* p = NULL;
switch ( dwType )
{
case ( DWORD )DATA_LENGTH_32:
{
p = m_pMemoryPool_32->GetBufferNode();
}
break;
case ( DWORD )DATA_LENGTH_64:
{
p = m_pMemoryPool_64->GetBufferNode();
}
break;
case ( DWORD )DATA_LENGTH_128:
{
p = m_pMemoryPool_128->GetBufferNode();
}
break;
case ( DWORD )DATA_LENGTH_256:
{
p = m_pMemoryPool_256->GetBufferNode();
}
break;
case ( DWORD )DATA_LENGTH_512:
{
p = m_pMemoryPool_512->GetBufferNode();
}
break;
case ( DWORD )DATA_LENGTH_1024:
{
p = m_pMemoryPool_1024->GetBufferNode();
}
break;
case ( DWORD )DATA_LENGTH_2048:
{
p = m_pMemoryPool_2048->GetBufferNode();
}
break;
case ( DWORD )DATA_LENGTH_4096:
{
p = m_pMemoryPool_4096->GetBufferNode();
}
break;
case ( DWORD )DATA_LENGTH_ERROR:
break;
default:
break;
}
return p;
}
BOOL CMemoryManager::AddBuffNode( char* pBuf, DWORD dwLenType )
{
if ( NULL == pBuf )
{
return FALSE;
}
BOOL b = TRUE;
switch ( dwLenType )
{
case ( DWORD )DATA_LENGTH_32:
{
m_pMemoryPool_32->AddBufferNode( pBuf );
}
break;
case ( DWORD )DATA_LENGTH_64:
{
m_pMemoryPool_64->AddBufferNode( pBuf );
}
break;
case ( DWORD )DATA_LENGTH_128:
{
m_pMemoryPool_128->AddBufferNode( pBuf );
}
break;
case ( DWORD )DATA_LENGTH_256:
{
m_pMemoryPool_256->AddBufferNode( pBuf );
}
break;
case ( DWORD )DATA_LENGTH_512:
{
m_pMemoryPool_512->AddBufferNode( pBuf );
}
break;
case ( DWORD )DATA_LENGTH_1024:
{
m_pMemoryPool_1024->AddBufferNode( pBuf );
}
break;
case ( DWORD )DATA_LENGTH_2048:
{
m_pMemoryPool_2048->AddBufferNode( pBuf );
}
break;
case ( DWORD )DATA_LENGTH_4096:
{
m_pMemoryPool_4096->AddBufferNode( pBuf );
}
break;
case ( DWORD )DATA_LENGTH_ERROR:
{
b = FALSE;
}
break;
default:
{
b = FALSE;
}
break;
}
return b;
}