对象池
从
对象池
中获取对象,如果没有对象,则创建一个,并返回使用对象
使用完成对象后,将对象还回
对象池
那么符合如下条件的,应该适合使用对象池
技术:
有一些对象虽然创建开销比较大,但是不一定能够重复使用。要使用
对象池
一定要确保对象能够重复使用。这个对象构建的时候,有一些耗时的资源可以重复利用。比如
redisContext
的网络连接。又或者如果对象的频繁申请释放会带来一些其他的资源使用问题,比如内存碎片
。重复利用能够提升程序的效率。对象池
的数量应该控制在能够接受的范围内,并不会无限膨胀。
对象池的实现
class Object{public:Object(std::string strInit) : m_strInit(strInit){std::cout << "Object()" << std::endl;}virtual ~Object(){std::cout << "~Object()" << std::endl;}private:std::string m_strInit;};
ObjectPool
中采用std::list
作为对象池的数据结构,存储的对象采用shared_ptr
包裹。GetObject
获取一个对象,传入的参数为Object
需要初始化的信息,如果池子里面没有,就创建一个返回,如果有就从池子中取出一个返回。ReturnObject
当应用程序使用完毕后,调用这个方法还回对象到对象池
class ObjectPool{public:ObjectPool() { ; }~ObjectPool() { ; }std::shared_ptr<Object> GetObject(std::string strInit){std::shared_ptr<Object> pObject;{std::lock_guard<std::mutex> guard(m_mutex);if (!m_lObjects.empty()){pObject = m_lObjects.front();m_lObjects.pop_front();}}if (!pObject){pObject = std::make_shared<Object>(strInit);}return pObject;}void ReturnObject(std::shared_ptr<Object> pObject){if (!pObject)return;std::lock_guard<std::mutex> guard(m_mutex);m_lObjects.push_front(pObject);}private:std::mutex m_mutex;std::list<std::shared_ptr<Object>> m_lObjects;};
ObjectPool objPool;auto pObj1 = objPool.GetObject("abc");//操作对象完成任务//......objPool.ReturnObject(pObj1);
针对不同类型的
Object
,是不是可以用模板去实现更加通用的实现一个对象池构造函数的参数列表,也可以是任意的形式
自动回收的对象池
template<typename T>class ObjectPool{public:ObjectPool(){m_fObjDeleter = [&](T* pObj) {if (m_bDeconstruct)delete pObj;else{std::lock_guard<std::mutex> guard(m_mutex);m_lObjects.push_front(std::shared_ptr<T>(pObj, m_fObjDeleter));}};}~ObjectPool(){m_bDeconstruct = true;}template<typename... Args>std::shared_ptr<T> GetObject(Args&&... args){std::shared_ptr<T> pObject;{std::lock_guard<std::mutex> guard(m_mutex);if (!m_lObjects.empty()){pObject = m_lObjects.front();m_lObjects.pop_front();}}if (!pObject){pObject.reset(new T(std::forward<Args>(args)...), m_fObjDeleter);}return pObject;}void ReturnObject(std::shared_ptr<T> pObject){if (!pObject)return;std::lock_guard<std::mutex> guard(m_mutex);m_lObjects.push_front(pObject);}private:std::function<void(T* pObj)> m_fObjDeleter;std::mutex m_mutex;std::list<std::shared_ptr<T>> m_lObjects;volatile bool m_bDeconstruct = false;};
自动回收
如果发现是
OjbectPool
调用了析构函数,则直接释放对象如果发现
OjbectPool
并没有调用析构函数,则将对象放入对象池中
m_fObjDeleter = [&](T* pObj) {if (m_bDeconstruct)delete pObj;else{std::lock_guard<std::mutex> guard(m_mutex);m_lObjects.push_front(std::shared_ptr<T>(pObj, m_fObjDeleter));}};
当创建对象的时候指定自定义的deleter:
pObject.reset(new T(std::forward<Args>(args)...), m_fObjDeleter);
模板支持
template<typename T>
class ObjectPool
{
public:
//......
template<typename... Args>
std::shared_ptr<T> GetObject(Args&&... args)
{
//......
}
void ReturnObject(std::shared_ptr<T> pObject)
{
//......
}
private:
std::function<void(T* pObj)> m_fObjDeleter;
//.....
std::list<std::shared_ptr<T>> m_lObjects;
//.......
};
可变函数参数完美转发
template<typename... Args>std::shared_ptr<T> GetObject(Args&&... args){std::shared_ptr<T> pObject;{std::lock_guard<std::mutex> guard(m_mutex);if (!m_lObjects.empty()){pObject = m_lObjects.front();m_lObjects.pop_front();}}if (!pObject){pObject.reset(new T(std::forward<Args>(args)...), m_fObjDeleter);}return pObject;}
其他
是否要在启动的时候初始化指定数量的对象?
对象池
的数量是否要设置一个上限或者下线对象池重复利用,当取出来后要注意,是不是要对对象做一次
reset
之类的操作,防止对象上一次的调用残留数据对本地调用构成影响,这个要根据自己对象的特点去进行相应的reset
操作有时候当这个
对象
可能出现了特别的情况需要销毁
,是否也需要考虑到?等等
参考
<<C++ Primer>>模板部分
<< thinking in object pool >>: https://www.cnblogs.com/qicosmos/p/4995248.html





