#include <iostream>
#include <functional>
#include <queue>
#include <atomic>
#include <mutex>
#include <thread>
#include <future>
#include <memory>
#include <chrono>
#include <list>
using namespace std;
enum class Status
{
STOP,
START
};
class ThreadPackage
{
private:
shared_ptr<function<void()>> _fun = nullptr;
shared_ptr<thread> t1 = nullptr;
public:
std::mutex _wait_release_m;
Status _thread_status = Status::STOP;
ThreadPackage(){};
~ThreadPackage();
void setWork(shared_ptr<function<void()>> fun);
void start();
};
ThreadPackage::~ThreadPackage()
{
if (t1->joinable())
{
t1->join();
}
};
void ThreadPackage::start()
{
_thread_status = Status::START;
t1 = make_shared<thread>([this]() {
std::unique_lock<std::mutex> lk(_wait_release_m);
this->_thread_status = Status::START;
(*(this->_fun))();
this->_thread_status = Status::STOP;
});
}
void ThreadPackage::setWork(shared_ptr<function<void()>> fun)
{
this->_fun = fun;
}
class ThreadPool
{
public:
ThreadPool(int pool_size);
ThreadPool(){};
~ThreadPool(){};
template <typename F, typename... Args>
decltype(auto) add_task(F &&func, Args &&...args);
private:
shared_ptr<thread> t_check;
shared_ptr<thread> t_realse;
shared_ptr<thread> t_dispatch;
std::atomic<int> _pool_size;
Status _status = Status::STOP;
queue<function<void()>> _wait_work_q;
std::mutex _wait_add_work_m;
queue<function<void()>> _add_wait_work_q;
std::mutex _working_m;
list<shared_ptr<ThreadPackage>> _starting_l;
std::mutex _wait_release_m;
list<shared_ptr<ThreadPackage>> _wait_release_l;
void release();
void dispatch();
void check();
};
void ThreadPool::release()
{
while (true)
{
{
std::unique_lock<std::mutex> lk(_wait_release_m);
for (auto i = _wait_release_l.begin(); i != _wait_release_l.end(); ++i)
{
if ((*i)->_thread_status == Status::STOP)
{
std::unique_lock<std::mutex> lk((*i)->_wait_release_m);
_wait_release_l.erase(i);
break;
}
}
}
std::this_thread::yield();
}
}
void ThreadPool::dispatch()
{
while (true)
{
if (_wait_work_q.size() > 0 && _starting_l.size() < _pool_size)
{
auto _temp_wait_task = _wait_work_q.front();
_wait_work_q.pop();
auto _temp_thread_package = std::make_shared<ThreadPackage>();
_temp_thread_package->setWork(make_shared<function<void()>>(_temp_wait_task));
_temp_thread_package->start();
std::unique_lock<std::mutex> lk(_working_m);
_starting_l.emplace_back(_temp_thread_package);
}
if (_add_wait_work_q.size() > 0)
{
{
std::unique_lock<std::mutex> lk(_wait_add_work_m);
auto _temp_add_wait_task = _add_wait_work_q.front();
_add_wait_work_q.pop();
_wait_work_q.push(_temp_add_wait_task);
}
}
std::this_thread::yield();
}
}
void ThreadPool::check()
{
while (true)
{
{
std::unique_lock<std::mutex> lk(_working_m);
for (auto i = _starting_l.begin(); i != _starting_l.end(); ++i)
{
if ((*i)->_thread_status == Status::STOP)
{
std::unique_lock<std::mutex> lk(_wait_release_m);
_wait_release_l.emplace_back(*i);
i = _starting_l.erase(i);
break;
}
}
}
std::this_thread::yield();
}
}
ThreadPool::ThreadPool(int pool_size)
{
this->_pool_size = pool_size;
t_check = make_shared<thread>(bind(&ThreadPool::check, this));
t_realse = make_shared<thread>(bind(&ThreadPool::release, this));
t_dispatch = make_shared<thread>(bind(&ThreadPool::dispatch, this));
}
template <typename F, typename... Args>
decltype(auto) ThreadPool::add_task(F &&func, Args &&...args)
{
using res_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared<std::packaged_task<res_type()>>(
std::bind(std::forward<F>(func), std::forward<Args>(args)...));
std::future<res_type> res = task->get_future();
{
std::unique_lock<std::mutex> lk(_wait_add_work_m);
_add_wait_work_q.emplace([task]() { (*task)(); });
}
return res;
}
int wc(int n)
{
int all = 1;
for (int i = 1; i < 100000000; ++i)
{
all *= i;
all %= 100000007;
}
cout << n << " ";
return all;
}
int main()
{
vector<future<int>> temp;
auto s1 = clock();
ThreadPool pt(10);
for (int i = 0; i < 8; ++i)
{
temp.emplace_back(pt.add_task(wc, 1));
}
auto s2 = clock();
for (int i = 0; i < temp.size(); ++i)
{
temp[i].get();
}
auto s3 = clock();
cout << endl;
for (int i = 0; i < 8; ++i)
{
wc(2);
}
auto s4 = clock();
cout << endl;
thread t1(wc, 3), t2(wc, 3), t3(wc, 3), t4(wc, 3), t5(wc, 3), t6(wc, 3), t7(wc, 3), t8(wc, 3);
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
t6.join();
t7.join();
t8.join();
auto s5 = clock();
cout << "end\n";
std::cout << (s2 - s1) << "\t" << (s3 - s1) << "\t" << (s4 - s3) << "\t" << (s5 - s4) << std::endl;
while (true)
{
std::this_thread::yield();
}
getchar();
return 0;
}