From 828ba1dcdd1fa803dddf94f4f1643452d5efa703 Mon Sep 17 00:00:00 2001
From: gong <3218757026@qq.com>
Date: 星期三, 06 十一月 2024 15:08:44 +0800
Subject: [PATCH] Merge branch 'master' of ssh://115.28.86.8:29418/~admin/昆仑_1025

---
 Server/王琨元/code/ConnectionPool.cpp |  204 ++++++++++++++++++++++++--------------------------
 1 files changed, 99 insertions(+), 105 deletions(-)

diff --git "a/Server/\347\216\213\347\220\250\345\205\203/code/ConnectionPool.cpp" "b/Server/\347\216\213\347\220\250\345\205\203/code/ConnectionPool.cpp"
index 367a7f1..ce7acb2 100644
--- "a/Server/\347\216\213\347\220\250\345\205\203/code/ConnectionPool.cpp"
+++ "b/Server/\347\216\213\347\220\250\345\205\203/code/ConnectionPool.cpp"
@@ -1,95 +1,102 @@
+#include "stdafx.h"
 #include "ConnectionPool.h"
-ConnectionPool::ConnectionPool()
-{
-	if (!parseXmlFile())
+
+#include <fstream>
+#include <iostream>
+#include <thread>
+
+ConnectionPool* ConnectionPool::getInstance() {
+	static ConnectionPool connPool;
+	return &connPool;
+}
+
+ConnectionPool::ConnectionPool() {
+	// 加载配置文件
+	if (!parseJsonFile()) {
+		std::cout << "parseJsonFile is failed!" << std::endl;
 		return;
-	for (m_num = 0; m_num < m_minSize;) {
-		bool flag = addConnection();
-		if (!flag) {
-			return;
-		}
 	}
-	// 如果子线程的任务函数是类的非静态函数,我们需要指定任务函数的地址和任务函数的所有者
-	thread producer(&ConnectionPool::productConnection, this); // 创建连接
-	thread recycler(&ConnectionPool::recycleConnection, this); // 检测并销毁连接
-															   // 线程分离,防止阻塞主线程
+	for ( int i = 0 ; i < m_min_conn ; i++ ) {
+		addConnection( );
+	}
+	// 创建一个线程,对连接数进行监控 ,连接数不足就再继续创建
+	std::thread producer(&ConnectionPool::produce, this);
+	// 对连接数进行监控 ,如果有太多空闲得线程 ,那么就对其进行销毁
+	std::thread recycler( &ConnectionPool::recycle,  this);
+
+	// 线程分离
 	producer.detach();
 	recycler.detach();
 }
-ConnectionPool::~ConnectionPool()
-{
-	while (!m_connections.empty()) {
-		MysqlConn* conn = m_connections.front();
-		m_connections.pop();
-		delete conn;
-	}
-}
-bool ConnectionPool::parseXmlFile()
-{
-	TiXmlDocument xml("mysql.xml");
-	// 加载文件
-	bool res = xml.LoadFile();
-	if (!res) {
-		return false; // 提示
-	}
-	// 根
-	TiXmlElement* rootElement = xml.RootElement();
-	TiXmlElement* childElement = rootElement->FirstChildElement("mysql");
-	// 读取信息
-	m_ip = childElement->FirstChildElement("ip")->GetText();
-	m_port = static_cast<unsigned short>(stoi(string(childElement->FirstChildElement("port")->GetText())));
-	m_user = childElement->FirstChildElement("username")->GetText();
-	m_passwd = childElement->FirstChildElement("password")->GetText();
-	m_dbName = childElement->FirstChildElement("dbName")->GetText();
-	m_minSize = static_cast<int>(stoi(string(childElement->FirstChildElement("minSize")->GetText())));
-	m_maxSize = static_cast<int>(stoi(string(childElement->FirstChildElement("maxSize")->GetText())));
-	m_maxIdleTime = static_cast<int>(stoi(string(childElement->FirstChildElement("maxIdleTime")->GetText())));
-	m_timeout = static_cast<int>(stoi(string(childElement->FirstChildElement("timeout")->GetText())));
-	return true;
-}
-bool ConnectionPool::addConnection()
-{
-	MysqlConn* conn = new MysqlConn;
-	bool res = conn->connect(m_user, m_passwd, m_dbName, m_ip, m_port);
-	if (res) {
-		// 刷新空闲时间
-		conn->refreashAliveTime();
-		m_connections.push(conn);
-		++m_num;
+
+bool ConnectionPool::parseJsonFile() {
+
+	/*std::ifstream ifs("dbconf.json");
+	Reader rd;
+	Value root;
+	rd.parse(ifs, root);
+	if ( root.isObject( ) ) {
+		m_ip = root["ip"].asString();
+		m_port = root["port"].asInt();
+		m_userName = root["userName"].asString();
+		m_passwd = root["password"].asString();
+		m_db = root["dbName"].asString();
+		m_min_conn = root["minSize"].asInt();
+		m_max_conn = root["maxSize"].asInt();
+		max_del_time = root["maxDleTime"].asInt();
+		m_timeout = root["timeout"].asInt();
 		return true;
+	}*/
+	return false;
+}
+
+void ConnectionPool::description() {
+	std::cout << m_ip << ". " << m_userName << ". " << m_passwd << ". " << m_db << ". "
+		       << m_port << ". " << m_max_conn << ". " << m_min_conn << ". " << m_timeout << ". " 
+		       << max_del_time << std::endl;
+}
+
+ConnectionPool::~ConnectionPool() {
+	while (!m_connkQueue.empty()) {
+		MysqlConn* conn = m_connkQueue.front();
+		m_connkQueue.pop();
+		delete  conn;
 	}
-	else {
+
+}
+
+void ConnectionPool::addConnection() {
+	MysqlConn* conn = new MysqlConn();
+	if ( !conn->connect( m_ip, m_userName, m_passwd, m_db, m_port  ) ) {
+		std::cout << "ConnectionPool connect to mysql is failed!" << std::endl;
 		delete conn;
-		return false; // 提示
+		return;
 	}
+	conn->refreshActiveTime( );
+	m_connkQueue.push(conn);
+	m_cond.notify_one();   // 唤醒一个线程
 }
-void ConnectionPool::productConnection()
-{
+
+void ConnectionPool::produce(){
 	while (true) {
-		unique_lock<mutex> lc(m_mutex);
-		m_cond.wait(lc, [this]() {return m_connections.empty(); });
-		if (m_num < m_maxSize) {
-			bool flag = addConnection();
-			if (!flag) {
-				return;
-			}
+		std::unique_lock<std::mutex> lock(m_mutex);
+		while (m_connkQueue.size() >= m_min_conn) { // 连接队列的数量大于最小的连接数
+			m_cond.wait(lock);
 		}
-		// 唤醒
-		m_cond1.notify_all();
+		addConnection();
 	}
 }
-void ConnectionPool::recycleConnection()
-{
-	while (true) {
-		// 休眠一段时间 0.5s
-		this_thread::sleep_for(milliseconds(500));
-		lock_guard<mutex> lc(m_mutex);
-		while (!m_connections.empty() && m_num > m_minSize) {
-			MysqlConn* conn = m_connections.front();
-			if (conn->getAliveTime() >= m_maxIdleTime) {
-				m_connections.pop();
+
+// 删除空闲连接
+void ConnectionPool::recycle() {
+	while ( true ) {
+		std::this_thread::sleep_for( std::chrono::milliseconds(500));   // 休眠500 ms
+		std::unique_lock<std::mutex>lock(m_mutex);
+		while ( m_connkQueue.size() > m_min_conn ) {
+			MysqlConn* conn = m_connkQueue.front( );
+			if (conn->getActiveTime() >= max_del_time) {
+				m_connkQueue.pop();
 				delete conn;
-				--m_num;
 			}
 			else {
 				break;
@@ -97,35 +104,22 @@
 		}
 	}
 }
-ConnectionPool* ConnectionPool::getConnectPool()
-{
-	// 不使用互斥锁的线程安全的懒汉模式
-	static ConnectionPool pool; // 只在第一次调用函数时初始化
-	return &pool;
-}
-shared_ptr<MysqlConn> ConnectionPool::getConnection()
-{
-	unique_lock<mutex> lc(m_mutex);
-	while (m_connections.empty()) {
-		if (cv_status::timeout == m_cond1.wait_for(lc, chrono::milliseconds(m_timeout))) {
-			if (m_connections.empty()) {
-				// cout << "out of time" << endl;
-				return nullptr; // 结束  // 提示
-								// continue; // 利用while配合continue 继续阻塞
-			}
+
+std::shared_ptr<MysqlConn>  ConnectionPool::getMysqlConn() {
+	
+	std::unique_lock<std::mutex>lock(m_mutex);
+	while ( m_connkQueue.empty()) {
+		// 如果等待一段时间后,队列还是为空,返回一个 null
+		if ( std::cv_status::timeout == m_cond.wait_for(lock, std::chrono::milliseconds(m_timeout)) ) {
+			if( m_connkQueue.empty( ) )    return nullptr;
 		}
 	}
-	// 要指定删除器destructor,来保证连接的归还
-	shared_ptr<MysqlConn> conn(m_connections.front(), [this](MysqlConn* conn) {
-		// 加锁保证队列线程安全
-		// m_mutex.lock(); // 1
-		unique_lock<mutex> lc(m_mutex); // 2
-		// lock_guard<mutex> lc(m_mutex); // 3
-		conn->refreashAliveTime();
-		m_connections.push(conn);
-		// m_mutex.unlock(); // 1
+	std::shared_ptr<MysqlConn> connPtr(std::move(m_connkQueue.front()), [this](MysqlConn* conn) {
+		std::unique_lock <std::mutex>lock(m_mutex) ;
+		conn->refreshActiveTime();
+		m_connkQueue.push(conn);
 		});
-	m_connections.pop();
-	m_cond.notify_all();
-	return conn;
-}
+	m_connkQueue.pop();
+	m_cond.notify_one();   // 唤醒阻塞的生产者线程,开始生产
+	return connPtr;
+}
\ No newline at end of file

--
Gitblit v1.8.0