Files
DP_S/src/CConnectPool.cpp
2024-04-24 10:25:44 +08:00

170 lines
4.1 KiB
C++

#include "CConnectPool.h"
#include <iostream>
#define POOL_SAFE_DELETE(ptr) \
if (ptr != NULL) \
{ \
delete ptr; \
ptr = NULL; \
}
CConnectPool *CConnectPool::s_pInstance = NULL;
CConnectPool::CConnectPool()
{
pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_cond, NULL);
// 初始化连接数
// 此处由主线程调用初始化,无需考虑锁问题
for (int i = 0; i < My_Info.MaxConnectCount; ++i)
{
MYSQL *pConn = _CreateConnect();
if (NULL == pConn)
{
exit(EXIT_FAILURE);
}
m_queueFree.push(pConn);
}
}
CConnectPool::~CConnectPool()
{
pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_cond);
MYSQL *pConn = NULL;
while (m_queueFree.size() > 0)
{
pConn = m_queueFree.front();
POOL_SAFE_DELETE(pConn);
m_queueFree.pop();
}
std::set<MYSQL *>::iterator it = m_setBusy.begin();
while (it != m_setBusy.end())
{
pConn = *it;
POOL_SAFE_DELETE(pConn);
// it = m_setBusy.erase(it);
it++;
}
}
void CConnectPool::CreatePool(int MinConnectCount, int MaxConnectCount, const char *Host, int Port, const char *Account, const char *Passwd)
{
if (NULL == s_pInstance)
{
s_pInstance = new CConnectPool;
s_pInstance->My_Info.MinConnectCount = MinConnectCount;
s_pInstance->My_Info.MaxConnectCount = MaxConnectCount;
s_pInstance->My_Info.Host = Host;
s_pInstance->My_Info.Port = Port;
s_pInstance->My_Info.Account = Account;
s_pInstance->My_Info.Passwd = Passwd;
s_pInstance->My_Info.KName = "taiwan_cain";
}
}
void CConnectPool::FreePool()
{
if (NULL != s_pInstance)
{
delete s_pInstance;
s_pInstance = NULL;
}
}
MYSQL *CConnectPool::GetConnect()
{
return s_pInstance->_GetConnect(false);
}
MYSQL *CConnectPool::TryGetConnect()
{
return s_pInstance->_GetConnect(true);
}
void CConnectPool::PutConnect(MYSQL *pConn)
{
s_pInstance->_PutConnect(pConn);
}
MYSQL *CConnectPool::_CreateConnect()
{
MYSQL *pConn = new MYSQL;
mysql_init(pConn);
if (!mysql_real_connect(pConn, My_Info.Host, My_Info.Account, My_Info.Passwd, My_Info.KName, MYSQL_PORT, NULL, CLIENT_FOUND_ROWS))
{
printf("connect error:%s\n", mysql_error(pConn));
delete pConn;
pConn = NULL;
}
return pConn;
}
MYSQL *CConnectPool::_GetConnect(bool bTry)
{
static bool bCheck;
MYSQL *pRet = NULL;
pthread_mutex_lock(&m_mutex);
// 取出来还要检查一下是否能正常使用
bCheck = true;
if (m_queueFree.size() > 0)
{
pRet = m_queueFree.front();
m_queueFree.pop();
}
else
{
// 连接数不足,继续创建
if (m_queueFree.size() + m_setBusy.size() < My_Info.MinConnectCount)
{
pRet = _CreateConnect();
bCheck = false;
}
else
{
if (!bTry)
{
// 阻塞等待空闲连接
pthread_cond_wait(&m_cond, &m_mutex);
// 肯定会有空闲连接的
if (m_queueFree.size() > 0)
{
pRet = m_queueFree.front();
m_queueFree.pop();
}
}
}
}
// 检查连接是否可用
if (NULL != pRet && true == bCheck && 0 != mysql_ping(pRet))
{
mysql_close(pRet);
pRet = _CreateConnect();
}
// 加入busy队列
if (NULL != pRet)
{
m_setBusy.insert(pRet);
}
pthread_mutex_unlock(&m_mutex);
return pRet;
}
void CConnectPool::_PutConnect(MYSQL *pConn)
{
if (NULL == pConn)
return;
pthread_mutex_lock(&m_mutex);
std::set<MYSQL *>::iterator it = m_setBusy.find(pConn);
if (it != m_setBusy.end())
{
m_setBusy.erase(it);
}
m_queueFree.push(pConn);
if (1 == m_queueFree.size())
{
// 唤醒等待线程
pthread_cond_signal(&m_cond);
}
pthread_mutex_unlock(&m_mutex);
}