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
| #pragma once #pragma once #ifndef THREAD_POOL_H #define THREAD_POOL_H
#include <vector> #include <queue> #include <memory> #include <thread> #include <mutex> #include <condition_variable> #include <future> #include <functional> #include <stdexcept> #include<chrono> #include<ctime> #include<Windows.h> class ThreadPool {
public: ThreadPool() { this->stop = false; } ThreadPool(size_t); template<class F, class... Args> auto enqueue(F&& f, Args&&... args)->std::future<typename std::result_of<F(Args...)>::type>; void init(size_t threads); void wait(); ~ThreadPool();
private: std::vector< std::thread > workers; std::queue< std::function<void()> > tasks;
std::mutex queue_mutex; std::condition_variable condition; std::condition_variable conditionWait; std::mutex wait_mutex; bool stop; };
inline ThreadPool::ThreadPool(size_t threads) { this->init(threads);
}
template<class F, class... Args> auto ThreadPool::enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> { using return_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared< std::packaged_task<return_type()> >( std::bind(std::forward<F>(f), std::forward<Args>(args)...) );
std::future<return_type> res = task->get_future(); { std::unique_lock<std::mutex> lock(queue_mutex); if (stop) throw std::runtime_error("enqueue on stopped ThreadPool");
tasks.emplace([task]() { (*task)(); }); } condition.notify_one(); return res; }
inline void ThreadPool::init(size_t threads) { this->stop = false; for (size_t i = 0; i < threads; ++i) workers.emplace_back( [this] { for (;;) { std::function<void()> task; { if (this->stop || this->tasks.empty()) { this->conditionWait.notify_all(); } std::unique_lock<std::mutex> lock(this->queue_mutex);
this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); });
if (this->stop && this->tasks.empty()) return;
task = std::move(this->tasks.front()); this->tasks.pop(); } task(); } } ); }
inline void ThreadPool::wait() { { std::unique_lock<std::mutex>lock(this->wait_mutex); this->conditionWait.wait(lock, [this]() {return this->stop || this->tasks.empty(); }); } } inline ThreadPool::~ThreadPool() { { std::unique_lock<std::mutex> lock(queue_mutex); stop = true; } condition.notify_all(); for (std::thread &worker : workers) worker.join(); }
#endif
|