From 8b9a514d5f50fa1fad3e77b621b00c182e1539f5 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 19 Apr 2013 17:59:01 -0400 Subject: [PATCH] Bug 863884 - Prepare WeakPtr to support a thread-safe variant; r=Waldo --- mfbt/RefPtr.h | 7 +++- mfbt/WeakPtr.h | 86 +++++++++++++++++++++++++++++++------------------- 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/mfbt/RefPtr.h b/mfbt/RefPtr.h index a298706e711..9f4163a21a8 100644 --- a/mfbt/RefPtr.h +++ b/mfbt/RefPtr.h @@ -10,6 +10,7 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" +#include "mozilla/TypeTraits.h" namespace mozilla { @@ -53,7 +54,11 @@ class RefCounted protected: RefCounted() : refCnt(0) { } - ~RefCounted() { MOZ_ASSERT(refCnt == detail::DEAD); } + ~RefCounted() { + MOZ_ASSERT(refCnt == detail::DEAD); + MOZ_STATIC_ASSERT((IsBaseOf, T>::value), + "T must derive from RefCounted"); + } public: // Compatibility with nsRefPtr. diff --git a/mfbt/WeakPtr.h b/mfbt/WeakPtr.h index b8437f5bcf6..d61b0b37d30 100644 --- a/mfbt/WeakPtr.h +++ b/mfbt/WeakPtr.h @@ -65,56 +65,68 @@ namespace mozilla { -template class WeakPtr; +template class WeakPtrBase; +template class SupportsWeakPtrBase; -template -class SupportsWeakPtr +namespace detail { + +// This can live beyond the lifetime of the class derived from SupportsWeakPtrBase. +template +class WeakReference : public RefCounted > { public: - WeakPtr asWeakPtr() { + explicit WeakReference(T* p) : ptr(p) {} + T* get() const { + return ptr; + } + + private: + friend class WeakPtrBase >; + friend class SupportsWeakPtrBase >; + void detach() { + ptr = nullptr; + } + T* ptr; +}; + +} // namespace detail + +template +class SupportsWeakPtrBase +{ + public: + WeakPtrBase asWeakPtr() { if (!weakRef) weakRef = new WeakReference(static_cast(this)); - return WeakPtr(weakRef); + return WeakPtrBase(weakRef); } protected: - ~SupportsWeakPtr() { - MOZ_STATIC_ASSERT((IsBaseOf, T>::value), "T must derive from SupportsWeakPtr"); + ~SupportsWeakPtrBase() { + MOZ_STATIC_ASSERT((IsBaseOf, T>::value), + "T must derive from SupportsWeakPtrBase"); if (weakRef) weakRef->detach(); } private: - friend class WeakPtr; - - // This can live beyond the lifetime of the class derived from SupportsWeakPtr. - class WeakReference : public RefCounted - { - public: - explicit WeakReference(T* p) : ptr(p) {} - T* get() const { - return ptr; - } - - private: - friend class WeakPtr; - friend class SupportsWeakPtr; - void detach() { - ptr = nullptr; - } - T* ptr; - }; + friend class WeakPtrBase; RefPtr weakRef; }; template -class WeakPtr +class SupportsWeakPtr : public SupportsWeakPtrBase > +{ +}; + +template +class WeakPtrBase { public: - WeakPtr(const WeakPtr& o) : ref(o.ref) {} + WeakPtrBase(const WeakPtrBase& o) : ref(o.ref) {} // Ensure that ref is dereferenceable in the uninitialized state - WeakPtr() : ref(new typename SupportsWeakPtr::WeakReference(nullptr)) {} + WeakPtrBase() : ref(new WeakReference(nullptr)) {} operator T*() const { return ref->get(); @@ -132,11 +144,21 @@ class WeakPtr } private: - friend class SupportsWeakPtr; + friend class SupportsWeakPtrBase; - explicit WeakPtr(const RefPtr::WeakReference> &o) : ref(o) {} + explicit WeakPtrBase(const RefPtr &o) : ref(o) {} - RefPtr::WeakReference> ref; + RefPtr ref; +}; + +template +class WeakPtr : public WeakPtrBase > +{ + typedef WeakPtrBase > Base; + public: + WeakPtr(const WeakPtr& o) : Base(o) {} + WeakPtr(const Base& o) : Base(o) {} + WeakPtr() {} }; } // namespace mozilla