8

我知道我可以std::future通过以下方式检查状态:

my_future.wait_for(std::chrono::seconds(0)) == std::future_status::ready

但根据cppreference.com std::future::wait_for在某些情况下可能会阻止:

由于调度或资源争用延迟,此函数可能会阻塞超过 timeout_duration。

0时仍然如此timeout_duration吗?如果是这样,是否有另一种方法以保证无等待的方式查询状态?

4

3 回答 3

6

来自 cppreference的引用只是为了提醒您操作系统调度程序是这里的一个因素,并且需要平台资源的其他任务可能正在使用您的线程需要的 CPU 时间才能从中返回wait_for()- 无论指定的超时持续时间为零或不。就这样。从技术上讲,您不能保证在非实时平台上获得更多。因此,C++ 标准对此只字未提,但您可以在那里看到其他有趣的东西——参见[futures.unique_future¶21]wait_for()下的段落:

效果:如果共享状态包含延迟函数([futures.async]),则无,否则阻塞,直到共享状态准备好或直到由指定的相对超时([thread.req.timing]) rel_­time到期。

这里没有提到额外的延迟,但它确实说你阻塞了,并且它仍然依赖于实现,wait_for()是在这种阻塞时首先执行yield()线程1还是在超时持续时间为零时立即返回。此外,实现还可能需要以锁定方式同步对未来状态的访问,这必须在检查是否发生潜在的立即返回之前应用。因此,您在这里甚至没有锁自由的保证,更不用说等待自由了。

请注意,这同样适用于wait_until过去时间的呼叫。

timeout_duration 为 0 时仍然如此吗?如果是这样,是否有另一种方法以保证无等待的方式查询状态?

所以是的,wait_free()尽管实施了,但情况仍然如此。因此,这是您检查状态时最接近无等待的方式。


1简单来说,这意味着“释放” CPU 并将您的线程放在调度程序队列的后面,给其他线程一些 CPU 时间。

于 2018-09-26T10:32:43.197 回答
3

要回答您的第二个问题,目前除了等待之外,没有其他方法可以检查未来是否准备就绪。我们可能会在某个时候得到这个:https ://en.cppreference.com/w/cpp/experimental/future/is_ready 。如果您的运行时库支持并发扩展并且您不介意experimental在代码中使用,那么您is_ready()现在可以使用。话虽如此,我知道在少数情况下您必须检查未来的状态。你确定有必要吗?

于 2018-09-26T12:09:41.870 回答
1

timeout_duration 为 0 时仍然如此吗?

是的。对于任何操作都是如此。操作系统调度程序可以暂停线程(或整个进程)以允许另一个线程在同一个 CPU 上运行。

如果是这样,是否有另一种方法以保证无等待的方式查询状态?

不,使用零超时是正确的方法。

甚至不能保证 a 的共享状态std::future不会锁定互斥体以检查它是否准备好,因此不可能保证它是无等待的。

对于 GCC 的实现,就绪标志是原子的,因此不需要互斥锁,如果它准备好了,则wait_for立即返回。如果它还没有准备好,那么还有更多的原子操作,然后检查超时是否已经过去,然后是系统调用。因此,对于零超时,只有一些原子加载和函数调用(没有系统调用)。

于 2018-09-26T12:08:59.753 回答