VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/ds/nsBaseHashtable.h@ 4837

Last change on this file since 4837 was 1, checked in by vboxsync, 54 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.1 KB
Line 
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 nsBaseHashtable_h__
39#define nsBaseHashtable_h__
40
41#include "nsTHashtable.h"
42#include "prlock.h"
43#include "nsDebug.h"
44
45template<class KeyClass,class DataType,class UserDataType>
46class nsBaseHashtable; // forward declaration
47
48/**
49 * the private nsTHashtable::EntryType class used by nsBaseHashtable
50 * @see nsTHashtable for the specification of this class
51 * @see nsBaseHashtable for template parameters
52 */
53template<class KeyClass,class DataType>
54class nsBaseHashtableET : public KeyClass
55{
56public:
57 DataType mData;
58 friend class nsTHashtable< nsBaseHashtableET<KeyClass,DataType> >;
59
60private:
61 typedef typename KeyClass::KeyType KeyType;
62 typedef typename KeyClass::KeyTypePointer KeyTypePointer;
63
64 nsBaseHashtableET(KeyTypePointer aKey);
65 nsBaseHashtableET(nsBaseHashtableET<KeyClass,DataType>& toCopy);
66 ~nsBaseHashtableET();
67};
68
69/**
70 * templated hashtable for simple data types
71 * This class manages simple data types that do not need construction or
72 * destruction. Thread-safety is optional, via a flag in Init()
73 *
74 * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
75 * for a complete specification.
76 * @param DataType the datatype stored in the hashtable,
77 * for example, PRUint32 or nsCOMPtr. If UserDataType is not the same,
78 * DataType must implicitly cast to UserDataType
79 * @param UserDataType the user sees, for example PRUint32 or nsISupports*
80 */
81template<class KeyClass,class DataType,class UserDataType>
82class nsBaseHashtable :
83 protected nsTHashtable< nsBaseHashtableET<KeyClass,DataType> >
84{
85public:
86 typedef typename KeyClass::KeyType KeyType;
87 typedef nsBaseHashtableET<KeyClass,DataType> EntryType;
88
89 // default constructor+destructor are fine
90
91 /**
92 * Initialize the object.
93 * @param initSize the initial number of buckets in the hashtable,
94 * default 16
95 * @param threadSafe whether to provide read/write
96 * locking on all class methods
97 * @return PR_TRUE if the object was initialized properly.
98 */
99 PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE)
100 { return nsTHashtable<EntryType>::Init(initSize); }
101
102 /**
103 * Check whether the table has been initialized.
104 * This function is especially useful for static hashtables.
105 * @return PR_TRUE if the table has been initialized.
106 */
107 PRBool IsInitialized() const { return this->mTable.entrySize; }
108
109 /**
110 * Return the number of entries in the table.
111 * @return number of entries
112 */
113 PRUint32 Count() const
114 { return nsTHashtable<EntryType>::Count(); }
115
116 /**
117 * retrieve the value for a key.
118 * @param aKey the key to retreive
119 * @param pData data associated with this key will be placed at this
120 * pointer. If you only need to check if the key exists, pData
121 * may be null.
122 * @return PR_TRUE if the key exists. If key does not exist, pData is not
123 * modified.
124 */
125 PRBool Get(KeyType aKey, UserDataType* pData) const
126 {
127 EntryType* ent = GetEntry(aKey);
128
129 if (!ent)
130 return PR_FALSE;
131
132 if (pData)
133 *pData = ent->mData;
134
135 return PR_TRUE;
136 }
137
138 /**
139 * put a new value for the associated key
140 * @param aKey the key to put
141 * @param aData the new data
142 * @return always PR_TRUE, unless memory allocation failed
143 */
144 PRBool Put(KeyType aKey, UserDataType aData)
145 {
146 EntryType* ent = PutEntry(aKey);
147
148 if (!ent)
149 return PR_FALSE;
150
151 ent->mData = aData;
152
153 return PR_TRUE;
154 }
155
156 /**
157 * remove the data for the associated key
158 * @param aKey the key to remove from the hashtable
159 */
160 void Remove(KeyType aKey) { RemoveEntry(aKey); }
161
162 /**
163 * function type provided by the application for enumeration.
164 * @param aKey the key being enumerated
165 * @param aData data being enumerated
166 * @parm userArg passed unchanged from Enumerate
167 * @return either
168 * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink or
169 * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink
170 */
171 typedef PLDHashOperator
172 (*PR_CALLBACK EnumReadFunction)(KeyType aKey,
173 UserDataType aData,
174 void* userArg);
175
176 /**
177 * enumerate entries in the hashtable, without allowing changes
178 * this function read-locks the hashtable, so other threads may read keys
179 * at the same time in multi-thread environments.
180 * @param enumFunc enumeration callback
181 * @param userArg passed unchanged to the EnumReadFunction
182 */
183 PRUint32 EnumerateRead(EnumReadFunction enumFunc, void* userArg) const
184 {
185 NS_ASSERTION(this->mTable.entrySize,
186 "nsBaseHashtable was not initialized properly.");
187
188 s_EnumReadArgs enumData = { enumFunc, userArg };
189 return PL_DHashTableEnumerate(NS_CONST_CAST(PLDHashTable*, &this->mTable),
190 s_EnumReadStub,
191 &enumData);
192 }
193
194 /**
195 * function type provided by the application for enumeration.
196 * @param aKey the key being enumerated
197 * @param aData Reference to data being enumerated, may be altered. e.g. for
198 * nsInterfaceHashtable this is an nsCOMPtr reference...
199 * @parm userArg passed unchanged from Enumerate
200 * @return bitflag combination of
201 * @link PLDHashOperator::PL_DHASH_REMOVE @endlink,
202 * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink, or
203 * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink
204 */
205 typedef PLDHashOperator
206 (*PR_CALLBACK EnumFunction)(KeyType aKey,
207 DataType& aData,
208 void* userArg);
209
210 /**
211 * enumerate entries in the hashtable, allowing changes. This
212 * functions write-locks the hashtable.
213 * @param enumFunc enumeration callback
214 * @param userArg passed unchanged to the EnumFunction
215 */
216 PRUint32 Enumerate(EnumFunction enumFunc, void* userArg)
217 {
218 NS_ASSERTION(this->mTable.entrySize,
219 "nsBaseHashtable was not initialized properly.");
220
221 s_EnumArgs enumData = { enumFunc, userArg };
222 return PL_DHashTableEnumerate(&this->mTable,
223 s_EnumStub,
224 &enumData);
225 }
226
227 /**
228 * reset the hashtable, removing all entries
229 */
230 void Clear() { nsTHashtable<EntryType>::Clear(); }
231
232protected:
233 /**
234 * used internally during EnumerateRead. Allocated on the stack.
235 * @param func the enumerator passed to EnumerateRead
236 * @param userArg the userArg passed to EnumerateRead
237 */
238 struct s_EnumReadArgs
239 {
240 EnumReadFunction func;
241 void* userArg;
242 };
243
244 static PLDHashOperator s_EnumReadStub(PLDHashTable *table,
245 PLDHashEntryHdr *hdr,
246 PRUint32 number,
247 void *arg);
248
249 struct s_EnumArgs
250 {
251 EnumFunction func;
252 void* userArg;
253 };
254
255 static PLDHashOperator s_EnumStub(PLDHashTable *table,
256 PLDHashEntryHdr *hdr,
257 PRUint32 number,
258 void *arg);
259};
260
261/**
262 * This class is a thread-safe version of nsBaseHashtable.
263 */
264template<class KeyClass,class DataType,class UserDataType>
265class nsBaseHashtableMT :
266 protected nsBaseHashtable<KeyClass,DataType,UserDataType>
267{
268public:
269 typedef typename
270 nsBaseHashtable<KeyClass,DataType,UserDataType>::EntryType EntryType;
271 typedef typename
272 nsBaseHashtable<KeyClass,DataType,UserDataType>::KeyType KeyType;
273 typedef typename
274 nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumFunction EnumFunction;
275 typedef typename
276 nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumReadFunction EnumReadFunction;
277
278 nsBaseHashtableMT() : mLock(nsnull) { }
279 ~nsBaseHashtableMT();
280
281 PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE);
282 PRBool IsInitialized() const { return (PRBool) mLock; }
283 PRUint32 Count() const;
284 PRBool Get(KeyType aKey, UserDataType* pData) const;
285 PRBool Put(KeyType aKey, UserDataType aData);
286 void Remove(KeyType aKey);
287
288 PRUint32 EnumerateRead(EnumReadFunction enumFunc, void* userArg) const;
289 PRUint32 Enumerate(EnumFunction enumFunc, void* userArg);
290 void Clear();
291
292protected:
293 PRLock* mLock;
294};
295
296
297//
298// nsBaseHashtableET definitions
299//
300
301template<class KeyClass,class DataType>
302nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET(KeyTypePointer aKey) :
303 KeyClass(aKey)
304{ }
305
306template<class KeyClass,class DataType>
307nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET
308 (nsBaseHashtableET<KeyClass,DataType>& toCopy) :
309 KeyClass(toCopy),
310 mData(toCopy.mData)
311{ }
312
313template<class KeyClass,class DataType>
314nsBaseHashtableET<KeyClass,DataType>::~nsBaseHashtableET()
315{ }
316
317
318//
319// nsBaseHashtable definitions
320//
321
322template<class KeyClass,class DataType,class UserDataType>
323PLDHashOperator
324nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumReadStub
325 (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void* arg)
326{
327 EntryType* ent = NS_STATIC_CAST(EntryType*, hdr);
328 s_EnumReadArgs* eargs = (s_EnumReadArgs*) arg;
329
330 PLDHashOperator res = (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg);
331
332 NS_ASSERTION( !(res & PL_DHASH_REMOVE ),
333 "PL_DHASH_REMOVE return during const enumeration; ignoring.");
334
335 if (res & PL_DHASH_STOP)
336 return PL_DHASH_STOP;
337
338 return PL_DHASH_NEXT;
339}
340
341template<class KeyClass,class DataType,class UserDataType>
342PLDHashOperator
343nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumStub
344 (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void* arg)
345{
346 EntryType* ent = NS_STATIC_CAST(EntryType*, hdr);
347 s_EnumArgs* eargs = (s_EnumArgs*) arg;
348
349 return (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg);
350}
351
352
353//
354// nsBaseHashtableMT definitions
355//
356
357template<class KeyClass,class DataType,class UserDataType>
358nsBaseHashtableMT<KeyClass,DataType,UserDataType>::~nsBaseHashtableMT()
359{
360 if (this->mLock)
361 PR_DestroyLock(this->mLock);
362}
363
364template<class KeyClass,class DataType,class UserDataType>
365PRBool
366nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Init(PRUint32 initSize)
367{
368 if (!nsTHashtable<EntryType>::IsInitialized() && !nsTHashtable<EntryType>::Init(initSize))
369 return PR_FALSE;
370
371 this->mLock = PR_NewLock();
372 NS_WARN_IF_FALSE(this->mLock, "Error creating lock during nsBaseHashtableL::Init()");
373
374 return (this->mLock != nsnull);
375}
376
377template<class KeyClass,class DataType,class UserDataType>
378PRUint32
379nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Count() const
380{
381 PR_Lock(this->mLock);
382 PRUint32 count = nsTHashtable<EntryType>::Count();
383 PR_Unlock(this->mLock);
384
385 return count;
386}
387
388template<class KeyClass,class DataType,class UserDataType>
389PRBool
390nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Get(KeyType aKey,
391 UserDataType* pData) const
392{
393 PR_Lock(this->mLock);
394 PRBool res =
395 nsBaseHashtable<KeyClass,DataType,UserDataType>::Get(aKey, pData);
396 PR_Unlock(this->mLock);
397
398 return res;
399}
400
401template<class KeyClass,class DataType,class UserDataType>
402PRBool
403nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Put(KeyType aKey,
404 UserDataType aData)
405{
406 PR_Lock(this->mLock);
407 PRBool res =
408 nsBaseHashtable<KeyClass,DataType,UserDataType>::Put(aKey, aData);
409 PR_Unlock(this->mLock);
410
411 return res;
412}
413
414template<class KeyClass,class DataType,class UserDataType>
415void
416nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Remove(KeyType aKey)
417{
418 PR_Lock(this->mLock);
419 nsBaseHashtable<KeyClass,DataType,UserDataType>::Remove(aKey);
420 PR_Unlock(this->mLock);
421}
422
423template<class KeyClass,class DataType,class UserDataType>
424PRUint32
425nsBaseHashtableMT<KeyClass,DataType,UserDataType>::EnumerateRead
426 (EnumReadFunction fEnumCall, void* userArg) const
427{
428 PR_Lock(this->mLock);
429 PRUint32 count =
430 nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumerateRead(fEnumCall, userArg);
431 PR_Unlock(this->mLock);
432
433 return count;
434}
435
436template<class KeyClass,class DataType,class UserDataType>
437PRUint32
438nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Enumerate
439 (EnumFunction fEnumCall, void* userArg)
440{
441 PR_Lock(this->mLock);
442 PRUint32 count =
443 nsBaseHashtable<KeyClass,DataType,UserDataType>::Enumerate(fEnumCall, userArg);
444 PR_Unlock(this->mLock);
445
446 return count;
447}
448
449template<class KeyClass,class DataType,class UserDataType>
450void
451nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Clear()
452{
453 PR_Lock(this->mLock);
454 nsBaseHashtable<KeyClass,DataType,UserDataType>::Clear();
455 PR_Unlock(this->mLock);
456}
457
458#endif // nsBaseHashtable_h__
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use