为什么从`性病::返回async`阻止未来的析构函数? [英] Why is the destructor of a future returned from `std::async` blocking?

查看:158
本文介绍了为什么从`性病::返回async`阻止未来的析构函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在试图回答另一个<一个href=\"http://stackoverflow.com/questions/23454793/whats-the-c-11-way-to-fire-off-an-asynchronous-task-and-forget-about-it\">Stackoverflow问题,我意识到,这个简单的C ++ 11片断隐含阻塞调用线程:

When trying to answer another Stackoverflow question, I realized that this simple C++11 snippet is implicitly blocking the calling thread:

std::async(std::launch::async, run_async_task)

对我来说这会是十分规范的C ++ 11发射任务异步,而无需关心结果的方式。相反,一个人必须显然明确创建和分离线程(见回答所提到的问题),以实现这一目标。

To me this would have seemed the canonical C++11 way to launch a task asynchronously without caring about the result. Instead one has to apparently explicitly create and detach a thread (see answer to mentioned question) in order to achieve this.

因此​​,这里是我的问题吗?那岂不是不够的,如果它放在 GET 块只否则,如果我不感兴趣的返回值或异常,它只是火,忘记?

So here's my question: Is there any reason in regards to safety/correctness that the destructor of a std::future has to be blocking? Wouldn't it be enough if it blocks on get only and otherwise, if I'm not interested in the return value or exception, it's simply fire and forget?

推荐答案

禁止通过和线程的的std ::异步的返回期货的析构函数:这是一个有争议的话题。以下按时间顺序论文名单反映了一些由委员会成员的讨论:

Blocking destructors of futures returned by std::async and of threads: That's a controversial topic. The following list of papers in chronological order reflects some of the discussions by the members of the committee:

  • N2802: A plea to reconsider detach-on-destruction for thread objects by Hans Boehm
  • N3630: async, ~future, and ~thread (Revision 1) by Herb Sutter
  • N3636: ~thread Should Join by Herb Sutter
  • N3637: async and ~future (Revision 3) by Herb Sutter, Chandler Carruth, Niklas Gustafsson
  • N3679: Async() future destructors must wait by Hans Boehm
  • N3773: async and ~future (Revision 4) by Herb Sutter, Chandler Carruth, Niklas Gustafsson
  • N3776: Wording for ~future by Herb Sutter
  • N3777: Wording for deprecating async by Herb Sutter

虽然有很多讨论,有计划在C ++ 14有关的的std ::未来的std ::线程的析构函数<的阻塞行为没有改变/ EM>

Although there was a lot of discussion, there are no changes planned for C++14 regarding the blocking behaviour of the destructors of std::future and std::thread.

关于你的问题,最有趣的文件可能是第二个由Hans贝姆。我引用某些部分来回答你的问题。

Regarding your question, the most interesting paper is probably the second by Hans Boehm. I quote some parts to answer your question.

N3679:异步()未来的析构函数必须等待

N3679: Async() future destructors must wait

[..]为相关的在他们的析构函数异步()异步启动策略等待返回期货共享状态准备就绪。这prevents在相关线程继续运行的情况下,并没有更长的时间来等待它完成,因为相关的未来已经被破坏的一种手段。没有英雄的努力,否则等待完成,这样的失控线程可以继续过去它所依赖的对象的生命周期中运行。

[..] Futures returned by async() with async launch policy wait in their destructor for the associated shared state to become ready. This prevents a situation in which the associated thread continues to run, and there is no longer a means to wait for it to complete because the associated future has been destroyed. Without heroic efforts to otherwise wait for completion, such a "run-away" thread can continue to run past the lifetime of the objects on which it depends.

【例】

最终的结果很可能是一个跨线程记忆粉碎。这个问题当然是可以避免的,如果的get()等待()被称为[..]之前他们[期货]被破坏。困难[..]是一个意外的异常可能会导致code被绕过。因此,通常需要某种范围的后卫,以确保安全。如果程序员忘记添加范围后卫,看来有可能使攻击者可以如产生在一个适当的点bad_alloc异常趁监督,并造成堆栈被覆盖。它可能也控制用于覆盖堆栈中的数据,并因此获得对过程的控制。这是一个微妙的足够错误,根据我们的经验,这很可能在现实code被忽视。

The end result is likely to be a cross-thread "memory smash". This problem is of course avoided if get() or wait() is called [..] before they [the futures] are destroyed. The difficulty [..] is that an unexpected exception may cause that code to be bypassed. Thus some sort of scope guard is usually needed to ensure safety. If the programmer forgets to add the scope guard, it appears likely that an attacker could generate e.g. a bad_alloc exception at an opportune point to take advantage of the oversight, and cause a stack to be overwritten. It may be possible to also control the data used to overwrite the stack, and thus gain control over the process. This is a sufficiently subtle error that, in our experience, it is likely to be overlooked in real code.

更新:光良的旅行报告的还包含有关会议的结果2013年9月一些有趣的信息:

Update: Michael Wong's Trip Report also contains some interesting information regarding the outcomes of the meeting in September 2013:

<一个href=\"https://www.ibm.com/developerworks/community/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/the_view_from_the_c_standard_meeting_september_2013_part_2?lang=en\">The查看从C ++标准会议2013年9月第2。2

The View from the C++ Standard meeting September 2013 Part 2 of 2.

在这个问题的异步析构函数不应该阻止我们专门讨论了很大的就可以了。 [..]是得到广泛支持的唯一位置就是[..]给咨询,未来的析构函数不会阻止,除非异步返回,使得它的显着的例外。 [..]后显著的讨论,我们试图携带的唯一部分是N3776,试图澄清的立场是〜未来〜shared_future 除了可能在异步的presence不阻止。有发行沿着C.德precate异步电动机无需更换线一德precation的尝试。这个运动实际上几乎提出。但是,[..]它甚至它达到了手术台前就去世了。

On the issue that async destructors should not block we devoted a great deal of discussion on it. [..] The only position that received considerable support was [..] giving advisory that future destructors will not block, unless returned from async, making it the notable exception. [..] After significant discussion, the only part that we tried to carry was N3776, an attempt to clarify the position that ~future and ~shared_future don’t block except possibly in the presence of async. There was an attempt to issue a deprecation along the lines of C. Deprecate async without replacement. This motion was actually almost put forward. But [..] it died even before it reached the operating table.

这篇关于为什么从`性病::返回async`阻止未来的析构函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆