mercredi 22 avril 2020

Must the std::condition_variable predicate be checked before waiting?

It is not clear to me from the documentation language whether one must check the predicate of a std::condition_variable before waiting.

On cppreference, there is the statement:

Any thread that intends to wait on std::condition_variable has to
    1. ...
    2. check the condition, in case it was already updated and notified 

In practice, it seems that one does not need to check. I am simply worried about undefined behavior if one does not.

The situation that I am concerned about is the one where a consumer comes online after a producer (that is, the condition variable has been notified by one thread before the other thread starts waiting for it):

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

int main() {
  std::condition_variable condition_var;
  std::mutex mutex;
  std::vector<std::thread> threads;
  bool flag = false;

  // Producer
  threads.emplace_back([&]() {
    {
      std::lock_guard<std::mutex> lock(mutex);
      flag = true;
      printf("%s\n", "flag = true");
    }
    condition_var.notify_all();
  });

  // Consumer
  threads.emplace_back([&]() {
    std::this_thread::sleep_for(std::chrono::seconds(3));
    {
      std::unique_lock<std::mutex> lock(mutex);
      condition_var.wait(lock, [&]() { return flag; });
      printf("%s\n", "Consumer finished");
    }
  });

  for (auto& thread : threads) {
    if (thread.joinable()) {
      thread.join();
    }
  }
  return 0;
}

In the above example, a producer starts up and notifies a condition variable. The consumer starts after that, and is put to sleep for a few seconds before checking the condition variable. This practically ensures that the consumer starts waiting after the producer has notified the condition variable.

Despite this, the code finishes on my computer and does not hang indefinitely. In fact, due to how quickly it finishes, I presume that this is not due to spurious wakeup, but I am not sure how I would check that.

Aucun commentaire:

Enregistrer un commentaire