From: Konrad Rosenbaum Date: Sat, 24 Mar 2012 19:23:12 +0000 (+0100) Subject: enhance shared dptr: allow decoupling X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=2fa3509533e164c318941b52a604f559924d7775;p=web%2Fkonrad%2Fsmoke.git enhance shared dptr: allow decoupling --- diff --git a/dptr/dptr_base.h b/dptr/dptr_base.h index 85f2e52..0342909 100644 --- a/dptr/dptr_base.h +++ b/dptr/dptr_base.h @@ -94,7 +94,19 @@ The d-pointer class Private is only forward declared, you have to fully declare Warning: shared d-pointers are not thread safe and they are only re-entrant if instances sharing the same d-pointer are only located in one thread, while instances with different d-pointers may be spread over different threads. \param dp name of the d-pointer*/ -#define DECLARE_SHARED_DPTR(dp) DECLARE_DPTR(dp) +#define DECLARE_SHARED_DPTR(dp) \ + private:\ + class Private; \ + class DPrivate{\ + public:DPrivate();DPrivate(const DPrivate&);~DPrivate();\ + DPrivate&operator=(const DPrivate&);\ + const Private*operator->()const{return d;}\ + Private*operator->(){return d;}\ + DPrivate clone()const;\ + void decouple();\ + private:Private*d;\ + }; \ + DPrivate dp; #ifdef DECLARE_NONCOPY_DPTR diff --git a/dptr/dptr_shared.h b/dptr/dptr_shared.h index 88dc7a4..e7c49bf 100644 --- a/dptr/dptr_shared.h +++ b/dptr/dptr_shared.h @@ -32,6 +32,8 @@ class SharedDPtr virtual void attach(){cnt++;} ///called by the wrapper to detach from an instance virtual void detach(){cnt--;if(cnt==0)delete this;} + ///called by the wrapper to enable copy-on-write logic + int currentRefCount()const{return cnt;} }; //hide the namespace @@ -58,5 +60,7 @@ To be used in implementation where the actual d-pointer class is implemented. Class::DPrivate::~DPrivate(){d->detach();}\ Class::DPrivate Class::DPrivate::clone()const{DPrivate r;*(r.d)=*d;return r;}\ Class::DPrivate& Class::DPrivate::operator=(const DPrivate&dp)\ - {if(d!=dp.d){d->detach();d=dp.d;d->attach();}return *this;} + {if(d!=dp.d){d->detach();d=dp.d;d->attach();}return *this;}\ + void Class::DPrivate::decouple()\ + {if(d->currentRefCount()>1){Private *p=new Class::Private(*d);d->detach();d=p;}}