一個依靠STL vector的接口進行申請和回收管理的內存池類( c++ 封裝)

問題描述:

1.利用STL vector維護不同的多個定長單元的內存塊;

2.當內存池外部申請內存是,利用STL vector at 接口和有效內存索引高效返回所需內存,然後增加有效內存索引到下一個;

3.當外部交還內存到池子時,交換這個有效內存到當前無效的內存塊位置,並縮減有效內存索引;

4.如此複雜的操作是問了保證內存池的性能;



程序代碼:

#ifndef _MEMORY_BLOCK_POOL_H_
#define _MEMORY_BLOCK_POOL_H_


#include <stdlib.h>
#include <vector>

#include "windows.h"


#define ALIGN( size, bits )  ( ( ( ( size - 1 ) >> bits ) + 1 ) << bits )


/*
* memory pool fixed length block 
*
*
*/
class MemoryBlockPool
{
public:
	static const int MAXBLOCK = 256;
	static const int MALLOCKSIZE = 4096;
	static const int DEFAULTBASELEN = 4;

	typedef struct tagMemStatInfo
	{
		char*   allocMem;
		size_t  allocSize;

		tagMemStatInfo():allocMem(0),allocSize(0)
		{

		}

		tagMemStatInfo( char* mem, size_t size ):allocMem(mem),
			           allocSize(size)
		{

		}

	}MemStatInfo, *pMemStatInfo;


	typedef struct tagMemoryBlock
	{
		std::vector<char*>      Block;
		size_t                  validIdx;

		tagMemoryBlock():Block(), validIdx(0)
		{

		}
	}MemoryBlock, *pMemoryBlock;

	typedef std::vector<char*> BlockContainer;



	/*
	*
	*
	*/
	MemoryBlockPool( size_t baseLen =  DEFAULTBASELEN ):m_pool(0),
		             m_poolSize(0), m_baseLen(baseLen),
					 m_memStat()
	{
		Init( m_baseLen );
	}


	/*
	*
	*
	*/
	~MemoryBlockPool()
	{
		Release();
	}


	/*
	* Release all memory allocated
	*
	*/
	void Release()
	{
		std::vector<MemStatInfo>::iterator iter = m_memStat.begin();
		while( iter != m_memStat.end() )
		{
			free( iter->allocMem );
			++iter;
		}

		for( size_t i = 0; i < m_poolSize; i++ )
		{
			m_pool[i].Block.clear();
		}
	}


	/*
	* get memory for given length from cahce array or os
	*
	*/
	void* Malloc( size_t len )
	{
		assert( len > 0 );
		size_t size = ALIGN( len, 2 );
		if( size > MAXBLOCK )
		{
			return malloc(size);
		}
		
		if( !m_pool[size].Block.size() )
		{
			size_t memLen = size + 4;
			char* buf = (char*)malloc( MALLOCKSIZE );
			size_t blockNums = MALLOCKSIZE / memLen;
            
			BlockContainer& container = m_pool[size].Block;
			container.reserve( blockNums );
			for( size_t i = 0; i < blockNums; i++ )
			{
				*(buf + i * size) = i;
				container.push_back( buf + i * size );
			}

			m_memStat.push_back( MemStatInfo( buf, MALLOCKSIZE ) );

		}
		else if( m_pool[size].validIdx == m_pool[size].Block.size() )
		{
			size_t memLen = size + 4;
			char* buf = (char*)malloc( MALLOCKSIZE );
			size_t blockNums = MALLOCKSIZE / memLen;

			BlockContainer& container = m_pool[size].Block;
			for( size_t i = 0; i < blockNums; i++ )
			{
				*(int*)(buf + i * size) = i + container.size();
				container.push_back( buf + i * size );
			}
		}

		char* buf = m_pool[size].Block.at( m_pool[size].validIdx );
		m_pool[size].validIdx++;

		return buf + 4;

	}


	/*
	* give back memory to cache or os
	*
	*/
	void Free( void* mem, size_t len )
	{
		assert( len > 0 );
		size_t size = ALIGN( len, 2 );
		if( size > MAXBLOCK )
		{
			return free( mem );
		}

		char* buf = (char*)mem;
		buf -= 4;

		if( m_pool[size].validIdx )
		{
			Swap( m_pool[size].Block.at( m_pool[size].validIdx - 1), buf );
			m_pool[size].validIdx--;
		}

	}

private:

	void Swap( char*& bufFirst, char*& bufSecond )
	{
		char* temp = bufFirst;
		bufFirst = bufSecond;
		bufSecond = temp;
	}

	/*
	*
	*
	*/
	void Init( size_t baseLen )
	{
		m_poolSize = MAXBLOCK / baseLen;
		m_pool = new MemoryBlock[m_poolSize];
	}

private:
	MemoryBlock         *m_pool;      // memory block array
	size_t               m_poolSize;  // the size of memory block array
	size_t               m_baseLen;   // 
	std::vector<MemStatInfo> m_memStat;

	
};

//test object one
typedef struct tagTestObjFirst
{
	int first;
	int second;

	tagTestObjFirst():first(0), second(0)
	{

	}

	tagTestObjFirst( int i, int j ):first(i), second(j)
	{

	}
}TestObjFirst, *pTestObjFrist;


// test object two
typedef struct tagTestObjSecond
{
	int first;
	int second;
	std::string  name;

	tagTestObjSecond():first(0), second(0)
	{

	}

	tagTestObjSecond( int i, int j, const char* str ):first(i), second(j), name( str )
	{

	}

}TestObjSecond, *pTestObjSecond;


/*
* Test os memory operation
*
*/
void BlockTestOSMemory()
{
	unsigned long start = GetTickCount();

	const int len = 2000000;
	int halfLen = len / 2;

	pTestObjFrist* objs = new pTestObjFrist[len];
	pTestObjSecond* objExts = new pTestObjSecond[len];
	for( int i = 0; i < len; i++ )
	{
		objs[i] = new TestObjFirst( i, i );
		objExts[i] = new TestObjSecond( i, i, "test" );
		delete objs[i];
		delete objExts[i];
		
	}

	
	
	unsigned long interval = GetTickCount() - start;
	printf(" system call consume time  %d for memory operation \n", interval );

	delete [] objs;
	delete [] objExts;
}

/*
*Test memory pool 
*
*
*/
void BlockTestMemoryBlock()
{
	unsigned long start = GetTickCount();

	const int len = 2000000;
	int halfLen = len / 2;

	MemoryBlockPool memPool;
	pTestObjFrist* objs = new pTestObjFrist[len];
	pTestObjSecond* objExts = new pTestObjSecond[len];
	for( int i = 0; i < len; i++ )
	{
		void* buf = memPool.Malloc( sizeof(TestObjFirst) );
		objs[i] = new (buf) TestObjFirst( i, i );

		buf = memPool.Malloc( sizeof(TestObjSecond) );
		objExts[i] = new (buf) TestObjSecond( i, i, "test" );

		memPool.Free( buf, sizeof(TestObjFirst) );

		memPool.Free( buf, sizeof(TestObjSecond) );
		
	}


	unsigned long interval = GetTickCount() - start;
	printf(" memory pool call consume time  %d for memory operation \n", interval );

	delete [] objs;
	delete [] objExts;
}


/*
*Test interface for memory operation
*
*
*/
void TestSuiteCacheBlock()
{

	BlockTestMemoryBlock();
	BlockTestOSMemory();
}

#endif 

compile and run in visual studio 2005
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章