<condition_variable>
: condition_variable_any::wait_for
returns cv_status::timeout
when the elapsed time is shorter than requested · Issue #4723 · microsoft/STL (original) (raw)
Describe the bug
Revealed by libc++ test test/std/thread/thread.condition/thread.condition.condvarany/wait_for.pass.cpp.
Returns:
cv_status::timeout
if the relative timeout ([thread.req.timing]) specified byrel_time
expired, otherwisecv_status::no_timeout
.
But MSVC STL's condition_variable_any::wait_for
sometimes returns cv_status::timeout
even though the elapsed time (measured by high_resolution_clock
) is shorter than the requested timeout.
Command-line test case
D:\test>type test-condvarany.cpp
#include <condition_variable>
#include <atomic>
#include <cassert>
#include <chrono>
#include <mutex>
#include <thread>
#include <print>
template <class Mutex>
struct MyLock : std::unique_lock<Mutex> {
using std::unique_lock<Mutex>::unique_lock;
};
template <class Function>
std::chrono::microseconds measure(Function f) {
std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
f();
std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<std::chrono::microseconds>(end - start);
}
template <class Lock>
void test() {
using Mutex = typename Lock::mutex_type;
// Test unblocking via a timeout.
//
// To test this, we create a thread that waits on a condition variable
// with a certain timeout, and we never awaken it. To guard against
// spurious wakeups, we wait again whenever we are awoken for a reason
// other than a timeout.
{
auto timeout = std::chrono::milliseconds(250);
std::condition_variable_any cv;
Mutex mutex;
std::thread t1([&] {
Lock lock(mutex);
std::cv_status result;
do {
auto elapsed = measure([&] { result = cv.wait_for(lock, timeout); });
if (result == std::cv_status::timeout)
if (elapsed < timeout) {
std::println("elapsed: {}", elapsed);
std::println("timeout: {}", timeout);
}
} while (result != std::cv_status::timeout);
});
t1.join();
}
}
int main(int, char**) {
test<std::unique_lock<std::mutex>>();
test<std::unique_lock<std::timed_mutex>>();
test<MyLock<std::mutex>>();
test<MyLock<std::timed_mutex>>();
return 0;
}
D:\test>cl /EHs /std:c++latest test-condvarany.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.41.33901 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
/std:c++latest is provided as a preview of language features from the latest C++
working draft, and we're eager to hear about bugs and suggestions for improvements.
However, note that these features are provided as-is without support, and subject
to changes or removal as the working draft evolves. See
https://go.microsoft.com/fwlink/?linkid=2045807 for details.
test-condvarany.cpp
Microsoft (R) Incremental Linker Version 14.41.33901.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:test-condvarany.exe
test-condvarany.obj
D:\test>.\test-condvarany.exe
elapsed: 249758us
timeout: 250ms
(You might need to execute the program several times to see the output.)
Expected behavior
.\test-condvarany.exe
should consistently produce no output