1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is C++ hashtable templates.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Benjamin Smedberg.
19 : * Portions created by the Initial Developer are Copyright (C) 2002
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #ifndef nsInterfaceHashtable_h__
39 : #define nsInterfaceHashtable_h__
40 :
41 : #include "nsBaseHashtable.h"
42 : #include "nsHashKeys.h"
43 : #include "nsCOMPtr.h"
44 :
45 : /**
46 : * templated hashtable class maps keys to interface pointers.
47 : * See nsBaseHashtable for complete declaration.
48 : * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
49 : * for a complete specification.
50 : * @param Interface the interface-type being wrapped
51 : * @see nsDataHashtable, nsClassHashtable
52 : */
53 : template<class KeyClass,class Interface>
54 : class nsInterfaceHashtable :
55 : public nsBaseHashtable< KeyClass, nsCOMPtr<Interface> , Interface* >
56 8 : {
57 : public:
58 : typedef typename KeyClass::KeyType KeyType;
59 : typedef Interface* UserDataType;
60 : typedef nsBaseHashtable< KeyClass, nsCOMPtr<Interface> , Interface* >
61 : base_type;
62 :
63 : /**
64 : * @copydoc nsBaseHashtable::Get
65 : * @param pData This is an XPCOM getter, so pData is already_addrefed.
66 : * If the key doesn't exist, pData will be set to nsnull.
67 : */
68 : bool Get(KeyType aKey, UserDataType* pData NS_OUTPARAM) const;
69 :
70 : /**
71 : * @copydoc nsBaseHashtable::Get
72 : */
73 : already_AddRefed<Interface> Get(KeyType aKey) const;
74 :
75 : /**
76 : * Gets a weak reference to the hashtable entry.
77 : * @param aFound If not nsnull, will be set to true if the entry is found,
78 : * to false otherwise.
79 : * @return The entry, or nsnull if not found. Do not release this pointer!
80 : */
81 : Interface* GetWeak(KeyType aKey, bool* aFound = nsnull) const;
82 : };
83 :
84 : /**
85 : * Thread-safe version of nsInterfaceHashtable
86 : * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
87 : * for a complete specification.
88 : * @param Interface the interface-type being wrapped
89 : */
90 : template<class KeyClass,class Interface>
91 : class nsInterfaceHashtableMT :
92 : public nsBaseHashtableMT< KeyClass, nsCOMPtr<Interface> , Interface* >
93 : {
94 : public:
95 : typedef typename KeyClass::KeyType KeyType;
96 : typedef Interface* UserDataType;
97 : typedef nsBaseHashtableMT< KeyClass, nsCOMPtr<Interface> , Interface* >
98 : base_type;
99 :
100 : /**
101 : * @copydoc nsBaseHashtable::Get
102 : * @param pData This is an XPCOM getter, so pData is already_addrefed.
103 : * If the key doesn't exist, pData will be set to nsnull.
104 : */
105 : bool Get(KeyType aKey, UserDataType* pData NS_OUTPARAM) const;
106 :
107 : // GetWeak does not make sense on a multi-threaded hashtable, where another
108 : // thread may remove the entry (and hence release it) as soon as GetWeak
109 : // returns
110 : };
111 :
112 :
113 : //
114 : // nsInterfaceHashtable definitions
115 : //
116 :
117 : template<class KeyClass,class Interface>
118 : bool
119 : nsInterfaceHashtable<KeyClass,Interface>::Get
120 : (KeyType aKey, UserDataType* pInterface) const
121 : {
122 : typename base_type::EntryType* ent = this->GetEntry(aKey);
123 :
124 : if (ent)
125 : {
126 : if (pInterface)
127 : {
128 : *pInterface = ent->mData;
129 :
130 : NS_IF_ADDREF(*pInterface);
131 : }
132 :
133 : return true;
134 : }
135 :
136 : // if the key doesn't exist, set *pInterface to null
137 : // so that it is a valid XPCOM getter
138 : if (pInterface)
139 : *pInterface = nsnull;
140 :
141 : return false;
142 : }
143 :
144 : template<class KeyClass, class Interface>
145 : already_AddRefed<Interface>
146 : nsInterfaceHashtable<KeyClass,Interface>::Get(KeyType aKey) const
147 : {
148 : typename base_type::EntryType* ent = this->GetEntry(aKey);
149 : if (!ent)
150 : return NULL;
151 :
152 : nsCOMPtr<Interface> copy = ent->mData;
153 : return copy.forget();
154 : }
155 :
156 : template<class KeyClass,class Interface>
157 : Interface*
158 : nsInterfaceHashtable<KeyClass,Interface>::GetWeak
159 : (KeyType aKey, bool* aFound) const
160 : {
161 : typename base_type::EntryType* ent = this->GetEntry(aKey);
162 :
163 : if (ent)
164 : {
165 : if (aFound)
166 : *aFound = true;
167 :
168 : return ent->mData;
169 : }
170 :
171 : // Key does not exist, return nsnull and set aFound to false
172 : if (aFound)
173 : *aFound = false;
174 : return nsnull;
175 : }
176 :
177 : //
178 : // nsInterfaceHashtableMT definitions
179 : //
180 :
181 : template<class KeyClass,class Interface>
182 : bool
183 : nsInterfaceHashtableMT<KeyClass,Interface>::Get
184 : (KeyType aKey, UserDataType* pInterface) const
185 : {
186 : PR_Lock(this->mLock);
187 :
188 : typename base_type::EntryType* ent = this->GetEntry(aKey);
189 :
190 : if (ent)
191 : {
192 : if (pInterface)
193 : {
194 : *pInterface = ent->mData;
195 :
196 : NS_IF_ADDREF(*pInterface);
197 : }
198 :
199 : PR_Unlock(this->mLock);
200 :
201 : return true;
202 : }
203 :
204 : // if the key doesn't exist, set *pInterface to null
205 : // so that it is a valid XPCOM getter
206 : if (pInterface)
207 : *pInterface = nsnull;
208 :
209 : PR_Unlock(this->mLock);
210 :
211 : return false;
212 : }
213 :
214 : #endif // nsInterfaceHashtable_h__
|