c++簡單對象池(或連接池)的實現

在服務器的開發中,對象池或者連接池的使用有兩種特別的使用場景:一是對象的產生和銷燬會消耗很大,二是對象的數量受到限制,比如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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章