今天看了github上点击量最大的一个C++2.0实现的线程池:链接,感觉看起来很简单明了 于是看后自己默写了一个线程池类,并对里面步骤进行注释,也是提升我自己的一部分 tips:原代码中的std::result_of 在C++17 的类型萃取库中已经移除,因此我改用指代更为清晰的decltype 进行修改。
具体代码如下,代码风格采用谷歌式: 这大概是CSDN上面最优雅的C++线程池代码了吧
#pragma once
#include <atomic>
#include <condition_variable>
#include <functional>
#include <future>
#include <memory>
#include <mutex>
#include <queue>
#include <thread>
#include <vector>
class ThreadPool final {
public:
ThreadPool(uint8_t _num = 0);
~ThreadPool();
ThreadPool(ThreadPool const&) = delete;
ThreadPool(ThreadPool&&) = delete;
ThreadPool& operator=(ThreadPool const&) = delete;
ThreadPool& operator=(ThreadPool&&) = delete;
template <class F, class... Args>
auto enqueue(F&& _func, Args&&... _args)
-> std::future<decltype(_func(_args...))> {
if (this->stop_.load()) {
throw std::runtime_error("enqueue on stopped ThreadPool");
}
using rtype = decltype(_func(_args...));
auto task = std::make_shared<std::packaged_task<rtype()>>(
std::bind(std::forward<F>(_func), std::forward<Args>(_args)...));
std::future<rtype> res = task->get_future();
{
std::lock_guard<std::mutex> lock(mtx_);
this->tasks_.emplace([task]() { (*task)(); });
}
this->cv_.notify_all();
return res;
}
private:
std::atomic<bool> stop_;
std::vector<std::thread> threads_;
std::queue<std::function<void()>> tasks_;
std::mutex mtx_;
std::condition_variable cv_;
};
#include "thread_pool.hpp"
ThreadPool::ThreadPool(uint8_t _num) : stop_{false} {
for (auto i{0}; i != _num; ++i) {
this->threads_.emplace_back([this] {
while (true) {
auto task = std::function<void()>();
{
std::unique_lock<std::mutex> lock(this->mtx_);
this->cv_.wait(lock, [this] {
if (this->stop_.load() or !this->tasks_.empty()) {
return true;
}
return false;
});
if (this->stop_.load() and this->tasks_.empty()) {
break;
}
task = std::move(this->tasks_.front());
this->tasks_.pop();
}
task();
}
});
}
}
ThreadPool::~ThreadPool() {
this->stop_.store(true);
this->cv_.notify_all();
for (auto&& thread : this->threads_) {
if (thread.joinable()) {
thread.join();
}
}
}
运用:
#include "thread_pool.hpp"
using namespace std::literals;
int main() {
auto pool = new ThreadPool(std::thread::hardware_concurrency());
auto func = [](int a, int b) -> int { return std::pow(a, b); };
auto futures = std::vector<std::future<int>>();
for (auto i{0}; i != 10; ++i) {
futures.push_back(pool->enqueue(func, i, 2));
}
std::this_thread::sleep_for(10ms);
for (auto&& future : futures) {
std::cout << future.get() << std::endl;
}
delete pool;
return 0;
}
|