nnolte
nnolte

Reputation: 1780

`std::condition_variable::wait_for` calls the predicate very often

Consider the following codesnippet:

#include <iostream>
#include <condition_variable>
#include <chrono>
#include <mutex>

int main () {
  std::mutex y;
  std::condition_variable x;
  std::unique_lock<std::mutex>lock{y};
  int i = 0;
  auto increment = [&] {++i; return false;};
  using namespace std::chrono_literals;

  //lock 5s if increment returns false
  //let's see how often was increment called?
  x.wait_for(lock, 5s, increment);
  std::cout << i << std::endl;

  //compare this with a simple loop:
  //how often can my system call increment in 5s?
  auto const end = std::chrono::system_clock::now() + 5s;
  i = 0;
  while (std::chrono::system_clock::now() < end) {
    increment();
  }
  std::cout << i;
}

As I understand wait_for, i should be O(1) after wait_for (let's assume spurious unlocks are rare).

However, I get
i ~= 3e8 for kernel 4.17.14, Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz,
i ~= 8e6 for kernel 3.10.0, Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz.

This sounds funny, so i check by comparing with a simple loop that runs 5 seconds. Roughly same results for i, only a 5-10% difference.

Question:
what is wait_for doing? Does it work as expected and I just understood cppreference wrong, or did I mess up?

Second, (optional) question: Where does this enormous difference in i come from?

Additional info: (gcc7.3, gcc8.2, clang6.0), flags: -O3 --std=c++17 all yield comparable results.

Upvotes: 8

Views: 602

Answers (3)

Alan Birtles
Alan Birtles

Reputation: 36399

libstdc++ has an unfortunate ability to compile and seemingly work without pthread however it wont function correctly.

See this libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58929

You need to add "-pthread" to your compile command.

Upvotes: 5

nos
nos

Reputation: 229128

You need to link to the pthread library using the -pthread flag to g++:

g++ cond_test.cpp -pthread

Most linux systems require you to link to the pthread library to use threading features. However programs using standard C++ threading seems to link successfully without explicitly linking to pthread, and instead produce undefined behavior at runtime (It often crashes, but with this code it seems not to, but instead produce unexpected behavior).

Example for this code:

$ g++ t.cpp  && ./a.out
5817437
18860410
$ g++ t.cpp  -pthread && ./a.out
2
19718764

Upvotes: 1

Slava
Slava

Reputation: 44258

You need to add -pthread flag to gcc when compiling, for example on gcc 5.1.0 on RE:

without pthread: 49752692
with pthread: 2

Upvotes: 1

Related Questions