Line data Source code
1 : /* Copyright (c) 2016-2017, Mohamed-Ghaith Kaabi <mohamedghaith.kaabi@gmail.com>
2 : *
3 : * This library is free software; you can redistribute it and/or modify it under
4 : * the terms of the GNU Lesser General Public License version 2.1 as published
5 : * by the Free Software Foundation.
6 : *
7 : * This library is distributed in the hope that it will be useful, but WITHOUT
8 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
10 : * details.
11 : *
12 : * You should have received a copy of the GNU Lesser General Public License
13 : * along with this library; if not, write to the Free Software Foundation, Inc.,
14 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
15 : */
16 :
17 : namespace lunchbox
18 : {
19 4 : ThreadPool::ThreadPool(const size_t size)
20 4 : : _stop(false)
21 : {
22 16 : for (size_t i = 0; i < size; ++i)
23 24 : _threads.emplace_back([this] { this->work(); });
24 4 : }
25 :
26 8 : ThreadPool::~ThreadPool()
27 : {
28 : {
29 8 : std::unique_lock<std::mutex> lock(_mutex);
30 4 : _stop = true;
31 4 : _condition.notify_all();
32 : }
33 4 : joinAll();
34 4 : }
35 :
36 1 : size_t ThreadPool::getSize() const
37 : {
38 1 : return _threads.size();
39 : }
40 :
41 : template <typename F>
42 111 : std::future<typename std::result_of<F()>::type> ThreadPool::post(F&& f)
43 : {
44 : using ReturnType = typename std::result_of<F()>::type;
45 :
46 : auto task =
47 222 : std::make_shared<std::packaged_task<ReturnType()> >(std::forward<F>(f));
48 :
49 111 : auto res = task->get_future();
50 : {
51 222 : std::unique_lock<std::mutex> lock(_mutex);
52 681 : _tasks.emplace([task]() { (*task)(); });
53 : }
54 111 : _condition.notify_one();
55 222 : return res;
56 : }
57 :
58 : template <typename F>
59 10 : void ThreadPool::postDetached(F&& f)
60 : {
61 : {
62 20 : std::unique_lock<std::mutex> lock(_mutex);
63 10 : _tasks.emplace(f);
64 : }
65 10 : _condition.notify_one();
66 10 : }
67 :
68 2 : bool ThreadPool::hasPendingJobs() const
69 : {
70 4 : std::unique_lock<std::mutex> lock(_mutex);
71 4 : return !_tasks.empty();
72 : }
73 :
74 4 : void ThreadPool::joinAll()
75 : {
76 16 : for (auto& thread : _threads)
77 12 : thread.join();
78 4 : }
79 :
80 37 : void ThreadPool::work()
81 : {
82 : for (;;)
83 : {
84 62 : std::function<void()> task;
85 : {
86 62 : std::unique_lock<std::mutex> lock(_mutex);
87 90 : _condition.wait(lock, [this] { return _stop || !_tasks.empty(); });
88 37 : if (_stop)
89 24 : return;
90 25 : task = std::move(_tasks.front());
91 25 : _tasks.pop();
92 : }
93 25 : task();
94 25 : }
95 : }
96 : }
|