template
bool wait_for(unique_lock& _Lck, const chrono::duration<_Rep, _Period>& _Rel_time, _Predicate _Pred) {
// wait for signal with timeout and check predicate
return _Wait_until1(_Lck, _To_absolute_time(_Rel_time), _Pred);
}
用法示例:
#include
#include
#include
std::condition_variable cv;
std::mutex mu;
using namespace std::chrono_literals;
bool flag = false;
bool noticed_flag = false;
int main() {
auto predicate_func = [&]() {
if (flag && noticed_flag) {
flag = false;
noticed_flag = false;
return true;
}
else {
return false;
}
};
auto wait_func = [&](int wait_time_out) {
std::unique_lock lck(mu);
bool status = cv.wait_for(lck, std::chrono::milliseconds(wait_time_out), predicate_func);
std::cout << int(status) << std::endl;
};
auto wake_and_wait = [&](bool flag_,int wait_time_out,int wake_delay) {
std::thread th(wait_func, wait_time_out);
/*
由于没有加延时,th 在执行wait_func之前,flag已经被外部设置了。所以基本上,大概率,
wait_func 的 cv.wait_for 在执行之前 flag 已经是 true 了。向系统要线程,延迟个3~4毫秒
都是可能的。
*/
/*
模拟在 wait_for 和 notify_one 之前就把数据(谓词)准备好。放到 std::thread th(wait_func, wait_time_out); 之前也可以,放在这里主要是展示线程启动是有延迟的。
*/
{
std::lock_guard lck(mu);
flag = flag_;
}
/*
某种原因导致谓词设置与cv.notify_one()中间隔了 wake_delay 毫秒
*/
Sleep(wake_delay);
{
std::lock_guard lck(mu);
//根据 https://en.cppreference.com/w/cpp/thread/condition_variable cv.notify_one()不需要加锁
//但是需要给 noticed 赋值,所以一起加锁了
cv.notify_one();
noticed_flag = true;
}
th.join();
};
bool temp_noticed = true;
while (1) {
std::cout << "----------------Test Results----------------\n";
flag = false; noticed_flag = temp_noticed;
wake_and_wait(true, 20, 10);
flag = false; noticed_flag = temp_noticed;
wake_and_wait(true, 10, 20);
flag = false; noticed_flag = temp_noticed;
wake_and_wait(false, 20, 10);
flag = false; noticed_flag = temp_noticed;
wake_and_wait(false, 10, 20);
}
return 0;
}
解释: wake_and_wait 启动一个线程,里面进行 wait_for,超时时间是 wait_time_out ;然后把谓词 flag 设为 flag_;延时 wake_delay 毫秒后,加锁的,条件变量唤醒,并且唤醒标志位设为 true。
分两种测试情况,
一是 temp_noticed 初始化为 true,这种情况下 wait_func 无需等待唤醒,即可结束等待。程序输出:
----------------Test Results----------------
1
1
0
0
二是 temp_noticed 初始化为 false,这种情况下 wait_func 必须等待唤醒(即temp_noticed 被设为 true 时)才能结束等待。程序输出:
----------------Test Results----------------
1
0
0
0
究其原因是 wait_for(wait 同理)内部第一次判断谓词为真时则不进入等待,即使没有被唤醒。
template
cv_status wait_for(unique_lock& _Lck, const chrono::duration<_Rep, _Period>& _Rel_time) {
// wait for duration
if (_Rel_time <= chrono::duration<_Rep, _Period>::zero()) {
return cv_status::timeout;
}
// TRANSITION, ABI: The standard says that we should use a steady clock,
// but unfortunately our ABI speaks struct xtime, which is relative to the system clock.
_CSTD xtime _Tgt;
const bool _Clamped = _To_xtime_10_day_clamped(_Tgt, _Rel_time);
const cv_status _Result = wait_until(_Lck, &_Tgt);
if (_Clamped) {
return cv_status::no_timeout;
}
return _Result;
}
不多介绍,msvc编译出来的执行结果不确定,表现为在没有任何唤醒的情况下,cv.wait_for(lck, std::chrono::milliseconds(10)) 会返回不超时。可能是如下原因:
TRANSITION, ABI: The standard says that we should use a steady clock, but unfortunately our ABI speaks struct xtime, which is relative to the system clock.