![](/img/trans.png)
[英]How does std::future affects the lifetime of an associated std::packaged_task?
[英]How is the storage associated with std::future allocated?
获取std::future
一种方法是通过std::async
:
int foo()
{
return 42;
}
...
std::future<int> x = std::async(foo);
在这个例子中,如何分配x
的异步状态的存储,以及哪个线程(如果涉及多个线程)负责执行分配? 此外, std::async
的客户端是否可以控制分配?
对于上下文,我看到std::promise
一个构造函数可能会收到一个分配器,但是我不清楚是否可以在std::async
级别自定义std::future
的分配。
内存由调用std::async
的线程分配,您无法控制它是如何完成的。 通常它将由new __internal_state_type
的某个变体完成,但不能保证; 它可以使用malloc
,或专门为此目的选择的分配器。
从30.6.8p3 [futures.async]:
“效果:第一个函数的行为与使用
launch::async | launch::deferred
的策略参数调用第二个函数以及F
和Args
的相同参数相同。第二个函数创建与之关联的共享状态返回的未来对象......“
“第一个功能”是没有启动策略的过载,而第二个功能是启动策略的重载。
在std::launch::deferred
的情况下,没有其他线程,所以一切都必须在调用线程上发生。 在std::launch::async
的情况下,30.6.8p3继续说:
- 如果
policy & launch::async
非零 - 调用INVOKE (DECAY_COPY (std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...)
(20.8。 2,30.3.1.2)好像在一个线程对象表示的新执行线程中,在调用async
的线程中对DECAY_COPY ()
的调用进行了评估。 ...
我加了重点。 由于函数和参数的副本必须在调用线程中发生,因此这基本上要求调用线程分配共享状态。
当然,您可以编写一个启动新线程的实现,等待它分配状态,然后返回引用它的future
,但为什么会这样?
仅从std::async
的仅仅参数判断,似乎没有办法控制内部std::promise
的分配,因此它可以只使用任何东西,尽管可能是std::allocator
。 虽然我认为理论上它是未指定的,但很可能共享状态是在调用线程内部分配的。 我没有在标准中找到关于此事的任何明确信息。 最终std::async
是容易的异步调用一个非常专业的设备,所以你不必想如果有实际上是一个std::promise
的任何地方。
为了更直接地控制异步调用的行为,还有std::packaged_task
,它确实有一个allocator参数。 但仅从标准引用来看,这个分配器是否仅用于为函数分配存储(因为std::packaged_task
是一种特殊的std::function
)或者它是否也用于分配共享状态,这一点并不十分清楚。内部std::promise
,虽然看起来很可能:
30.6.9.1 [futures.task.members]:
效果:构造具有共享状态的新的
packaged_task
对象,并使用std::forward<F>(f)
初始化对象的存储任务。 采用Allocator
参数的构造函数使用它来分配存储内部数据结构所需的内存。
那么,它甚至不说有一个std::promise
下(同样为std::async
),它可能只是一个未定义的类型连接到std::future
。
因此,如果确实没有指定std::packaged_task
如何分配其内部共享状态,那么最好的办法可能是为异步函数调用实现自己的工具。 考虑到这一点,简单地说, std::packaged_task
只是一个与std::promise
捆绑在一起的std::function
而std::async
只是在一个新线程中启动一个std::packaged_task
(好吧,除非它没有),这不应该是一个太大的问题。
但实际上这可能是规范中的疏忽。 虽然分配控制并不真正适合std::async
,但std::packaged_task
的解释及其对分配器的使用可能会更清楚一些。 但这也可能是故意的,所以std::packaged_task
可以随意使用它甚至不需要内部的std::promise
。
编辑:再次阅读,我认为上面的标准引用确实说, std::packaged_task
的共享状态是使用提供的分配器分配的,因为它是“内部数据结构”的一部分 ,无论那些是什么(没有但是,我需要成为一个真正的std::promise
。 所以我认为std::packaged_task
应该足以明确控制异步任务的std::future
的共享状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.