Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't std::move on a std::unique_lock have any effect?

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?

like image 461
John Tyner Avatar asked Aug 29 '17 19:08

John Tyner


People also ask

Is unique_lock movable?

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.

What does std :: move () do?

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.

Is std :: move necessary?

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).

What is the benefit of using std :: unique_lock <> between instances?

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.


1 Answers

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.

like image 170
Revolver_Ocelot Avatar answered Oct 24 '22 00:10

Revolver_Ocelot