std::unique_ptr智能指针定制删除器在连接池中的应用

用智能指针管理连接池(如数据库连接池、redis连接池),当智能指针离开作用域时,调用定制的删除器,删除器中调用指定的函数,并不是将连接断开,而是将连接放进一个容器中。当需要获取连接时,从连接池中获取一个空闲的连接。

目录

自定义删除器

scoped_ptr.h

api_redis.h

main.cpp


自定义删除器

scoped_ptr.h

#ifndef SCOPED_PTR_H_INCLUDED
#define SCOPED_PTR_H_INCLUDED
#include 
template 
class PoolFunction
{
public:
        virtual T* get() = 0;
        virtual bool release(T *) = 0;
        virtual ~PoolFunction() {}
};


template
struct PoolDeleter {

        explicit PoolDeleter(PoolFunction *pool = 0):m_pool(pool) {}
		
        inline void operator()(T* ptr) const {
            
				if (m_pool){
               		 m_pool->release(ptr); //调用pool中方法
				}
        }
		void setPool(PoolFunction *pool){
				m_pool = pool;
		}
private:
        PoolFunction *m_pool;
};

#endif // SCOPED_PTR_H_INCLUDED

api_redis.h

以redis为例。以下只是举个例子,类RedisConn将hiredis中的api重新包装下即可。

#ifndef _API_REDIS_H_
#define _API_REDIS_H_

#include 
#include 
#include 
#include 
#include 
#include 
#include "scoped_ptr.h"
namespace redis
{
	typedef struct conn_info_s
	{
		std::string host;
		int			port;
		int			db;
	} conn_info_t;
	class RedisConn {
		private:
			std::string m_host;
			int m_port;
			int m_db;
			struct timeval m_timeout_tv;
			redisContext* m_context;
	
		public:
			RedisConn(std::string& host, int port, int db = 0, int timeout_ms = 1000);
			~RedisConn() { if(m_context != NULL) { redisFree(m_context); } }

            /*
             实现redis各种命令:CONNECT, HSET, HGET ....
            此处省略
            **/
    };

    class RedisPool :public PoolFunction {
		private:
			std::deque m_conns; //调用删除器release的时候,将空闲连接存在deque中
			std::mutex m_lock;
			std::string m_host;
			int m_port;
			int m_db;
		public:
			RedisPool(const std::string& host, int port, int db = 0) : m_host(host), m_port(port), m_db(db) { };
			RedisConn* get();
			bool release(RedisConn* redis_conn);
	};


};

typedef std::unique_ptr > RedisConnUniquePtr;

api_redis.cpp

#include "api_redis.h"

#include 
using std::string;
using std::vector;
using std::map;
using std::cout;
using std::endl;

redis::RedisConn::RedisConn(string& host, int port, int db, int timeout_ms) : m_host(host), m_port(port), m_db(db), m_context(NULL) {
	m_timeout_tv.tv_sec = timeout_ms/1000;
	m_timeout_tv.tv_usec = (timeout_ms % 1000) * 1000;
}
/*
实现RedisConn的其他方法
*/


//get从连接池中获取一个空闲的连接,如果没有空闲的连接则新建一个连接。
redis::RedisConn* redis::RedisPool::get() {
	RedisConn* conn = NULL;
	if(true) {
		std::unique_lock autolock(m_lock);
		if(!m_conns.empty()) {
			conn = m_conns.front();
			m_conns.pop_front();
			std::cout << "get pop_front" <release方法
bool redis::RedisPool::release(RedisConn* redis_conn) {
	if(redis_conn == NULL) {
		return true;
	}
	
	std::unique_lock autolock(m_lock);
	m_conns.push_back(redis_conn);
	std::cout << "release" <

main.cpp

使用实例

在实际使用中,可将g_redis_pool 和g_redis_conn_delter设置为全局变量。那么在业务的各种线程中可通过一行代码来从redis连接池中获取redis连接,作用域结束后将调用删除器将连接放入空闲连接池:

RedisConnUniquePtr conn_Redis(g_redis_pool->get(), g_redis_conn_delter);

int main() 
{

redis::conn_info_t redisConf;
		redisConf.host = "127.0.0.1";
		redisConf.port = "6379";
		redis::RedisPool * g_redis_pool = new redis::RedisPool(redisConf.host, redisConf.port);//new一个pool
		PoolDeleter g_redis_conn_delter;//删除器
		g_redis_conn_delter.setPool(g_redis_pool);//设置pool

		{
			std::unique_ptr > conn_Redis(g_redis_pool->get(), g_redis_conn_delter);
		}
		{
			RedisConnUniquePtr conn_Redis(g_redis_pool->get(), g_redis_conn_delter);
		}
		{
			RedisConnUniquePtr conn_Redis(g_redis_pool->get(), g_redis_conn_delter);
		}

    return 0
}

你可能感兴趣的:(C++,智能指针,unique_ptr,删除器)