I have the following class that is supposed to be thread safe and has a std::shared_ptr member that refers to some shared resource.
class ResourceHandle
{
using Resource = /* unspecified */;
std::shared_ptr<Resource> m_resource;
};
Multiple threads may acquire a copy of a resource handle from some central location and the central resource handle may be updated at any time. So reads and writes to the same ResourceHandle may take place concurrently.
// Centrally:
ResourceHandle rh;
// Thread 1: reads the central handle into a local copy for further processing
auto localRh = rh;
// Thread 2: creates a new resource and updates the central handle
rh = ResourceHandle{/* ... */};
Because these threads perform non-const operations on the same std::shared_ptr, according to CppReference, I should use the std::atomic_...<std::shared_ptr> specializations to manipulate the shared pointer.
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; the shared_ptr overloads of atomic functions can be used to prevent the data race.
So I want to implement the copy and move operations of the ResourceHandle class using these atomic operations such that manipulating a single resource handle from multiple threads avoids all data races.
The notes section of the CppReference page on std::atomic_...<std::shared_ptr> specializations states the following:
To avoid data races, once a shared pointer is passed to any of these functions, it cannot be accessed non-atomically. In particular, you cannot dereference such a shared_ptr without first atomically loading it into another shared_ptr object, and then dereferencing through the second object.
So I probably want to use some combination of std::atomic_load and std::atomic_store, but I am unsure where and when they should be applied.
How should the copy and move operations of my ResourceHandle class be implemented to not introduce any data races?
shared_ptralready has atomic copy and move operations. - NathanOliverResourceinto the object owned by them_resource, or to modifym_resourceto own a differentResource? - Calethclass Widgetwas thestruct Fooof the 1990s and early 2000s. Scott Meyers uses the term extensively in his Items, iirc. - jonspaceharper