内存池

#ifndef __MEMORYPOOL__H__
#define __MEMORYPOOL__H__

#include <mutex>

#define MemCount  13
//#define UseMulThread

enum MemorySize
{
	Mem4 = 0,
	Mem8 = 1,
	Mem16 = 2,
	Mem32 = 3,
	Mem64 = 4,
	Mem128 = 5,
	Mem256 = 6,
	Mem512 = 7,
	Mem1024 = 8,
	Mem2048 = 9,
	Mem4096 = 10,
	Mem8192 = 11,
	MemBig = 12
};

struct MemoryNode
{
	MemoryNode(){
		memset(this, 0, sizeof(*this));
	}
	char *data;
	MemoryNode *next;
};

struct MemoryData
{
	MemoryData(){
		memset(this, 0, sizeof(*this));
	}
	int nCount;
	int nUnit;
	MemoryNode *use;
	MemoryNode *free;
	MemoryNode *freeLast;
	MemoryData *next;
	char *data;

};

class MemoryPool
{
public:
	MemoryPool();
	~MemoryPool();
	bool Init();
	int GetMemSize(int num);
	int GetMemKey(int nSize);
	void *GetMem(int nSize);
	MemoryData * CreateMeo(int nKey);
	MemoryData * CreateBigMeo(int nSize);
	bool FreeMeo(void *address, int nSize = 0);
	bool FreeOnKey(void *address, int nKey);
	void DestoryMeo();

public:
#ifdef UseMulThread
	std::mutex m_DataMutex;
#endif
	MemoryData m_Data[MemCount];
	int m_nCount;		//单个模块小块数量
};


extern MemoryPool *g_Memory;
#endif


#include "MemoryPool.h"

MemoryPool *g_Memory = nullptr;

MemoryPool::MemoryPool()
{

}

MemoryPool::~MemoryPool()
{
	DestoryMeo();
}

int MemoryPool::GetMemSize(int num)
{
	switch (num)
	{
	case Mem4: return 4;
	case Mem8: return 8;
	case Mem16: return 16;
	case Mem32:return 32;
	case Mem64:return 64;
	case Mem128:return 128;
	case Mem256:return 256;
	case Mem512:return 512;
	case Mem1024:return 1024;
	case Mem2048:return 2048;
	case Mem4096:return 4096;
	case Mem8192:return 8192;
	case MemBig:return 0;
	default:
		return -1;
	}
}

//初始化
bool MemoryPool::Init()
{
	//每个块数量
	m_nCount = 1000;

	for (int i = 0; i < MemCount; i++)
	{
		if (i == MemBig)
			continue;
		//当前块大小
		int nUnit = GetMemSize(i);
		if (nUnit <= 0)
			continue;
		m_Data[i].nCount = m_nCount;
		m_Data[i].nUnit = nUnit;
		//申请内存
		m_Data[i].data = new char[m_nCount * nUnit];

		//申请失败 数量减半重新申请
		while (m_Data[i].nCount > 0 && m_Data[i].data == nullptr)
		{
			m_Data[i].nCount /= 2;
			m_Data[i].data = new char[m_Data[i].nCount * nUnit];
		}

		//每个大模块未使用小块 单独用指针连接起来
		for (int j = 0; j < m_Data[i].nCount; j++)
		{
			MemoryNode * n = new MemoryNode;
			n->data = m_Data[i].data + j * m_Data[i].nUnit;
			if (m_Data[i].free == nullptr)
			{
				m_Data[i].free = n;
				m_Data[i].freeLast = n;
			}
			else
			{
				m_Data[i].freeLast->next = n;
				m_Data[i].freeLast = n;
			}
		}
	}

	return true;
}

int MemoryPool::GetMemKey(int nSize)
{
	//当前大小 匹配对应的模块id
	int i = Mem8192;
	for (i = Mem8192; i >= 0; i--)
	{
		int nUnit = GetMemSize(i);
		if (nSize > nUnit)
			return i + 1;
	}
	return Mem4;
}

//申请内存
void *MemoryPool::GetMem(int nSize)
{
	if (nSize <= 0) return nullptr;

#ifdef UseMulThread
	m_DataMutex.lock();
#endif

	//申请内存大小的对应模块id
	int nKey = GetMemKey(nSize);
	//std::cout << "分配大小 = " << nSize << std::endl;
	//当前大模块是否还有未使用小块
	MemoryData *t = &m_Data[nKey];
	while (t)
	{
		if (t->free != nullptr)
			break;
		t = t->next;
	}

	//不是超大模块
	if (nKey != MemBig)
	{
		//还有未使用小块
		if (t)
		{
			//取出未使用小块
			MemoryNode *n = t->free;
			t->free = t->free->next;
			n->next = nullptr;

			//使用小块链表为空
			if (t->use == nullptr)
			{
				t->use = n;
			}
			else{
				//将取出小块添加到 使用链表中
				MemoryNode *m = t->use;
				while (m && m->next)
				{
					m = m->next;
				}
				m->next = n;
			}
#ifdef UseMulThread
			m_DataMutex.unlock();
#endif
			return n->data;
		}
		else{
			//没有为使用的小块了
			//重新分配一个大模块
			MemoryData * newdata = CreateMeo(nKey);
			if (newdata == nullptr)
			{
#ifdef UseMulThread
				m_DataMutex.unlock();
#endif
				return nullptr;
			}

			//添加到对应模块id中
			t = &m_Data[nKey];
			while (t && t->next)
			{
				t = t->next;
			}
			t->next = newdata;

			t = newdata;

			//从重新分配的大模块中取出为使用的小块
			MemoryNode *n = t->free;
			t->free = t->free->next;
			n->next = nullptr;

			//添加到使用链表中
			if (t->use == nullptr)
			{
				t->use = n;
			}
			else{
				MemoryNode *m = t->use;
				while (m && m->next)
				{
					m = m->next;
				}
				m->next = n;
			}
#ifdef UseMulThread
			m_DataMutex.unlock();
#endif
			return n->data;
		}
	}
	else{
		//当前是超大模块 超过8192大小
		t = &m_Data[nKey];
		//根节点为空 直接申请内存
		if (t->data == nullptr)
		{
			t->nUnit = nSize;
			t->nCount = 1;
			t->data = new char[nSize];
#ifdef UseMulThread
			m_DataMutex.unlock();
#endif
			return t->data;
		}
		else{
			//申请内存 并添加到超大模块链表中
			MemoryData * newdata = CreateBigMeo(nSize);
			if (newdata == nullptr)
			{
#ifdef UseMulThread
				m_DataMutex.unlock();
#endif
				return nullptr;
			}
#ifdef UseMulThread
			m_DataMutex.unlock();
#endif
			return newdata->data;
		}
	}
#ifdef UseMulThread
	m_DataMutex.unlock();
#endif
	return nullptr;
}

MemoryData * MemoryPool::CreateBigMeo(int nSize)
{
	/*MemoryData *t = &m_Data[MemBig];
	while (t)
	{
	if (t->nCount == 0 && t->data != nullptr && t->nUnit >= nSize)
	{
	t->nCount = 1;
	return t;
	}
	t = t->next;
	}*/

	//申请超大内存
	MemoryData * dd = new MemoryData;
	dd->nUnit = nSize;
	dd->nCount = 1;
	dd->data = new char[nSize];
	if (dd->data == nullptr)
	{
		delete dd;
		dd = nullptr;
		return nullptr;
	}

	//添加到链表中
	MemoryData *t = &m_Data[MemBig];
	while (t && t->next)
	{
		t = t->next;
	}
	t->next = dd;
	return dd;

}

//重新分配大模块
MemoryData * MemoryPool::CreateMeo(int nKey)
{
	//当前模块单位大小
	int nUint = GetMemSize(nKey);
	MemoryData * dd = new MemoryData;
	if (nUint > 0)
	{
		dd->nUnit = nUint;
		dd->nCount = m_nCount;
		dd->data = new char[dd->nUnit * dd->nCount];

		//分配失败 数量减半重新申请
		while (dd->nCount > 0 && dd->data == nullptr)
		{
			dd->nCount /= 2;
			dd->data = new char[dd->nUnit * dd->nCount];
		}
		//将未使用小块 添加到未使用链表中
		for (int j = 0; j < dd->nCount; j++)
		{
			MemoryNode * n = new MemoryNode;
			n->data = dd->data + j * dd->nUnit;
			if (dd->free == nullptr)
			{
				dd->free = n;
				dd->freeLast = n;
			}
			else
			{
				dd->freeLast->next = n;
				dd->freeLast = n;
			}
		}
	}
	else{
		delete dd;
		dd = nullptr;
		return nullptr;
	}

	return dd;
}

bool MemoryPool::FreeOnKey(void *address, int nKey)
{
	//是超大内存
	if (nKey == MemBig)
	{
		MemoryData *t = &m_Data[nKey];
		MemoryData *father = t;
		while (t)
		{
			if (t->data == address)
			{
				if (t == &m_Data[nKey])
				{
					delete m_Data[nKey].data;
					m_Data[nKey].data = nullptr;
				}
				else{
					father->next = t->next;
					delete t->data;
					t->data = nullptr;

					delete t;
					t = nullptr;
				}
				return true;
			}
			father = t;
			t = t->next;
		}
	}
	else{
		//不是超大内存 查找当前模块
		MemoryData *t = &m_Data[nKey];
		while (t)
		{
			int a = (int)t->data;
			int b = (int)(t->data + t->nUnit * t->nCount);
			//地址的范围
			int min = (a > b ? b : a);
			int max = (a > b ? a : b);
			int id = (int)address;

			//当前释放地址在 当前模块地址范围内
			if (id >= min && id <= max)
			{
				//
				MemoryNode *inFind = t->use;
				MemoryNode *father = inFind;
				//从使用链表中删除当前小块 加入到未使用链表中
				while (inFind)
				{
					if (inFind->data == address)
					{
						t->freeLast->next = inFind;
						t->freeLast = inFind;

						if (father == t->use)
						{
							t->use = nullptr;
						}
						else{
							father->next = inFind->next;
						}
						return true;
					}
					father = inFind;
					inFind = inFind->next;
				}
			}
			t = t->next;
		}
	}
	return false;
}

//释放内存
bool MemoryPool::FreeMeo(void *address, int nSize)
{
	if (address == nullptr) return false;
	//std::cout << "释放大小 = " << nSize << std::endl;

#ifdef UseMulThread
	m_DataMutex.lock();
#endif

	if (nSize != 0)
	{
		//释放内存大小对应的模块id
		int nKey = GetMemKey(nSize);
		//释放对应模块的内存
		bool result = FreeOnKey(address, nKey);

#ifdef UseMulThread
		m_DataMutex.unlock();
#endif

		return  result;
	}
	else{
		//不知道释放大小 从各个模块中依次查找
		for (int i = Mem4; i <= MemBig; i++)
		{
			if (FreeOnKey(address, i))
			{

#ifdef UseMulThread
				m_DataMutex.unlock();
#endif

				return true;
			}
		}
	}

#ifdef UseMulThread
	m_DataMutex.unlock();
#endif
	return false;
}

//销毁内存池
void MemoryPool::DestoryMeo()
{
	for (int i = 0; i < MemCount; i++)
	{
		MemoryData *first = &m_Data[i];
		while (first)
		{
			if (first->data)
			{
				delete[] first->data;
				first->data = nullptr;
			}

			MemoryNode * second = first->free;
			while (second)
			{
				MemoryNode *freenode = second;
				second = second->next;

				delete freenode;
				freenode = nullptr;
			}

			if (first->freeLast)
			{
				delete first->freeLast;
				first->freeLast = nullptr;
			}

			second = first->use;
			while (second)
			{
				MemoryNode *freenode = second;
				second = second->next;

				delete freenode;
				freenode = nullptr;
			}

			MemoryData *mustFree = first;
			first = first->next;

			if (mustFree != &m_Data[i])
			{
				delete mustFree;
				mustFree = nullptr;
			}
			else{
				m_Data[i].next = nullptr;
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值