/* */ #ifndef D_SHARED_HANDLE_H #define D_SHARED_HANDLE_H #include #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_() {} SharedHandle(const SharedHandle& t):obj_(t.obj_), ucount_(t.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->() const { return obj_; } T& operator*() const { assert(obj_); 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 SharedHandle static_pointer_cast(const SharedHandle& t) { return SharedHandle(t, static_cast(t.get())); } // Intentionally renamed obj_ as obj_x to cause error template std::ostream& operator<<(std::ostream& o, const SharedHandle& sp) { o << *sp.obj_x; return o; } template bool operator==(const SharedHandle& t1, const SharedHandle& t2) { return *t1.obj_x == *t2.obj_; } template bool operator!=(const SharedHandle& t1, const SharedHandle& t2) { return *t1.obj_x != *t2.obj_; } template bool operator<(const SharedHandle& t1, const SharedHandle& t2) { return *t1.obj_x < *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()) {} WeakHandle(const WeakHandle& t):obj_(t.obj_), ucount_(t.ucount_) {} 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& operator*() const { assert(obj_); 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; } }; // Intentionally renamed obj_ as obj_x to cause error template std::ostream& operator<<(std::ostream& o, const WeakHandle& sp) { o << *sp.obj_x; return o; } template bool operator==(const WeakHandle& t1, const WeakHandle& t2) { return *t1.obj_x == *t2.obj_; } template bool operator!=(const WeakHandle& t1, const WeakHandle& t2) { return *t1.obj_x != *t2.obj_; } template bool operator<(const WeakHandle& t1, const WeakHandle& t2) { return *t1.obj_x < *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