CPP线程池的实现 | Blurred code

CPP线程池的实现

2020/12/01

Updated:2020/12/01

Categories: cpp

在DiRender中有一份 C++线程池 ,主要用于渲染中的图像的分块并行。 这个线程池大概是从 thread pool 或者其他的项目中改过来的。

为什么需要有线程池

在早期的我的某个版本渲染器中,是没有线程池的,起初为了实现并行渲染我设计的每一行像素一个线程,一张200x200的图片要使用200个线程,按照每个线程2MB的栈内存开销,开销400M。但是当图片到2000x2000的分辨率的时候,内存的开销就相当大了。其实线程池的思想还是比较容易理解的:有一定数量的线程,当消费者角色不断的从一个线程共享的队列取出任务执行。 但是实现起来还是有一定的难度,主要是线程池需要执行的是具有不同签名的函数,而我们只有一个容器,所以必须要对任务进行装箱,涉及到模板编程。

装箱的实现

template <typename F, typename... Args>
decltype(auto) ThreadPool::enqueue_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(queue_mutex_);
    if (!this->stop_) {
      tasks_.emplace([task]() { (*task)(); });
    }
  }
  this->queue_cv_.notify_one();
  return res;
}
std::function<void()> wrapperfunc = [task_ptr]() {
  (*task_ptr)(); 
};