-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconnectionPool.cpp
More file actions
190 lines (163 loc) · 4.73 KB
/
Copy pathconnectionPool.cpp
File metadata and controls
190 lines (163 loc) · 4.73 KB
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#include "connectionPool.h"
#include <json/json.h>
#include <fstream>
#include <thread>
using namespace Json;
ConnectionPool::ConnectionPool()
{
//加载配置文件
if(!parseJsonFile())
{
return ;
}
//初始化 新的数据库连接
for(int i=0;i<m_minSize;i++)
{
// MysqlConn* conn=new MysqlConn;
// conn->connect(m_user,m_passwd,m_dbName,m_ip,m_port);
// //放入连接队列
// m_connectionQ.push(conn);
//封装为函数
addConnection();
}
//产生连接
thread producer(&ConnectionPool::produceConnection,this); //任务函数 指定当前实例对象
//销毁连接
thread recycler(&ConnectionPool::recycleConnection,this);
//线程分离,确保 主线程不会阻塞
producer.detach();
recycler.detach();
}
//初始化新的数据库连接
void ConnectionPool::addConnection()
{
MysqlConn* conn=new MysqlConn;
conn->connect(m_user,m_passwd,m_dbName,m_ip,m_port);
//记录时间戳
conn->refreshAliveTime();
//放入连接队列
m_connectionQ.push(conn);
}
//添加数据库连接
void ConnectionPool::produceConnection()
{
//判断连接是否够用
while (true)
{
//封装 互斥锁对象,由 unique_lock 自动管理
unique_lock<mutex> locker(m_mutexQ);
while (m_connectionQ.size()>=m_minSize)
{
//满足最小连接数,就阻塞 不在添加新的数据库连接
m_cond.wait(locker);
}
//创建新的数据库连接
addConnection();
//唤醒 消费者
m_cond.notify_all();
}
}
//销毁数据库连接
void ConnectionPool::recycleConnection()
{
while (true)
{
//定时执行,使用线程休眠
//this_thread::sleep_for(chrono::seconds(1)); //休眠1S
this_thread::sleep_for(chrono::milliseconds(500));
//自动管理 连接队列
lock_guard<mutex> locker(m_mutexQ);
while (m_connectionQ.size()>m_minSize)
{
//判断空闲时长
//取出队头连接
MysqlConn* conn=m_connectionQ.front();
//超过最大空闲时长就销毁
if(conn->getAliveTime() >= m_maxIdleTime)
{
m_connectionQ.pop();
delete conn;
}
else
{
break;
}
}
}
}
//获取该实现类
ConnectionPool* ConnectionPool::getConnectPool()
{
//静态变量,紧跟进程
static ConnectionPool pool;
return &pool;
}
bool ConnectionPool::parseJsonFile()
{
//读入文件
ifstream ifs("dbconf.json");
//读取流对象
Reader rd;
Value root;
//将读到的
rd.parse(ifs,root);
if(root.isObject())
{
//判断是否是JSON对象,如果是就读出所有json数据
m_ip=root["ip"].asString(); //通过key获取到value
m_port=root["port"].asInt();
m_user=root["userName"].asString();
m_passwd=root["password"].asString();
m_dbName=root["dbName"].asString();
m_minSize=root["minSize"].asInt();
m_maxSize=root["maxSize"].asInt();
m_maxIdleTime=root["maxIDleTime"].asInt();
m_timeout=root["timeout"].asInt();
return true;
}
return false;
}
//用户调用 数据库连接的接口
shared_ptr<MysqlConn> ConnectionPool::getConnection()
{
//互斥锁
unique_lock<mutex> locker(m_mutexQ);
while(m_connectionQ.empty())
{
//连接队列为空,就需要 阻塞新的 连接请求
if(cv_status::timeout == m_cond.wait_for(locker,chrono::milliseconds(m_timeout)))
{
//如果阻塞结束后 该线程没有被唤醒,就继续等待,直到取到可用的数据库连接
if(m_connectionQ.empty())
{
continue;
}
}
}
//直到找到可用的数据库连接,取出该连接
// MysqlConn* conn=m_connectionQ.front();
//指定删除器,销毁连接但不析构
shared_ptr<MysqlConn> connptr(m_connectionQ.front(),[this](MysqlConn* conn)
{
//互斥对象加锁
lock_guard<mutex> locker(m_mutexQ); //缺陷:无法控制加锁的范围
//更新时间戳
conn->refreshAliveTime();
m_connectionQ.push(conn);
});
m_connectionQ.pop();
//唤醒生产者
m_cond.notify_all();
//return conn;
return connptr; //通过智能指针管理 数据库连接资源
}
ConnectionPool::~ConnectionPool()
{
//判断任务队列中的数据,析构连接队列
while(!m_connectionQ.empty())
{
MysqlConn* conn=m_connectionQ.front();
m_connectionQ.pop();
delete conn;
}
}