Memory pool implementation with c + + code

To: memory pool
1. Avoid frequent memory allocation and release.
2. Even if the memory user forgets to release the memory, the memory will not be lost. They are still stored in the memory pool. When the memory pool is destroyed, the memory will be destroyed automatically.

3. Realize dynamic variable size allocation of memory, break the limit of solidification size of simple memory pool in the past.

MemPool.h

#pragma once
#include <list>
using namespace std;


//Memory pool
class CMemPool
{
public:
	//uMaxSize: threshold
	CMemPool(UINT uMaxFree = 5);
	virtual ~CMemPool(void);

	//List node
	struct list_node
	{
		list_node():size(0),pbuf(NULL)
		{}
		UINT  size;
		char* pbuf;
	};

	typedef list<list_node> LISTMEMORY;
	typedef list<list_node>::iterator ITLISTMEM0RY;

public:
	//Initialization threshold uMaxSize: threshold
	void InitMem(UINT uMaxFree);

	//Request memory
	char * NewMem(size_t size);

	//Free memory
	void FreeMem(char * pbuf);

	//Free all memory
	void FreeAllMem();

protected:
	//Allocate a new block of memory - use in critical area
	char * Newbuf(size_t size);
	//Get maximum memory block size - use in critical area
	UINT GetMaxBuf();

private:
	CRITICAL_SECTION    m_cris;       //Cache critical area

	LISTMEMORY          m_listFree;   //Free memory block
	LISTMEMORY          m_listUsed;   //Memory block in use

	UINT                m_uMaxFree;   //Free memory threshold, which can be directly released and returned to the system
};

MemPool.cpp

#include "StdAfx.h"
#include "MemPool.h"
#include <assert.h>


CMemPool::CMemPool(UINT uMaxFree/* = 5*/)
					: m_uMaxFree(uMaxFree)
{
	//Judge whether the parameters are legal
	assert(uMaxFree);
	//Critical area
	InitializeCriticalSection(&m_cris);
}

CMemPool::~CMemPool(void)
{
	EnterCriticalSection(&m_cris);
	ITLISTMEM0RY it;
	//Free free queue memory
	if (!m_listFree.empty())
	{
		for(it = m_listFree.begin();it != m_listFree.end();it++)
		{
			if( (*it).pbuf )
				delete[] (*it).pbuf;
		}
		m_listFree.clear();
	}
	//Free memory in use
	if (!m_listUsed.empty())
	{
		for(it = m_listUsed.begin();it != m_listUsed.end();it++)
		{
			if( (*it).pbuf )
				delete[] (*it).pbuf;
		}
		m_listUsed.clear();
	}
	LeaveCriticalSection(&m_cris);
	//Delete critical area
	DeleteCriticalSection(&m_cris);
}
//Initialization threshold
void CMemPool::InitMem(UINT uMaxFree)
{
	//Judge whether the parameters are legal
	assert(uMaxFree);
	m_uMaxFree = uMaxFree;
}
//Request memory
char * CMemPool::NewMem(size_t size)
{
	EnterCriticalSection(&m_cris);

	char * ptr = NULL;
	//Determine whether there is free memory block currently
	if(!m_listFree.empty() && GetMaxBuf()>=size)
	{
		ITLISTMEM0RY it = m_listFree.begin();
		for(; it!=m_listFree.end(); it++)
		{
			if( (*it).size >= size )
			{
				ptr = (*it).pbuf;
				//Put memory block in use queue
				m_listUsed.push_back(*it);
				m_listFree.erase(it);
				//Sign out
				LeaveCriticalSection(&m_cris);
				return ptr;
			}
		}
	}
	//Allocate a new piece of memory
	try{
		ptr = Newbuf(size);
	}
	catch(...)
	{
	}
	LeaveCriticalSection(&m_cris);
	return ptr;
}

//Free memory
void CMemPool::FreeMem(char * pbuf)
{
	if (!pbuf) return;
	EnterCriticalSection(&m_cris);
	//Find blocks of memory to free in use queue
	ITLISTMEM0RY it = m_listUsed.begin();
	for(;it != m_listUsed.end();++it)
	{
		if ( (*it).pbuf == pbuf)
		{
			//Determine whether the current idle queue is greater than the initial value
			if (m_listFree.size() < m_uMaxFree)
			{
				//If it is less than the threshold, put the memory block in the idle queue
				memset( (*it).pbuf,0, (*it).size);
				m_listFree.push_back(*it);
			}
			else
			{
				//Determine whether the current idle queue is greater than or equal to the threshold, then release the memory block
				if( (*it).pbuf )
					delete[] (*it).pbuf;
			}
			//Remove memory block from use queue
			m_listUsed.erase(it);
			break;
		}
	}
	LeaveCriticalSection(&m_cris);
}

//Free all memory
void CMemPool::FreeAllMem()
{
	//Move blocks of memory from the use list to the free list
	EnterCriticalSection(&m_cris);
	ITLISTMEM0RY it = m_listUsed.begin();
	for(; it != m_listUsed.end() && m_listFree.size() < m_uMaxFree; it++)
	{
		if( (*it).pbuf && (*it).size)
		{
			memset( (*it).pbuf,0,(*it).size);
			m_listFree.push_back(*it);
		}
	}
	//Directly destroy the part exceeding the threshold
	for(;it != m_listUsed.end(); it++)
	{
		if( (*it).pbuf )
			delete[] (*it).pbuf;
	}
	//Clear use list
	m_listUsed.clear();
	LeaveCriticalSection(&m_cris);
}

//Allocate a new piece of memory
char * CMemPool::Newbuf(size_t size)
{
	list_node node;
	//Allocate a new piece of memory
	node.pbuf = new char[size];

	ASSERT(node.pbuf);
	if(!node.pbuf)
		return NULL;
	node.size = size;
	memset(node.pbuf,0,node.size);//Clean up memory

	m_listUsed.push_back(node);
	return node.pbuf;
}

//Get the maximum memory block size
UINT CMemPool::GetMaxBuf()
{
	UINT uiMax = 0;
	ITLISTMEM0RY it = m_listFree.begin();
	for(;it != m_listFree.end(); it++)
	{
		if( (*it).size > uiMax)
			uiMax = (*it).size;
	}
	return uiMax;
}

This code is included in the project of Zhongzhuo COM32.

Tags: less

Posted on Tue, 05 May 2020 14:13:26 -0400 by spetstnelis