下面是一些显示线程池简单实现的代码。
代码的灵感来自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);
}
答案 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
本身可以以这种方式退出循环 - 例如在析构函数中。