|
1 /* -*- Mode: C++; tab-width: 2; 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 |
|
6 #ifndef nsInterfaceHashtable_h__ |
|
7 #define nsInterfaceHashtable_h__ |
|
8 |
|
9 #include "nsBaseHashtable.h" |
|
10 #include "nsHashKeys.h" |
|
11 #include "nsCOMPtr.h" |
|
12 |
|
13 /** |
|
14 * templated hashtable class maps keys to interface 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 Interface the interface-type being wrapped |
|
19 * @see nsDataHashtable, nsClassHashtable |
|
20 */ |
|
21 template<class KeyClass,class Interface> |
|
22 class nsInterfaceHashtable : |
|
23 public nsBaseHashtable< KeyClass, nsCOMPtr<Interface> , Interface* > |
|
24 { |
|
25 public: |
|
26 typedef typename KeyClass::KeyType KeyType; |
|
27 typedef Interface* UserDataType; |
|
28 typedef nsBaseHashtable< KeyClass, nsCOMPtr<Interface> , Interface* > |
|
29 base_type; |
|
30 |
|
31 nsInterfaceHashtable() |
|
32 { |
|
33 } |
|
34 explicit nsInterfaceHashtable(uint32_t aInitSize) |
|
35 : nsBaseHashtable<KeyClass,nsCOMPtr<Interface>,Interface*>(aInitSize) |
|
36 { |
|
37 } |
|
38 |
|
39 /** |
|
40 * @copydoc nsBaseHashtable::Get |
|
41 * @param pData This is an XPCOM getter, so pData is already_addrefed. |
|
42 * If the key doesn't exist, pData will be set to nullptr. |
|
43 */ |
|
44 bool Get(KeyType aKey, UserDataType* pData) const; |
|
45 |
|
46 /** |
|
47 * @copydoc nsBaseHashtable::Get |
|
48 */ |
|
49 already_AddRefed<Interface> Get(KeyType aKey) const; |
|
50 |
|
51 /** |
|
52 * Gets a weak reference to the hashtable entry. |
|
53 * @param aFound If not nullptr, will be set to true if the entry is found, |
|
54 * to false otherwise. |
|
55 * @return The entry, or nullptr if not found. Do not release this pointer! |
|
56 */ |
|
57 Interface* GetWeak(KeyType aKey, bool* aFound = nullptr) const; |
|
58 }; |
|
59 |
|
60 template <typename K, typename T> |
|
61 inline void |
|
62 ImplCycleCollectionUnlink(nsInterfaceHashtable<K, T>& aField) |
|
63 { |
|
64 aField.Clear(); |
|
65 } |
|
66 |
|
67 template <typename K, typename T> |
|
68 inline void |
|
69 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, |
|
70 const nsInterfaceHashtable<K, T>& aField, |
|
71 const char* aName, |
|
72 uint32_t aFlags = 0) |
|
73 { |
|
74 nsBaseHashtableCCTraversalData userData(aCallback, aName, aFlags); |
|
75 |
|
76 aField.EnumerateRead(ImplCycleCollectionTraverse_EnumFunc<typename K::KeyType,T*>, |
|
77 &userData); |
|
78 } |
|
79 |
|
80 // |
|
81 // nsInterfaceHashtable definitions |
|
82 // |
|
83 |
|
84 template<class KeyClass,class Interface> |
|
85 bool |
|
86 nsInterfaceHashtable<KeyClass,Interface>::Get |
|
87 (KeyType aKey, UserDataType* pInterface) const |
|
88 { |
|
89 typename base_type::EntryType* ent = this->GetEntry(aKey); |
|
90 |
|
91 if (ent) |
|
92 { |
|
93 if (pInterface) |
|
94 { |
|
95 *pInterface = ent->mData; |
|
96 |
|
97 NS_IF_ADDREF(*pInterface); |
|
98 } |
|
99 |
|
100 return true; |
|
101 } |
|
102 |
|
103 // if the key doesn't exist, set *pInterface to null |
|
104 // so that it is a valid XPCOM getter |
|
105 if (pInterface) |
|
106 *pInterface = nullptr; |
|
107 |
|
108 return false; |
|
109 } |
|
110 |
|
111 template<class KeyClass, class Interface> |
|
112 already_AddRefed<Interface> |
|
113 nsInterfaceHashtable<KeyClass,Interface>::Get(KeyType aKey) const |
|
114 { |
|
115 typename base_type::EntryType* ent = this->GetEntry(aKey); |
|
116 if (!ent) |
|
117 return nullptr; |
|
118 |
|
119 nsCOMPtr<Interface> copy = ent->mData; |
|
120 return copy.forget(); |
|
121 } |
|
122 |
|
123 template<class KeyClass,class Interface> |
|
124 Interface* |
|
125 nsInterfaceHashtable<KeyClass,Interface>::GetWeak |
|
126 (KeyType aKey, bool* aFound) const |
|
127 { |
|
128 typename base_type::EntryType* ent = this->GetEntry(aKey); |
|
129 |
|
130 if (ent) |
|
131 { |
|
132 if (aFound) |
|
133 *aFound = true; |
|
134 |
|
135 return ent->mData; |
|
136 } |
|
137 |
|
138 // Key does not exist, return nullptr and set aFound to false |
|
139 if (aFound) |
|
140 *aFound = false; |
|
141 return nullptr; |
|
142 } |
|
143 |
|
144 #endif // nsInterfaceHashtable_h__ |