Search code examples
c++c++11move-semanticsrvo

C++11 move when returning a lock


In the book "C++ Concurrency in Action" reading the following method

std::unique_lock<std::mutex> wait_for_data()
{
    std::unique_lock<std::mutex> head_lock(head_mutex);
    data_cond.wait(head_lock,[&]{return head.get()!=get_tail();});
    return std::move(head_lock);
 }

I cannot understand why the head_lock is std::move-ed when returned. My notion and gut feeling of the move usage and RVO matches the opinion shared in C++11 rvalues and move semantics confusion (return statement)

But I kind of tend to trust the author to know better. Can someone clarify when std::move the return value is better and is there something specifically about the locks? Thanks.


Solution

  • It's fine with or without the std::move. The name of a local variable* is treated as an rvalue in the return statement, causing the move constructor to be invoked in both cases. The authors presumably used std::move for stylistic reasons, to make it clear that the lock is being moved. It does interfere with NRVO, but the cost of moving a unique_lock here is probably minimal compared to the cost of the lock and the wait.

    In @Deduplicator's words, it's "a pessimization in order to emphasize the actual semantics".

    You can test this yourself - unique_lock can't be copied, so return head_lock; wouldn't have compiled if it were a copy.


    * This is the C++14 rule. The C++11 rule is restricted to cases where copy elision is allowed or would be allowed except for the fact that the variable is a function parameter. This difference is immaterial as far as this question is concerned, since head_lock obviously qualifies for copy elision.