Search code examples
c++multithreadingatomic

Atomic operations on shared_ptr


Assume I have shared_ptr<T> a and two threads running concurrently where one does:

a.reset();

and another does:

auto b = a;

if the operations are atomic, then I either end up with two empty shared_ptrs or a being empty and b pointing to what was pointed to by a. I am fine with either outcome, however, due to the interleaving of the instructions, these operations might not be atomic. Is there any way I can assure that?

To be more precise I only need a.reset() to be atomic.

UPD: as pointed out in the comments my question is silly if I don't get more specific. It is possible to achieve atomicity with a mutex. However, I wonder if, on the implementation level of shared_ptr, things are already taken care of. From cppreference.com, copy assignment and copy constructors are thread-safe. So auto b = a is alright to run without a lock. However, from this it's unclear if a.reset() is also thread-safe.

UPD1: it would be great if there is some document that specifies which methods of shared_ptr are thread-safe. From cppreference:

If multiple threads of execution access the same shared_ptr without synchronization and any of those accesses uses a non-const member function of shared_ptr then a data race will occur

It is unclear to me which of the methods are non-const.


Solution

  • Let the other thread use a weak_ptr. The lock() operation on weak pointer is documented to be atomic.

    Create:

    std::shared_ptr<A> a = std::make_shared<A>();
    std::weak_ptr<A> a_weak = std::weak_ptr<A>(a);
    

    Thread 1:

    a.reset();
    

    Thread 2:

    b = a_weak.get();
    if (b != nullptr)
    {
        ...
    }