/* */ #ifndef _D_SHARED_HANDLE_H_ #define _D_SHARED_HANDLE_H_ #include namespace aria2 { typedef struct StrongRef {} StrongRef; typedef struct WeakRef {} WeakRef; class RefCount { private: size_t _strongRefCount; size_t _weakRefCount; public: RefCount():_strongRefCount(1), _weakRefCount(1) {} RefCount(const WeakRef&):_strongRefCount(0), _weakRefCount(1) {} inline void addRefCount() { ++_strongRefCount; ++_weakRefCount; } inline void addWeakRefCount() { ++_weakRefCount; } inline void releaseRefCount() { --_strongRefCount; --_weakRefCount; } inline void releaseWeakRefCount() { --_weakRefCount; } inline size_t getStrongRefCount() { return _strongRefCount; } inline size_t getWeakRefCount() { return _weakRefCount; } }; class WeakCount; class SharedCount { private: friend class WeakCount; RefCount* _refCount; public: SharedCount():_refCount(new RefCount()) {} SharedCount(const SharedCount& s):_refCount(s._refCount) { _refCount->addRefCount(); } ~SharedCount() { _refCount->releaseRefCount(); if(_refCount->getWeakRefCount() == 0) { delete _refCount; } } bool reassign(const SharedCount& s) { s._refCount->addRefCount(); _refCount->releaseRefCount(); if(_refCount->getWeakRefCount() == 0) { delete _refCount; _refCount = s._refCount; return true; } size_t thisCount = _refCount->getStrongRefCount(); _refCount = s._refCount; return thisCount == 0; } inline size_t getRefCount() const { return _refCount->getStrongRefCount(); } }; class WeakCount { private: RefCount* _refCount; public: WeakCount(const WeakRef& t):_refCount(new RefCount(t)) {} WeakCount(const StrongRef& t):_refCount(new RefCount()) {} WeakCount(const WeakCount& w):_refCount(w._refCount) { _refCount->addWeakRefCount(); } WeakCount(const SharedCount& s):_refCount(s._refCount) { _refCount->addWeakRefCount(); } ~WeakCount() { _refCount->releaseWeakRefCount(); if(_refCount->getWeakRefCount() == 0) { delete _refCount; } } bool reassign(const SharedCount& s) { s._refCount->addWeakRefCount(); _refCount->releaseWeakRefCount(); if(_refCount->getWeakRefCount() == 0) { delete _refCount; _refCount = s._refCount; return true; } _refCount = s._refCount; return false; } bool reassign(const WeakCount& s) { s._refCount->addWeakRefCount(); _refCount->releaseWeakRefCount(); if(_refCount->getWeakRefCount() == 0) { delete _refCount; _refCount = s._refCount; return true; } _refCount = s._refCount; return false; } inline size_t getRefCount() const { return _refCount->getStrongRefCount(); } }; 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); template friend class SharedHandle; template friend class WeakHandle; T* obj; SharedCount ucount; public: SharedHandle():obj(0), ucount() {} explicit SharedHandle(T* obj):obj(obj), ucount() {} template SharedHandle(const SharedHandle& t):obj(t.obj), ucount(t.ucount) {} template SharedHandle(const SharedHandle& t, T* p): obj(p), ucount(t.ucount) {} ~SharedHandle() { if(ucount.getRefCount() == 1) { delete obj; } } SharedHandle& operator=(const SharedHandle& t) { if(ucount.reassign(t.ucount)) { delete obj; } obj = t.obj; return *this; } template SharedHandle& operator=(const SharedHandle& t) { if(ucount.reassign(t.ucount)) { delete obj; } obj = t.obj; return *this; } T* operator->() { return obj; } T* operator->() const { return obj; } T* get() const { return obj; } size_t getRefCount() const { return ucount.getRefCount(); } void reset() { *this = SharedHandle(); } void reset(T* t) { *this = SharedHandle(t); } bool isNull() const { return obj == 0; } }; template SharedHandle dynamic_pointer_cast(const SharedHandle& t) { if(T* p = dynamic_cast(t.get())) { return SharedHandle(t, p); } else { return SharedHandle(); } } 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); template friend class WeakHandle; T* obj; WeakCount ucount; public: WeakHandle():obj(0), ucount(WeakRef()) {} explicit WeakHandle(T* obj):obj(obj), ucount(StrongRef()) {} template WeakHandle(const SharedHandle& t):obj(t.obj), ucount(t.ucount) {} template WeakHandle(const WeakHandle& t, T* p): obj(p), ucount(t.ucount) {} ~WeakHandle() {} WeakHandle& operator=(const WeakHandle& t) { ucount.reassign(t.ucount); obj = t.obj; return *this; } template WeakHandle& operator=(const SharedHandle& t) { ucount.reassign(t.ucount); obj = t.obj; return *this; } template WeakHandle& operator=(const WeakHandle& t) { ucount.reassign(t.ucount); obj = t.obj; return *this; } T* operator->() { return obj; } T* operator->() const { return obj; } T* get() const { if(isNull()) { return 0; } else { return obj; } } size_t getRefCount() const { return ucount.getRefCount(); } void reset() { *this = WeakHandle(); } bool isNull() const { return ucount.getRefCount() == 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; } template WeakHandle dynamic_pointer_cast(const WeakHandle& t) { if(T* p = dynamic_cast(t.get())) { return WeakHandle(t, p); } else { return WeakHandle(); } } } // namespace aria2 #endif // _D_SHARED_HANDLE_H_