diff -r 000000000000 -r 6474c204b198 xpcom/glue/nsRefPtrHashtable.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xpcom/glue/nsRefPtrHashtable.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 2; 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 nsRefPtrHashtable_h__ +#define nsRefPtrHashtable_h__ + +#include "nsBaseHashtable.h" +#include "nsHashKeys.h" +#include "nsAutoPtr.h" + +/** + * templated hashtable class maps keys to reference pointers. + * See nsBaseHashtable for complete declaration. + * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h + * for a complete specification. + * @param RefPtr the reference-type being wrapped + * @see nsDataHashtable, nsClassHashtable + */ +template +class nsRefPtrHashtable : + public nsBaseHashtable< KeyClass, nsRefPtr , RefPtr* > +{ +public: + typedef typename KeyClass::KeyType KeyType; + typedef RefPtr* UserDataType; + typedef nsBaseHashtable< KeyClass, nsRefPtr , RefPtr* > base_type; + + nsRefPtrHashtable() + { + } + explicit nsRefPtrHashtable(uint32_t aInitSize) + : nsBaseHashtable,RefPtr*>(aInitSize) + { + } + + /** + * @copydoc nsBaseHashtable::Get + * @param pData This is an XPCOM getter, so pData is already_addrefed. + * If the key doesn't exist, pData will be set to nullptr. + */ + bool Get(KeyType aKey, UserDataType* pData) const; + + /** + * Gets a weak reference to the hashtable entry. + * @param aFound If not nullptr, will be set to true if the entry is found, + * to false otherwise. + * @return The entry, or nullptr if not found. Do not release this pointer! + */ + RefPtr* GetWeak(KeyType aKey, bool* aFound = nullptr) const; + + // Overload Remove, rather than overriding it. + using base_type::Remove; + + /** + * Remove the data for the associated key, swapping the current value into + * pData, thereby avoiding calls to AddRef and Release. + * @param aKey the key to remove from the hashtable + * @param pData This is an XPCOM getter, so pData is already_addrefed. + * If the key doesn't exist, pData will be set to nullptr. Must be non-null. + */ + bool Remove(KeyType aKey, UserDataType* pData); +}; + +template +inline void +ImplCycleCollectionUnlink(nsRefPtrHashtable& aField) +{ + aField.Clear(); +} + +template +inline void +ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, + nsRefPtrHashtable& aField, + const char* aName, + uint32_t aFlags = 0) +{ + nsBaseHashtableCCTraversalData userData(aCallback, aName, aFlags); + + aField.EnumerateRead(ImplCycleCollectionTraverse_EnumFunc, + &userData); +} + +// +// nsRefPtrHashtable definitions +// + +template +bool +nsRefPtrHashtable::Get + (KeyType aKey, UserDataType* pRefPtr) const +{ + typename base_type::EntryType* ent = this->GetEntry(aKey); + + if (ent) { + if (pRefPtr) { + *pRefPtr = ent->mData; + + NS_IF_ADDREF(*pRefPtr); + } + + return true; + } + + // if the key doesn't exist, set *pRefPtr to null + // so that it is a valid XPCOM getter + if (pRefPtr) { + *pRefPtr = nullptr; + } + + return false; +} + +template +RefPtr* +nsRefPtrHashtable::GetWeak + (KeyType aKey, bool* aFound) const +{ + typename base_type::EntryType* ent = this->GetEntry(aKey); + + if (ent) { + if (aFound) { + *aFound = true; + } + + return ent->mData; + } + + // Key does not exist, return nullptr and set aFound to false + if (aFound) { + *aFound = false; + } + + return nullptr; +} + +template +bool +nsRefPtrHashtable::Remove(KeyType aKey, + UserDataType* pRefPtr) +{ + MOZ_ASSERT(pRefPtr); + typename base_type::EntryType* ent = this->GetEntry(aKey); + + if (ent) { + ent->mData.forget(pRefPtr); + this->Remove(aKey); + return true; + } + + // If the key doesn't exist, set *pRefPtr to null + // so that it is a valid XPCOM getter. + *pRefPtr = nullptr; + return false; +} + +#endif // nsRefPtrHashtable_h__