c++条件变量wait_for的行为不符合预期

C++ condition variable wait_for not behaving as expected

本文关键字:不符合 for 条件 变量 wait c++      更新时间:2023-10-16

我在理解为什么我认为应该通过的测试用例大多数时候都失败了。我已经将测试压缩到条件变量,并使用wait_for方法,专门测试它,看看它是否确实等待至少与指定的持续时间一样长。

测试代码片段如下:

TEST_CASE("Condition variable test")
{
    std::mutex m;
    std::unique_lock<std::mutex> lock(m);
    std::condition_variable cv;
    bool ex = false;
    std::chrono::milliseconds rel_time(50);
    auto start = std::chrono::steady_clock::now();
    cv.wait_for(lock, rel_time, [&ex] {return(ex);});
    auto end = std::chrono::steady_clock::now();
    REQUIRE(std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() >= rel_time.count());
}

根据我对c++ 11标准的理解,我希望这应该一直通过。具有讽刺意味的是,如果我将时钟类型更改为系统时钟,则无法使测试失败。

摘自cplusplus.com的condition_variable::wait_for方法声明:"如果指定了pred(2),该函数仅在pred返回false时阻塞,并且只有当pred变为true时通知才能解除阻塞线程(这对于检查虚假唤醒调用特别有用)。"它的行为就好像实现为:return wait_until (lck, chrono::steady_clock::now() + rel_time, std::move(pred));"

这对我来说意味着使用稳定时钟来获取我的参考时间戳是正确的时钟。

我正在使用MinGW环境与gcc 4.8.2编译器进行编译。

这听起来像是您的供应商实现中的错误。我不明白这个测试怎么会失败。

现在,您的REQUIRE语句可以大大简化:

REQUIRE(end - start >= rel_time);

durations之间的比较总是精确。

正如所写的那样,有一种方法可能导致测试失败:如果std::chrono::steady_clock::duration大于毫秒,则表达式duration_cast<milliseconds>(end - start)可能导致0ms。为了防止这种糟糕的实现,您可以添加:

static_assert(std::chrono::steady_clock::duration{1} <= std::chrono::milliseconds{1},
    "This steady_clock implementation has an outrageously coarse duration");