带有错误

时间:2017-01-23 18:47:28

标签: c++ multithreading c++11 task stdthread

下面是一些显示线程池简单实现的代码。

代码的灵感来自this post

我用clang++ -std=c++11 threadpool.cpp -o threadpool -lpthread

编译它

执行后我得到了以下内容:

./threadpool 
terminate called without an active exception

正如我所看到的,问题是失去了函数pool_t::pop()及其无限循环。

我的问题是,如何优雅地摆脱循环?

遗忘的代码 - 道歉 -

#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <functional>
#include <condition_variable>

struct tasks_t
{
  std::queue<std::function<void()>> queue;

  std::mutex mutex;
};

struct threads_t
{
  std::vector<std::thread> vector;

  std::condition_variable condition;
};

struct pool_t
{
  tasks_t tasks;

  threads_t threads;

  void pop()
  {
    while(true)
    {
      std::function<void()> task;
      {
        std::unique_lock<std::mutex> lock(tasks.mutex);

        threads.condition.wait(lock,[this]{return !tasks.queue.empty();});

        task = tasks.queue.front();

        tasks.queue.pop();
      }
      task();
    }
  }

  void push(std::function<void()> function)
  {
    {
      std::unique_lock<std::mutex> lock(tasks.mutex);

      tasks.queue.push(function);
    }
    threads.condition.notify_one();
  }

  void start()
  {
    for (int i=0,j=std::thread::hardware_concurrency(); i!=j; ++i)
    {
      threads.vector.push_back(std::thread(&pool_t::pop,this));
    }
  }
};

#include <chrono>
#include <iostream>

std::function<void()> t0 = []
{
  std::cout << "t0" << std::endl;
  std::this_thread::sleep_for(std::chrono::seconds(1));
  return;
};

std::function<void()> t1 = []
{
  std::cout << "t1" << std::endl;
  std::this_thread::sleep_for(std::chrono::seconds(2));
  return;
};

int main()
{
  pool_t pool;

  pool.start();

  pool.push(t0);

  pool.push(t1);
}

1 个答案:

答案 0 :(得分:0)

在这种情况下,最简单的方法通常是将一个简单地抛出特定类型的异常的任务排队,而不是可以捕获并采取行动......

struct pool_t {
  class quit_exception {};
  tasks_t tasks;
  threads_t threads;

  void pop ()
  {
    while (true) {
      std::function<void()> task;
      {
        std::unique_lock<std::mutex> lock(tasks.mutex);
        threads.condition.wait(lock, [this]{ return !tasks.queue.empty(); });
        task = tasks.queue.front();
        tasks.queue.pop();
      }
      try {
        task();
      }
      catch (quit_exception &ex) {
        return;
      }
    }
  }

当你需要突破循环时,只需...

pool.push([](){ throw pool::quit_exception(); });

根据精确用法,您可能希望quit_exception为私有类型,以便只有pool_t本身可以以这种方式退出循环 - 例如在析构函数中。