In the absence of multithreading, the implementation of copy-on-write for
shared_ptr (either from boost or tr1) using unique() is
straightforward. Which changes need to be made when multithreading?
The reference count is atomic so I assume I can create, copy-construct,
read and destroy instances of shared_ptr without further concerns.
How about updating them, in general, and particularly when implementing
copy-on-write? Are locks needed? Or use boost::atomic_store
(why is it not documented)? Or wait for a fully atomic version of
shared_ptr (not an option)?
Edit:
sfossen, thank you for your helpful reply.
So I conclude that if I change a pointed-to object only after detaching
it via COW, so that only the current thread owns it, no locking is needed
and the COW implementation looks just like the single-threaded one
when using shared_ptr with atomic ref-counts.
With COW you only need locking when copying objects that may be in the middle of being changed.
So if the COW of the object, is an object set up before the threads and never changes, no locking required.
However if you are making copies of the copies, then you need to atleast lock during the initial write, or make sure that the copy has all changes before being able to be copied again.
If you can't completely guarantee those, then use locking or atomic updates.
There does appear to be an atomic version in the trunk right now.
If you can't update boost, you could either import the required functions for now or wrap it in a lock like the reader/writer lock.
from shared_ptr.hpp
template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )
{
boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
sp.lock();
p->swap( r );
sp.unlock();
return r; // return std::move( r )
}
article on RWLocks
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