00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef FXREFEDOBJECT_H
00023 #define FXREFEDOBJECT_H
00024
00025 #include "QThread.h"
00026 #include "FXException.h"
00027 #include "FXPolicies.h"
00028 #include "qvaluelist.h"
00029
00030 namespace FX {
00031
00046 #ifndef FXREFINGOBJECT_DEBUGKNOWALLOC
00047 #ifdef DEBUG
00048 #define FXREFINGOBJECT_DEBUGKNOWALLOC 1
00049 #else
00050 #define FXREFINGOBJECT_DEBUGKNOWALLOC 0
00051 #endif
00052 #endif
00053
00054 class FXRefingObjectBase
00055 {
00056 protected:
00057 #if FXREFINGOBJECT_DEBUGKNOWALLOC
00058 struct Allocated
00059 {
00060 const char *file;
00061 int lineno;
00062 Allocated(const char *_file, int _lineno) : file(_file), lineno(_lineno) { }
00063 } allocated;
00064 FXRefingObjectBase(const char *_file, int _lineno) : allocated(_file, _lineno) { }
00065 public:
00066 FXRefingObjectBase &operator=(const FXRefingObjectBase &o)
00067 {
00068 if(o.allocated.file)
00069 {
00070 allocated.file=o.allocated.file;
00071 allocated.lineno=o.allocated.lineno;
00072 }
00073 return *this;
00074 }
00075 const char *int_allocated_file() const throw() { return allocated.file; }
00076 int int_allocated_lineno() const throw() { return allocated.lineno; }
00077 #else
00078 FXRefingObjectBase(const char *_file, int _lineno) { }
00079 public:
00080 const char *int_allocated_file() const throw() { return 0; }
00081 int int_allocated_lineno() const throw() { return 0; }
00082 #endif
00083 };
00084 template<class type> class FXRefingObject;
00085 namespace FXRefingObjectImpl {
00086 template<bool mutexed, class type> struct dataHolderI;
00087 template<class type> class refedObject;
00088 }
00089
00090 namespace FXRefedObjectImpl
00091 {
00092 template<typename type> class countHolder
00093 {
00094 type myrefcount;
00095 bool mydying;
00096 protected:
00097 bool int_increfcount()
00098 {
00099 if(mydying) return false;
00100 ++myrefcount;
00101 return true;
00102 }
00103 bool int_decrefcount()
00104 {
00105 if(!--myrefcount && !mydying)
00106 {
00107 mydying=true;
00108 return false;
00109 }
00110 return true;
00111 }
00112 public:
00113 countHolder() : myrefcount(0), mydying(false) { }
00114 countHolder(const countHolder &o) : myrefcount(0), mydying(false) { }
00116 const type &refCount() const throw() { return myrefcount; }
00118 void resetDying() throw() { mydying=false; }
00119 };
00120
00121 template<> class countHolder<FXAtomicInt>
00122 {
00123
00124
00125 QShrdMemMutex myrefcountlock;
00126 int myrefcount;
00127 bool mydying;
00128 protected:
00129 bool int_increfcount()
00130 {
00131 myrefcountlock.lock();
00132 if(mydying)
00133 {
00134 myrefcountlock.unlock();
00135 return false;
00136 }
00137 ++myrefcount;
00138 myrefcountlock.unlock();
00139 return true;
00140 }
00141 bool int_decrefcount()
00142 {
00143 myrefcountlock.lock();
00144 if(!--myrefcount && !mydying)
00145 {
00146 mydying=true;
00147 myrefcountlock.unlock();
00148 return false;
00149 }
00150 myrefcountlock.unlock();
00151 return true;
00152 }
00153 public:
00154 countHolder() : myrefcountlock(FXINFINITE), myrefcount(0), mydying(false) { }
00155 countHolder(const countHolder &o) : myrefcountlock(FXINFINITE), myrefcount(0), mydying(false) { }
00156
00157 const int &refCount() const throw() { return myrefcount; }
00159 void resetDying() throw() { mydying=false; }
00160 };
00161
00162 }
00163
00164 namespace Pol {
00169 struct unknownReferrers
00170 {
00171 protected:
00172 struct ReferrerEntry { };
00173 unknownReferrers() { }
00174 void int_addReferrer(FXRefingObjectBase *r, QMutex *lock) { }
00175 void int_removeReferrer(FXRefingObjectBase *r, QMutex *lock) { }
00176 const QValueList<ReferrerEntry> *int_referrers() const { return 0; }
00177 };
00178 #ifdef _MSC_VER
00179 #pragma warning(push)
00180 #pragma warning(disable: 4251)
00181 #endif
00182
00186 struct knowReferrers
00187 {
00188 protected:
00189 struct ReferrerEntry
00190 {
00191 FXRefingObjectBase *ref;
00192 FXulong threadId;
00193 ReferrerEntry(FXRefingObjectBase *_ref) : ref(_ref), threadId(QThread::id()) { }
00194 bool operator==(const ReferrerEntry &o) const throw() { return ref==o.ref; }
00195 };
00196 QValueList<ReferrerEntry> referrers;
00197 knowReferrers() { }
00198 void int_addReferrer(FXRefingObjectBase *r, QMutex *lock)
00199 {
00200 QMtxHold h(lock, QMtxHold::AcceptNullMutex);
00201 referrers.push_back(ReferrerEntry(r));
00202 }
00203 void int_removeReferrer(FXRefingObjectBase *r, QMutex *lock)
00204 {
00205 QMtxHold h(lock, QMtxHold::AcceptNullMutex);
00206 referrers.remove(ReferrerEntry(r));
00207 }
00208 const QValueList<ReferrerEntry> *int_referrers() const { return &referrers; }
00209 };
00210 #ifdef _MSC_VER
00211 #pragma warning(pop)
00212 #endif
00213
00217 struct hasLastUsed
00218 {
00219 private:
00220 mutable FXuint lastusedtimestamp;
00221 protected:
00222 hasLastUsed() : lastusedtimestamp(0) { }
00223 public:
00227 FXuint lastUsed() const throw() { return lastusedtimestamp; }
00228 };
00229 }
00255 template<typename intType,
00256 class lastUsed=Pol::None0,
00257 class referrersPolicy=Pol::unknownReferrers> class FXRefedObject : public FXRefedObjectImpl::countHolder<intType>, public lastUsed, private referrersPolicy
00258 {
00259 template<class type> friend class FXRefingObjectImpl::refedObject;
00260 template<bool mutexed, class type> friend struct FXRefingObjectImpl::dataHolderI;
00261 template<class type> friend class FXRefedObject_DisableCount;
00262 typedef FXRefedObject MyFXRefedObjectSpec;
00263 intType disableCount;
00264 public:
00265 FXRefedObject() : disableCount(0) { }
00266 virtual ~FXRefedObject() { }
00267 FXRefedObject(const FXRefedObject &o) : lastUsed(o), referrersPolicy(), disableCount(o.disableCount) { }
00268 protected:
00270 virtual void noMoreReferrers() { delete this; }
00271 using referrersPolicy::ReferrerEntry;
00272 using referrersPolicy::int_referrers;
00273 };
00274
00275 namespace FXRefingObjectImpl {
00276 template<bool mutexed, class type> struct dataHolderI
00277 {
00278 type *data;
00279 dataHolderI(type *p) : data(p) { }
00280 inline void addRef();
00281 inline void delRef();
00282 };
00283 template<class type> struct dataHolderI<true, type>
00284 {
00285 type *data;
00286 dataHolderI(type *p) : data(p) { }
00287 inline void addRef();
00288 inline void delRef();
00289 };
00290 template<class type> struct dataHolder
00291 : public dataHolderI<Generic::convertible<QMutex &, type &>::value, type>
00292 {
00293 dataHolder(type *p) : dataHolderI<Generic::convertible<QMutex &, type &>::value, type>(p) { }
00294 };
00295 template<bool hasLastUsed, class type> class lastUsedI : protected dataHolder<type>
00296 {
00297 protected:
00298 lastUsedI(type *p) : dataHolder<type>(p) { }
00299 type *accessData() const throw() { return dataHolder<type>::data; }
00300 };
00301 template<class type> class lastUsedI<true, type> : protected dataHolder<type>
00302 {
00303 protected:
00304 lastUsedI(type *p) : dataHolder<type>(p) { }
00305 type *accessData() const
00306 {
00307 if(dataHolder<type>::data) dataHolder<type>::data->lastusedtimestamp=FXProcess::getMsCount();
00308 return dataHolder<type>::data;
00309 }
00310 };
00311 template<class type> class refedObject
00312 : private lastUsedI<Generic::convertible<Pol::hasLastUsed &, type &>::value, type>
00313 {
00314 template<bool, class> friend struct FXRefingObjectImpl::dataHolderI;
00315 typedef lastUsedI<Generic::convertible<Pol::hasLastUsed &, type &>::value, type> Base;
00316 void inc()
00317 {
00318 if(Base::data && !Base::data->disableCount)
00319 {
00320 if(Base::data->int_increfcount())
00321 Base::addRef();
00322 else
00323 Base::data=0;
00324 }
00325 }
00326 void dec()
00327 {
00328 if(Base::data && !Base::data->disableCount)
00329 {
00330 Base::delRef();
00331 if(!Base::data->int_decrefcount())
00332 static_cast<typename type::MyFXRefedObjectSpec *>(Base::data)->noMoreReferrers();
00333 Base::data=0;
00334 }
00335 }
00336 public:
00337 refedObject(type *d) : Base(d) { inc(); }
00338 refedObject(const refedObject &o) : Base(o) { inc(); }
00339 refedObject &operator=(const refedObject &o)
00340 {
00341 dec();
00342 Base::data=o.data;
00343 inc();
00344 return *this;
00345 }
00346 ~refedObject()
00347 {
00348 dec();
00349 }
00350 friend type *PtrPtr(refedObject &p) { return p.accessData(); }
00351 friend const type *PtrPtr(const refedObject &p) { return p.accessData(); }
00352 friend type *&PtrRef(refedObject &p) { return p.data; }
00353 friend const type *PtrRef(const refedObject &p) { return p.data; }
00354 };
00355
00356 }
00357
00361 template<class type> class FXRefedObject_DisableCount
00362 {
00363 type *object;
00364 public:
00365 FXRefedObject_DisableCount(type *obj) : object(obj) { ++object->disableCount; }
00366 ~FXRefedObject_DisableCount() { --object->disableCount; }
00367 };
00368
00413 template<class type> class FXRefingObject
00414 : public FXRefingObjectBase, public Generic::ptr<type, FXRefingObjectImpl::refedObject>
00415 {
00416 public:
00418 FXRefingObject(type *data=0, const char *file=0, int lineno=0)
00419 : FXRefingObjectBase(file, lineno), Generic::ptr<type, FXRefingObjectImpl::refedObject>(data) { }
00420 explicit FXRefingObject(FXAutoPtr<type> &ptr)
00421 : FXRefingObjectBase(0, 0), Generic::ptr<type, FXRefingObjectImpl::refedObject>(ptr) { }
00422 #if FXREFINGOBJECT_DEBUGKNOWALLOC
00423 #if 1
00424
00425 FXRefingObject(const FXRefingObject &o, const char *file=0, int lineno=0)
00426 : FXRefingObjectBase(o.allocated.file ? o.allocated.file : file, o.allocated.file ? o.allocated.lineno : lineno), Generic::ptr<type, FXRefingObjectImpl::refedObject>(o) { }
00427 #else
00428
00429 FXRefingObject(const FXRefingObject &o, const char *file=0, int lineno=0)
00430 : FXRefingObjectBase(file ? file : o.allocated.file, file ? lineno : o.allocated.lineno), Generic::ptr<type, FXRefingObjectImpl::refedObject>(o) { }
00431 #endif
00432 #else
00433 FXRefingObject(const FXRefingObject &o, const char *file=0, int lineno=0)
00434 : FXRefingObjectBase(0, 0), Generic::ptr<type, FXRefingObjectImpl::refedObject>(o) { }
00435 #endif
00436
00439 friend FXRefingObject PtrDetach(FXRefingObject &p)
00440 {
00441 FXAutoPtr<type> v;
00442 type *pv=PtrPtr(p);
00443 assert(pv);
00444 FXERRHM(v=new type(*pv));
00445 return FXRefingObject(v);
00446 }
00447 };
00448
00449 namespace FXRefingObjectImpl
00450 {
00451 template<bool mutexed, class type> inline void dataHolderI<mutexed, type>::addRef()
00452 {
00453 data->int_addReferrer(static_cast<FXRefingObject<type> *>(this), 0);
00454 }
00455 template<bool mutexed, class type> inline void dataHolderI<mutexed, type>::delRef()
00456 {
00457 data->int_removeReferrer(static_cast<FXRefingObject<type> *>(this), 0);
00458 }
00459 template<class type> inline void dataHolderI<true, type>::addRef()
00460 {
00461 data->int_addReferrer(static_cast<FXRefingObject<type> *>(this), data);
00462 }
00463 template<class type> inline void dataHolderI<true, type>::delRef()
00464 {
00465 data->int_removeReferrer(static_cast<FXRefingObject<type> *>(this), data);
00466 }
00467 }
00468
00469 }
00470
00471 #endif