michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsMaybeWeakPtr_h_ michael@0: #define nsMaybeWeakPtr_h_ michael@0: michael@0: #include "nsCOMPtr.h" michael@0: #include "nsWeakReference.h" michael@0: #include "nsTArray.h" michael@0: #include "nsCycleCollectionNoteChild.h" michael@0: michael@0: // nsMaybeWeakPtr is a helper object to hold a strong-or-weak reference michael@0: // to the template class. It's pretty minimal, but sufficient. michael@0: michael@0: class nsMaybeWeakPtr_base michael@0: { michael@0: protected: michael@0: // Returns an addref'd pointer to the requested interface michael@0: void* GetValueAs(const nsIID& iid) const; michael@0: michael@0: nsCOMPtr mPtr; michael@0: }; michael@0: michael@0: template michael@0: class nsMaybeWeakPtr : private nsMaybeWeakPtr_base michael@0: { michael@0: public: michael@0: nsMaybeWeakPtr(nsISupports *ref) { mPtr = ref; } michael@0: nsMaybeWeakPtr(const nsCOMPtr &ref) { mPtr = ref; } michael@0: nsMaybeWeakPtr(const nsCOMPtr &ref) { mPtr = ref; } michael@0: michael@0: bool operator==(const nsMaybeWeakPtr &other) const { michael@0: return mPtr == other.mPtr; michael@0: } michael@0: michael@0: operator const nsCOMPtr() const { return GetValue(); } michael@0: michael@0: protected: michael@0: const nsCOMPtr GetValue() const { michael@0: return nsCOMPtr(dont_AddRef(static_cast michael@0: (GetValueAs(NS_GET_TEMPLATE_IID(T))))); michael@0: } michael@0: }; michael@0: michael@0: // nsMaybeWeakPtrArray is an array of MaybeWeakPtr objects, that knows how to michael@0: // grab a weak reference to a given object if requested. It only allows a michael@0: // given object to appear in the array once. michael@0: michael@0: typedef nsTArray< nsMaybeWeakPtr > isupports_array_type; michael@0: nsresult NS_AppendWeakElementBase(isupports_array_type *aArray, michael@0: nsISupports *aElement, bool aWeak); michael@0: nsresult NS_RemoveWeakElementBase(isupports_array_type *aArray, michael@0: nsISupports *aElement); michael@0: michael@0: template michael@0: class nsMaybeWeakPtrArray : public nsTArray< nsMaybeWeakPtr > michael@0: { michael@0: public: michael@0: nsresult AppendWeakElement(T *aElement, bool aOwnsWeak) michael@0: { michael@0: return NS_AppendWeakElementBase( michael@0: reinterpret_cast(this), aElement, aOwnsWeak); michael@0: } michael@0: michael@0: nsresult RemoveWeakElement(T *aElement) michael@0: { michael@0: return NS_RemoveWeakElementBase( michael@0: reinterpret_cast(this), aElement); michael@0: } michael@0: }; michael@0: michael@0: template michael@0: inline void michael@0: ImplCycleCollectionUnlink(nsMaybeWeakPtrArray& aField) michael@0: { michael@0: aField.Clear(); michael@0: } michael@0: michael@0: template michael@0: inline void michael@0: ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, michael@0: nsMaybeWeakPtrArray& aField, michael@0: const char* aName, michael@0: uint32_t aFlags = 0) michael@0: { michael@0: aFlags |= CycleCollectionEdgeNameArrayFlag; michael@0: size_t length = aField.Length(); michael@0: for (size_t i = 0; i < length; ++i) { michael@0: CycleCollectionNoteChild(aCallback, aField[i].get(), aName, aFlags); michael@0: } michael@0: } michael@0: michael@0: // Call a method on each element in the array, but only if the element is michael@0: // non-null. michael@0: michael@0: #define ENUMERATE_WEAKARRAY(array, type, method) \ michael@0: for (uint32_t array_idx = 0; array_idx < array.Length(); ++array_idx) { \ michael@0: const nsCOMPtr &e = array.ElementAt(array_idx); \ michael@0: if (e) \ michael@0: e->method; \ michael@0: } michael@0: michael@0: #endif