如何分配与std :: future关联的存储?

Jar*_*ock 12 c++ asynchronous future c++-standard-library c++11

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

int foo()
{
  return 42;
}

...

std::future<int> x = std::async(foo);
Run Code Online (Sandbox Code Playgroud)

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

对于情况下,我看到一个构造函数std::promise可能会收到一个分配器,但如果它是可以自定义的配置,目前还不清楚我std::future的水平std::async.

Ant*_*ams 7

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

从30.6.8p3 [futures.async]:

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

"第一个功能"是没有启动策略的过载,而第二个功能是启动策略的重载.

在这种情况下std::launch::deferred,没有其他线程,所以一切都必须在调用线程上发生.在std::launch::async30.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引用它的那个,但为什么会这样?


Chr*_*ica 7

从仅仅的论点判断,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分配其内部共享状态,那么最好的办法可能是为异步函数调用实现自己的工具.考虑到这一点,简单地说,a std::packaged_task只是std::function捆绑了a std::promise,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.