(原创)一个超级对象池的实现
2014-05-08 10:27
369 查看
转自:http://www.cnblogs.com/qicosmos/p/3673723.html
对象池对于创建开销比较大的对象来说很有意义,为了避免重复创建开销比较大的对象,我们可以通过对象池来优化。对象池的思路比较简单,事先创建好一批对象,放到一个集合中,以后每当程序需要新的对象时候,都从对象池里获取,每当程序用完该对象后,都把该对象归还给对象池。这样会避免重复的对象创建,提高程序性能。先来看看对象池的简单实现:
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
View Code
这个object pool的实现很典型,初始创建一定数量的对象,取的时候就直接从池子中取,用完之后再回收到池子。一般的对象池的实现思路和这个类似,这种实现方式虽然能达到目的,但是存在以下不足:
对象池ObjectPool<T>只能容纳特定类型的对象,不能容纳所有类型的对象,可以支持重载的和参数不同的构造函数;
对象用完之后需要手动回收,用起来不够方便,更大的问题是存在忘记回收的风险;
我希望能有一个更强大的对象池,这个对象池能容纳所有的对象,还能自动回收用完了对象,不需要手动回收,用起来更方便。要实现这样的对象池需要解决前面提到的两个问题,通过c++11就可以解决这两个问题。
对于问题1:容纳所有的对象。本质上需要将对象池中的对象类型擦除,这里用Any类型就可以解决。
对于问题2:自动回收用完的对象。这里用智能指针就可以解决,在创建智能指针时可以指定删除器,在删除器中不删除对象,而是回收到对象池中,而这个过程对外界来说是看不见的,由智能指针自己完成。关于Any的实现见我前面的博客内容:c++11打造好用的Any。
下面来看看超级对象池的具体实现吧。
测试代码:
测试结果:
![](http://images.cnitblog.com/i/468725/201404/181722485255778.jpg)
可以看到这个对象池不仅仅能容纳所有类型的对象还能自动回收用完的对象,强大而又方便。
2)(原创)C++半同步半异步线程池
http://www.cnblogs.com/qicosmos/archive/2013/05/30/3108010.html
3)(原创)如何使用boost.asio写一个简单的通信程序(一)
http://www.cnblogs.com/qicosmos/p/3461116.html
4)(原创)如何使用boost.asio写一个简单的通信程序(二)
http://www.cnblogs.com/qicosmos/p/3471314.html
5)(原创)谈谈boost.asio的异步发送
http://www.cnblogs.com/qicosmos/p/3487169.html
6)http://www.cnblogs.com/qicosmos/category/538859.html
(原创)用c++11打造好用的any
http://www.cnblogs.com/qicosmos/p/3420095.html
(原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
http://www.cnblogs.com/qicosmos/p/3555668.html
(原创)composite模式和bridge模式是天生的好朋友
http://www.cnblogs.com/qicosmos/p/3658750.html
对象池对于创建开销比较大的对象来说很有意义,为了避免重复创建开销比较大的对象,我们可以通过对象池来优化。对象池的思路比较简单,事先创建好一批对象,放到一个集合中,以后每当程序需要新的对象时候,都从对象池里获取,每当程序用完该对象后,都把该对象归还给对象池。这样会避免重复的对象创建,提高程序性能。先来看看对象池的简单实现:
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#include <list> template<typename Object> class ObjectPool { public: ObjectPool(size_t unSize) : m_unSize(unSize) { for (size_t unIdx = 0; unIdx < m_unSize; ++ unIdx) { m_oPool.push_back(new Object()); } } ~ObjectPool() { typename std::list<Object *>::iterator oIt = m_oPool.begin(); while (oIt != m_oPool.end()) { delete (*oIt); ++ oIt; } m_unSize = 0; } Object * GetObject() { Object * pObj = NULL; if (0 == m_unSize) { pObj = new Object(); } else { pObj = m_oPool.front(); m_oPool.pop_front(); -- m_unSize; } return pObj; } void ReturnObject(Object * pObj) { m_oPool.push_back(pObj); ++ m_unSize; } private: size_t m_unSize; std::list<object *> m_oPool; };
View Code
这个object pool的实现很典型,初始创建一定数量的对象,取的时候就直接从池子中取,用完之后再回收到池子。一般的对象池的实现思路和这个类似,这种实现方式虽然能达到目的,但是存在以下不足:
对象池ObjectPool<T>只能容纳特定类型的对象,不能容纳所有类型的对象,可以支持重载的和参数不同的构造函数;
对象用完之后需要手动回收,用起来不够方便,更大的问题是存在忘记回收的风险;
我希望能有一个更强大的对象池,这个对象池能容纳所有的对象,还能自动回收用完了对象,不需要手动回收,用起来更方便。要实现这样的对象池需要解决前面提到的两个问题,通过c++11就可以解决这两个问题。
对于问题1:容纳所有的对象。本质上需要将对象池中的对象类型擦除,这里用Any类型就可以解决。
对于问题2:自动回收用完的对象。这里用智能指针就可以解决,在创建智能指针时可以指定删除器,在删除器中不删除对象,而是回收到对象池中,而这个过程对外界来说是看不见的,由智能指针自己完成。关于Any的实现见我前面的博客内容:c++11打造好用的Any。
下面来看看超级对象池的具体实现吧。
#include <string> #include <functional> #include <tuple> #include <map> using namespace std; #include <Any.hpp> const int MaxObjectNum = 10; class ObjectPool { template<typename T, typename... Args> using Constructor = std::function<std::shared_ptr<T>(Args...)>; public: ObjectPool() { } ~ObjectPool() { } //默认创建多少个对象 template<typename T, typename... Args> void Create(int num) { if (num <= 0 || num > MaxObjectNum) throw std::logic_error("object num errer"); auto constructName = typeid(Constructor<T, Args...>).name(); Constructor<T, Args...> f = [constructName, this](Args... args) { return std::shared_ptr<T>(new T(args...),[constructName, this](T* t) { m_object_map.emplace(constructName, std::shared_ptr<T>(t)); }); }; m_map.emplace(typeid(T).name(), f); m_counter.emplace(constructName, num); } template<typename T, typename... Args> std::shared_ptr<T> Get(Args... args) { using ConstructType = Constructor<T, Args...>; string constructName = typeid(ConstructType).name(); auto range = m_map.equal_range(typeid(T).name()); for (auto it = range.first; it != range.second; ++it) { if (it->second.Is<ConstructType>()) { auto ptr = GetInstance<T>(constructName, args...); if (ptr != nullptr) return ptr; return CreateInstance<T, Args...>(it->second, constructName, args...); } } return nullptr; } private: template<typename T, typename... Args> std::shared_ptr<T> CreateInstance(Any& any, string& constructName, Args... args) { using ConstructType = Constructor<T, Args...>; ConstructType f = any.AnyCast<ConstructType>(); InitPool(f, constructName, args...); return f(args...); } template<typename T, typename... Args> void InitPool(T& f, string& constructName, Args... args) { int num = m_counter[constructName]; if (num != 0) { for (int i = 0; i < num - 1; i++) { m_object_map.emplace(constructName, f(args...)); } m_counter[constructName] = 0; } } template<typename T, typename... Args> std::shared_ptr<T> GetInstance(string& constructName, Args... args) { auto it = m_object_map.find(constructName); if (it == m_object_map.end()) return nullptr; auto ptr = it->second.AnyCast<std::shared_ptr<T>>(); if (sizeof...(Args)>0) *ptr.get() = std::move(T(args...)); m_object_map.erase(it); return ptr; } private: multimap<string, Any> m_map; multimap<string, Any> m_object_map; map<string, int> m_counter; };
测试代码:
struct AT { AT(){} AT(int a, int b) :m_a(a), m_b(b){} void Fun() { cout << m_a << " " << m_b << endl; } int m_a = 0; int m_b = 0; }; struct BT { void Fun() { cout << "from object b " << endl; } }; void TestObjectPool() { ObjectPool pool; pool.Create<AT>(2); pool.Create<BT>(2); pool.Create<AT, int, int>(2); { auto p = pool.Get<AT>(); p->Fun(); } auto pb = pool.Get<BT>(); pb->Fun(); auto p = pool.Get<AT>(); p->Fun(); int a = 5, b = 6; auto p2 = pool.Get<AT>(a, b); p2->Fun(); auto p3 = pool.Get<AT>(3, 4); p3->Fun(); { auto p4 = pool.Get<AT>(3, 4); p4->Fun(); } auto p4 = pool.Get<AT>(7, 8); p4->Fun(); }
测试结果:
![](http://images.cnitblog.com/i/468725/201404/181722485255778.jpg)
可以看到这个对象池不仅仅能容纳所有类型的对象还能自动回收用完的对象,强大而又方便。
2)(原创)C++半同步半异步线程池
http://www.cnblogs.com/qicosmos/archive/2013/05/30/3108010.html
3)(原创)如何使用boost.asio写一个简单的通信程序(一)
http://www.cnblogs.com/qicosmos/p/3461116.html
4)(原创)如何使用boost.asio写一个简单的通信程序(二)
http://www.cnblogs.com/qicosmos/p/3471314.html
5)(原创)谈谈boost.asio的异步发送
http://www.cnblogs.com/qicosmos/p/3487169.html
6)http://www.cnblogs.com/qicosmos/category/538859.html
(原创)用c++11打造好用的any
http://www.cnblogs.com/qicosmos/p/3420095.html
(原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
http://www.cnblogs.com/qicosmos/p/3555668.html
(原创)composite模式和bridge模式是天生的好朋友
http://www.cnblogs.com/qicosmos/p/3658750.html
相关文章推荐
- (原创)一个超级对象池的实现
- IOS一个课程表的实现,是原创的,是一个mysql+jsp+ios的小项目
- [PHP][Function]实现将一个文件夹下的所有文件及文件夹复制到另一个文件夹里(保持原有结构)[已验证][原创]
- 一个通用并发对象池的实现
- [原创]超级经典聊天室系统实现 Ajax+PHP+Javascrcript+Json无刷新技术倾力打造(二)
- 如何实现一个对象池
- Gtest源码剖析:1.实现一个超级简单的测试框架xtest
- 网上一堆代码,没有一个真正实现curl传图片成功过的,这儿,我来个成功的,超级简单,扩展性强【广告一下】
- 用jquery实现的一个超级简单的下拉菜单
- 原创翻译 在Windows CE上实现一个全功能的webserver
- (原创)一个轻量级、高性能的消息分发器的实现
- (转载)一个通用并发对象池的实现
- 一个本世纪的超级报道:(原创)
- 用jquery实现的一个超级简单的下拉菜单
- 实现 一个类,使得该类任何形式的 派生类 无论怎么定义和实现,都无法产生任何对象 实例 (原创)
- 仿照everything写的一个超级速查 原创
- 【原创】在winform程序中实现在IE浏览器中打开一个新的页面,全屏化并屏蔽IE窗口的工具栏和地址栏
- Cocos2dx对象池的一个实现
- [原创]WCF后续之旅(10): 通过WCF Extension实现以对象池的方式创建Service Instance