C++RAII技术以及在数据库连接池上的应用

C++RAII技术以及在数据库连接池上的应用

C++ RAII

C++面向对象编程时,创建变量会执行构造函数,销毁对象时执行析构函数,若进程堆资源在构造函数中获取,在析构函数中释放资源,即实现了RAII,理论上该技术可以以用于任何的系统资源。

数据库连接池

一个常规的数据库连接池所包含的组件如下所示。

//connection.h
class connection_pool{
public:
	MYSQL *GetConnection();				 //获取数据库连接
	bool ReleaseConnection(MYSQL *conn); //释放连接
	int GetFreeConn();					 //获取连接
	void DestroyPool();					 //销毁所有连接
	//单例模式
	static connection_pool *GetInstance();
	void init(string url, string User, string PassWord, string DataBaseName, int Port, int MaxConn, int close_log); 
private:
	connection_pool();//私有构造函数,防止类外申请变量。
	~connection_pool();
	int m_MaxConn;  //最大连接数
	int m_CurConn;  //当前已使用的连接数
	int m_FreeConn; //当前空闲的连接数
	locker lock;
	list<MYSQL *> connList; //连接池
	sem reserve;
public:
	string m_url;			 //主机地址
	string m_Port;		 //数据库端口号
	string m_User;		 //登陆数据库用户名
	string m_PassWord;	 //登陆数据库密码
	string m_DatabaseName; //使用数据库名
	int m_close_log;	//日志开关
};
connection.cpp
connection_pool::connection_pool(){
	m_CurConn = 0;
	m_FreeConn = 0;
}
connection_pool *connection_pool::GetInstance(){
	static connection_pool connPool;
	return &connPool;
}

//构造初始化
void connection_pool::init(string url, string User, string PassWord, string DBName, int Port, int MaxConn, int close_log){
	m_url = url;
	m_Port = Port;
	m_User = User;
	m_PassWord = PassWord;
	m_DatabaseName = DBName;
	m_close_log = close_log;
	for (int i = 0; i < MaxConn; i++){
		MYSQL *con = NULL;
		con = mysql_init(con);
		if (con == NULL){
			LOG_ERROR("MySQL Error");
			exit(1);
		}
		con = mysql_real_connect(con, url.c_str(), User.c_str(), PassWord.c_str(), DBName.c_str(), Port, NULL, 0);
		if (con == NULL){
			LOG_ERROR("MySQL Error");
			exit(1);
		}
		connList.push_back(con);
		++m_FreeConn;
	}
	reserve = sem(m_FreeConn);
	m_MaxConn = m_FreeConn;
}
//使用指针可以访问到池子
//当有请求时,从数据库连接池中返回一个可用连接,更新使用和空闲连接数

MYSQL *connection_pool::GetConnection(){
	MYSQL *con = NULL;
	if (0 == connList.size())
		return NULL;
	reserve.wait();
	lock.lock();
	con = connList.front();
	connList.pop_front();
	--m_FreeConn;
	++m_CurConn;
	lock.unlock();
	return con;
}

//释放当前使用的连接

bool connection_pool::ReleaseConnection(MYSQL *con){
	if (NULL == con)
		return false;
	lock.lock();
	connList.push_back(con);
	++m_FreeConn;
	--m_CurConn;
	lock.unlock();
	reserve.post();
	return true;
}

//销毁数据库连接池
void connection_pool::DestroyPool(){
	lock.lock();
	if (connList.size() > 0){
		list<MYSQL *>::iterator it;
		for (it = connList.begin(); it != connList.end(); ++it){
			MYSQL *con = *it;
			mysql_close(con);
		}
		m_CurConn = 0;
		m_FreeConn = 0;
		connList.clear();
	}
	lock.unlock();
}



在数据库连接池中使用RAII技术如下所示:

//RAII.h
class connectionRAII{
public:
	connectionRAII(MYSQL **con, connection_pool *connPool);
	~connectionRAII();
private:
	MYSQL *conRAII;
	connection_pool *poolRAII;
//RAII.c
connectionRAII::connectionRAII(MYSQL **SQL, connection_pool *connPool){
	*SQL = connPool->GetConnection();
	
	conRAII = *SQL;
	poolRAII = connPool;
}

connectionRAII::~connectionRAII(){
	poolRAII->ReleaseConnection(conRAII);
}

};

分析:
在使用时通过调用GetInstance()生成数据库连接池,将数据库连接池永恒放在静态栈中,代码如下所示:

m_connPool = connection_pool::GetInstance();
m_connPool->init("localhost", m_user, m_passWord, m_databaseName, 3306, m_sql_num, m_close_log);
//初始化数据库读取表
users->initmysql_result(m_connPool);

当程序出该作用域时mysqlcon函数自动析构,释放该条数据库的连接。


connectionRAII mysqlcon(&request->mysql, m_connPool);
request->process();
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值