并发TS:std :: future< ...> ::那么,如何保持链存活而不存储返回的未来?

时间:2015-12-11 13:38:46

标签: c++ future c++17

我正在构建一组在事件调度期间在GUI线程中工作的期货,并希望采用std :: future的API,但是遇到了链接期货的问题(非阻塞异步执行)。

假设我们有一个返回未来的函数,我们希望在未来准备好后执行某些事情

disconnect().then([](std::future<State> &&f) {
   ...
});

我的理解是,当从“then”对返回的未来做任何事情时,它将被销毁,未来将被中止,并且该函数将不再被执行。因此,为了确保链仍然存在并正确执行,我们必须在某处保存未来(可能作为数据成员)。

如果我们对返回的未来不感兴趣,但是只在操作链中并且函数执行正确,我们该怎么办?我们应该将返回的未来移动到new std::future<R>(...)并在完成后将其删除在lambda中,例如“delete&amp; f;” ?但这看起来不错。

1 个答案:

答案 0 :(得分:1)

我不相信您需要按住future以确保调用完成处理程序。销毁第二个future并不要求销毁shared_state,它只会减少其引用计数。

2012年Herb Sutter的C++ Concurrency演示文稿中,您自己实施then的一种方式是作为一个免费功能调用std::asyncpage 6 of the slides PDF) :

template<typename Fut, typename Work>
auto then( Fut f, Work w ) -> future<decltype(w(f.get()))>
  { return async([=]{ w( f.get() ); }); }

这占用了一个线程,但是你得到了then( disconnect(), [](std::future<State> &&f) {...});的调用者不需要阻塞的语义。即使我们丢弃了then调用的结果,返回的future也会被销毁,并且其共享状态会被清除,但是您传入的future f不会被销毁。

然后有destroying a future returned by async may block until the async completes的规则,这意味着如果你丢弃这个then实现的结果,你可以阻止(page 21)。所以你毕竟不能这样做。

在期望的效果中,then的运行方式就好像它将对您的功能对象的引用放入一个“延续时隙”中。 future的共享状态,以及函数对象的返回类型的第二个promise,并返回该第二个future的{​​{1}}。因此原始promise引用原始future共享状态,第二个{{1}引用第二个promise共享状态},所以任何共享状态都不会被您对第二个future所做的任何事情所破坏。

一旦原始promise得到满足,共享状态就会看到它占用了延续槽,所以刚刚完成的值中的make_ready_future也是如此,并将其提供给您的函数对象,设置值进入第二个future,因为你抛弃了第二个promise而没有效果。但是没有效果&#34;在lambda的输出上。

(实现方面,第二个promise可能是对第二个共享状态的唯一引用,future只是行为的说明,第二个共享状态可以被销毁没有强制销毁第一个共享状态。我希望在内部它可以比值future更好...)