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
|
#define THREAD_POOL_H
#include <vector> #include <queue> #include <memory> #include <thread> #include <mutex> #include <condition_variable> #include <future> #include <functional> #include <stdexcept>
class { public: ThreadPool(size_t); template<class F, class... Args> auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type>; ~ThreadPool(); private: std::vector< std::thread > workers_; std::queue< std::function<void()> > tasks_; std::mutex m_; std::condition_variable cv_; bool stop_; };
inline ThreadPool::ThreadPool(size_t threads) : stop_(false) { for(size_t i = 0;i<threads;++i) workers_.emplace_back( [this] { for(;;) { std::function<void()> task;
{ std::unique_lock<std::mutex> lock(this->m_); this->cv_.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(); } } ); }
template<class F, class... Args> auto ::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(m_);
if(stop_) throw std::runtime_error("enqueue on stopped ThreadPool");
tasks_.emplace([task](){ (*task)(); }); } cv_.notify_one(); return res; }
inline ThreadPool::~ThreadPool() { { std::unique_lock<std::mutex> lock(m_); stop_ = true; } cv_.notify_all(); for(std::thread &worker: workers_) worker.join(); }
#endif
|
近期评论