gpt4 book ai didi

c++ - std::packaged_task 是如何工作的

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:32:59 25 4
gpt4 key购买 nike

我正在分析以下代码片段并试图详细理解它:

template<typename FUNCTION, typename... ARGUMENTS>
auto ThreadPool::add( FUNCTION&& Function, ARGUMENTS&&... Arguments ) -> std::future<typename std::result_of<FUNCTION(ARGUMENTS...)>::type>
{
using PackedTask = std::packaged_task<typename std::result_of<FUNCTION(ARGUMENTS...)>::type()>;

auto task = std::make_shared<PackedTask>(std::bind(std::forward<FUNCTION>(Function), std::forward<ARGUMENTS>(Arguments)...));

// get the future to return later
auto ret = task->get_future();

{
std::lock_guard<std::mutex> lock{jobsMutex};
jobs.emplace([task]() { (*task)(); });
}

// let a waiting thread know there is an available job
jobsAvailable.notify_one();

return ret;
}

关于 std::packaged_task 我几乎没有问题.

正如您在 add(...) 中看到的那样方法体,std::packaged_task 的实例- task是局部变量,其作用域在方法执行结束时结束。返回值retstd::future类型由拷贝返回。 ret 的值给出了 task (这是本地的)。所以一旦方法执行完成,task超出范围,所以我预计返回的连接的 std::future 实例变得无效,我的理解正确吗?

在方法执行期间,线程中要执行的任务方法被放置到std::queue<Job> jobs中.为什么只有指针指向operator()std::packaged_task其中包含对 Function 的引用作为 std::queue 中的方法参数给出?我希望直接存储 std::packaged_task为了保存对正在创建的实例的引用...?

无论如何,源代码片段来自 ThreadPool 实现,可以在这里找到 https://github.com/dabbertorres/ThreadPool并且似乎正在充分发挥作用。所以我认为它是正确的但不幸的是我并不完全清楚......如果有人能解释这些东西是如何工作的我会很高兴......

非常感谢任何愿意提供帮助的人。干杯马丁

最佳答案

As you can see in the add(...) method body, the instance of std::packaged_task - task is local variable which scope ends with the end of the method execution.

是的,它是std::shared_ptr<PackedTask>的一个局部变量.当它超出范围时,它会将引用计数减 1。如果新的引用计数为 0,它会删除它指向的对象。幸运的是,jobs持有该共享指针的拷贝,以便指向对象保持事件状态。

The return value ret of std::future type is returned by copy.

不完全是。 ret 更有可能通过移动而不是通过复制返回。

the task goes out of scope and so I expect the connected std::future instance being returned becomes invalid, is my understanding correct?

再次,task是共享指针。 jobs队列使它保持事件状态,并且可能 ret持有该共享指针的另一个拷贝(实际提取 task 的结果)。因此,只要任务在队列中并且有人掌握该结果的 future ,就没有什么是无效的。

I would expect to store directly the std::packaged_task in order to hold the reference to the instance being created...?

没错,它本可以存储 std::packaged_task直接地。我的猜测是这个库的作者不想搞乱不可复制/不可移动的仿函数。如果 std::bind 的结果是不可复制的不可移动的,你不能真正移动std::packaged_task进入队列。使用共享指针解决了这个问题,因为您不复制/移动 packaged_task 本身,只复制/移动指针。然而,您可以将任务对象直接构建到队列中,但是在持有锁的情况下进行这并不是一个好的做法。

不过我同意,这可能会移动 task进入 lambda 比复制它更有效。

关于c++ - std::packaged_task 是如何工作的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46661995/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com