如何解决C++中线程池的队列条目
我正在尝试实现一个 thredpool,我发现有两个实现。都是使用queue来管理任务,只是queue的入口不同。我想知道哪个更好以及实现的合理性。为什么第二个版本需要 function_wrapper
。
第一个版本使用 std::queue<std::packaged_task<void()> > tasks;
class ThreadPool {
public:
explicit ThreadPool(size_t);
template <class F,class... Args>
decltype(auto) enqueue(F&& f,Args&&... args);
~ThreadPool();
private:
// need to keep track of threads so we can join them
std::vector<std::thread> workers;
// the task queue
std::queue<std::packaged_task<void()> > tasks;
// synchronization
std::mutex queue_mutex;
std::condition_variable condition;
bool stop;
};
// add new work item to the pool
template <class F,class... Args>
decltype(auto) ThreadPool::enqueue(F&& f,Args&&... args) {
using return_type = decltype(f(args...));
std::packaged_task<return_type()> task(
std::bind(std::forward<F>(f),std::forward<Args>(args)...));
std::future<return_type> res = task.get_future();
{
std::unique_lock<std::mutex> lock(queue_mutex);
// don't allow enqueueing after stopping the pool
if (stop) throw std::runtime_error("enqueue on stopped ThreadPool");
tasks.emplace(std::move(task));
}
condition.notify_one();
return res;
}
第二个版本使用 thread_safe_queue<function_wrapper> work_queue;
class function_wrapper {
struct impl_base {
virtual void call() = 0;
virtual ~impl_base() {}
};
std::unique_ptr<impl_base> impl;
template <typename F>
struct impl_type : impl_base {
F f;
impl_type(F&& f_) : f(std::move(f_)) {}
void call() { f(); }
};
public:
template <typename F>
function_wrapper(F&& f) : impl(new impl_type<F>(std::move(f))) {}
void operator()() { impl->call(); }
function_wrapper() = default;
function_wrapper(function_wrapper&& other) : impl(std::move(other.impl)) {}
function_wrapper& operator=(function_wrapper&& other) {
impl = std::move(other.impl);
return *this;
}
function_wrapper(const function_wrapper&) = delete;
function_wrapper(function_wrapper&) = delete;
function_wrapper& operator=(const function_wrapper&) = delete;
};
class thread_pool {
thread_safe_queue<function_wrapper> work_queue;
void worker_thread() {
while (!done) {
function_wrapper task;
if (work_queue.try_pop(task)) {
task();
} else {
std::this_thread::yield();
}
}
}
public:
template <typename FunctionType>
std::future<typename std::result_of<FunctionType()>::type> submit(
FunctionType f) {
typedef typename std::result_of<FunctionType()>::type result_type;
std::packaged_task<result_type()> task(std::move(f));
std::future<result_type> res(task.get_future());
work_queue.push(std::move(task));
return res;
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。