-
Notifications
You must be signed in to change notification settings - Fork 3
/
ThreadPool.h
90 lines (72 loc) · 1.78 KB
/
ThreadPool.h
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
#pragma once
#include <future>
#include <queue>
class ThreadPool
{
public:
explicit ThreadPool (int threads = 0);
virtual ~ThreadPool ();
template<class F, class... Args>
auto enqueue (F &&f, Args&&... args)
->std::future<typename std::result_of<F(Args...)>::type>;
public:
static int get_thread_count ()
{
auto threads = std::thread::hardware_concurrency();
return threads ? static_cast<int>(threads) : 1;
}
private:
bool _stop;
std::mutex _mutex {};
std::condition_variable _cond {};
std::vector<std::thread> _threads {};
std::queue<std::function<void()>> _tasks {};
};
inline ThreadPool::ThreadPool (int threads)
: _stop(false)
{
if (threads <= 0)
threads = get_thread_count();
for (auto i = 0; i < threads; ++i)
{
_threads.emplace_back([this] () {
for (;;)
{
std::function<void()> task;
std::unique_lock<std::mutex> lock(_mutex);
_cond.wait(lock, [this] { return _stop || !_tasks.empty(); });
if (_stop && _tasks.empty())
break;
task = std::move(_tasks.front());
_tasks.pop();
lock.unlock();
task();
}
});
}
}
inline ThreadPool::~ThreadPool ()
{
std::unique_lock<std::mutex> lock(_mutex);
_stop = true;
lock.unlock();
_cond.notify_all();
for (auto &worker : _threads)
worker.join();
}
template<class F, class... Args>
auto ThreadPool::enqueue (F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type>
{
using ret_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared<std::packaged_task<ret_type()>> (
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
std::future<ret_type> res = task->get_future();
std::unique_lock<std::mutex> lock(_mutex);
if (!_stop)
_tasks.emplace([task] () { (*task)(); });
lock.unlock();
_cond.notify_one();
return res;
}