Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

ThreadPool 实现问题 #35

YiRanMushroom started this conversation in Show and tell
Discussion options

任务队列其实可以使用std::queue<std::function<void()>>,参考如下代码:

using Task = std::packaged_task<void()>;
std::queue<Task> tasks_;
while (!stop_) {
 Task task;
 {
 std::unique_lock<std::mutex> lock{ mutex_ };
 cv_.wait(lock, [this] {return stop_ || !tasks_.empty(); });
 if (tasks_.empty()) return;
 task = std::move(tasks_.front());
 tasks_.pop();
 }
 task(); 
 // 1:这里task(std::packaged_task<void()>)被调用。其他地方从来没有获取这个task的future。返回的future是另一个由共享指针创建的,不是这个task的。
}
auto task = std::make_shared<std::packaged_task<RetType()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
 
std::future<RetType> ret = task->get_future(); 
// 2:这个task(std::packaged_task<RetType()>)由std::make_shared创建,之后返回这个task的future
{
 std::lock_guard<std::mutex> lc{ mutex_ };
 tasks_.emplace([task] {(*task)(); }); 
 // 2处task被wrap在这个lambda中,此处lambda隐式转换为1处std::packaged_task,1处task只被调用而没有获取到future。
}

直接改写成std::function<void()> tasks_; 应该可以通过编译。
这里存在思维混乱问题,using Task = std::packaged_task<void()>; 其实根本没怎么使用,在创建共享指针时使用的是std::packaged_task<RetType()>, 我认为可能直接改成 using Task = std::function<void()>就对了。

You must be logged in to vote

Replies: 5 comments

Comment options

我不认为这是好的改动,且你描述十分混乱。

You must be logged in to vote
0 replies
Comment options

不好意思我现在中文能力不太好,我的意思就是任务队列如果使用std::function<void()>在这个程序中是足够的,使用std::packaged_task<void()>显得思维混乱。具体来说,using Task = std::packaged_task<void()>不是必须的,如果改成using Task = std::function<void()>,只改动这一处,程序依然可以正常编译,运行。参考:https://godbolt.org/z/5hc8zEzs1

You must be logged in to vote
0 replies
Comment options

其实我主要是做了好几步类型擦除,擦除也就是通过包装。

之所以 std::make_shared<std::packaged_task<RetType()>> 是为了我要返回 future,让外部得以获得返回值。

然后插入到容器中 tasks_.emplace([task] {(*task)(); }); 则是利用 lambda 表达式再套一层,擦除了类型。

using Task 是什么,反而不怎么重要了,只要是能够存储我的这个擦除后的可调用对象即可。

You must be logged in to vote
0 replies
Comment options

倒也不是混乱,稍微想一下就能注意到无非是擦除了点类型,包装一下,Task 用什么都问题不大,这个无所谓。

You must be logged in to vote
0 replies
Comment options

这个确实问题不大,使用packaged_task也不会有性能问题。总之我觉得不好的地方是使用std::packaged_task<void()> implies 这个变量使用多线程有关操作,但实际上没有使用相关功能。这个问题不大不改也行,就是我刚开始看的时候造成一些误解所以在这提出来。

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement 内容改进与增强
Converted from issue

This discussion was converted from issue #34 on October 16, 2024 04:00.

AltStyle によって変換されたページ (->オリジナル) /