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);

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;		// 单次回收的最大数量
};

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++ 中,pool_.Acquire 是一个自定义的对象池Object Pool)方法,用于获取一个新的对象。它的使用方式通常如下: 1. 定义一个对象池类,其中包含一个对象池变量 pool_,以及一个类模板 T。 ``` template <typename T> class ObjectPool { public: // 获取一个新的对象 T* Acquire(); // 释放一个对象 void Release(T* obj); }; ``` 2. 在 T 类中实现一个无参构造函数,用于创建对象。在 Acquire() 方法中,首先从对象池中获取一个对象,如果对象池为空,则调用 T 类的无参构造函数创建一个新对象并返回。 3. 在 Release(T *obj) 方法中,将传入的对象添加到对象池中。 下面是一个简单的示例代码: ``` template <typename T> class ObjectPool { public: T* Acquire() { if (pool_.empty()) { return new T(); } else { T* obj = pool_.back(); pool_.pop_back(); return obj; } } void Release(T *obj) { pool_.push_back(obj); } private: vector<T*> pool_; }; class MyClass { public: MyClass() { cout << "MyClass constructor called" << endl; } void SayHello() { cout << "Hello World!" << endl; } }; int main() { ObjectPool<MyClass> pool; MyClass* obj1 = pool.Acquire(); // 创建一个新的 MyClass 实例 obj1->SayHello(); // 输出 "Hello World!" pool.Release(obj1); // 将 obj1 添加到对象池中 MyClass* obj2 = pool.Acquire(); // 从对象池中获取 obj1 obj2->SayHello(); // 输出 "Hello World!" pool.Release(obj2); // 将 obj2 添加到对象池中 return 0; } ``` 在上述代码中,ObjectPool 类使用了 vector 容器来存储对象池。在 Acquire() 方法中,如果对象池为空,则调用 MyClass 的无参构造函数来创建一个新的 MyClass 实例,并返回新建的实例。在 Release() 方法中,将传入的对象添加到 vector 容器的末尾。在 main() 函数中,我们首先从对象池中获取一个 MyClass 实例,然后将其释放到对象池中。接着,我们再次从对象池中获取 MyClass 实例,验证对象池是否正常工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值