-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathThreadPool.h
More file actions
320 lines (261 loc) · 7.99 KB
/
Copy pathThreadPool.h
File metadata and controls
320 lines (261 loc) · 7.99 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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
/*
* 文件名称:ThreadPool.h
* 语言标准:C++17
*
* 创建日期:2017年09月22日
* 更新日期:2023年09月12日
*
* 摘要
* 1.线程池类ThreadPool定义于此文件,实现于ThreadPool.cpp。
* 2.当无任务时,阻塞守护线程;当新增任务时,激活守护线程,通知线程执行任务。
* 3.当无闲置线程时,阻塞守护线程;当存在闲置线程时,激活守护线程,通知闲置线程执行任务。
* 4.当销毁线程池时,等待守护线程退出。而守护线程在退出之前,等待所有线程退出。
* 线程在退出之前,默认执行任务队列的所有任务。可选取出所有任务或者清空队列,以实现线程立即退出。
* 5.提供增删线程策略,由守护线程增删线程。
* 当任务队列非空时,一次性增加线程;当存在闲置线程时,逐个删减线程。
* 6.以原子操作确保接口的线程安全性,并且新增成员类Proxy,用于减少原子操作,针对频繁操作提升性能。
* 7.守护线程主函数声明为静态成员,除去与类成员指针this的关联性。
* 8.引入强化条件类模板Condition,当激活先于阻塞时,确保守护线程正常退出。
* 9.引入双缓冲队列类模板DoubleQueue,提高放入和取出任务的效率。
*
* 作者:许聪
* 邮箱:solifree@qq.com
*
* 版本:v2.3.0
* 变化
* v2.0.1
* 1.运用Condition的宽松策略,提升激活守护线程的性能。
* v2.0.2
* 1.消除谓词对条件实例有效性的重复判断。
* v2.0.3
* 1.修复条件谓词异常。
* 在延迟删减线程之时,未减少闲置线程数量,导致守护线程不必等待通知的条件谓词异常。
* v2.0.4
* 1.以原子操作确保移动语义的线程安全性。
* 2.新增成员类Proxy,提供轻量接口,减少原子操作。
* 3.新增任务可选复制语义或者移动语义。
* v2.1.0
* 1.修复线程池扩容问题。
* 由于未增加总线程数量,因此无限创建线程;同时未增加闲置线程数量,守护线程无法调度新线程执行任务,即线程泄漏。
* 2.修复线程池缩容问题。
* 在延迟删减线程之时,未减少总线程数量,导致线程池反复删减线程,直至线程池为空。
* v2.2.0
* 1.完善代码风格。
* 2.设置线程池容量函数返回合理值。
* v2.2.1
* 1.修复移动赋值运算符函数的资源泄漏问题。
* v2.2.2
* 1.优化移动语义。
* 2.确保移动构造函数和析构函数的异常安全性。
* v2.3.0
* 1.确保移动赋值运算符函数的异常安全性。
* 2.在销毁线程池时,当任务队列为空,并且所有线程闲置,守护线程才退出,否则守护线程阻塞,直至满足退出条件。
*/
#pragma once
#include <functional>
#include <utility>
#include <memory>
#include <list>
#include <mutex>
#include "Common.hpp"
ETERFREE_SPACE_BEGIN
class ThreadPool final
{
// 线程池数据结构体
struct Structure;
public:
// 线程池代理类
class Proxy;
private:
using DataType = std::shared_ptr<Structure>;
public:
using TaskType = std::function<void()>;
using TaskQueue = std::list<TaskType>;
using SizeType = TaskQueue::size_type;
private:
mutable std::mutex _mutex;
DataType _data;
private:
// 移动数据
static DataType move(ThreadPool& _left, \
ThreadPool&& _right);
// 创建线程池
static void create(DataType&& _data, \
SizeType _capacity);
// 销毁线程池
static void destroy(DataType&& _data);
// 调整线程数量
static SizeType adjust(DataType& _data);
// 守护线程主函数
static void execute(DataType _data);
public:
// 获取支持的并发线程数量
static SizeType getConcurrency() noexcept;
private:
// 加载非原子数据
auto load() const
{
std::lock_guard lock(_mutex);
return _data;
}
public:
// 默认构造函数
ThreadPool(SizeType _capacity = getConcurrency());
// 构造函数
DEPRECATED
ThreadPool(SizeType _size, SizeType _capacity);
// 删除默认复制构造函数
ThreadPool(const ThreadPool&) = delete;
// 默认移动构造函数
ThreadPool(ThreadPool&& _another) noexcept;
// 默认析构函数
~ThreadPool() noexcept;
// 删除默认复制赋值运算符函数
ThreadPool& operator=(const ThreadPool&) = delete;
// 默认移动赋值运算符函数
ThreadPool& operator=(ThreadPool&& _threadPool) noexcept;
// 获取线程最大数量
REPLACEMENT(getCapacity)
auto getMaxThreads() const
{
return getCapacity();
}
// 获取线程池容量
SizeType getCapacity() const;
// 设置线程最大数量
REPLACEMENT(setCapacity)
bool setMaxThreads(SizeType _capacity)
{
return setCapacity(_capacity);
}
// 设置线程池容量
bool setCapacity(SizeType _capacity);
// 获取线程数量
REPLACEMENT(getTotalSize)
auto getThreads() const
{
return getTotalSize();
}
// 获取线程数量
REPLACEMENT(getTotalSize)
auto getSize() const
{
return getTotalSize();
}
// 获取总线程数量
SizeType getTotalSize() const;
// 设置线程数量
DEPRECATED
bool setThreads(SizeType size)
{
return false;
}
// 获取空闲线程数量
REPLACEMENT(getIdleSize)
auto getFreeThreads() const
{
return getIdleSize();
}
// 获取闲置线程数量
SizeType getIdleSize() const;
// 获取任务数量
REPLACEMENT(getTaskSize)
auto getTasks() const
{
return getTaskSize();
}
// 获取任务数量
SizeType getTaskSize() const;
// 放入任务
bool pushTask(const TaskType& _task);
bool pushTask(TaskType&& _task);
// 适配不同任务接口,推进线程池模板化
template <typename _Functor>
bool pushTask(const _Functor& _functor)
{
return pushTask(TaskType(_functor));
}
template <typename _Functor>
bool pushTask(_Functor&& _functor)
{
return pushTask(TaskType(std::forward<_Functor>(_functor)));
}
template <typename _Functor, typename... _Args>
bool pushTask(_Functor&& _functor, _Args&&... _args);
// 批量放入任务
bool pushTask(TaskQueue& _taskQueue);
bool pushTask(TaskQueue&& _taskQueue);
// 批量取出任务
bool popTask(TaskQueue& _taskQueue);
// 清空任务
void clearTask();
// 获取代理
Proxy getProxy() const;
};
class ThreadPool::Proxy final
{
DataType _data;
public:
Proxy(const decltype(_data)& _data) noexcept : \
_data(_data) {}
explicit operator bool() const noexcept { return valid(); }
// 是否有效
bool valid() const noexcept
{
return static_cast<bool>(_data);
}
// 获取线程池容量
SizeType getCapacity() const noexcept;
// 设置线程池容量
bool setCapacity(SizeType _capacity);
// 获取线程数量
REPLACEMENT(getTotalSize)
auto getSize() const noexcept
{
return getTotalSize();
}
// 获取总线程数量
SizeType getTotalSize() const noexcept;
// 获取闲置线程数量
SizeType getIdleSize() const noexcept;
// 获取任务数量
SizeType getTaskSize() const noexcept;
// 放入任务
bool pushTask(const TaskType& _task);
bool pushTask(TaskType&& _task);
// 适配不同任务接口,推进线程池模板化
template <typename _Functor>
bool pushTask(const _Functor& _functor)
{
return pushTask(TaskType(_functor));
}
template <typename _Functor>
bool pushTask(_Functor&& _functor)
{
return pushTask(TaskType(std::forward<_Functor>(_functor)));
}
template <typename _Functor, typename... _Args>
bool pushTask(_Functor&& _functor, _Args&&... _args);
// 批量放入任务
bool pushTask(TaskQueue& _taskQueue);
bool pushTask(TaskQueue&& _taskQueue);
// 批量取出任务
bool popTask(TaskQueue& _taskQueue);
// 清空任务
void clearTask();
};
template <typename _Functor, typename... _Args>
bool ThreadPool::Proxy::pushTask(_Functor&& _functor, _Args&&... _args)
{
auto functor = std::bind(std::forward<_Functor>(_functor), \
std::forward<_Args>(_args)...);
return pushTask(TaskType(functor));
}
template <typename _Functor, typename... _Args>
bool ThreadPool::pushTask(_Functor&& _functor, _Args&&... _args)
{
auto functor = std::bind(std::forward<_Functor>(_functor), \
std::forward<_Args>(_args)...);
return pushTask(TaskType(functor));
}
ETERFREE_SPACE_END