
13 Feb
2013
13 Feb
'13
12:17 p.m.
On 02/11/2013 11:45 PM, Jeffrey Lee Hellrung, Jr. wrote: > On Mon, Feb 11, 2013 at 11:00 AM, Ralph Tandetzky < > ralph.tandetzky@googlemail.com> wrote: > >> 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'm not sure what you mean, but I didn't literally mean a shared_ptr< T > const >; just some smart pointer to shared objects where the only way to > mutate said objects through the smart pointer is via explicit copy-on-write. Well, then we are on the same page. :) > 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? > I haven't taken the time to look at value_ptr or copy_on_write, but I think > the ideal situation is a pair of smart pointers, one like I just described > above (smart pointer to shared object), and one like (or precisely) > unique_ptr. This makes the deep copying and mutation explicit and safe. But > I should note I haven't looked in detail at any of the smart pointers > discussed in this thread yet :/ unique_ptr wouldn't work, because it does not provide cloning and a dynamic deleter, which must be transported back to the read_ptr<T> at some point. But an appropriate non-copyable but movable pointer type makes sense. > - Jeff