/* * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ #ifndef _WEAK_REFERENCEABLE_H #define _WEAK_REFERENCEABLE_H #include #include namespace BPrivate { class BWeakReferenceable; class WeakPointer : public BReferenceable { public: WeakPointer(BWeakReferenceable* object); ~WeakPointer(); BWeakReferenceable* Get(); bool Put(); int32 UseCount() const; void GetUnchecked(); private: friend class BWeakReferenceable; int32 fUseCount; BWeakReferenceable* fObject; }; class BWeakReferenceable { public: BWeakReferenceable(); virtual ~BWeakReferenceable(); status_t InitCheck(); void AcquireReference() { fPointer->GetUnchecked(); } bool ReleaseReference() { return fPointer->Put(); } int32 CountReferences() const { return fPointer->UseCount(); } WeakPointer* GetWeakPointer(); private: WeakPointer* fPointer; }; template class BWeakReference { public: BWeakReference() : fPointer(NULL) { } BWeakReference(Type* object) : fPointer(NULL) { SetTo(object); } BWeakReference(const BWeakReference& other) : fPointer(NULL) { SetTo(other); } BWeakReference(const BReference& other) : fPointer(NULL) { SetTo(other); } template BWeakReference(const BReference& other) : fPointer(NULL) { SetTo(other.Get()); } template BWeakReference(const BWeakReference& other) : fPointer(NULL) { SetTo(other); } ~BWeakReference() { Unset(); } void SetTo(Type* object) { Unset(); if (object != NULL) fPointer = object->GetWeakPointer(); } void SetTo(const BWeakReference& other) { Unset(); if (other.fPointer) { fPointer = other.fPointer; fPointer->AcquireReference(); } } template void SetTo(const BWeakReference& other) { // Just a compiler check if the types are compatible. OtherType* otherDummy = NULL; Type* dummy = otherDummy; dummy = NULL; Unset(); if (other.PrivatePointer()) { fPointer = const_cast(other.PrivatePointer()); fPointer->AcquireReference(); } } void SetTo(const BReference& other) { SetTo(other.Get()); } void Unset() { if (fPointer != NULL) { fPointer->ReleaseReference(); fPointer = NULL; } } bool IsAlive() { if (fPointer == NULL) return false; Type* object = static_cast(fPointer->Get()); if (object == NULL) return false; fPointer->Put(); return true; } BReference GetReference() { if (fPointer == NULL) return BReference(); Type* object = static_cast(fPointer->Get()); return BReference(object, true); } BWeakReference& operator=(const BWeakReference& other) { if (this == &other) return *this; SetTo(other); return *this; } BWeakReference& operator=(Type* other) { SetTo(other); return *this; } BWeakReference& operator=(const BReference& other) { SetTo(other.Get()); return *this; } template BWeakReference& operator=(const BReference& other) { SetTo(other.Get()); return *this; } template BWeakReference& operator=(const BWeakReference& other) { SetTo(other); return *this; } bool operator==(const BWeakReference& other) const { return fPointer == other.fPointer; } bool operator!=(const BWeakReference& other) const { return fPointer != other.fPointer; } /*! Do not use this if you do not know what you are doing. The WeakPointer is for internal use only. */ const WeakPointer* PrivatePointer() const { return fPointer; } private: WeakPointer* fPointer; }; } // namespace BPrivate using BPrivate::BWeakReferenceable; using BPrivate::BWeakReference; #endif // _WEAK_REFERENCEABLE_H