在服务器的开发中,对象池或者连接池的使用有两种特别的使用场景:一是对象的产生和销毁会消耗很大,二是对象的数量受到限制,比如mysql的连接对象。这个时候就可以采用池化的技术来解决该问题。池化的意思就是将对象一开始创建好放进池中,当需要时,从里面去,不需要时,在放回池中。
#ifndef __OBJECT_POOL_H__
#define __OBJECT_POOL_H__
#include <queue>
#include <mutex>
#include <memory>
#include "nocopyable.h"
//传入的T是一个裸指针
template <typename T>
class ObjectPool
:public nocopyable
{
public:
ObjectPool(size_t chunk_size = pool_size);
virtual ~ObjectPool();
//从对象池中去除一个对象
std::shared_ptr<T> Take_out_object();
//将使用的对象放回到对象池中
void Put_back_object(std::shared_ptr<T> obj);
protected:
//分配对象池
void allocate_chunk();
//构造一个对象
inline static std::shared_ptr<T> construct();
private:
std::queue<std::shared_ptr<T>> m_free_list;
size_t m_chunk_size; //对象池中预分配对象个数
std::mutex m_mutex; //锁空闲对象队列的
static const int pool_size = 50; //默认给定的对象池中的大小
};
template <typename T>
std::shared_ptr<T> ObjectPool<T>::construct()
{
return std::shared_ptr<T>(new T);
}
template <typename T>
ObjectPool<T>::ObjectPool(size_t chunk_size) : m_chunk_size(chunk_size)
{
if (m_chunk_size <= 0)
{
std::cout << "Object size invalid" << std::endl;
}
else
{
for (size_t i = 0; i != m_chunk_size; ++i)
{
allocate_chunk();
}
}
}
template <typename T>
ObjectPool<T>::~ObjectPool()
{
}
template <typename T>
void ObjectPool<T>::allocate_chunk()
{
std::unique_lock<std::mutex> _(m_mutex);
m_free_list.push(construct());
}
//注意:该内存池采用的是动态增长,即对象不够时,会重新创建对象,但是不会释放对象。所以解决
//了对象数量不容易设置合理的问题,但是却存在对象没有缩减的现象
template <typename T>
std::shared_ptr<T> ObjectPool<T>::Take_out_object()
{
std::unique_lock<std::mutex> _(m_mutex);
if (m_free_list.empty())
{
allocate_chunk();
}
std::shared_ptr<T> obj = m_free_list.front();
m_free_list.pop();
return obj;
}
template <typename T>
void ObjectPool<T>::Put_back_object(std::shared_ptr<T> obj)
{
std::unique_lock<std::mutex> _(m_mutex);
m_free_list.push(obj);
}
#endif //!__OBJECT_POOL_H__
测试:
#include <iostream>
#include "ObjectPool.hpp"
using namespace std;
class A
{
public:
A() { std::cout << "A 的构造" << std::endl; }
~A() { std::cout << "A的析构" << std::endl; }
void sss(){ std::cout << "hello 对象池" << std::endl; }
};
int main()
{
{
ObjectPool<A> opool(2);
auto item = opool.Take_out_object();
item->sss();
opool.Put_back_object(item);
auto item2 = opool.Take_out_object();
item2->sss();
item = opool.Take_out_object();
item->sss();
opool.Put_back_object(item);
opool.Put_back_object(item2);
}
system("pause");
return 0;
}