00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #pragma once
00017
00019 #include "nvsgcommon.h"
00020
00021 #include "nvutil/Allocator.h"
00022
00023
00024 #ifdef _DEBUG
00025 # ifndef new
00026 # define new new(__FILE__, __LINE__)
00027 # define _DEFINED_DBGNEW // restrict the 'new' macro to this header file only
00028 # endif
00029 #endif
00030
00031 namespace nvutil
00032 {
00034
00055 class RCObject : public IAllocator
00056 {
00057 public:
00059
00060 RCObject() : m_refcnt(0), m_shareable(true) {};
00061
00063
00069 NVSG_API void addRef() const;
00071
00074 NVSG_API void removeRef() const;
00076
00079 NVSG_API void markUnshareable();
00081
00084 NVSG_API bool isShareable() const;
00086
00090 NVSG_API bool isShared() const;
00091
00092 protected:
00093
00095
00097 RCObject(const RCObject& rhs) : m_refcnt(0), m_shareable(true) {}
00098
00100
00102 RCObject& operator=(const RCObject& rhs) { return *this; }
00103
00105
00107 virtual ~RCObject() {}
00108
00109 private:
00111 mutable int m_refcnt;
00112 bool m_shareable;
00113 };
00114
00116
00119 template<typename T>
00120 class RCVector : public std::vector<T>, public RCObject
00121 {
00122 public:
00124 RCVector()
00125 {
00126 }
00127
00129
00130 RCVector( size_t n
00131 )
00132 : std::vector<T>(n)
00133 {
00134 }
00135 };
00136
00138
00145 template <typename T>
00146 class RCPtr
00147 {
00149
00165 template <typename U>
00166 friend void writeAccess( RCPtr<U> &rcPtr
00167 );
00168
00169 public:
00170 explicit RCPtr(T* pRCObj=0);
00171 RCPtr(const RCPtr& rhs);
00172 ~RCPtr();
00173 RCPtr<T>& operator=(const RCPtr<T>& rhs);
00174
00175 T* operator->();
00176 const T* operator->() const;
00177 T& operator*();
00178 const T& operator*() const;
00179
00180 private:
00181 void init();
00182 void clone();
00183
00184
00185 T * m_ptr;
00186 };
00187
00189
00193 template <typename T>
00194 class RCIPtr
00195 {
00197
00213 template <typename U>
00214 friend void writeAccess( RCIPtr<U> &rcPtr
00215 );
00216
00217 public:
00218 explicit RCIPtr(T* pObj=0);
00219 RCIPtr(const RCIPtr& rhs);
00220 ~RCIPtr();
00221 RCIPtr<T>& operator=(const RCIPtr<T>& rhs);
00222
00223 T* operator->();
00224 const T* operator->() const;
00225 T& operator*();
00226 const T& operator*() const;
00227
00228 private:
00229
00230
00231 struct CountHolder : public RCObject
00232 {
00233
00234
00235 ~CountHolder() { delete m_ptr; }
00236 T * m_ptr;
00237 };
00238
00239 CountHolder * m_cntHolder;
00240
00241 void init();
00242 void clone();
00243 };
00244
00246
00248 template <typename T>
00249 class RCObject_AutoPtr
00250 {
00251 template<typename U>
00252 friend class RCObject_AutoPtr;
00253
00254 public:
00255 explicit RCObject_AutoPtr(T * ptr=0);
00256 template <typename U>
00257 RCObject_AutoPtr(const RCObject_AutoPtr<U>& rhs);
00258 ~RCObject_AutoPtr();
00259 template <typename U>
00260 RCObject_AutoPtr<T>& operator=(const RCObject_AutoPtr<U>& rhs);
00261
00262 T * get() const;
00263 T * operator->() const;
00264 T& operator*() const;
00265 T * release();
00266 void reset(T * ptr);
00267
00268 private:
00269 void deletePointer();
00270 T * m_ptr;
00271 };
00272
00273
00274
00275
00276
00277 inline void RCObject::addRef() const
00278 {
00279 ++m_refcnt;
00280 }
00281
00282 inline void RCObject::removeRef() const
00283 {
00284 __ASSERT(m_refcnt>0);
00285 if (!--m_refcnt)
00286 {
00287 delete this;
00288 }
00289 }
00290
00291 inline void RCObject::markUnshareable()
00292 {
00293 m_shareable=false;
00294 }
00295
00296 inline bool RCObject::isShareable() const
00297 {
00298 return m_shareable==true;
00299 }
00300
00301 inline bool RCObject::isShared() const
00302 {
00303 return m_refcnt>1;
00304 }
00305
00306 template <typename T>
00307 inline RCPtr<T>::RCPtr(T* pRCObj)
00308 : m_ptr(pRCObj)
00309 {
00310 init();
00311 }
00312
00313 template <typename T>
00314 inline RCPtr<T>::RCPtr(const RCPtr& rhs)
00315 : m_ptr(rhs.m_ptr)
00316 {
00317 init();
00318 }
00319
00320 template <typename T>
00321 inline RCPtr<T>::~RCPtr()
00322 {
00323 if ( m_ptr )
00324 {
00325 m_ptr->removeRef();
00326 }
00327 }
00328
00329 template <typename T>
00330 inline RCPtr<T>& RCPtr<T>::operator=(const RCPtr<T>& rhs)
00331 {
00332 if ( m_ptr != rhs.m_ptr )
00333 {
00334
00335 m_ptr->removeRef();
00336 m_ptr = rhs.m_ptr;
00337 init();
00338 }
00339 return *this;
00340 }
00341
00342 template <typename T>
00343 inline T* RCPtr<T>::operator->()
00344 {
00345 return m_ptr;
00346 }
00347
00348 template <typename T>
00349 inline const T* RCPtr<T>::operator->() const
00350 {
00351 return m_ptr;
00352 }
00353
00354 template <typename T>
00355 inline T& RCPtr<T>::operator*()
00356 {
00357 return *m_ptr;
00358 }
00359
00360 template <typename T>
00361 inline const T& RCPtr<T>::operator*() const
00362 {
00363 return *m_ptr;
00364 }
00365
00366 template <typename T>
00367 inline void RCPtr<T>::init()
00368 {
00369 if ( !m_ptr ) return;
00370
00371 if ( !m_ptr->isShareable() )
00372 {
00373
00374 m_ptr = new T(*m_ptr);
00375 }
00376 m_ptr->addRef();
00377 }
00378
00379 template <typename T>
00380 inline void RCPtr<T>::clone()
00381 {
00382 if ( m_ptr->isShared() )
00383 {
00384
00385 T * pOldVal = m_ptr;
00386 m_ptr->removeRef();
00387 m_ptr = new T(*pOldVal);
00388 m_ptr->addRef();
00389 }
00390 }
00391
00392 template <typename T>
00393 inline RCIPtr<T>::RCIPtr(T * pObj)
00394 : m_cntHolder(new CountHolder)
00395 {
00396 m_cntHolder->m_ptr = pObj;
00397 init();
00398 }
00399
00400 template <typename T>
00401 inline RCIPtr<T>::RCIPtr(const RCIPtr<T>& rhs)
00402 : m_cntHolder(rhs.m_cntHolder)
00403 {
00404 init();
00405 }
00406
00407 template <typename T>
00408 inline RCIPtr<T>::~RCIPtr()
00409 {
00410 m_cntHolder->removeRef();
00411 }
00412
00413 template <typename T>
00414 inline RCIPtr<T>& RCIPtr<T>::operator=(const RCIPtr<T>& rhs)
00415 {
00416 if ( m_cntHolder != rhs.m_cntHolder )
00417 {
00418 m_cntHolder->removeRef();
00419 m_cntHolder = rhs.m_cntHolder;
00420 init();
00421 }
00422 return *this;
00423 }
00424
00425 template <typename T>
00426 inline const T* RCIPtr<T>::operator->() const
00427 {
00428
00429 return m_cntHolder->m_ptr;
00430 }
00431
00432 template <typename T>
00433 inline T* RCIPtr<T>::operator->()
00434 {
00435
00436
00437 return m_cntHolder->m_ptr;
00438 }
00439
00440 template <typename T>
00441 inline const T& RCIPtr<T>::operator*() const
00442 {
00443
00444 return *(m_cntHolder->m_ptr);
00445 }
00446
00447 template <typename T>
00448 inline T& RCIPtr<T>::operator*()
00449 {
00450
00451
00452 return *(m_cntHolder->m_ptr);
00453 }
00454
00455 template <typename T>
00456 inline void RCIPtr<T>::init()
00457 {
00458 if ( !m_cntHolder->isShareable() )
00459 {
00460
00461 _ASSERTE(!m_cntHolder->isShared());
00462
00463
00464 T * pOldVal = m_cntHolder->m_ptr;
00465 m_cntHolder = new CountHolder;
00466 m_cntHolder->m_ptr = new T(*pOldVal);
00467 }
00468 m_cntHolder->addRef();
00469 }
00470
00471 template <typename T>
00472 inline void RCIPtr<T>::clone()
00473 {
00474 if ( m_cntHolder->isShared() )
00475 {
00476 T * pOldVal = m_cntHolder->m_ptr;
00477 m_cntHolder->removeRef();
00478 m_cntHolder = new CountHolder;
00479 m_cntHolder->m_ptr = new T(*pOldVal);
00480 m_cntHolder->addRef();
00481 }
00482 }
00483
00484
00485 template <typename T>
00486 inline RCObject_AutoPtr<T>::RCObject_AutoPtr(T * ptr)
00487 : m_ptr(ptr)
00488 {
00489 }
00490
00491 template <typename T>
00492 template <typename U>
00493 inline RCObject_AutoPtr<T>::RCObject_AutoPtr(const RCObject_AutoPtr<U>& rhs)
00494 : m_ptr(rhs.release())
00495 {
00496
00497 }
00498
00499 template <typename T>
00500 inline RCObject_AutoPtr<T>::~RCObject_AutoPtr()
00501 {
00502 deletePointer();
00503 }
00504
00505 template <typename T>
00506 template <typename U>
00507 inline RCObject_AutoPtr<T>& RCObject_AutoPtr<T>::operator=(const RCObject_AutoPtr<U>& rhs)
00508 {
00509 if ( this != &rhs )
00510 {
00511 reset(rhs.release());
00512 }
00513 return *this;
00514 }
00515
00516 template <typename T>
00517 inline T * RCObject_AutoPtr<T>::get() const
00518 {
00519 return m_ptr;
00520 }
00521
00522 template <typename T>
00523 inline T * RCObject_AutoPtr<T>::operator->() const
00524 {
00525 return m_ptr;
00526 }
00527
00528 template <typename T>
00529 inline T& RCObject_AutoPtr<T>::operator*() const
00530 {
00531 return *m_ptr;
00532 }
00533
00534 template <typename T>
00535 inline T * RCObject_AutoPtr<T>::release()
00536 {
00537 T * ptr = m_ptr;
00538 m_ptr = 0;
00539 return ptr;
00540 }
00541
00542 template <typename T>
00543 void RCObject_AutoPtr<T>::reset(T * ptr)
00544 {
00545 if ( m_ptr != ptr )
00546 {
00547 deletePointer();
00548 m_ptr = ptr;
00549
00550 }
00551 }
00552
00553 template <typename T>
00554 void RCObject_AutoPtr<T>::deletePointer()
00555 {
00556 if ( m_ptr )
00557 {
00558 m_ptr->addRef();
00559 m_ptr->removeRef();
00560 }
00561 }
00562
00563
00564 template <typename T>
00565 inline void writeAccess( RCPtr<T> &rcPtr )
00566 {
00567
00568 rcPtr.clone();
00569 }
00570
00571
00572 template <typename T>
00573 inline void writeAccess( RCIPtr<T> &rcPtr )
00574 {
00575
00576 rcPtr.clone();
00577 }
00578
00579
00581
00596 struct addReference
00597 {
00599
00601 template <typename RCOBJPTR>
00602 RCOBJPTR operator()( RCOBJPTR pRCObject
00603 );
00604
00606
00608 template <typename AnyType, typename RCOBJPTR>
00609 const std::pair<AnyType, RCOBJPTR>& operator()( std::pair<AnyType,RCOBJPTR>& p
00610 );
00611 };
00612
00613 template <typename RCOBJPTR>
00614 RCOBJPTR addReference::operator()( RCOBJPTR pRCObject )
00615 {
00616 pRCObject->addRef();
00617 return pRCObject;
00618 }
00619
00620 template <typename AnyType, typename RCOBJPTR>
00621 const std::pair<AnyType, RCOBJPTR>& addReference::operator()( std::pair<AnyType,RCOBJPTR>& p )
00622 {
00623 p.second->addRef();
00624 return p;
00625 }
00626
00627
00629 struct removeReference
00630 {
00632 template <typename RCOBJPTR>
00633 RCOBJPTR operator()(RCOBJPTR pRCObject)
00634 { pRCObject->removeRef(); return pRCObject; }
00635
00637 template <typename AnyType, typename RCOBJPTR>
00638 const std::pair<AnyType, RCOBJPTR>& operator() (std::pair<AnyType,RCOBJPTR>& p)
00639 { p.second->removeRef(); return p; }
00640 };
00641
00642 }
00643
00644 #ifdef _DEFINED_DBGNEW
00645 # undef new
00646 #endif