From e1fed132d22ae23350588ad03bd63c2e4f68f061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 7 Apr 2009 12:01:30 +0000 Subject: [PATCH] * Added a WeakReferenceable implementation, completely untested yet. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29990 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/shared/WeakReferenceable.h | 261 +++++++++++++++++++++ src/kits/support/Jamfile | 1 + src/kits/support/WeakReferenceable.cpp | 13 + src/system/kernel/lib/Jamfile | 1 + 4 files changed, 276 insertions(+) create mode 100644 headers/private/shared/WeakReferenceable.h create mode 100644 src/kits/support/WeakReferenceable.cpp diff --git a/headers/private/shared/WeakReferenceable.h b/headers/private/shared/WeakReferenceable.h new file mode 100644 index 0000000000..2cd42f5287 --- /dev/null +++ b/headers/private/shared/WeakReferenceable.h @@ -0,0 +1,261 @@ +/* + * 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 + + +namespace BPrivate { + +class WeakReferenceable; + +class WeakPointer : public Referenceable { +public: + WeakReferenceable* Get(); + bool Put(); + + int32 UseCount() const; + +private: + friend class WeakReferenceable; + + WeakPointer(WeakReferenceable* object); + ~WeakPointer(); + +private: + bool _GetUnchecked(); + +private: + vint32 fUseCount; + WeakReferenceable* fObject; +}; + +class WeakReferenceable { +public: + WeakReferenceable(); + virtual ~WeakReferenceable(); + + void AddReference() + { fPointer->_GetUnchecked(); } + + bool RemoveReference() + { return fPointer->Put(); } + + int32 CountReferences() const + { return fPointer->UseCount(); } + + WeakPointer* GetWeakPointer(); + +protected: + WeakPointer* fPointer; +}; + +template +class WeakReference { +public: + WeakReference() + : + fPointer(NULL), + fObject(NULL) + { + } + + WeakReference(Type* object) + : + fPointer(NULL), + fObject(NULL) + { + SetTo(object); + } + + WeakReference(const WeakPointer& other) + : + fPointer(NULL), + fObject(NULL) + { + SetTo(&other); + } + + WeakReference(const WeakReference& other) + : + fPointer(NULL), + fObject(NULL) + { + SetTo(other.fPointer); + } + + ~WeakReference() + { + Unset(); + } + + void SetTo(Type* object) + { + Unset(); + + if (object != NULL) { + fPointer = object->GetWeakPointer(); + fObject = fPointer->Get(); + } + } + + void SetTo(WeakPointer* pointer) + { + Unset(); + + if (pointer != NULL) { + fPointer = pointer->AddReference(); + fObject = pointer->Get(); + } + } + + void Unset() + { + if (fPointer != NULL) { + if (fObject != NULL) { + fPointer->Put(); + fObject = NULL; + } + fPointer->RemoveReference(); + fPointer = NULL; + } + } + + Type* Get() const + { + return fObject; + } + + Type* Detach() + { + Type* object = fObject; + Unset(); + return object; + } + + Type& operator*() const + { + return *fObject; + } + + Type* operator->() const + { + return fObject; + } + + WeakReference& operator=(const WeakReference& other) + { + SetTo(other.fPointer); + return *this; + } + + WeakReference& operator=(const Type& other) + { + SetTo(&other); + return *this; + } + + bool operator==(const WeakReference& other) const + { + return fPointer == other.fPointer; + } + + bool operator!=(const WeakReference& other) const + { + return fPointer != other.fPointer; + } + +private: + WeakPointer* fPointer; + Type* fObject; +}; + + +// #pragma mark - + + +inline WeakReferenceable* +WeakPointer::Get() +{ + int32 count; + + do { + count = fUseCount; + if (count == 0) + return NULL; + } while (atomic_test_and_set(&fUseCount, count, count + 1) != count); + + return fObject; +} + + +inline bool +WeakPointer::Put() +{ + if (atomic_add(&fUseCount, -1) == 1) { + delete fObject; + return true; + } + + return false; +} + + +inline int32 +WeakPointer::UseCount() const +{ + return fUseCount; +} + + +inline +WeakPointer::WeakPointer(WeakReferenceable* object) + : + fUseCount(1), + fObject(object) +{ +} + + +inline +WeakPointer::~WeakPointer() +{ +} + + +inline bool +WeakPointer::_GetUnchecked() +{ + return atomic_add(&fUseCount, 1) == 1; +} + + +// #pragma - + + +inline +WeakReferenceable::WeakReferenceable() + : + fPointer(new WeakPointer(this)) +{ +} + + +inline WeakPointer* +WeakReferenceable::GetWeakPointer() +{ + fPointer->AddReference(); + return fPointer; +} + +} // namespace BPrivate + +using BPrivate::WeakReferenceable; +using BPrivate::WeakPointer; +using BPrivate::WeakReference; + +#endif // _WEAK_REFERENCEABLE_H diff --git a/src/kits/support/Jamfile b/src/kits/support/Jamfile index 31126dde36..d84418203d 100644 --- a/src/kits/support/Jamfile +++ b/src/kits/support/Jamfile @@ -18,4 +18,5 @@ MergeObject support_kit.o : Referenceable.cpp StopWatch.cpp String.cpp + WeakReferenceable.cpp ; diff --git a/src/kits/support/WeakReferenceable.cpp b/src/kits/support/WeakReferenceable.cpp new file mode 100644 index 0000000000..85a508c3ba --- /dev/null +++ b/src/kits/support/WeakReferenceable.cpp @@ -0,0 +1,13 @@ +/* + * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include + + +WeakReferenceable::~WeakReferenceable() +{ +} + diff --git a/src/system/kernel/lib/Jamfile b/src/system/kernel/lib/Jamfile index c4cf4c1efc..4eae750831 100644 --- a/src/system/kernel/lib/Jamfile +++ b/src/system/kernel/lib/Jamfile @@ -120,6 +120,7 @@ SEARCH_SOURCE = [ FDirName $(HAIKU_TOP) src kits support ] ; KernelMergeObject kernel_misc.o : Referenceable.cpp + WeakReferenceable.cpp : $(TARGET_KERNEL_PIC_CCFLAGS) ;