1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef XPCOM_DS_NSREFCOUNTEDHASHTABLE_H_
8 #define XPCOM_DS_NSREFCOUNTEDHASHTABLE_H_
10 #include "nsBaseHashtable.h"
11 #include "nsHashKeys.h"
14 * templated hashtable class maps keys to reference pointers.
15 * See nsBaseHashtable for complete declaration.
16 * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
17 * for a complete specification.
18 * @param PtrType the reference-type being wrapped
19 * @see nsClassHashtable, nsTHashMap
21 template <class KeyClass
, class PtrType
>
22 class nsRefCountedHashtable
23 : public nsBaseHashtable
<
25 typename
mozilla::detail::SmartPtrTraits
<PtrType
>::RawPointerType
> {
27 using KeyType
= typename
KeyClass::KeyType
;
28 using SmartPtrTraits
= mozilla::detail::SmartPtrTraits
<PtrType
>;
29 using PointeeType
= typename
SmartPtrTraits::PointeeType
;
30 using RawPointerType
= typename
SmartPtrTraits::RawPointerType
;
31 using base_type
= nsBaseHashtable
<KeyClass
, PtrType
, RawPointerType
>;
33 using base_type::base_type
;
35 static_assert(SmartPtrTraits::IsRefCounted
);
38 * @copydoc nsBaseHashtable::Get
39 * @param aData This is an XPCOM getter, so aData is already_addrefed.
40 * If the key doesn't exist, *aData will be set to nullptr.
42 bool Get(KeyType aKey
, RawPointerType
* aData
) const;
45 * @copydoc nsBaseHashtable::Get
47 [[nodiscard
]] already_AddRefed
<PointeeType
> Get(KeyType aKey
) const;
50 * Gets a weak reference to the hashtable entry.
51 * @param aFound If not nullptr, will be set to true if the entry is found,
53 * @return The entry, or nullptr if not found. Do not release this pointer!
55 [[nodiscard
]] RawPointerType
GetWeak(KeyType aKey
,
56 bool* aFound
= nullptr) const;
58 using base_type::InsertOrUpdate
;
61 typename
= std::enable_if_t
<std::is_base_of_v
<PointeeType
, U
>>>
64 typename
SmartPtrTraits::template OtherSmartPtrType
<U
>&& aData
);
67 typename
= std::enable_if_t
<std::is_base_of_v
<PointeeType
, U
>>>
68 [[nodiscard
]] bool InsertOrUpdate(
70 typename
SmartPtrTraits::template OtherSmartPtrType
<U
>&& aData
,
71 const mozilla::fallible_t
&);
74 typename
= std::enable_if_t
<std::is_base_of_v
<PointeeType
, U
>>>
75 void InsertOrUpdate(KeyType aKey
, already_AddRefed
<U
>&& aData
);
78 typename
= std::enable_if_t
<std::is_base_of_v
<PointeeType
, U
>>>
79 [[nodiscard
]] bool InsertOrUpdate(KeyType aKey
, already_AddRefed
<U
>&& aData
,
80 const mozilla::fallible_t
&);
83 * Remove the entry associated with aKey (if any), optionally _moving_ its
84 * current value into *aData, thereby avoiding calls to AddRef and Release.
85 * Return true if found.
86 * @param aKey the key to remove from the hashtable
87 * @param aData where to move the value (if non-null). If an entry is not
88 * found it will be set to nullptr.
89 * @return true if an entry for aKey was found (and removed)
91 inline bool Remove(KeyType aKey
, RawPointerType
* aData
= nullptr);
93 nsRefCountedHashtable
Clone() const {
94 return this->template CloneAs
<nsRefCountedHashtable
>();
98 template <typename K
, typename T
>
99 inline void ImplCycleCollectionUnlink(nsRefCountedHashtable
<K
, T
>& aField
) {
103 template <typename K
, typename T
>
104 inline void ImplCycleCollectionTraverse(
105 nsCycleCollectionTraversalCallback
& aCallback
,
106 nsRefCountedHashtable
<K
, T
>& aField
, const char* aName
,
107 uint32_t aFlags
= 0) {
108 for (auto iter
= aField
.ConstIter(); !iter
.Done(); iter
.Next()) {
109 CycleCollectionNoteChild(aCallback
, iter
.UserData(), aName
, aFlags
);
114 // nsRefCountedHashtable definitions
117 template <class KeyClass
, class PtrType
>
118 bool nsRefCountedHashtable
<KeyClass
, PtrType
>::Get(
119 KeyType aKey
, RawPointerType
* aRefPtr
) const {
120 typename
base_type::EntryType
* ent
= this->GetEntry(aKey
);
124 *aRefPtr
= ent
->GetData();
126 NS_IF_ADDREF(*aRefPtr
);
132 // if the key doesn't exist, set *aRefPtr to null
133 // so that it is a valid XPCOM getter
141 template <class KeyClass
, class PtrType
>
142 already_AddRefed
<typename nsRefCountedHashtable
<KeyClass
, PtrType
>::PointeeType
>
143 nsRefCountedHashtable
<KeyClass
, PtrType
>::Get(KeyType aKey
) const {
144 typename
base_type::EntryType
* ent
= this->GetEntry(aKey
);
149 PtrType copy
= ent
->GetData();
150 return copy
.forget();
153 template <class KeyClass
, class PtrType
>
154 typename nsRefCountedHashtable
<KeyClass
, PtrType
>::RawPointerType
155 nsRefCountedHashtable
<KeyClass
, PtrType
>::GetWeak(KeyType aKey
,
156 bool* aFound
) const {
157 typename
base_type::EntryType
* ent
= this->GetEntry(aKey
);
164 return ent
->GetData();
167 // Key does not exist, return nullptr and set aFound to false
175 template <class KeyClass
, class PtrType
>
176 template <typename U
, typename
>
177 void nsRefCountedHashtable
<KeyClass
, PtrType
>::InsertOrUpdate(
179 typename
SmartPtrTraits::template OtherSmartPtrType
<U
>&& aData
) {
180 if (!InsertOrUpdate(aKey
, std::move(aData
), mozilla::fallible
)) {
181 NS_ABORT_OOM(this->mTable
.EntrySize() * this->mTable
.EntryCount());
185 template <class KeyClass
, class PtrType
>
186 template <typename U
, typename
>
187 bool nsRefCountedHashtable
<KeyClass
, PtrType
>::InsertOrUpdate(
189 typename
SmartPtrTraits::template OtherSmartPtrType
<U
>&& aData
,
190 const mozilla::fallible_t
&) {
191 typename
base_type::EntryType
* ent
= this->PutEntry(aKey
, mozilla::fallible
);
197 ent
->SetData(std::move(aData
));
202 template <class KeyClass
, class PtrType
>
203 template <typename U
, typename
>
204 void nsRefCountedHashtable
<KeyClass
, PtrType
>::InsertOrUpdate(
205 KeyType aKey
, already_AddRefed
<U
>&& aData
) {
206 if (!InsertOrUpdate(aKey
, std::move(aData
), mozilla::fallible
)) {
207 NS_ABORT_OOM(this->mTable
.EntrySize() * this->mTable
.EntryCount());
211 template <class KeyClass
, class PtrType
>
212 template <typename U
, typename
>
213 bool nsRefCountedHashtable
<KeyClass
, PtrType
>::InsertOrUpdate(
214 KeyType aKey
, already_AddRefed
<U
>&& aData
, const mozilla::fallible_t
&) {
215 typename
base_type::EntryType
* ent
= this->PutEntry(aKey
, mozilla::fallible
);
221 ent
->SetData(std::move(aData
));
226 template <class KeyClass
, class PtrType
>
227 bool nsRefCountedHashtable
<KeyClass
, PtrType
>::Remove(KeyType aKey
,
228 RawPointerType
* aRefPtr
) {
229 typename
base_type::EntryType
* ent
= this->GetEntry(aKey
);
233 ent
->GetModifiableData()->forget(aRefPtr
);
235 this->RemoveEntry(ent
);
245 #endif // XPCOM_DS_NSREFCOUNTEDHASHTABLE_H_