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 <iostream>
template <typename T>
class PoolFunction
{
public:
        virtual T* get() = 0;
        virtual bool release(T *) = 0;
        virtual ~PoolFunction() {}
};


template<typename T>
struct PoolDeleter {

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

#endif // SCOPED_PTR_H_INCLUDED

api_redis.h

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

#ifndef _API_REDIS_H_
#define _API_REDIS_H_

#include <vector>
#include <string>
#include <map>
#include <deque>
#include <stdint.h>
#include <hiredis/hiredis.h>
#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<RedisConn> {
		private:
			std::deque<RedisConn *> 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<redis::RedisConn, PoolDeleter<redis::RedisConn> > RedisConnUniquePtr;

api_redis.cpp

#include "api_redis.h"

#include <iostream>
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<std::mutex> autolock(m_lock);
		if(!m_conns.empty()) {
			conn = m_conns.front();
			m_conns.pop_front();
			std::cout << "get pop_front" <<endl;
			return conn;
		}
	}
	std::cout << "get new" <<endl;
	conn = new RedisConn(m_host, m_port, m_db);
	return conn;
}

//删除器中调用了pool->release方法
bool redis::RedisPool::release(RedisConn* redis_conn) {
	if(redis_conn == NULL) {
		return true;
	}
	
	std::unique_lock<std::mutex> autolock(m_lock);
	m_conns.push_back(redis_conn);
	std::cout << "release" <<endl;
    return true;
}

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<redis::RedisConn> g_redis_conn_delter;//删除器
		g_redis_conn_delter.setPool(g_redis_pool);//设置pool

		{
			std::unique_ptr<redis::RedisConn, PoolDeleter<redis::RedisConn> > 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
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值