14

获得 a 的一种方法std::future是通过std::async

int foo()
{
  return 42;
}

...

std::future<int> x = std::async(foo);

在此示例中,如何x分配 的异步状态的存储,以及哪个线程(如果涉及多个线程)负责执行分配?此外,客户std::async是否可以控制分配?

对于上下文,我看到的构造函数之一std::promise可能会接收分配器,但我不清楚是否可以std::futurestd::async.

4

2 回答 2

8

内存是由调用的线程分配的std::async,你无法控制它是如何完成的。通常它会由 的一些变体完成new __internal_state_type,但不能保证;它可以使用malloc, 或专门为此目的选择的分配器。

从 30.6.8p3 [futures.async] 开始:

“效果:第一个函数的行为与调用第二个函数的行为相同,策略参数为launch::async | launch::deferred和 的参数相同。第二个函数创建FArgs返回的未来对象相关联的共享状态。......”

“第一个功能”是没有启动策略的过载,而第二个是带有启动策略的过载。

在 的情况下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) 就好像在一个由线程对象表示的新执行线程中,调用. DECAY_COPY ()async...

我已经添加了重点。由于函数和参数的复制必须发生在调用线程中,这本质上要求共享状态由调用线程分配。

当然,您可以编写一个启动新线程的实现,等待它分配状态,然后返回一个future引用该状态的实现,但您为什么要这样做呢?

于 2012-10-11T08:01:53.343 回答
7

仅从论点来看std::async,似乎没有办法控制内部的分配,std::promise因此它可以使用任何东西,尽管可能是std::allocator. 虽然我猜理论上它是未指定的,但共享状态很可能是在调用线程内分配的。我没有在标准中找到任何关于这个问题的明确信息。最后std::async是一个非常专业的工具,可以轻松进行异步调用,因此您不必考虑是否真的任何std::promise地方。

为了更直接地控制异步调用的行为,还有std::packaged_task,它确实有一个分配器参数。但是从纯粹的标准引用来看,这个分配器是否只是用于为函数分配存储空间(因为std::packaged_task它是一种特殊的std::function)或者它是否也用于分配 internal 的共享状态std::promise,虽然看起来很可能:

30.6.9.1 [futures.task.members]:

效果:构造一个packaged_task具有共享状态的新对象,并用 初始化该对象的存储任务std::forward<F>(f)。接受Allocator参数的构造函数使用它来分配存储内部数据结构所需的内存。

好吧,它甚至没有说下面有astd::promise同样 for std::async),它可能只是一个可连接到 a 的未定义类型std::future

因此,如果确实没有指定如何std::packaged_task分配其内部共享状态,那么最好的选择可能是实现自己的异步函数调用设施。考虑到,简单地说,astd::packaged_task只是与 astd::function捆绑在一起,std::promise并且std::async只是在一个新线程中启动 a std::packaged_task(好吧,除非它没有),这应该不是太大的问题。

但实际上这可能是规范中的疏忽。虽然分配控制并不真正适合std::async,但分配器的解释std::packaged_task及其使用可能会更清楚一些。但这也可能是有意的,因此std::packaged_task可以随意使用它想要的任何东西,甚至不需要std::promise内部。

编辑:再读一遍,我认为上面的标准引用确实说,std::packaged_task的共享状态使用提供的分配器分配的,因为它是“内部数据结构”的一部分,无论是什么(不需要是一个实际的std::promise,虽然)。所以我认为std::packaged_task应该足以显式控制异步任务的共享状态std::future

于 2012-10-11T08:04:06.753 回答