在服務器的開發中,對象池或者連接池的使用有兩種特別的使用場景:一是對象的產生和銷燬會消耗很大,二是對象的數量受到限制,比如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;
}