
On 02/11/2013 06:22 PM, Jeffrey Lee Hellrung, Jr. wrote:
On Sun, Feb 10, 2013 at 2:27 AM, Pyry Jahkola<pyry.jahkola@iki.fi> wrote: [...]
The biggest difference and, in my opinion, the most important advantage in favour of adobe::copy_on_write is that the copying is explicit; given a
copy_on_write<T> x;
you can only use
x->const_member(); // no refcount overhead even if x is non-const
to access const members of T. Whenever you need to modify the instance, you'll need to explicitly tell copy_on_write about it by calling write():
T & r = x.write(); // write() performs the copy if needed r.mutating_member();
or, matching the use case of cow::cow_ptr<T>::apply:
f(x.write());
This interface maps very nicely to dealing with value types: as long as you're treating everything as a value (i.e. read-only), there aren't any hidden costs of making a copy either. And as soon as you need to make changes to the data, the overhead of the internal copy will be visible in the code responsible of the mutations as well. I guess that's enough to clear most concerns about the thread-safety issues too.
It would probably make sense to rename apply and apply_const to modify and read. The same with the macro. The get() member function is fine in my opinion, but what about operator->()? You can accidently trigger a copy with the non-const version. Should I take the non-const version out?
+1 for explicit copy-on-write. At that point, you're basically just dealing with something close to an augmented shared_ptr< T const >.
- Jeff
Not quiet, since the guts of shared_ptr<T const> can be changed by someone else without you noticing it. That's the thing about shared_ptr. It's really "shared". And const doesn't really mean const, but read-only. I've notices that cow_ptr actually does three things: 1. It implements copy-on-write, similar to copy_on_write. 2. It adds value semantics to polymorphic copyable/clonable types like value_ptr. This way these polymorphic objects can be put into standard containers and get all these nice features value types have. 3. It enables one to add cloning non-intrusively to a class hierarchy that doesn't support cloning. 4. It can be used as a pimpl pointer for value classes. copy_on_write doesn't do 2, 3 and 4. value_ptr doesn't do 1. Hence cow_ptr combines the positive sides of both worlds in an efficient manner. You could combine the template classes copy_on_write<T> and value_ptr<T> to do the same thing (copy_on_write<value_ptr<T>>), but it would be more verbose and not as efficient as cow_ptr<T>. (More indirection, extra allocations, more verbose client code, etc.) It would provide a better separation of concerns though. Possibly a bool template argument could change the behaviour between the current implementation of cow_ptr and value_ptr. What do you think of that?