I have the following C++(11) code:
#include <mutex>
void unlock(std::unique_lock<std::mutex> && ulock)
{
}
int main(void)
{
std::mutex m;
std::unique_lock<std::mutex> ulock(m);
unlock(std::move(ulock));
if (ulock.mutex() == &m || ulock.owns_lock())
{
throw std::runtime_error("");
}
return 0;
}
What I can't figure out is why the mutex is still held after the return from unlock()
. My expectation is that the std::move()
causes the lock to go out of scope (and become unlocked by the destructor) upon return from the call to unlock()
. At the very least, it seems like the std::move()
should have caused ulock
to become "unbound" from the mutex m
.
What am I missing?
But a unique_lock does not really have to own a lock. Therefore, it can be moved to transfer the ownership of the held lock to another scope. The compiler automatically moves a unique_lock if it is a prvalue returned from a function, or a unique_lock variable can be moved explicitly via std::move.
std::move is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object. In particular, std::move produces an xvalue expression that identifies its argument t . It is exactly equivalent to a static_cast to an rvalue reference type.
A: You should use std::move if you want to call functions that support move semantics with an argument which is not an rvalue (temporary expression).
There are two primary benefits to using std::unique_lock<> over std::lock_guard<> : you can transfer ownership of the lock between instances, and. the std::unique_lock<> object does not have to own the lock on the mutex it is associated with.
void unlock(std::unique_lock<std::mutex> && ulock)
Here ulock
is a reference. A special kind of reference, but still a reference. It is just an alias for another object. Its creation does not involve creation of a new object, or any kind of ownership transfer. Likewise, end of its lifetime does not lead to any destructor call, it just means that you lost the alias for referring to some other object (not that it matters, since the function is ending anyway).
If you want to transfer ownership, you need an object, so pass by value instead of by reference:
void unlock(std::unique_lock<std::mutex> ulock)
Now, you will have to move
the original lock, since std::unique_lock
does not support copy construction, only move construction.
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