std::async是如何实现的?

3

我想知道在性能导向的代码中使用std::async是否合适。具体来说:

  1. 从工作线程到主线程捕获异常是否会有惩罚?
  2. 如何将值从工作线程返回给主线程?
  3. 传递的输入参数通过引用实际上是否不会被复制?

我计划将一个重型会话对象传递给一个线程或编写std::async

bool fun(MySession& sessRef);
MySession sess;
auto r = std::async(&fun, sess);

编辑:

  • 我计划在GCC 4.9.1和VS2013上使用它,因为该应用程序是平台无关的。然而,大多数部署将基于*nix,所以至少需要GCC性能良好。

1
如果你想传递一个引用,你需要使用std::refstd::cref将其封装在reference_wrapper。就像std::bindstd::thread构造函数一样,std::async会将其参数复制到其他存储空间,使它们的生命周期与调用的范围不同。 - Casey
2
你可以使用一个 Promise 和一个线程来实现自己的显式 async 参考链接 - Kerrek SB
1
如果不使用std::launch::async作为std::async的策略,那么它不能保证并行执行。实现还可以自由地使用其他实现定义的值作为默认值,甚至可以急切地执行回调函数。 - Mgetz
1
通常你想一次只问一个问题,而不是3个。检查你的问题是否合适是个好主意。实现细节将会是特定于编译器的,不是吗? - Yakk - Adam Nevraumont
@Yakk:我的问题是关于异步使用的一般性问题。如果有其他人有任何意见,请提出来。 - prem.baranwal
1个回答

2
我们无法确切地告诉您 “std::async 是如何实现的”,因为您没有指明提供该实现的特定工具链。

1. 从工作线程捕获异常到主线程是否会有任何惩罚?


“Penalty”是以什么方式准确定义的?除非您澄清您的关注点/要求,否则无法回答该问题。通常情况下,只需在创建抛出异常的线程中捕获异常即可避免任何罚款。这只涉及到可能通过join()将异常提供给创建线程,并因此产生一些代价来保留特定异常通过join()的处理。
2.工作线程如何向主线程返回值?
引用关于此点的C++标准定义所说的:

30.6.8 函数模板 async

4 返回:一个类型为future<typename result_of<typename decay<F>::type(typename decay<Args>::type...)>::type>的对象,该对象引用由此调用async所创建的共享状态。


3. 输入参数通过引用传递时,是否实际上从未被复制过呢?这一点在这里得到了详细解答:将参数通过引用传递给std::async失败。正如你所看到的,默认情况下它们会被复制。
根据@Yakk的评论,可能可以通过使用std::ref来传递这些参数,以避免对副本进行操作,而是取得引用。
“std::async” 实现的具体方法,我只能根据 C++ 标准的要求来解释。除非你指的是某个特定的工具链,它试图提供一个合适的实现方式。

你对第三个问题的回答我觉得是错误的(它们被复制,然后在另一个线程中被引用,除非你通过 std::ref 传递)。你对第一个问题的回答只是一条评论,不是一个答案。 - Yakk - Adam Nevraumont
目前我正在使用Poco::Thread并在同一线程中捕获异常。异常属于频繁发生的类型(约每分钟1次),因此想了解在主线程中使用std::future的性能如何。 - prem.baranwal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接