I have a few data structures I allocate on the heap that are rarely modified but need fast read access. One example would be a struct allocated on the heap that is accessed by many threads very frequently in a read-only fashion. Periodically this struct needs to be re-written and to avoid locking contention I was wondering if it's safe to use auto_ptr
to basically allow threads that have acquired a reference to keep processing until they're finished but allowing the writer to make a copy of the struct, rewrite it and quickly swap pointers with the new auto_ptr
instance of the struct.
I got this idea from CopyOnWriteArrayList
in Java and hoping to perform something similarly performant in C++.
std::auto_ptr
does not having any thread-safety guarantees when calling a non-const member such as reset()
as you are suggesting. Moreover, neither does std::unique_ptr
which you should consider as a replacement for auto_ptr
as auto_ptr
is effectively deprecated.
std::shared_ptr
does provide such thread-saftey guarantees.
What you are typically guaranteed with shared_ptr
is that the reference count is manipulated in an atomic manner, meaning that you are safe from data races when creating a copy of a shared_ptr
, provided that nobody is currently modifying the shared_ptr
at that very moment.
Consider the following use case for your shared_ptr
. You have a global shared_ptr<string> sharedString;
that is currently pointing to an instance of std::string
. It is safe for many threads to call get()
to retrieve a pointer to the string. They may also create their own shared pointer to it as so: shared_ptr<string> myString = sharedString;
, provided that nobody is changing what the shared pointer points to.
Now, lets go back and fix the race condition that exists in the example. When it comes time to change what the global shared pointer points to, a thread may be making a copy of it -- that is a problem since it could leave the copy in an inconsistent state. So, we have to make sure that we change and copy it atomically.
Luckily for us, shared_ptr
provides a number of specializations of the C++11 atomic operations: atomic_load
, atomic_store
, and atomic_exchange
.
When making a copy of the shared_ptr
, use atomic_load
, and when updating the shared_ptr
, use atomic_store
.
Doing it this way is important for two reasons.
Now, it is important to note that using thread-safe operations on a shared_ptr
does not provide any thread safety to the type it points to. You always have to take care that the object pointed to is being used in a thread safe way.
You can reassign an auto_ptr on the fly with reset(), by the way, it destroys the object instance formerly pointed.
However, auto_ptr is deprecated by unique_ptr, which have a swap() function which somewhat seems to stick to what you are seeking.
Keep in mind that these classes are not thread-safe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With