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 nsInterfaceHashtable_h__
8 #define nsInterfaceHashtable_h__
10 #include "nsBaseHashtable.h"
11 #include "nsHashKeys.h"
15 * templated hashtable class maps keys to interface pointers.
16 * See nsBaseHashtable for complete declaration.
17 * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
18 * for a complete specification.
19 * @param Interface the interface-type being wrapped
20 * @see nsDataHashtable, nsClassHashtable
22 template <class KeyClass
, class Interface
>
23 class nsInterfaceHashtable
24 : public nsBaseHashtable
<KeyClass
, nsCOMPtr
<Interface
>, Interface
*> {
26 typedef typename
KeyClass::KeyType KeyType
;
27 typedef Interface
* UserDataType
;
28 typedef nsBaseHashtable
<KeyClass
, nsCOMPtr
<Interface
>, Interface
*> base_type
;
30 nsInterfaceHashtable() = default;
31 explicit nsInterfaceHashtable(uint32_t aInitLength
)
32 : nsBaseHashtable
<KeyClass
, nsCOMPtr
<Interface
>, Interface
*>(
36 * @copydoc nsBaseHashtable::Get
37 * @param aData This is an XPCOM getter, so aData is already_addrefed.
38 * If the key doesn't exist, aData will be set to nullptr.
40 bool Get(KeyType aKey
, UserDataType
* aData
) const;
43 * @copydoc nsBaseHashtable::Get
45 already_AddRefed
<Interface
> Get(KeyType aKey
) const;
48 * Gets a weak reference to the hashtable entry.
49 * @param aFound If not nullptr, will be set to true if the entry is found,
51 * @return The entry, or nullptr if not found. Do not release this pointer!
53 Interface
* GetWeak(KeyType aKey
, bool* aFound
= nullptr) const;
56 * Allows inserting a value into the hashtable, moving its owning reference
57 * count into the hashtable, avoiding an AddRef.
59 void Put(KeyType aKey
, already_AddRefed
<Interface
>&& aData
) {
60 if (!Put(aKey
, std::move(aData
), mozilla::fallible
)) {
61 NS_ABORT_OOM(this->mTable
.EntrySize() * this->mTable
.EntryCount());
65 [[nodiscard
]] bool Put(KeyType aKey
, already_AddRefed
<Interface
>&& aData
,
66 const mozilla::fallible_t
&);
70 * Remove the entry associated with aKey (if any), optionally _moving_ its
71 * current value into *aData, thereby avoiding calls to AddRef and Release.
72 * Return true if found.
73 * @param aKey the key to remove from the hashtable
74 * @param aData where to move the value (if non-null). If an entry is not
75 * found it will be set to nullptr.
76 * @return true if an entry for aKey was found (and removed)
78 inline bool Remove(KeyType aKey
, Interface
** aData
= nullptr);
81 template <typename K
, typename T
>
82 inline void ImplCycleCollectionUnlink(nsInterfaceHashtable
<K
, T
>& aField
) {
86 template <typename K
, typename T
>
87 inline void ImplCycleCollectionTraverse(
88 nsCycleCollectionTraversalCallback
& aCallback
,
89 const nsInterfaceHashtable
<K
, T
>& aField
, const char* aName
,
90 uint32_t aFlags
= 0) {
91 for (auto iter
= aField
.ConstIter(); !iter
.Done(); iter
.Next()) {
92 CycleCollectionNoteChild(aCallback
, iter
.UserData(), aName
, aFlags
);
97 // nsInterfaceHashtable definitions
100 template <class KeyClass
, class Interface
>
101 bool nsInterfaceHashtable
<KeyClass
, Interface
>::Get(
102 KeyType aKey
, UserDataType
* aInterface
) const {
103 typename
base_type::EntryType
* ent
= this->GetEntry(aKey
);
107 *aInterface
= ent
->GetData();
109 NS_IF_ADDREF(*aInterface
);
115 // if the key doesn't exist, set *aInterface to null
116 // so that it is a valid XPCOM getter
118 *aInterface
= nullptr;
124 template <class KeyClass
, class Interface
>
125 already_AddRefed
<Interface
> nsInterfaceHashtable
<KeyClass
, Interface
>::Get(
126 KeyType aKey
) const {
127 typename
base_type::EntryType
* ent
= this->GetEntry(aKey
);
132 nsCOMPtr
<Interface
> copy
= ent
->GetData();
133 return copy
.forget();
136 template <class KeyClass
, class Interface
>
137 Interface
* nsInterfaceHashtable
<KeyClass
, Interface
>::GetWeak(
138 KeyType aKey
, bool* aFound
) const {
139 typename
base_type::EntryType
* ent
= this->GetEntry(aKey
);
146 return ent
->GetData();
149 // Key does not exist, return nullptr and set aFound to false
156 template <class KeyClass
, class Interface
>
157 bool nsInterfaceHashtable
<KeyClass
, Interface
>::Put(
158 KeyType aKey
, already_AddRefed
<Interface
>&& aValue
,
159 const mozilla::fallible_t
&) {
160 typename
base_type::EntryType
* ent
= this->PutEntry(aKey
);
165 ent
->SetData(std::move(aValue
));
169 template <class KeyClass
, class Interface
>
170 bool nsInterfaceHashtable
<KeyClass
, Interface
>::Remove(KeyType aKey
,
172 typename
base_type::EntryType
* ent
= this->GetEntry(aKey
);
176 ent
->GetModifiableData()->forget(aData
);
178 this->RemoveEntry(ent
);
188 #endif // nsInterfaceHashtable_h__