2015-06-03 55 views
2

我在理解为什么一个我认为应该传递的测试用例大部分时间都失败的问题。我已经将测试提取到条件变量并使用wait_for方法,特别是对其进行测试以确定它是否确实至少等待指定的持续时间。C++条件变量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标准的理解想到,这应该通过所有的时间。讽刺的是,如果我将时钟类型更改为系统时钟,我无法使测试失败。

对于condition_variable :: wait_for方法,摘自cplusplus.com指出“如果指定pred(2),函数只会在pred返回false时阻止,并且通知只能在线程变为true时解除阻塞(尤其是用于检查虚假的唤醒呼叫),其行为如同实现为: return wait_until(lck,chrono :: steady_clock :: now() + rel_time,std :: move(pred));“

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

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

+0

Collin,开始和结束都是time_points。我正在减去时间点来形成一个持续时间。我将测量的持续时间与期望的持续时间进行比较。我的系统上的分辨率对于此测量已足够。我已经将期望的持续时间增加到了500ms和5s,并且测试仍然失败。我仍然很想知道更多关于为什么你认为这是一个糟糕的测试的细节。 –

回答

3

这听起来像是供应商实施中的一个错误。我不明白这个测试可能会失败。

FWIW,你REQUIRE语句可以大大简化:中durations

REQUIRE(end - start >= rel_time); 

比较是总是准确。

您的测试有一种写法可能会失败:如果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"); 
+0

如果'steady_clock'具有例如16毫秒的分辨率,那么这很容易失败。即使您请求了50毫秒,“wait_for”可能会延迟64毫秒。 –

+0

@CollinDauphinee那样会失败的测试如何? –

+0

@CollinDauphinee:如果'wait_for'延迟了64毫秒,那么写入的测试通过,假设'REQUIRE'是个好名字。 –

相关问题