数据库连接池的配置文件 mysql.ini
#数据库连接池的配置文件
ip=127.0.0.1
port=3306
username=root
password=123456
dbname=chat
initSize=10
maxSize=1024
#最大空闲时间默认单位是秒
maxIdleTime=60
#连接超时时间单位是毫秒
connectionTimeOut=100
CommomConnectionPool.h
#pragma once
#include <string>
#include <queue>
#include <mutex>
#include <iostream>
#include <atomic>
#include <thread>
#include <condition_variable>
#include <memory>
#include <functional>
using namespace std;
#include "Connection.h"
class ConnectionPool
{
public:
static ConnectionPool* getConnectionPool();
shared_ptr<Connection> getConnection();
private:
ConnectionPool();
bool loadConfigFile();
void produceConnectionTask();
void scannerConnectionTask();
string _ip;
unsigned short _port;
string _username;
string _password;
string _dbname;
int _initSize;
int _maxSize;
int _maxIdleTime;
int _connectionTimeout;
queue<Connection*> _connectionQue;
mutex _queueMutex;
atomic_int _connectionCnt;
condition_variable cv;
};
CommomConnectionPool.cpp
#include "pch.h"
#include "CommonConnectionPool.h"
#include "public.h"
ConnectionPool* ConnectionPool::getConnectionPool()
{
static ConnectionPool pool;
return &pool;
}
bool ConnectionPool::loadConfigFile()
{
FILE *pf = fopen("mysql.ini", "r");
if (pf == nullptr)
{
LOG("mysql.ini file is not exist!");
return false;
}
while (!feof(pf))
{
char line[1024] = { 0 };
fgets(line, 1024, pf);
string str = line;
int idx = str.find('=', 0);
if (idx == -1)
{
continue;
}
int endidx = str.find('\n', idx);
string key = str.substr(0, idx);
string value = str.substr(idx + 1, endidx - idx - 1);
if (key == "ip")
{
_ip = value;
}
else if (key == "port")
{
_port = atoi(value.c_str());
}
else if (key == "username")
{
_username = value;
}
else if (key == "password")
{
_password = value;
}
else if (key == "dbname")
{
_dbname = value;
}
else if (key == "initSize")
{
_initSize = atoi(value.c_str());
}
else if (key == "maxSize")
{
_maxSize = atoi(value.c_str());
}
else if (key == "maxIdleTime")
{
_maxIdleTime = atoi(value.c_str());
}
else if (key == "connectionTimeOut")
{
_connectionTimeout = atoi(value.c_str());
}
}
return true;
}
ConnectionPool::ConnectionPool()
{
if (!loadConfigFile())
{
return;
}
for (int i = 0; i < _initSize; ++i)
{
Connection *p = new Connection();
p->connect(_ip, _port, _username, _password, _dbname);
p->refreshAliveTime();
_connectionQue.push(p);
_connectionCnt++;
}
thread produce(std::bind(&ConnectionPool::produceConnectionTask, this));
produce.detach();
thread scanner(std::bind(&ConnectionPool::scannerConnectionTask, this));
scanner.detach();
}
void ConnectionPool::produceConnectionTask()
{
for (;;)
{
unique_lock<mutex> lock(_queueMutex);
while (!_connectionQue.empty())
{
cv.wait(lock);
}
if (_connectionCnt < _maxSize)
{
Connection *p = new Connection();
p->connect(_ip, _port, _username, _password, _dbname);
p->refreshAliveTime();
_connectionQue.push(p);
_connectionCnt++;
}
cv.notify_all();
}
}
shared_ptr<Connection> ConnectionPool::getConnection()
{
unique_lock<mutex> lock(_queueMutex);
while (_connectionQue.empty())
{
if (cv_status::timeout == cv.wait_for(lock, chrono::milliseconds(_connectionTimeout)))
{
if (_connectionQue.empty())
{
LOG("获取空闲连接超时了...获取连接失败!");
return nullptr;
}
}
}
shared_ptr<Connection> sp(_connectionQue.front(),
[&](Connection *pcon)
{
unique_lock<mutex> lock(_queueMutex);
pcon->refreshAliveTime();
_connectionQue.push(pcon);
});
_connectionQue.pop();
cv.notify_all();
return sp;
}
void ConnectionPool::scannerConnectionTask()
{
for (;;)
{
this_thread::sleep_for(chrono::seconds(_maxIdleTime));
unique_lock<mutex> lock(_queueMutex);
while (_connectionCnt > _initSize)
{
Connection *p = _connectionQue.front();
if (p->getAliveeTime() >= (_maxIdleTime * 1000))
{
_connectionQue.pop();
_connectionCnt--;
delete p;
}
else
{
break;
}
}
}
}