/* */ #ifndef _D_SHARED_HANDLE_H_ #define _D_SHARED_HANDLE_H_ #include class RefCount { public: RefCount():totalRefCount(0), strongRefCount(0) {} RefCount(int32_t totalRefCount, int32_t strongRefCount) :totalRefCount(totalRefCount), strongRefCount(strongRefCount) {} int32_t totalRefCount; int32_t strongRefCount; }; template class SharedHandle; template class WeakHandle; template class SharedHandle { private: template friend std::ostream& operator<<(std::ostream& o, const SharedHandle& sp); template friend bool operator==(const SharedHandle& t1, const SharedHandle& t2); template friend bool operator!=(const SharedHandle& t1, const SharedHandle& t2); template friend bool operator<(const SharedHandle& t1, const SharedHandle& t2); T* obj; RefCount* ucount; void releaseReference() { if(--ucount->strongRefCount == 0) { delete obj; obj = 0; } if(--ucount->totalRefCount == 0) { delete ucount; ucount = 0; } } public: SharedHandle():obj(new T()), ucount(new RefCount(1, 1)) {} SharedHandle(T* obj):obj(obj), ucount(new RefCount(1, 1)) {} SharedHandle(const SharedHandle& t):obj(t.get()), ucount(t.getRefCount()) { ++ucount->totalRefCount; ++ucount->strongRefCount; } template SharedHandle(const SharedHandle& t) { obj = dynamic_cast(t.get()); if(obj) { ucount = t.getRefCount(); ++ucount->totalRefCount; ++ucount->strongRefCount; } else { ucount = new RefCount(1, 1); } } ~SharedHandle() { releaseReference(); } SharedHandle& operator=(const SharedHandle& t) { ++t.getRefCount()->totalRefCount; ++t.getRefCount()->strongRefCount; releaseReference(); obj = t.get(); ucount = t.getRefCount(); return *this; } template SharedHandle& operator=(const SharedHandle& t) { T* to = dynamic_cast(t.get()); if(to) { ++t.getRefCount()->totalRefCount; ++t.getRefCount()->strongRefCount; releaseReference(); obj = to; ucount = t.getRefCount(); } else { releaseReference(); obj = 0; ucount = new RefCount(1, 1); } return *this; } T* operator->() { return obj; } T* operator->() const { return obj; } T* get() const { return obj; } RefCount* getRefCount() const { return ucount; } bool isNull() const { return obj == 0; } }; template std::ostream& operator<<(std::ostream& o, const SharedHandle& sp) { o << *sp.obj; return o; } template bool operator==(const SharedHandle& t1, const SharedHandle& t2) { return *t1.obj == *t2.obj; } template bool operator!=(const SharedHandle& t1, const SharedHandle& t2) { return *t1.obj != *t2.obj; } template bool operator<(const SharedHandle& t1, const SharedHandle& t2) { return *t1.obj < *t2.obj; } template class WeakHandle { private: template friend std::ostream& operator<<(std::ostream& o, const WeakHandle& sp); template friend bool operator==(const WeakHandle& t1, const WeakHandle& t2); template friend bool operator!=(const WeakHandle& t1, const WeakHandle& t2); template friend bool operator<(const WeakHandle& t1, const WeakHandle& t2); T* obj; RefCount* ucount; void releaseReference() { if(--ucount->totalRefCount == 0) { delete ucount; ucount = 0; } } public: WeakHandle():obj(0), ucount(new RefCount(1, 0)) {} WeakHandle(T* obj):obj(obj), ucount(new RefCount(1, 1)) {} WeakHandle(const WeakHandle& t):obj(t.get()), ucount(t.getRefCount()) { ++ucount->totalRefCount; } template WeakHandle(const SharedHandle& t):obj(t.get()), ucount(t.getRefCount()) { obj = dynamic_cast(t.get()); if(obj) { ucount = t.getRefCount(); ++ucount->totalRefCount; } else { ucount = new RefCount(1, 0); } } template WeakHandle(const WeakHandle& t) { obj = dynamic_cast(t.get()); if(obj) { ucount = t.getRefCount(); ++ucount->totalRefCount; } else { ucount = new RefCount(1, 0); } } ~WeakHandle() { releaseReference(); } WeakHandle& operator=(const WeakHandle& t) { ++t.getRefCount()->totalRefCount; releaseReference(); obj = t.get(); ucount = t.getRefCount(); return *this; } template WeakHandle& operator=(const SharedHandle& t) { T* to = dynamic_cast(t.get()); if(to) { ++t.getRefCount()->totalRefCount; releaseReference(); obj = to; ucount = t.getRefCount(); } else { releaseReference(); obj = 0; ucount = new RefCount(1, 0); } return *this; } template WeakHandle& operator=(const WeakHandle& t) { T* to = dynamic_cast(t.get()); if(to) { ++t.getRefCount()->totalRefCount; releaseReference(); obj = to; ucount = t.getRefCount(); } else { releaseReference(); obj = 0; ucount = new RefCount(1, 0); } return *this; } T* operator->() { return obj; } T* operator->() const { return obj; } T* get() const { if(isNull()) { return 0; } else { return obj; } } RefCount* getRefCount() const { return ucount; } bool isNull() const { return ucount->strongRefCount == 0 || obj == 0; } }; template std::ostream& operator<<(std::ostream& o, const WeakHandle& sp) { o << *sp.obj; return o; } template bool operator==(const WeakHandle& t1, const WeakHandle& t2) { return *t1.obj == *t2.obj; } template bool operator!=(const WeakHandle& t1, const WeakHandle& t2) { return *t1.obj != *t2.obj; } template bool operator<(const WeakHandle& t1, const WeakHandle& t2) { return *t1.obj < *t2.obj; } #endif // _D_SHARED_HANDLE_H_