Boost logo

Boost :

Subject: Re: [boost] [smart ptr] Any interest in copy-on-write pointer for C++11?
From: Ralph Tandetzky (ralph.tandetzky_at_[hidden])
Date: 2013-02-13 07:17:56


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_at_[hidden]> 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_at_[hidden]>
>>> 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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk