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 nsInterfaceHashtable_h__
8 : #define nsInterfaceHashtable_h__
9 :
10 : #include "nsBaseHashtable.h"
11 : #include "nsHashKeys.h"
12 : #include "nsCOMPtr.h"
13 :
14 : /**
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
21 : */
22 : template<class KeyClass, class Interface>
23 1164 : class nsInterfaceHashtable
24 : : public nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*>
25 : {
26 : public:
27 : typedef typename KeyClass::KeyType KeyType;
28 : typedef Interface* UserDataType;
29 : typedef nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*> base_type;
30 :
31 1427 : nsInterfaceHashtable() {}
32 17 : explicit nsInterfaceHashtable(uint32_t aInitLength)
33 17 : : nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*>(aInitLength)
34 : {
35 17 : }
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 : * @copydoc nsBaseHashtable::Get
46 : */
47 : already_AddRefed<Interface> Get(KeyType aKey) const;
48 :
49 : /**
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,
52 : * to false otherwise.
53 : * @return The entry, or nullptr if not found. Do not release this pointer!
54 : */
55 : Interface* GetWeak(KeyType aKey, bool* aFound = nullptr) const;
56 :
57 : /**
58 : * Remove the entry associated with aKey (if any), optionally _moving_ its
59 : * current value into *aData, thereby avoiding calls to AddRef and Release.
60 : * Return true if found.
61 : * @param aKey the key to remove from the hashtable
62 : * @param aData where to move the value (if non-null). If an entry is not
63 : * found it will be set to nullptr.
64 : * @return true if an entry for aKey was found (and removed)
65 : */
66 : inline bool Remove(KeyType aKey, Interface** aData = nullptr);
67 : };
68 :
69 : template<typename K, typename T>
70 : inline void
71 0 : ImplCycleCollectionUnlink(nsInterfaceHashtable<K, T>& aField)
72 : {
73 0 : aField.Clear();
74 0 : }
75 :
76 : template<typename K, typename T>
77 : inline void
78 1 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
79 : const nsInterfaceHashtable<K, T>& aField,
80 : const char* aName,
81 : uint32_t aFlags = 0)
82 : {
83 2 : for (auto iter = aField.ConstIter(); !iter.Done(); iter.Next()) {
84 1 : CycleCollectionNoteChild(aCallback, iter.UserData(), aName, aFlags);
85 : }
86 1 : }
87 :
88 : //
89 : // nsInterfaceHashtable definitions
90 : //
91 :
92 : template<class KeyClass, class Interface>
93 : bool
94 574 : nsInterfaceHashtable<KeyClass, Interface>::Get(KeyType aKey,
95 : UserDataType* aInterface) const
96 : {
97 574 : typename base_type::EntryType* ent = this->GetEntry(aKey);
98 :
99 574 : if (ent) {
100 341 : if (aInterface) {
101 341 : *aInterface = ent->mData;
102 :
103 341 : NS_IF_ADDREF(*aInterface);
104 : }
105 :
106 341 : return true;
107 : }
108 :
109 : // if the key doesn't exist, set *aInterface to null
110 : // so that it is a valid XPCOM getter
111 233 : if (aInterface) {
112 233 : *aInterface = nullptr;
113 : }
114 :
115 233 : return false;
116 : }
117 :
118 : template<class KeyClass, class Interface>
119 : already_AddRefed<Interface>
120 982 : nsInterfaceHashtable<KeyClass, Interface>::Get(KeyType aKey) const
121 : {
122 982 : typename base_type::EntryType* ent = this->GetEntry(aKey);
123 982 : if (!ent) {
124 64 : return nullptr;
125 : }
126 :
127 1836 : nsCOMPtr<Interface> copy = ent->mData;
128 918 : return copy.forget();
129 : }
130 :
131 : template<class KeyClass, class Interface>
132 : Interface*
133 657 : nsInterfaceHashtable<KeyClass, Interface>::GetWeak(KeyType aKey,
134 : bool* aFound) const
135 : {
136 657 : typename base_type::EntryType* ent = this->GetEntry(aKey);
137 :
138 657 : if (ent) {
139 242 : if (aFound) {
140 0 : *aFound = true;
141 : }
142 :
143 242 : return ent->mData;
144 : }
145 :
146 : // Key does not exist, return nullptr and set aFound to false
147 415 : if (aFound) {
148 0 : *aFound = false;
149 : }
150 415 : return nullptr;
151 : }
152 :
153 : template<class KeyClass, class Interface>
154 : bool
155 76 : nsInterfaceHashtable<KeyClass, Interface>::Remove(KeyType aKey,
156 : Interface** aData)
157 : {
158 76 : typename base_type::EntryType* ent = this->GetEntry(aKey);
159 :
160 76 : if (ent) {
161 65 : if (aData) {
162 0 : ent->mData.forget(aData);
163 : }
164 65 : this->RemoveEntry(ent);
165 65 : return true;
166 : }
167 :
168 11 : if (aData) {
169 0 : *aData = nullptr;
170 : }
171 11 : return false;
172 : }
173 :
174 : #endif // nsInterfaceHashtable_h__
|