简体   繁体   中英

condition_variable::wait_until passes through unexpectedly g++ (9.4.0)

I am trying to understand the behaviour of condition_variable::wait_until . I have two pieces of code which I expect will wait one second and then exit. However, when I execute the programs (compiled with g++ 9.4.0, libc6 2.3.2) the first does not wait at all, whereas the second example does.

( see Update below for how to get correct behaviour in both examples )

Here's the first example which does not wait (unlike what I would expect) when executed:

// foo_passes_thru.cpp
// I compiled with `g++ foo_passes_thru.cpp`
#include <chrono>
#include <mutex>
#include <condition_variable>

std::condition_variable cv;
std::mutex m;

int main(int argc, char * argv[]) {

    using namespace std::chrono_literals;
    
    std::unique_lock<std::mutex> lk(m);
    const auto now = std::chrono::high_resolution_clock::now();
    cv.wait_until(lk, now + 1000ms);

    return 0;

}

And the second example, which, when executed, does wait as expected:

// foo_waits_1sec.cpp
// I compiled with `g++ foo_waits_1sec.cpp -lpthread`
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <thread>

std::condition_variable cv;
std::mutex m;

int main(int argc, char * argv[]) {

    using namespace std::chrono_literals;

    std::thread causes_wait([]{});
    // don't even need the thread to run
    causes_wait.join();

    std::unique_lock<std::mutex> lk(m);
    const auto now = std::chrono::high_resolution_clock::now();
    cv.wait_until(lk, now + 1000ms);

    return 0;

}
  • There does not appear to be a difference in the compiled wait_until .
  • In both programs, there is ultimately a call to pthread_cond_timedwait .

I am not sure if this is a case of unspecified behaviour or there is something incorrect in g++/STL/pthread. The documentation for pthread_cond_timedwait didn't suggest to me that there should be differences in behaviour.

Update

Upon posting, a related question came up that I hadn't yet seen. The behaviour that I expect is restored for the first example if I add the -pthread compiler option. This option should be used to build both.

wait_until is allowed to wake up spuriously. There is no guarantee that it will wait until the specified time. You need to call wait_until in a loop, check the return value to determine whether a timeout occurred and you need some condition to check in order to decide whether the non-timeout wakeup was spurious. Alternatively you can use the second overload of wait_until that takes the condition as a predicate and implements the loop.

Without the -pthread option the program is single-threaded and a corresponding implementation is probably being used. In that implementation there can never be a non-spurious wakeup, so I think it is not surprising that it would be implemented to return immediately, although I have not checked the sources (of glibc or whichever libc implementation you use).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM