std::condition_variable::wait_for 的两种重载用法https://blog.csdn.net/smalbig/article/details/130152253
(以下简称上篇)直观上介绍了 std::condition_variable::wait_for 的使用效果,这篇对没解释清楚的注释、执行结果进行解释。
1.线程创建到函数执行的时间
上篇中线程 th
std::thread th(wait_func, wait_time_out);
创建后 wait_func 不会立即执行,原因是创建线程只是程序向系统申请资源的过程,并不保证函数的执行。线程创建到函数执行的时间,受cpu使用状态影响,最佳情况可能需要 3ms。
创建线程后立即给 flag 赋值,会导致上篇中的 predicate_func 在 wait_func 执行时立刻返回true,也就不会进入等待的过程。
auto predicate_func = [&]() {
t2 = std::chrono::steady_clock::now();
if (flag) {
flag = false;
return true;
}
else {
return false;
}
};
2.wait_for 返回值的意义
初识 std::condition_variable::wait_for 时,误以为返回值代表是否超时,其实其真正意义是 predicate_func 的返回值。当 flag 为 true 时,即使已经超时,wait_for 也会返回 true,原因是超时后又调用了一次 predicate_func,并把 predicate_func 的返回值作为 wait_for 的返回值返回。
要想让 wait_for 的返回值代表是否超时,就要这样在锁作用域内 notify_one() and flag = true
{
std::lock_guard<std::mutex> lck(mu);
cv.notify_one();
flag = true;
}
3.是否有必要精确获知线程在创建时其函数什么时候执行
答案当然是不必要的,应该通过设计来避免这种需求。一般是预先创建线程,其内部函数通过 wait 等待触发。但是在测试时,为了简单起见还是会有这种操作,即线程创建后希望其函数开始执行(或执行到某一步)后才执行后面的代码。在windows平台测试中,为了获得更精确的延时,可以这样:
void LoopDelay(int delay) {
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point end;
while (true) {
end = std::chrono::steady_clock::now();
if ((end - start).count() / (1000.f * 1000.f) >= delay)
break;
}
}
4.predicate_func的执行时机
bool status = cv.wait_for(lck, std::chrono::milliseconds(wait_time_out), predicate_func);
时执行一次,超时 或 cv.notify_one() 时执行一次。