According the this, unique_lock
can be used for recursive locking by declaring a std::unique_lock<std::recursive_mutex>
, and in fact that compiles fine.
However, it appears from examining the code (gcc 4.8.2 and 4.9.0) that unique_lock
doesn't defer to _Mutex.lock
, but rather implements the lock method itself:
void
lock()
{
if (!_M_device)
__throw_system_error(int(errc::operation_not_permitted));
else if (_M_owns)
__throw_system_error(int(errc::resource_deadlock_would_occur));
else
{
_M_device->lock();
_M_owns = true;
}
Clearly, this prevents recursive locking of the mutex, and in fact attempting to recursively lock throws the resource_deadlock_would_occur
exception.
Am I missing something here, is this a bug, or is the documentation for unique_lock just wrong?
TIA!!!
A common mistake is to confuse the mutex
with the lock
. A mutex
is an object that can be shared among threads (otherwise it would be useless). A lock however is not itself a thread-safe object. It should not be shared among threads. It is typically a local object on a stack. For example:
void foo()
{
std::unique_lock<std::mutex> lk(mut); // mut comes from some other scope
// mut locked here
// ...
} // mut unlocked here
In the example above, if foo()
is called recursively, you have undefined behavior because you will lock mut
recursively. On each recursion, you get a new unique_lock
though. So the unique_lock
is not aware of the recursion. If you really need to call foo()
recursively, you need to use a recursive mutex, for example:
void foo()
{
std::unique_lock<std::recursive_mutex> lk(mut); // mut comes from some other scope
// mut locked here
// ...
} // mut unlocked here
So: Yes, you can use std::unique_lock<std::recursive_mutex>
, and yes, your implementation is correct.