Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::conditional_variable::wait_for, std::thread::sleep_for on Windows are affected by adjusting clock

Well. I have Win10 x64 and this pretty simple code:

int main() {
    std::conditional_variable cv;
    std::mutex m;
    std::unique_lock<std::mutex> lock(m);
    while(1) {
        cv.wait_for(lock, 1000ms, [](){return false;});
        std::cout << "!" << std::endl;
    }
}

Yes. The code works just like I expect; It shows '!' every second. But If I change my local time (minus 1 hour/minute e.g.) it holds forever. If I replace cv.wait_for(...) with WinAPI Sleep(1000) it works fine. Also WinAPI SleepConditionVariableCS works fine.

I have tried this:

cv.wait_until(lock, std::chrono::steady_clock::now() + 1000ms, [](){return false;});

And it gives me the same result.

BTW: The behavior of the calls like std::this_thread::sleep_for, std::this_thread::sleep_until is the same.

So the question is: Is it possible to use std::condition_variable with expected behavior? Or I just have to replace it with my own CONDITION_VARIABLE wrapper?

like image 285
Sergio Pv Avatar asked Nov 17 '17 11:11

Sergio Pv


1 Answers

This was a known bug with VS2015's condition_variable which unfortunately is ABI-breaking to fix. I fixed it in our next major release (I completely rewrote the condition variable implementation from scratch), but I don't know when that will happen next. Note that VS2017 was a minor release as far as the standard libraries are concerned.

The problem is that the API contract exposed by msvcp140.dll expects an absolute time against the system clock, so if the system clock changes the effective wait length changes. The standard permits implementing an unsteady clock out of a steady clock but not the reverse; my predecessors apparently didn't get that memo :)

like image 134
Billy ONeal Avatar answered Sep 28 '22 05:09

Billy ONeal