Line data Source code
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/. */
6 :
7 : #ifndef nsRefPtrHashtable_h__
8 : #define nsRefPtrHashtable_h__
9 :
10 : #include "nsBaseHashtable.h"
11 : #include "nsHashKeys.h"
12 : #include "nsAutoPtr.h"
13 :
14 : /**
15 : * templated hashtable class maps keys to reference 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 PtrType the reference-type being wrapped
20 : * @see nsDataHashtable, nsClassHashtable
21 : */
22 : template<class KeyClass, class PtrType>
23 1704 : class nsRefPtrHashtable
24 : : public nsBaseHashtable<KeyClass, RefPtr<PtrType>, PtrType*>
25 : {
26 : public:
27 : typedef typename KeyClass::KeyType KeyType;
28 : typedef PtrType* UserDataType;
29 : typedef nsBaseHashtable<KeyClass, RefPtr<PtrType>, PtrType*> base_type;
30 :
31 2154 : nsRefPtrHashtable() {}
32 13 : explicit nsRefPtrHashtable(uint32_t aInitLength)
33 13 : : nsBaseHashtable<KeyClass, RefPtr<PtrType>, PtrType*>(aInitLength)
34 : {
35 13 : }
36 :
37 : /**
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.
41 : */
42 : bool Get(KeyType aKey, UserDataType* aData) const;
43 :
44 : /**
45 : * Gets a weak reference to the hashtable entry.
46 : * @param aFound If not nullptr, will be set to true if the entry is found,
47 : * to false otherwise.
48 : * @return The entry, or nullptr if not found. Do not release this pointer!
49 : */
50 : PtrType* GetWeak(KeyType aKey, bool* aFound = nullptr) const;
51 :
52 : // Overload Put, rather than overriding it.
53 : using base_type::Put;
54 :
55 : void Put(KeyType aKey, already_AddRefed<PtrType> aData);
56 :
57 : MOZ_MUST_USE bool Put(KeyType aKey, already_AddRefed<PtrType> aData,
58 : const mozilla::fallible_t&);
59 :
60 : /**
61 : * Remove the entry associated with aKey (if any), optionally _moving_ its
62 : * current value into *aData, thereby avoiding calls to AddRef and Release.
63 : * Return true if found.
64 : * @param aKey the key to remove from the hashtable
65 : * @param aData where to move the value (if non-null). If an entry is not
66 : * found it will be set to nullptr.
67 : * @return true if an entry for aKey was found (and removed)
68 : */
69 : inline bool Remove(KeyType aKey, UserDataType* aData = nullptr);
70 : };
71 :
72 : template<typename K, typename T>
73 : inline void
74 0 : ImplCycleCollectionUnlink(nsRefPtrHashtable<K, T>& aField)
75 : {
76 0 : aField.Clear();
77 0 : }
78 :
79 : template<typename K, typename T>
80 : inline void
81 17 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
82 : nsRefPtrHashtable<K, T>& aField,
83 : const char* aName,
84 : uint32_t aFlags = 0)
85 : {
86 17 : for (auto iter = aField.ConstIter(); !iter.Done(); iter.Next()) {
87 0 : CycleCollectionNoteChild(aCallback, iter.UserData(), aName, aFlags);
88 : }
89 17 : }
90 :
91 : //
92 : // nsRefPtrHashtable definitions
93 : //
94 :
95 : template<class KeyClass, class PtrType>
96 : bool
97 4395 : nsRefPtrHashtable<KeyClass, PtrType>::Get(KeyType aKey,
98 : UserDataType* aRefPtr) const
99 : {
100 4395 : typename base_type::EntryType* ent = this->GetEntry(aKey);
101 :
102 4395 : if (ent) {
103 2016 : if (aRefPtr) {
104 2016 : *aRefPtr = ent->mData;
105 :
106 2016 : NS_IF_ADDREF(*aRefPtr);
107 : }
108 :
109 2016 : return true;
110 : }
111 :
112 : // if the key doesn't exist, set *aRefPtr to null
113 : // so that it is a valid XPCOM getter
114 2379 : if (aRefPtr) {
115 2379 : *aRefPtr = nullptr;
116 : }
117 :
118 2379 : return false;
119 : }
120 :
121 : template<class KeyClass, class PtrType>
122 : PtrType*
123 2579 : nsRefPtrHashtable<KeyClass, PtrType>::GetWeak(KeyType aKey, bool* aFound) const
124 : {
125 2579 : typename base_type::EntryType* ent = this->GetEntry(aKey);
126 :
127 2579 : if (ent) {
128 1609 : if (aFound) {
129 141 : *aFound = true;
130 : }
131 :
132 1609 : return ent->mData;
133 : }
134 :
135 : // Key does not exist, return nullptr and set aFound to false
136 970 : if (aFound) {
137 0 : *aFound = false;
138 : }
139 :
140 970 : return nullptr;
141 : }
142 :
143 : template<class KeyClass, class PtrType>
144 : void
145 0 : nsRefPtrHashtable<KeyClass, PtrType>::Put(KeyType aKey,
146 : already_AddRefed<PtrType> aData)
147 : {
148 0 : if (!Put(aKey, mozilla::Move(aData), mozilla::fallible)) {
149 0 : NS_ABORT_OOM(this->mTable.EntrySize() * this->mTable.EntryCount());
150 : }
151 0 : }
152 :
153 : template<class KeyClass, class PtrType>
154 : bool
155 0 : nsRefPtrHashtable<KeyClass, PtrType>::Put(KeyType aKey,
156 : already_AddRefed<PtrType> aData,
157 : const mozilla::fallible_t&)
158 : {
159 0 : typename base_type::EntryType* ent = this->PutEntry(aKey, mozilla::fallible);
160 :
161 0 : if (!ent) {
162 0 : return false;
163 : }
164 :
165 0 : ent->mData = aData;
166 :
167 0 : return true;
168 : }
169 :
170 : template<class KeyClass, class PtrType>
171 : bool
172 56 : nsRefPtrHashtable<KeyClass, PtrType>::Remove(KeyType aKey,
173 : UserDataType* aRefPtr)
174 : {
175 56 : typename base_type::EntryType* ent = this->GetEntry(aKey);
176 :
177 56 : if (ent) {
178 49 : if (aRefPtr) {
179 26 : ent->mData.forget(aRefPtr);
180 : }
181 49 : this->RemoveEntry(ent);
182 49 : return true;
183 : }
184 :
185 7 : if (aRefPtr) {
186 7 : *aRefPtr = nullptr;
187 : }
188 7 : return false;
189 : }
190 :
191 : #endif // nsRefPtrHashtable_h__
|