240717班级,工业化控制系统,煤矿相关行业,昆仑系统
congmu
2024-10-31 ad2a36a8425406799db94a2e26d1fba82db6aa60
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#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;
}