Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::condition_variable take a unique_lock instead of a lock_guard? [duplicate]

std::condition_variable in use as the following:

std::condition_variable cv;
...
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return processed;});

Seems to me to have an interesting problem. unique_lock could be deferred, it could have been swapped away. It could have numerous other reasons by code design and not necessarily bad mistakes that it is not actually locked. eg.

std::unique_lock<std::mutex> lk(m, std::try_to_lock_t); // or  std::defer_lock_t
// Try to lock fails.
cv.wait(lk, []{return processed;});

Why not enforce a locked situation by making std::conditional_variable work with lock_guard instead? Then you would be very hard pressed to get into this situation. In fact the only way would be to do this:

// m is not already locked
std::lock_gaurd<std::mutex> lk(m, std::adopt_lock);
cv.wait(lk, []{return processed;});

Rather than the multitude of ways available in unique_lock. Is there a technical reason to use unique_lock over lock_guard for a condition_variable?

like image 590
Fantastic Mr Fox Avatar asked Aug 10 '18 07:08

Fantastic Mr Fox


2 Answers

The condition variable needs to be able to lock and unlock the mutex, lock_guard doesn't allow this. lock_guard also doesn't allow access to the mutex itself which most condition variable implementations probably require.

like image 167
Alan Birtles Avatar answered Oct 19 '22 10:10

Alan Birtles


lock_guard and unique_lock are pretty similar. However a lock_guard locks on construction and unlocks on destruction. Using condition_variable the mutex needs to be possible locked and unlocked multiple times.

You can basically use unique_locks everywhere, however they impose more overhead than a simple lock_guard.

std::condition_variable works only with std::unique_lock; this restriction allows for maximal efficiency on some platforms. std::condition_variable_any provides a condition variable that works with any BasicLockable object, such as std::shared_lock.

taken from cppreference

like image 1
rmm19433 Avatar answered Oct 19 '22 09:10

rmm19433