#include "ConnectionPool.h"
|
ConnectionPool::ConnectionPool()
|
{
|
if (!parseXmlFile())
|
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); // ¼ì²â²¢Ïú»ÙÁ¬½Ó
|
// Ï̷߳ÖÀ룬·ÀÖ¹×èÈûÖ÷Ïß³Ì
|
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;
|
return true;
|
}
|
else {
|
delete conn;
|
return false; // Ìáʾ
|
}
|
}
|
void ConnectionPool::productConnection()
|
{
|
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;
|
}
|
}
|
// »½ÐÑ
|
m_cond1.notify_all();
|
}
|
}
|
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();
|
delete conn;
|
--m_num;
|
}
|
else {
|
break;
|
}
|
}
|
}
|
}
|
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 ¼ÌÐø×èÈû
|
}
|
}
|
}
|
// ÒªÖ¸¶¨É¾³ýÆ÷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
|
});
|
m_connections.pop();
|
m_cond.notify_all();
|
return conn;
|
}
|