获得一种方法 std::future
通过 std::async
:
int foo()
{
return 42;
}
...
std::future<int> x = std::async(foo);
在这个例子中,存储是如何的 x
分配了异步状态,以及哪个线程(如果涉及多个线程)负责执行分配?而且,是客户的 std::async
对分配有什么控制权?
对于上下文,我看到了 其中一个构造函数 的 std::promise
可能会收到一个分配器,但我不清楚是否可以自定义分配 std::future
在...的水平 std::async
。
仅仅从仅仅的论点来判断 std::async
似乎没有办法控制内部的分配 std::promise
因此它可以只使用任何东西,尽管可能是 std::allocator
。虽然我认为理论上它是未指定的,但很可能共享状态是在调用线程内分配的。我没有在标准中找到关于此事的任何明确信息。到底 std::async
是一个非常专业的工具,可以轻松进行异步调用,因此您不必考虑是否存在 是 一个 std::promise
任何地方。
为了更直接地控制异步调用的行为,还有 std::packaged_task
,确实有一个分配器参数。但仅仅从标准报价来看,这个分配器是否仅仅用于为函数分配存储空间并不是很清楚(因为 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
与...捆绑在一起 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
。
内存由调用的线程分配 std::async
,你无法控制它是如何完成的。通常它将由一些变体完成 new __internal_state_type
,但没有保证;它可能会使用 malloc
,或专门为此目的选择的分配器。
从30.6.8p3 [futures.async]:
“效果:第一个函数的行为与使用策略参数调用第二个函数的行为相同 launch::async | launch::deferred
和相同的论点 F
和 Args
。第二个函数创建与返回的future对象关联的共享状态。 ......”
“第一个功能”是没有启动策略的过载,而第二个功能是启动策略的重载。
如果是 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
引用了那个,但为什么你呢?
仅仅从仅仅的论点来判断 std::async
似乎没有办法控制内部的分配 std::promise
因此它可以只使用任何东西,尽管可能是 std::allocator
。虽然我认为理论上它是未指定的,但很可能共享状态是在调用线程内分配的。我没有在标准中找到关于此事的任何明确信息。到底 std::async
是一个非常专业的工具,可以轻松进行异步调用,因此您不必考虑是否存在 是 一个 std::promise
任何地方。
为了更直接地控制异步调用的行为,还有 std::packaged_task
,确实有一个分配器参数。但仅仅从标准报价来看,这个分配器是否仅仅用于为函数分配存储空间并不是很清楚(因为 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
与...捆绑在一起 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
。
内存由调用的线程分配 std::async
,你无法控制它是如何完成的。通常它将由一些变体完成 new __internal_state_type
,但没有保证;它可能会使用 malloc
,或专门为此目的选择的分配器。
从30.6.8p3 [futures.async]:
“效果:第一个函数的行为与使用策略参数调用第二个函数的行为相同 launch::async | launch::deferred
和相同的论点 F
和 Args
。第二个函数创建与返回的future对象关联的共享状态。 ......”
“第一个功能”是没有启动策略的过载,而第二个功能是启动策略的重载。
如果是 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
引用了那个,但为什么你呢?