#include "CConnectPool.h" #include #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::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::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); }