Reputation: 563
In this example, std::unique_lock call with flag std::defer_lock. On cppreference written: "defer_lock_t do not acquire ownership of the mutex" and : "(destructor) unlocks the associated mutex, if owned "
And now, the question!
Why in this example, std::unique_lock calls unlock in destructors?
void transfer(Box &from, Box &to, int num)
{
// don't actually take the locks yet
std::unique_lock<std::mutex> lock1(from.m, std::defer_lock);
std::unique_lock<std::mutex> lock2(to.m, std::defer_lock);
// lock both unique_locks without deadlock
std::lock(lock1, lock2);
from.num_things -= num;
to.num_things += num;
// 'from.m' and 'to.m' mutexes unlocked in 'unique_lock' dtors
}
?????
Upvotes: 1
Views: 1376
Reputation: 3560
Because std::defer_lock
serves to say "I will obtain the lock somehow later on", which the call to std::lock(lock1, lock2)
does. Because of this, the locks call unlock in destructor. To test this out, you could try giving the mutexes to std::lock
directly: std::lock(from.m, to.m);
. If you do this, the unique_lock
s will not unlock the mutexes, as they don't own them.
There is also std::adopt_lock
, which says "I already own the lock".
These two approaches are mostly equivalent, except that you cannot use std::defer_lock
with std::lock_guard
, as it does not have lock
method.
Upvotes: 4