std :: condition_variable wait_until令人惊讶的行为

时间:2016-08-19 14:23:54

标签: c++11 visual-c++-2013

使用VS2013构建,为条件变量chrome.runtime.onMessageExternal.addListener( function(request, sender, sendResponse) { if (sender.url == blacklistedWebsite) return; // don't allow this web page access if (request.openUrlInEditor) openUrl(request.openUrlInEditor); }); 指定time_point::max()会导致立即超时。

这似乎不直观 - 我天真地期望wait_until无限期地等待(或者至少非常长时间)。任何人都可以确认这是否有记录,预期的行为或特定于MSVC的东西?

以下示例程序;注意用time_point::max()替换time_point::max()会产生预期的行为(一旦通知cv就会now + std::chrono::hours(1)退出,没有超时)

wait_for

1 个答案:

答案 0 :(得分:1)

我调试了MSCV 2015的实现,wait_until在内部调用了wait_for,其实现如下:

template<class _Rep,
        class _Period>
        _Cv_status wait_for(
            unique_lock<mutex>& _Lck,
            const chrono::duration<_Rep, _Period>& _Rel_time)
        {   // wait for duration
        _STDEXT threads::xtime _Tgt = _To_xtime(_Rel_time); // Bug!
        return (wait_until(_Lck, &_Tgt));
        }

此处的错误是_To_xtime溢出,导致未定义的行为,结果是否定 time_point

template<class _Rep,
    class _Period> inline
    xtime _To_xtime(const chrono::duration<_Rep, _Period>& _Rel_time)
    {   // convert duration to xtime
    xtime _Xt;
    if (_Rel_time <= chrono::duration<_Rep, _Period>::zero())
        {   // negative or zero relative time, return zero
        _Xt.sec = 0;
        _Xt.nsec = 0;
        }
    else
        {   // positive relative time, convert
        chrono::nanoseconds _T0 =
            chrono::system_clock::now().time_since_epoch();
        _T0 += chrono::duration_cast<chrono::nanoseconds>(_Rel_time); //Overflow!
        _Xt.sec = chrono::duration_cast<chrono::seconds>(_T0).count();
        _T0 -= chrono::seconds(_Xt.sec);
        _Xt.nsec = (long)_T0.count();
        }
    return (_Xt);
    }

std::chrono::nanoseconds默认情况下将其值存储在long long中,因此在定义后,_T0的值为1'471'618'263'082'939'000(这显然会发生变化)。添加_Rel_time9'223'244'955'544'505'510)结果肯定会出现签名溢出。

我们已经传递了所有可能的负time_point,因此会发生超时。