Search code examples
c++c++11thread-safetymoveshared-ptr

Is std::move of shared_ptr thread safe?


The following snippet runs fine:

#include <memory>
#include <cassert>
int main()
{
    auto ptr1 = std::make_shared<int>(10);
    assert(ptr1.use_count() == 1);

    auto ptr2 = std::move(ptr1);
    assert(ptr1 == nullptr);

    auto ptr3 = static_cast<std::shared_ptr<int>&&>(ptr2);
    assert(ptr2 == nullptr);
    assert(ptr3.use_count() == 1);
}

It looks std::move does several operations, one of them is reseting the moved shared pointer somehow, so is this thread safe? For instance if i have something like:

void ThreadLogic()
{
    if (sharedPtr != nullptr)
    {
        DoSomething(std::move(sharedPtr));
    }
    else
    {
        DoSomethingElse();
    }
}

Is that std::move(sharedPtr) atomic or should I protect the check (the critical section) there by some other means?


Solution

  • You have a misconception about what std::move does. In fact std::move does nothing. It's just a compile time mechanism with the meaning: I no longer need this named value.

    This then causes the compiler to use the value in different ways, like call a move constructor/assignment instead of copy constructor/assignment. But the std::move itself generates no code so nothing to be affected by threads.

    The real question you should be asking is whether the move constructor of shared_ptr is thread safe and the answer is: No.

    But the point of the shared_ptr is not to share the shared_ptr but to share what it points too. Do not pass a shared_ptr by reference to threads, instead pass it by value so each thread gets it own shared_ptr. Then it is free to move that around at will without problems.

    The shared_ptr protects the lifetime of the thing it points to. The reference count the shared_ptr uses is thread safe but nothing else. It only manages the lifetime of the pointed to objects in a thread safe way so it doesn't get destroyed as long as any shared_ptr has hold of the object.