//#include"ThreadPool.h"
#include<iostream>
#include<vector>
#include<queue>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<future>
#include<functional>
#include<stdexcept>
using namespace std;
#pragma once
class ThreadPool
{
public:
ThreadPool();
ThreadPool(int threads);
~ThreadPool();
template<class F, class... Args>
auto enqueue(F&& f, Args&&... args)->future<typename result_of<F(Args...)>::type>;
private:
vector<thread> workers;
queue<function<void()>> tasks;
mutex queue_mutex;
condition_variable condition;
bool stop;
};
ThreadPool::ThreadPool()
{
for (size_t i = 0; i < 3; i++)
{
workers.emplace_back(
[this] {
for (; ; )
{
function<void()> task;
{
unique_lock<mutex> lock(this->queue_mutex);
this->condition.wait(lock, [this] {return this->stop || !this->tasks.empty(); });
if (this->stop && this->tasks.empty())return;
task = move(this->tasks.front());
this->tasks.pop();
}
task();
}
}
);
}
}
ThreadPool::~ThreadPool()
{
{
unique_lock<mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
for (thread &worker : workers)
{
worker.join();
}
}
ThreadPool::ThreadPool(int threads) :stop(false) {
for (size_t i = 0; i < threads; i++)
{
workers.emplace_back(
[this] {
for (; ; )
{
function<void()> task;
{
unique_lock<mutex> lock(this->queue_mutex);
this->condition.wait(lock, [this] {return this->stop || !this->tasks.empty(); });
if (this->stop && this->tasks.empty())return;
task = move(this->tasks.front());
this->tasks.pop();
}
task();
}
}
);
}
}
template<class F,class...Args>
auto ThreadPool::enqueue(F&& f, Args&&... args)->future<typename result_of<F(Args...)>::type>
{
using return_type = typename result_of<F(Args...)>::type;
auto task = make_shared<packaged_task<return_type()>>(bind(forward<F>(f),forward<Args>(args)...));
future<return_type> res = task->get_future();
{
unique_lock<mutex> lock(queue_mutex);
if (stop) {
throw runtime_error("enqueue on stopped ThreadPool");
}
tasks.emplace([task]() {(*task)(); });
}
condition.notify_one();
return res;
}
//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 = make_shared<packaged_task<return_type()>>(bind(forward<F>(f), forward<Args>(args)...));
// std::packaged_task<return_type()> task(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);
// tasks.push(std::move(task));
// }
// condition.notify_one();
//
// return res;
//}
int main() {
size_t t = 4;
ThreadPool pool;
vector<future<void>> results;
for (int i = 0; i < 16; i++)
{
int copy_i = i;
results.emplace_back(pool.enqueue([copy_i]() {
cout << "Task " << copy_i << " running on thread " << this_thread::get_id() << endl;
}));
}
for (auto &res : results)
{
res.get();
}
cin.get();
return 0;
}