获取 std::future 的状态
Posted
技术标签:
【中文标题】获取 std::future 的状态【英文标题】:Get the status of a std::future 【发布时间】:2012-06-09 01:17:22 【问题描述】:是否可以检查std::future
是否已完成?据我所知,唯一的方法是使用零持续时间调用wait_for
并检查状态是否为ready
,但有没有更好的方法?
【问题讨论】:
@CatPlusPlus 除非我弄错了,valid
只检查未来是否具有共享状态(即它返回true
直到get
被调用到未来)。
那么,如果get
已经被调用并返回了存储的值,你还想要true
吗? (我不确定为什么这会有用,因为您只能获得一次值。)
@JamesMcNellis 也许我误解或滥用期货,但我想知道线程(或执行计算的任何东西)是否完成。基本上相当于Qt的QFuture::isFinished
。
超时时间为零的等待是许多平台上的大多数 API 处理此类概念的方式...如此之多,以至于我将其视为处理该概念的“标准”方式。这让我对“更好的方法”这个概念有点疑惑……
@asveikau 我不知道这是一种标准做法。当我不想等待时调用等待函数感觉很奇怪。
【参考方案1】:
你是对的,除了用过去的时间(相当于)调用wait_until
之外没有更好的方法。
如果你想要更方便的语法,你总是可以写一个小包装器:
template<typename R>
bool is_ready(std::future<R> const& f)
return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
注意如果函数被延迟,这将永远不会返回 true,因此在您可能希望在经过一定时间后或系统负载较低时同步运行延迟任务的情况下,最好直接检查 wait_for
。
【讨论】:
wait_for 不会改变未来,因此可以将参数声明为 const。 如果 get 已被调用或 future 从未初始化,请考虑首先检查 valid() 以避免运行时错误。 wait_for(chrono::seconds(0)) 是否保证立即返回,或者它是否可以在某些实现中产生几毫秒的线程控制?这一点很重要,因为在编写游戏代码时,几毫秒是很长的时间...... @kynnysmatto,在某些实现中,它获取一个互斥锁以安全地检查未来的状态,因此如果该锁被争用(因为另一个线程正在使状态准备好,或者也在检查准备情况)然后它会阻塞,并且另一个线程可以运行,但是在一个好的实现中,互斥锁不应该被保持超过几条指令,所以甚至不是一毫秒。 GCC 当前的实现根本不使用互斥锁,但前一个实现了,并且通过交换两个指针来完成状态准备,因此互斥锁仅在发生这种情况时被非常短暂地锁定。 大部分时间是获取当前时间。如果您使用wait_until(chrono::system_clock::time_point::min())
,则不需要当前时间,它是faster。不过,这种优化是针对 GCC 的,对于 GCC 11,您需要使用 steady_clock
而不是 system_clock
,因为我们即将更改幕后使用的时钟。【参考方案2】:
std::future 有一个 is_ready 成员函数 in the works。同时,VC 实现有一个 _Is_ready() 成员。
【讨论】:
请注意,_Is_ready() 成员函数不是线程安全的。它以不受保护的方式访问关联状态的 _Ready 标志。至少 VS2019 16.2 是这种情况。【参考方案3】:我的第一个赌注是调用持续时间为 0 的 wait_for
,并检查可以是 future_status::ready
、future_status::deferred
或 future_status::timeout
之一的结果代码。
*this
指的是共享状态,则valid()
将返回true
,与该状态是否就绪无关。见cppreference。
【讨论】:
cppreference 现已更新并声明“检查未来是否具有共享状态”。 (不确定您是要删除第二段还是编辑它,所以我不会自己修改)。以上是关于获取 std::future 的状态的主要内容,如果未能解决你的问题,请参考以下文章
为啥 std::future 从 std::packaged_task 和 std::async 返回不同?
使用 shared_from_this 参数等待 std::future 获取 std::async 会阻止对 this 的破坏