Skip navigation

Monthly Archives: January 2006

Since nobody complained, checked in cow_wrapper.hxx in a new module, under the tools project (which seemed to me the right place for a tools package): o3tl/inc/o3tl/cow_wrapper.hxx contains the stuff, the remainder of the module is currently a mere unit test for said template.

The scope for o3tl is admittedly kind of ambitious, as it should contain “…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).”

Advertisement

After fixing a self-assignment blunder in basegfx/source/matrix/b2dhommatrix.cxx, which happened in the copy-on-write-related parts of operator=, I began to wonder why on earth everybody and his grandma was doing cow (copy-on-write) by hand (a search for mnRefCount and m_nRefCount (though certainly only a subset) should give you an idea how abundant this theme is. BTW: I generally agree with Herb Sutter, that cow has disadvantages in a multi-threaded world — but, alas, giant objects like bitmaps or polygons should better still provide a cow implementation in the back).

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 the idea).

Consequently, I cobbled together a cow_wrapper, tailored to the usual, pimpled use of cow in OOo:

class Impl;

class MyClass
{
public:
   MyClass();

   void set( int v );
   int  get() const;

private:
   cow_wrapper mpImpl;
};

where the get() and set() methods simply forward to the Impl methods:

void MyClass::set( int v )
{
    mpImpl->set(v);
}
int MyClass::get() const
{
    return mpImpl->get();
}

And the trick is: cow_wrapper has operator-> overloaded for const and non-const access. For non-const access, the potentially shared copy of the Impl object gets copied (i.e. made unique).

Except that cow_wrapper doesn’t yet have all wanted features (checked_delete support still missing), and possibly needs some testing, I think this holds up for quite painless cow implementations (yes, I intend to move at least basegfx to cow_wrapper, eventually).