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