简体   繁体   中英

Passing a dummy lock to std::condition_variable_any::wait

Suppose there are three threads A, B, and C. B and C suspend at a certain point, waiting for A to signal them to continue. Among the thread synchronization facilities provided by standard C++, std::condition_variable seems to best fit in here (though still bad). Since std::condition_variable must be used with a lock, the code for B and C may contain lines like:

{
  std::mutex mut;
  std::unique_lock<std::mutex> lock(mut);
  cond_var.wait(lock);  // cond_var is a global variable of type std::condition_variable`
}

Note that mut is used here not for synchronization purposes at all, but just to fit the signature of std::condition_variable::wait . With this observation, I'm thinking that maybe we can do better by implementing a dummy lock class, let's say dummy_lock , and replace std::condition_variable with std::condition_variable_any . dummy_lock meets the BasicLockable requirements with all its methods essentially doing nothing. Thereby, we get code similar to the following:

{
  dummy_lock lock;
  cond_var.wait(lock);  // cond_var is a global variable of type std::condition_variable_any`
}

This, if works at all, should be of higher efficiency than the original one. But the question is, does it even work according to the standard (language-lawyers are apt here) ? Even if it works, this is by-no-means an elegant solution. So, do any of you folks have better ideas?

You are working on a false premise.

The mutex does not only protect the condition predicate, it also protects the condition_variable itself.

So the mutex should be at the same scope as the condition_variable and all locks should lock that same mutex.

like this:

// global scope
std::mutex mut;
std::condition_variable cond_var;

// thread scope
{
  std::unique_lock<std::mutex> lock(mut);
  cond_var.wait(lock);
}

see here: Why do pthreads' condition variable functions require a mutex?

What you're suggesting would be undefined behavior. The section on condition_variable_any leads with, emphasis mine:

A Lock type shall meet the BasicLockable requirements (30.2.5.2). [ Note: All of the standard mutex types meet this requirement. If a Lock type other than one of the standard mutex types or a unique_lock wrapper for a standard mutex type is used with condition_variable_any, the user must ensure that any necessary synchronization is in place with respect to the predicate associated with the condition_variable_any instance. —end note ]

The BasicLockable requirements themselves don't just describe the interface, they also describe the required semantics:

A type L meets the BasicLockable requirements if the following expressions are well-formed and have the specified semantics (m denotes a value of type L).

m.lock()
2 Effects: Blocks until a lock can be acquired for the current execution agent. If an exception is thrown then a lock shall not have been acquired for the current execution agent.

If your dummy_lock doesn't actually acquire a lock, it isn't a BasicLockable , and so you fail to meet the premise for condition_variable_any . At that point, all bets are off, and you cannot expect wait() to do anything reasonable.

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