Skip to content

ThreadPool 实现问题 #34

Closed
Closed

Description

@YiRanMushroom

任务队列其实可以使用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()>就对了。

Activity

  1. Mq-b commented on Oct 16, 2024

    @Mq-b
    Owner

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

  2. YiRanMushroom commented on Oct 16, 2024

    @YiRanMushroom
    Author

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

  3. Mq-b commented on Oct 16, 2024

    @Mq-b
    Owner

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

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

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

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

  4. Mq-b commented on Oct 16, 2024

    @Mq-b
    Owner

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

  5. YiRanMushroom commented on Oct 16, 2024

    @YiRanMushroom
    Author

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

  6. Repository owner locked and limited conversation to collaborators on Oct 16, 2024
  7. converted this issue into a discussion #35 on Oct 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions