-
Notifications
You must be signed in to change notification settings - Fork 53
ThreadPool 实现问题 #35
-
任务队列其实可以使用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()>就对了。
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 5 comments
-
我不认为这是好的改动,且你描述十分混乱。
Beta Was this translation helpful? Give feedback.
All reactions
-
不好意思我现在中文能力不太好,我的意思就是任务队列如果使用std::function<void()>在这个程序中是足够的,使用std::packaged_task<void()>显得思维混乱。具体来说,using Task = std::packaged_task<void()>不是必须的,如果改成using Task = std::function<void()>,只改动这一处,程序依然可以正常编译,运行。参考:https://godbolt.org/z/5hc8zEzs1
Beta Was this translation helpful? Give feedback.
All reactions
-
其实我主要是做了好几步类型擦除,擦除也就是通过包装。
之所以 std::make_shared<std::packaged_task<RetType()>>
是为了我要返回 future,让外部得以获得返回值。
然后插入到容器中 tasks_.emplace([task] {(*task)(); });
则是利用 lambda 表达式再套一层,擦除了类型。
using Task
是什么,反而不怎么重要了,只要是能够存储我的这个擦除后的可调用对象即可。
Beta Was this translation helpful? Give feedback.
All reactions
-
倒也不是混乱,稍微想一下就能注意到无非是擦除了点类型,包装一下,Task 用什么都问题不大,这个无所谓。
Beta Was this translation helpful? Give feedback.
All reactions
-
这个确实问题不大,使用packaged_task也不会有性能问题。总之我觉得不好的地方是使用std::packaged_task<void()> implies 这个变量使用多线程有关操作,但实际上没有使用相关功能。这个问题不大不改也行,就是我刚开始看的时候造成一些误解所以在这提出来。
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1