From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- xpcom/base/nsMaybeWeakPtr.h | 170 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 xpcom/base/nsMaybeWeakPtr.h (limited to 'xpcom/base/nsMaybeWeakPtr.h') diff --git a/xpcom/base/nsMaybeWeakPtr.h b/xpcom/base/nsMaybeWeakPtr.h new file mode 100644 index 0000000000..165a8c23c1 --- /dev/null +++ b/xpcom/base/nsMaybeWeakPtr.h @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsMaybeWeakPtr_h_ +#define nsMaybeWeakPtr_h_ + +#include "mozilla/Attributes.h" +#include "nsCOMPtr.h" +#include "nsIWeakReferenceUtils.h" +#include "nsTArray.h" +#include "nsCycleCollectionNoteChild.h" + +// nsMaybeWeakPtr is a helper object to hold a strong-or-weak reference +// to the template class. It's pretty minimal, but sufficient. + +template +class nsMaybeWeakPtr { + public: + nsMaybeWeakPtr() = default; + MOZ_IMPLICIT nsMaybeWeakPtr(T* aRef) : mPtr(aRef), mWeak(false) {} + MOZ_IMPLICIT nsMaybeWeakPtr(const nsCOMPtr& aRef) + : mPtr(aRef), mWeak(true) {} + + nsMaybeWeakPtr& operator=(T* aRef) { + mPtr = aRef; + mWeak = false; + return *this; + } + + nsMaybeWeakPtr& operator=(const nsCOMPtr& aRef) { + mPtr = aRef; + mWeak = true; + return *this; + } + + bool operator==(const nsMaybeWeakPtr& other) const { + return mPtr == other.mPtr; + } + + nsISupports* GetRawValue() const { return mPtr.get(); } + bool IsWeak() const { return mWeak; } + + const nsCOMPtr GetValue() const; + + private: + nsCOMPtr mPtr; + bool mWeak; +}; + +// nsMaybeWeakPtrArray is an array of MaybeWeakPtr objects, that knows how to +// grab a weak reference to a given object if requested. It only allows a +// given object to appear in the array once. + +template +class nsMaybeWeakPtrArray : public CopyableTArray> { + typedef nsTArray> MaybeWeakArray; + + nsresult SetMaybeWeakPtr(nsMaybeWeakPtr& aRef, T* aElement, + bool aOwnsWeak) { + nsresult rv = NS_OK; + + if (aOwnsWeak) { + aRef = do_GetWeakReference(aElement, &rv); + } else { + aRef = aElement; + } + + return rv; + } + + public: + nsresult AppendWeakElement(T* aElement, bool aOwnsWeak) { + nsMaybeWeakPtr ref; + MOZ_TRY(SetMaybeWeakPtr(ref, aElement, aOwnsWeak)); + + MaybeWeakArray::AppendElement(ref); + return NS_OK; + } + + nsresult AppendWeakElementUnlessExists(T* aElement, bool aOwnsWeak) { + nsMaybeWeakPtr ref; + MOZ_TRY(SetMaybeWeakPtr(ref, aElement, aOwnsWeak)); + + if (MaybeWeakArray::Contains(ref)) { + return NS_ERROR_INVALID_ARG; + } + + MaybeWeakArray::AppendElement(ref); + return NS_OK; + } + + nsresult RemoveWeakElement(T* aElement) { + if (MaybeWeakArray::RemoveElement(aElement)) { + return NS_OK; + } + + // Don't use do_GetWeakReference; it should only be called if we know + // the object supports weak references. + nsCOMPtr supWeakRef = do_QueryInterface(aElement); + if (!supWeakRef) { + return NS_ERROR_INVALID_ARG; + } + + nsCOMPtr weakRef; + nsresult rv = supWeakRef->GetWeakReference(getter_AddRefs(weakRef)); + NS_ENSURE_SUCCESS(rv, rv); + + if (MaybeWeakArray::RemoveElement(weakRef)) { + return NS_OK; + } + + return NS_ERROR_INVALID_ARG; + } +}; + +template +const nsCOMPtr nsMaybeWeakPtr::GetValue() const { + if (!mPtr) { + return nullptr; + } + + nsCOMPtr ref; + nsresult rv; + + if (mWeak) { + nsCOMPtr weakRef = do_QueryInterface(mPtr); + if (weakRef) { + ref = do_QueryReferent(weakRef, &rv); + if (NS_SUCCEEDED(rv)) { + return ref; + } + } + } else { + ref = do_QueryInterface(mPtr, &rv); + if (NS_SUCCEEDED(rv)) { + return ref; + } + } + + return nullptr; +} + +template +inline void ImplCycleCollectionUnlink(nsMaybeWeakPtrArray& aField) { + aField.Clear(); +} + +template +inline void ImplCycleCollectionTraverse( + nsCycleCollectionTraversalCallback& aCallback, + nsMaybeWeakPtrArray& aField, const char* aName, uint32_t aFlags = 0) { + aFlags |= CycleCollectionEdgeNameArrayFlag; + size_t length = aField.Length(); + for (size_t i = 0; i < length; ++i) { + CycleCollectionNoteChild(aCallback, aField[i].GetRawValue(), aName, aFlags); + } +} + +// Call a method on each element in the array, but only if the element is +// non-null. + +#define ENUMERATE_WEAKARRAY(array, type, method) \ + for (uint32_t array_idx = 0; array_idx < array.Length(); ++array_idx) { \ + const nsCOMPtr& e = array.ElementAt(array_idx).GetValue(); \ + if (e) e->method; \ + } + +#endif -- cgit v1.2.3