I'm hunting down a bug we have with some messy thread/condition variable classes being updated to use C++11 threads. During the course of the hunt, I've come across the following in the GCC codebase:
template<typename _Lock>
void
wait(_Lock& __lock)
{
unique_lock<mutex> __my_lock(_M_mutex);
_Unlock<_Lock> __unlock(__lock);
// _M_mutex must be unlocked before re-locking __lock so move
// ownership of _M_mutex lock to an object with shorter lifetime.
unique_lock<mutex> __my_lock2(std::move(__my_lock));
_M_cond.wait(__my_lock2);
}
Despite the comment, I'm having difficulty understanding the purpose of the move constructor here to __my_lock2. Why is __my_lock moved to __my_lock2 here?
This does not look like condition_variable
code. It looks like condition_variable_any
code. The latter has a templated wait function. The former does not.
N2406 may shed light on what you are seeing. In N2406, condition_variable_any
is instead named gen_cond_var
, but otherwise, the types are identical. This paper describes a deadlock scenario whereupon deadlock is achieved unless great care is taken to assure that _M_mutex
and __lock
are locked and unlocked in a very specific order.
While the code you show, and the code at N2406, is not the same, I strongly suspect that they are both built to lock and unlock these two locks in an order so as to avoid the deadlock described in N2406. Without further insight into the definition of _Unlock
, I can not be absolutely certain though. However a strong clue is the final comment in N2406 of the this wait function:
} // mut_.unlock(), external.lock()
I.e. the member mutex must be unlocked prior to locking the external __lock
. By moving __my_lock
to a local variable with scope less than that of __unlock
, it is highly likely that the correct ordering of
} // _M_mutex.unlock(), __lock.lock()
has been achieved. To understand why this ordering is so critically important, you have to read the associated section of N2406 (it prevents deadlock).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With