nsRefPtrHashtable.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef nsRefPtrHashtable_h__
  6. #define nsRefPtrHashtable_h__
  7. #include "nsBaseHashtable.h"
  8. #include "nsHashKeys.h"
  9. #include "nsAutoPtr.h"
  10. /**
  11. * templated hashtable class maps keys to reference pointers.
  12. * See nsBaseHashtable for complete declaration.
  13. * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
  14. * for a complete specification.
  15. * @param PtrType the reference-type being wrapped
  16. * @see nsDataHashtable, nsClassHashtable
  17. */
  18. template<class KeyClass, class PtrType>
  19. class nsRefPtrHashtable
  20. : public nsBaseHashtable<KeyClass, RefPtr<PtrType>, PtrType*>
  21. {
  22. public:
  23. typedef typename KeyClass::KeyType KeyType;
  24. typedef PtrType* UserDataType;
  25. typedef nsBaseHashtable<KeyClass, RefPtr<PtrType>, PtrType*> base_type;
  26. nsRefPtrHashtable() {}
  27. explicit nsRefPtrHashtable(uint32_t aInitLength)
  28. : nsBaseHashtable<KeyClass, RefPtr<PtrType>, PtrType*>(aInitLength)
  29. {
  30. }
  31. /**
  32. * @copydoc nsBaseHashtable::Get
  33. * @param aData This is an XPCOM getter, so aData is already_addrefed.
  34. * If the key doesn't exist, aData will be set to nullptr.
  35. */
  36. bool Get(KeyType aKey, UserDataType* aData) const;
  37. /**
  38. * Gets a weak reference to the hashtable entry.
  39. * @param aFound If not nullptr, will be set to true if the entry is found,
  40. * to false otherwise.
  41. * @return The entry, or nullptr if not found. Do not release this pointer!
  42. */
  43. PtrType* GetWeak(KeyType aKey, bool* aFound = nullptr) const;
  44. // Overload Put, rather than overriding it.
  45. using base_type::Put;
  46. void Put(KeyType aKey, already_AddRefed<PtrType> aData);
  47. MOZ_MUST_USE bool Put(KeyType aKey, already_AddRefed<PtrType> aData,
  48. const mozilla::fallible_t&);
  49. // Overload Remove, rather than overriding it.
  50. using base_type::Remove;
  51. /**
  52. * Remove the data for the associated key, swapping the current value into
  53. * pData, thereby avoiding calls to AddRef and Release.
  54. * @param aKey the key to remove from the hashtable
  55. * @param aData This is an XPCOM getter, so aData is already_addrefed.
  56. * If the key doesn't exist, aData will be set to nullptr. Must be non-null.
  57. */
  58. bool Remove(KeyType aKey, UserDataType* aData);
  59. };
  60. template<typename K, typename T>
  61. inline void
  62. ImplCycleCollectionUnlink(nsRefPtrHashtable<K, T>& aField)
  63. {
  64. aField.Clear();
  65. }
  66. template<typename K, typename T>
  67. inline void
  68. ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
  69. nsRefPtrHashtable<K, T>& aField,
  70. const char* aName,
  71. uint32_t aFlags = 0)
  72. {
  73. for (auto iter = aField.ConstIter(); !iter.Done(); iter.Next()) {
  74. CycleCollectionNoteChild(aCallback, iter.UserData(), aName, aFlags);
  75. }
  76. }
  77. //
  78. // nsRefPtrHashtable definitions
  79. //
  80. template<class KeyClass, class PtrType>
  81. bool
  82. nsRefPtrHashtable<KeyClass, PtrType>::Get(KeyType aKey,
  83. UserDataType* aRefPtr) const
  84. {
  85. typename base_type::EntryType* ent = this->GetEntry(aKey);
  86. if (ent) {
  87. if (aRefPtr) {
  88. *aRefPtr = ent->mData;
  89. NS_IF_ADDREF(*aRefPtr);
  90. }
  91. return true;
  92. }
  93. // if the key doesn't exist, set *aRefPtr to null
  94. // so that it is a valid XPCOM getter
  95. if (aRefPtr) {
  96. *aRefPtr = nullptr;
  97. }
  98. return false;
  99. }
  100. template<class KeyClass, class PtrType>
  101. PtrType*
  102. nsRefPtrHashtable<KeyClass, PtrType>::GetWeak(KeyType aKey, bool* aFound) const
  103. {
  104. typename base_type::EntryType* ent = this->GetEntry(aKey);
  105. if (ent) {
  106. if (aFound) {
  107. *aFound = true;
  108. }
  109. return ent->mData;
  110. }
  111. // Key does not exist, return nullptr and set aFound to false
  112. if (aFound) {
  113. *aFound = false;
  114. }
  115. return nullptr;
  116. }
  117. template<class KeyClass, class PtrType>
  118. void
  119. nsRefPtrHashtable<KeyClass, PtrType>::Put(KeyType aKey,
  120. already_AddRefed<PtrType> aData)
  121. {
  122. if (!Put(aKey, mozilla::Move(aData), mozilla::fallible)) {
  123. NS_ABORT_OOM(this->mTable.EntrySize() * this->mTable.EntryCount());
  124. }
  125. }
  126. template<class KeyClass, class PtrType>
  127. bool
  128. nsRefPtrHashtable<KeyClass, PtrType>::Put(KeyType aKey,
  129. already_AddRefed<PtrType> aData,
  130. const mozilla::fallible_t&)
  131. {
  132. typename base_type::EntryType* ent = this->PutEntry(aKey);
  133. if (!ent) {
  134. return false;
  135. }
  136. ent->mData = aData;
  137. return true;
  138. }
  139. template<class KeyClass, class PtrType>
  140. bool
  141. nsRefPtrHashtable<KeyClass, PtrType>::Remove(KeyType aKey,
  142. UserDataType* aRefPtr)
  143. {
  144. MOZ_ASSERT(aRefPtr);
  145. typename base_type::EntryType* ent = this->GetEntry(aKey);
  146. if (ent) {
  147. ent->mData.forget(aRefPtr);
  148. this->Remove(aKey);
  149. return true;
  150. }
  151. // If the key doesn't exist, set *aRefPtr to null
  152. // so that it is a valid XPCOM getter.
  153. *aRefPtr = nullptr;
  154. return false;
  155. }
  156. #endif // nsRefPtrHashtable_h__