00001
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef MXFLIB__SMARTPTR_H
00040 #define MXFLIB__SMARTPTR_H
00041
00042
00043
00044 #define PTRDEBUG( x )
00045
00046
00047
00048
00049 #define PTRCHECK( x )
00050
00051
00052
00053 #include <stdlib.h>
00054
00055 namespace mxflib
00056 {
00057
00058 template <class T> class SmartPtr;
00059
00060
00061 template <class T> class ParentPtr;
00062
00064
00067 template <class T> class IRefCount
00068 {
00069
00070 friend class SmartPtr<T>;
00071
00072
00073 friend class ParentPtr<T>;
00074
00075 protected:
00076
00077
00078 virtual void __IncRefCount() = 0;
00079 virtual void __DecRefCount() = 0;
00080 virtual T * GetPtr() = 0;
00081 virtual IRefCount<T> * GetRef() = 0;
00082
00083 virtual void AddRef(ParentPtr<T> &Ptr) = 0;
00084 virtual void DeleteRef(ParentPtr<T> &Ptr) = 0;
00085 virtual void ClearParents(void) = 0;
00086
00087 virtual ~IRefCount() {};
00088 };
00089
00090
00091 typedef std::pair<void*,std::string> PtrCheckListItemType;
00092 typedef std::list<PtrCheckListItemType> PtrCheckListType;
00093 PTRCHECK( extern PtrCheckListType PtrCheckList; )
00094 }
00095
00096
00097 namespace mxflib
00098 {
00099
00101
00113 template <class T> class RefCount : public IRefCount<T>
00114 {
00115 protected:
00116 int __m_counter;
00117
00118 typedef ParentPtr<T> LocalParent;
00119 typedef std::list<LocalParent*> LocalParentList;
00120 LocalParentList *ParentPointers;
00121
00122 protected:
00124 virtual void __IncRefCount()
00125 {
00126 __m_counter++;
00127
00128 PTRDEBUG( debug("%p Increment count -> %p\n", this, __m_counter); )
00129 }
00130
00132 virtual void __DecRefCount()
00133 {
00134 __m_counter--;
00135
00136 PTRDEBUG( debug("%p Decrement count -> %d\n", this, __m_counter); )
00137
00138 if(__m_counter<=0)
00139 {
00140 PTRDEBUG( debug("%p Destroying\n", this); )
00141
00142 __DestroyRef();
00143 }
00144 }
00145
00147 virtual T * GetPtr()
00148 {
00149 return ((T *)this);
00150 }
00151
00153 virtual IRefCount<T>* GetRef()
00154 {
00155 return this;
00156 }
00157
00159
00161 virtual void __DestroyRef()
00162 {
00163 if(GetPtr()!=NULL)
00164 {
00165
00166 PTRCHECK
00167 (
00168 PtrCheckListType::iterator it = PtrCheckList.begin();
00169 while(it != PtrCheckList.end())
00170 {
00171 if((*it).first == (void*)this)
00172 {
00173 PtrCheckList.erase(it);
00174 break;
00175 }
00176 it++;
00177 }
00178 )
00179
00180 delete GetPtr();
00181 }
00182 }
00183
00185 virtual void AddRef(ParentPtr<T> &Ptr)
00186 {
00187 PTRDEBUG( debug("Adding ParentPtr(%p) to %p\n", &Ptr, this); )
00188
00189 if(!ParentPointers) ParentPointers = new LocalParentList;
00190 ParentPointers->push_back(&Ptr);
00191 }
00192
00194 virtual void DeleteRef(ParentPtr<T> &Ptr)
00195 {
00196 if(ParentPointers)
00197 {
00198 typename LocalParentList::iterator it = ParentPointers->begin();
00199 while(it != ParentPointers->end())
00200 {
00201 if((*it) == &Ptr)
00202 {
00203 PTRDEBUG( debug("Deleting ParentPtr(%p) from %p\n", &Ptr, this); )
00204 ParentPointers->erase(it);
00205 return;
00206 }
00207 it++;
00208 }
00209 }
00210 error("Tried to clear ParentPtr(%p) from %p but that ParentPtr does not exist\n", &Ptr, this);
00211 }
00212
00213 protected:
00215 RefCount()
00216 {
00217
00218
00219
00220 PTRCHECK( PtrCheckList.push_front(PtrCheckListItemType((void*)this, PrintInfo())); )
00221
00222
00223 __m_counter = 0;
00224
00225
00226 ParentPointers = NULL;
00227
00228 PTRDEBUG( debug("%p Build new (zero) count\n", this); )
00229 }
00230
00231
00233 virtual ~RefCount()
00234 {
00235 if(ParentPointers) ClearParents();
00236 }
00237
00239 virtual void ClearParents(void);
00240
00241 PTRCHECK
00242 (
00243 public:
00244 virtual std::string PrintInfo(void)
00245 {
00246 char buffer[1024];
00247 sprintf(&buffer[0], "Item size = %d :", sizeof(T));
00248 for(int i=0; i<min(sizeof(T), 64); i++) sprintf(&buffer[strlen(buffer)], " %02x", ((UInt8*)(this))[i]);
00249 return std::string(buffer);
00250 }
00251
00252 void SetDebug(std::string str)
00253 {
00254 PtrCheckListType::iterator it = PtrCheckList.begin();
00255 while(it != PtrCheckList.end())
00256 {
00257 if((*it).first == (void*)this)
00258 {
00259 PTRDEBUG( debug("Setting text to (%s)\n", str.c_str()); )
00260 (*it).second = str;
00261 return;
00262 }
00263 it++;
00264 }
00265 }
00266 )
00267 };
00268
00269
00270 template <class T> void mxflib::RefCount<T>::ClearParents(void)
00271 {
00272 if(ParentPointers)
00273 {
00274 typename LocalParentList::iterator it = ParentPointers->begin();
00275 while(it != ParentPointers->end())
00276 {
00277 (*it)->ClearFromParent();
00278 it++;
00279 }
00280
00281 delete ParentPointers;
00282 }
00283 }
00284 }
00285
00286
00287 namespace mxflib
00288 {
00290
00333 template <class T> class SmartPtr
00334 {
00335 protected:
00336 IRefCount<T> *__m_refcount;
00337
00339 PTRDEBUG( std::string DebugName; )
00340
00342
00345 class __RefCounter : public RefCount<T>
00346 {
00347 private:
00348 T *__m_ptr;
00349 protected:
00351 virtual T * GetPtr() const { return __m_ptr; }
00352
00354
00356 virtual void __DestroyRef() { delete this; }
00357
00358 public:
00360 __RefCounter(T *ptr)
00361 {
00362 __m_ptr = ptr;
00363 }
00364
00366 virtual ~__RefCounter()
00367 {
00368 RefCount<T>::__DestroyRef();
00369 }
00370 };
00371
00373
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00392
00399 virtual void __Assign(IRefCount<T> *refcount)
00400 {
00401 PTRDEBUG( if(DebugName.size()) debug("%s changing from %p to %p\n", DebugName.c_str(), __m_refcount, refcount); )
00402
00403
00404
00405
00406
00407
00408 if(refcount!=NULL) refcount->__IncRefCount();
00409
00410
00411 IRefCount<T> *oldref = __m_refcount;
00412
00413
00414 __m_refcount = refcount;
00415
00416
00417 if(oldref!=NULL) oldref->__DecRefCount();
00418 }
00419
00420 public:
00422 SmartPtr()
00423 {
00424 __m_refcount = NULL;
00425 }
00426
00428 SmartPtr(IRefCount<T> * ptr)
00429 {
00430 __m_refcount = NULL;
00431 __Assign(ptr);
00432 }
00433
00435 SmartPtr(const SmartPtr<T> &sp)
00436 {
00437 __m_refcount = NULL;
00438 __Assign(sp.__m_refcount);
00439 }
00440
00442 virtual ~SmartPtr()
00443 {
00444 __Assign((IRefCount<T> *)NULL);
00445 }
00446
00448 T *GetPtr() const
00449 {
00450 if(__m_refcount==NULL) return NULL;
00451 return __m_refcount->GetPtr();
00452 }
00453
00455 IRefCount<T> *GetRef() const
00456 {
00457 if(__m_refcount==NULL) return NULL;
00458 return __m_refcount->GetRef();
00459 }
00460
00462 SmartPtr & operator = (const SmartPtr<T> &sp) {__Assign(sp.__m_refcount); return *this;}
00463
00465 SmartPtr & operator = (IRefCount<T> * ptr) {__Assign(ptr); return *this;}
00466
00468 T * operator ->()
00469 {
00470 ASSERT(GetPtr()!=NULL);
00471 return GetPtr();
00472 }
00473
00475 const T * operator ->() const
00476 {
00477 ASSERT(GetPtr()!=NULL);
00478 return (const T*)GetPtr();
00479 }
00480
00482 operator T* () const
00483 {
00484 return GetPtr();
00485 }
00486
00488 bool operator !()
00489 {
00490 return GetPtr()==NULL;
00491 }
00492
00494 bool operator ==(const SmartPtr &sp)
00495 {
00496 return GetPtr()==sp.GetPtr();
00497 }
00498
00500 bool operator !=(const SmartPtr &sp)
00501 {
00502 return GetPtr()!=sp.GetPtr();
00503 }
00504
00506 bool operator<(SmartPtr &Other) { return this.operator<(*Other->GetPtr()); }
00507
00509
00514 template <class U> U* Cast(U*) { return dynamic_cast<U*>(GetPtr()); }
00515
00517 PTRDEBUG( void SetDebugName(std::string Name) { DebugName = Name; } )
00518 };
00519 }
00520
00521
00522 namespace mxflib
00523 {
00525
00529
00530 template<class T> class ParentPtr : public SmartPtr<T>
00531 {
00532 protected:
00534
00537 virtual void __Assign(IRefCount<T> *refcount)
00538 {
00539 PTRDEBUG( debug("Assigning parent pointer at %p to %p\n", this, refcount); )
00540
00541
00542 if(this->__m_refcount) this->__m_refcount->DeleteRef(*this);
00543
00544
00545 this->__m_refcount = refcount;
00546
00547
00548 if(refcount) refcount->AddRef(*this);
00549 }
00550
00551 public:
00553 ParentPtr()
00554 {
00555 this->__m_refcount = NULL;
00556 }
00557
00559 ParentPtr(SmartPtr<T> ptr)
00560 {
00561 this->__m_refcount = NULL;
00562 __Assign(ptr.GetRef());
00563 }
00564
00566 ParentPtr(IRefCount<T> * ptr)
00567 {
00568 this->__m_refcount = NULL;
00569 __Assign(ptr);
00570 }
00571
00573 ParentPtr(const ParentPtr &rhs)
00574 {
00575 this->__m_refcount = NULL;
00576 __Assign(rhs.GetRef());
00577 }
00578
00580 ~ParentPtr()
00581 {
00582
00583 if(this->__m_refcount) (this->__m_refcount)->DeleteRef(*this);
00584
00585 this->__m_refcount = NULL;
00586 }
00587
00589 ParentPtr & operator=(const SmartPtr<T> &sp) { __Assign(sp.GetRef()); return *this;}
00590
00592 ParentPtr & operator=(const ParentPtr<T> &sp) { __Assign(sp.__m_refcount); return *this;}
00593
00595 ParentPtr & operator=(T *Ptr) { __Assign((IRefCount<T>*)Ptr); return *this; }
00596
00598 void Clear(void)
00599 {
00600
00601 if(this->__m_refcount) this->__m_refcount->DeleteRef(*this);
00602
00603 this->__m_refcount = NULL;
00604 }
00605
00607
00608 void ClearFromParent(void) { this->__m_refcount = NULL; };
00609 };
00610 }
00611
00612
00614 #define SmartPtr_Cast(Ptr, Type) ( Ptr.Cast((Type*)NULL) )
00615
00616 #endif // MXFLIB__SMARTPTR_H