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
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
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;}}