I used boost::intrusive_ptr when I did that, along with the mixin class attached at the end. The mixin requires a couple of methods, but otherwise provides most of the standard handle/COW methods. It is presumed to be used in a PIMPL implementation where the handle class inherits from the mixin and contains a smart pointer to the implementation instance. COW is done by cloning the implementation instance when appropriate. That's basically calling unshare() before modifying the instance. I don't use smart pointers directly because I want to hide the pointer-ness from the client. At 12:33 PM 7/16/2008, Michiel Helvensteijn wrote:
I am looking for a simple way to implement copy-on-write classes.
Several `copies' of an instantiation of such a class can coexist and share the same data in memory until someone changes their `copy' (calls a non-const member function). At that time, a deep copy is made and the change is only made in that one location. The deep copy is not needed, of course, if the instantiation has only one handle. All of this should be transparent to the user of the class.
I think implementing such a class would be easier with a special class to inherit from and/or a useful set of macro's designed for this purpose.
This seems like something that would (or should) exist in boost. Does boost provide something like this?
If not, I will write it myself. But I'm still not sure how to approach it. I imagine shared_ptr would play a role, though. Any ideas?
/** Mixin for (some) standard handle class methods.
This is moderately useful, but is precluded from additional utility by the
strictures of the design. It can only use the public API because, as a
template, its implementation is always inline. Access to any insulated
types / methods / data destroys the insulation.
This makes the following assumptions about the class T (which can't be
avoided, as we can't pass in pointers to members of T).
- There is a method named @c instance which returns a pointer to the implementation
instance for this handle, creating it if necessary.
- There is a method named @c ptr which returns a pointer to the implementation
instance for this handle, returning @c NIL if there is no instance.
Standard methods that need to be implemented but aren't by this mixin
- @c unshare
Typical @c unshare implementation where @c _p is the implementation pointer.
@code
T& T::unshare()
{
if (_p && _p->_reference_count > 1)
_p = new imp_type(*_p);
return *this;
}
@endcode
*/
template