Reputation: 1617
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.
Upvotes: 1
Views: 2251
Reputation: 119164
std::shared_ptr<T>
is what some call a "thread-compatible" class, meaning that as long as each instance of a std::shared_ptr<T>
can only have one thread calling its member functions at a given point in time, such member function invocations do not cause race conditions, even if multiple threads are accessing shared_ptr
s that share ownership with each other.
std::shared_ptr<T>
is not a thread-safe class; it is not safe for one thread to call a non-const
method of an std::shared_ptr<T>
instance while another thread is also accessing the same instance. If you need potentially concurrent reads and writes to not race, then synchronize them using a mutex.
Upvotes: 2
Reputation: 104514
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)
{
...
}
Upvotes: 3