cow_wrapper proposal (was: [dev] Helper of the Day: call for papers)
well, this one does not exactly present an existing helper, but
rather introduces a new one.
After fixing a self-assignment blunder in
basegfx/source/matrix/b2dhommatrix.cxx, which happened in the
copy-on-write-related parts of operator=(), I started to wonder why on
earth everybody and his grandma was doing cow (copy-on-write) by hand.
So, I dug at the usual places, and in the corners of boost and ASL, I
indeed found a cow_ptr and a copy_on_write wrapper. Nice. Only that I
found cow_ptr too ambitious (all the cloning stuff should be
irrelevant for OOo's cow usage), and copy_on_write lacked some of
boost::shared_ptr commodities I got used to (checked_delete, glue for
boost::mem_fn, operator forwarding, standard-compatible swap, you get
Thus, I hacked up the following cow_wrapper template, which is
particularly tailored to our usual, pimpled use of COW (i.e. a wrapper
class, containing a pointer to an opaque implementation class, which
might be shared between multiple instances):
This template provides copy-on-write semantics for the wrapped
type: when copying, the operation is performed shallow,
i.e. different cow_wrapper objects share the same underlying
instance. Only when accessing the underlying object via
non-const methods, a unique copy is provided.
The type parameter <code>T</code> must satisfy the following
requirements: it must be default-constructible, copyable (it
need not be assignable), and be of non-reference type. Note
that, despite the fact that this template provides access to
the wrapped type via pointer-like methods
(<code>operator->()</code> and <code>operator*()</code>), it does
<em>not</em> work like e.g. the boost pointer wrappers
(shared_ptr, scoped_ptr, etc.). Internally, the cow_wrapper
holds a by-value instance of the wrapped object. This is to
avoid one additional heap allocation, and providing access via
<code>operator->()</code>/<code>operator*()</code> is because
<code>operator.()</code> cannot be overridden.
Regarding thread safety: this wrapper is <em>not</em>
thread-safe per se, because cow_wrapper has no way of
syncronizing the potentially many different cow_wrapper
instances, that reference a single shared value_type
instance. Accessing a thread-safe pointee through multiple
cow_wrapper instances might be thread-safe, if the individual
pointee methods are thread-safe, <em>including</em> pointee's
copy constructor. Any wrapped object that needs external
synchronisation (e.g. via an external mutex, which arbitrates
access to object methods, and can be held across multiple
object method calls) cannot easily be dealt with in a
thread-safe way, because, as noted, objects are shared behind
the client's back.
@attention if one wants to use the pimpl idiom together with
cow_wrapper (i.e. put an opaque type into the cow_wrapper),
then <em>all<em> methods in the surrounding class needs to be
non-inline (<em>including</em> destructor, copy constructor
and assignment operator).
cow_wrapper_client( const cow_wrapper_client& );
Yep. OK, if you're still with me, I've got another (related)
proposal. I'd like to see cow_wrapper (and various other stuff,
e.g. Nikolai's heap_ptr) in a new module, with a name like 'o3tl' (for
OpenOffice.org template lib). The scope for this lib should be very
basic (template) functionality, comparable to what's provided by boost
or stl, but specific to OOo (what comes to mind are e.g. stl adapters
for our own datatypes and UNO, and stuff that could in principle be
upstreamed to boost, but isn't as of now).
Feedback greatly appreciated.
If you're not failing some of the time, you're not trying hard enough.
To unsubscribe, e-mail: [hidden email] For additional commands, e-mail: [hidden email]