#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>classThreadPool{public:ThreadPool(size_t);template<classF,class... Args>autoenqueue(F&&f,Args&&...args)->std::future<typenamestd::result_of<F(Args...)>::type>;~ThreadPool();private:// need to keep track of threads so we can join themstd::vector<std::thread>workers;// the task queuestd::queue<std::function<void()>>tasks;// synchronizationstd::mutexqueue_mutex;std::condition_variablecondition;boolstop;};// the constructor just launches some amount of workersinlineThreadPool::ThreadPool(size_tthreads):stop(false){for(size_ti=0;i<threads;++i)workers.emplace_back([this]{for(;;){std::function<void()>task;{std::unique_lock<std::mutex>lock(this->queue_mutex);this->condition.wait(lock,[this]{returnthis->stop||!this->tasks.empty();});if(this->stop&&this->tasks.empty())return;task=std::move(this->tasks.front());this->tasks.pop();}task();}});}// add new work item to the pooltemplate<classF,class... Args>autoThreadPool::enqueue(F&&f,Args&&...args)->std::future<typenamestd::result_of<F(Args...)>::type>{usingreturn_type=typenamestd::result_of<F(Args...)>::type;autotask=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);// don't allow enqueueing after stopping the poolif(stop)throwstd::runtime_error("enqueue on stopped ThreadPool");tasks.emplace([task](){(*task)();});}condition.notify_one();returnres;}// the destructor joins all threadsinlineThreadPool::~ThreadPool(){{std::unique_lock<std::mutex>lock(queue_mutex);stop=true;}condition.notify_all();for(std::thread&worker:workers)worker.join();}#endif
// create thread pool with 4 worker threadsThreadPoolpool(4);// enqueue and store futureautoresult=pool.enqueue([](intanswer){returnanswer;},42);// get result from futurestd::cout<<result.get()<<std::endl;