c++实现,对象池 object_pool

简言

1. boost的对象池object_pool在释放时采用的遍历,有性能问题

2. 也不是什么大问题,优化后可用。但是仅仅为了一个对象池,引入boost,没必要

3. 笔者这里一份简单实现的对象池,windows和linux下通用

4. 代码量很小,仅仅两百行,支持对象池高峰过后,逐步回收

接口介绍

1. // 初始化(初始数量,一次增长的数量, 单次收缩的数量)

bool init(int initNum = 200, int increaseNum = 100, int reduceNum = 50);

2. // 分配一个新对象
    T* alloc();

3. // 回收一个对象
    void dealloc(T* pObj);

扫描二维码关注公众号,回复: 9325835 查看本文章

4. // 执行一次回收,用来使用高峰过后的缩减
    void dorecycle();

代码下载地址

windows版:https://download.csdn.net/download/yzf279533105/11989303

实验如下图(特意标记出来两次回收之后的,每次回收50个,空闲列表free_list的数量)

完整代码

#pragma once

#include <unordered_set>
#include <string.h>

//对象池模板类
template<class T>
class class_obj_pool
{
public:
	enum
	{
		MAX_INIT_NUM = 100000,	// 初始化最大数量,暂定10万
	};

	class_obj_pool()
	{
		clear();
	}

	~class_obj_pool()
	{
		clear();
	}
public:
	// 初始化(初始数量,一次增长的数量, 单次收缩的数量)
	bool init(int initNum = 200, int increaseNum = 100, int reduceNum = 50)
	{
		// 参数检测
		if (initNum <= 0 || increaseNum <= 0 || reduceNum <= 0)
		{
			printf("init(), param error, initNum=%d, nIncreaseNum=%d, reduceNum=%d\n", initNum, increaseNum, reduceNum);
			return false;
		}

		nInitNum		= initNum;
		nIncreaseNum	= increaseNum;
		nShrinkNum		= reduceNum;

		// 参数修正
		nInitNum		= nInitNum>MAX_INIT_NUM ? MAX_INIT_NUM : nInitNum;			// 初始个数
		nIncreaseNum	= nIncreaseNum>MAX_INIT_NUM ? MAX_INIT_NUM : nIncreaseNum;	// 一次增长的数量

		// 初始化对象
		for (int i = 0; i<nInitNum; ++i)
		{
			T* pObj = new(std::nothrow)T();
			if (pObj == NULL)
			{
				printf("new obj failed \n");
				continue;
			}

			// T对象需提供init函数进行初始化
			if (pObj->init() == false)
			{
				printf("pObj->init() failed \n");
				delete pObj;
				continue;
			}

			free_list.insert(pObj);
		}

		return true;
	}

	// 分配一个新对象
	T* alloc()
	{
		T* pRet = NULL;

		// 空闲列表中有,则取一个
		if (free_list.size() > 0)
		{
			unordered_set<T*>::iterator iter = free_list.begin();
			pRet = *iter;

			free_list.erase(iter);
			used_list.insert(pRet);

			// 超过最大使用记录量,则更新
			if (used_list.size() > nUsedMax)
			{
				nUsedMax = used_list.size();
			}

			return pRet;
		}

		// 空闲列表中没有时,则新建一批
		for (int i = 0; i<nIncreaseNum; i++)
		{
			T* pObj = new(std::nothrow)T();
			if (pObj == NULL)
			{
				printf("alloc(), new obj failed \n");
				continue;
			}

			// T对象需提供init函数进行初始化
			if (pObj->init() == false)
			{
				printf("pObj->init() failed \n");
				delete pObj;
				continue;
			}

			// 没赋值的先赋值;已赋值的压入空闲列表
			if (pRet == NULL)
			{
				pRet = pObj;
				used_list.insert(pObj);
			}
			else
			{
				free_list.insert(pObj);
			}
		}

		// 超过最大使用记录量,则更新
		if (used_list.size() > nUsedMax)
		{
			nUsedMax = used_list.size();
		}

		return pRet;
	}

	// 回收一个对象
	void dealloc(T* pObj)
	{
		if (pObj == NULL)
		{
			printf("dealloc(), pObj == NULL");
			return;
		}

		// 不存在
		unordered_set<T*>::iterator it = used_list.find(pObj);
		if (it == used_list.end())
		{
			printf("dealloc(), find pObj failed \n");
			return;
		}

		// T对象需提供reset()函数进行重置
		pObj->reset();

		free_list.insert(pObj);
		used_list.erase(pObj);
	}

	// 执行一次回收,用来使用高峰过后的缩减
	void dorecycle()
	{
		// 空闲列表中有对象,且超过一次增量时,才进行回收
		int nfree = free_list.size();
		if (nfree <= nIncreaseNum)
		{
			return;
		}

		// 要回收的数量
		nfree = (nfree - nIncreaseNum);
		int i = 0;
		for (unordered_set<T*>::iterator iter = free_list.begin(); iter != free_list.end();)
		{
			T* pObj = *iter;
			if (pObj != NULL)
			{
				delete pObj;
			}

			free_list.erase(iter++);
			
			// 超过一次回收的最大量,就跳出
			i++;
			if (i>=nShrinkNum)
			{
				break;
			}
		}
	}

	// 打印出各个变量
	void showinfo()
	{
		printf("free_list.size=%d, used_list.size=%d, nUsedMax=%d \n", free_list.size(), used_list.size(), nUsedMax);
	}

	// 回收
	void clear()
	{
		for (std::unordered_set<T*>::iterator iter = free_list.begin(); iter != free_list.end(); iter++)
		{
			T* pObj = *iter;
			if (pObj != NULL)
			{
				delete pObj;
			}
		}
		free_list.clear();

		for (std::unordered_set<T*>::iterator iter = used_list.begin(); iter != used_list.end(); iter++)
		{
			T* pObj = *iter;
			if (pObj != NULL)
			{
				delete pObj;
			}
		}
		used_list.clear();

		nInitNum = 0;	// 初始个数
		nUsedMax = 0;	// 曾经使用的最大个数
		nIncreaseNum = 0;	// 一次增长的数量
		nShrinkNum = 0;	// 单次回收的最大数量
	}
private:
	std::unordered_set<T*> 	free_list;		// 空闲列表
	std::unordered_set<T*> 	used_list;		// 使用中的列表
	int 					nInitNum;		// 初始个数
	int 					nUsedMax;		// 曾经使用的最大个数
	int 					nIncreaseNum;	// 一次增长的数量
	int 					nShrinkNum;		// 单次回收的最大数量
};
发布了105 篇原创文章 · 获赞 58 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/yzf279533105/article/details/103177192