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