VirtualBox

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

Last change on this file since 101975 was 101975, checked in by vboxsync, 14 months ago

libs/xpcom/xpcom: Convert some code from using PRLock to IPRT's RTSEMFASTMUTEX locks, bugref:10545

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette