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
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/
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
15 * The Original Code is C++ hashtable templates.
17 * The Initial Developer of the Original Code is
19 * Portions created by the Initial Developer are Copyright (C) 2002
20 * the Initial Developer. All Rights Reserved.
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.
36 * ***** END LICENSE BLOCK ***** */
38 #ifndef nsBaseHashtable_h__
39 #define nsBaseHashtable_h__
41 #include "nsTHashtable.h"
45 template<class KeyClass
,class DataType
,class UserDataType
>
46 class nsBaseHashtable
; // forward declaration
49 * the private nsTHashtable::EntryType class used by nsBaseHashtable
50 * @see nsTHashtable for the specification of this class
51 * @see nsBaseHashtable for template parameters
53 template<class KeyClass
,class DataType
>
54 class nsBaseHashtableET
: public KeyClass
58 friend class nsTHashtable
< nsBaseHashtableET
<KeyClass
,DataType
> >;
61 typedef typename
KeyClass::KeyType KeyType
;
62 typedef typename
KeyClass::KeyTypePointer KeyTypePointer
;
64 nsBaseHashtableET(KeyTypePointer aKey
);
65 nsBaseHashtableET(nsBaseHashtableET
<KeyClass
,DataType
>& toCopy
);
70 * templated hashtable for simple data types
71 * This class manages simple data types that do not need construction or
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*
81 template<class KeyClass
,class DataType
,class UserDataType
>
82 class nsBaseHashtable
:
83 protected nsTHashtable
< nsBaseHashtableET
<KeyClass
,DataType
> >
86 typedef typename
KeyClass::KeyType KeyType
;
87 typedef nsBaseHashtableET
<KeyClass
,DataType
> EntryType
;
89 // default constructor+destructor are fine
92 * Initialize the object.
93 * @param initSize the initial number of buckets in the hashtable,
95 * locking on all class methods
96 * @return PR_TRUE if the object was initialized properly.
98 PRBool
Init(PRUint32 initSize
= PL_DHASH_MIN_SIZE
)
99 { return nsTHashtable
<EntryType
>::Init(initSize
); }
102 * Check whether the table has been initialized.
103 * This function is especially useful for static hashtables.
104 * @return PR_TRUE if the table has been initialized.
106 PRBool
IsInitialized() const { return !!this->mTable
.entrySize
; }
109 * Return the number of entries in the table.
110 * @return number of entries
112 PRUint32
Count() const
113 { return nsTHashtable
<EntryType
>::Count(); }
116 * retrieve the value for a key.
117 * @param aKey the key to retreive
118 * @param pData data associated with this key will be placed at this
119 * pointer. If you only need to check if the key exists, pData
121 * @return PR_TRUE if the key exists. If key does not exist, pData is not
124 PRBool
Get(KeyType aKey
, UserDataType
* pData NS_OUTPARAM
) const
126 EntryType
* ent
= this->GetEntry(aKey
);
138 * For pointer types, get the value, returning NULL if the entry is not
139 * present in the table.
141 * @param aKey the key to retrieve
142 * @return The found value, or NULL if no entry was found with the given key.
143 * @note If NULL values are stored in the table, it is not possible to
144 * distinguish between a NULL value and a missing entry.
146 UserDataType
Get(KeyType aKey
) const
148 EntryType
* ent
= this->GetEntry(aKey
);
156 * put a new value for the associated key
157 * @param aKey the key to put
158 * @param aData the new data
159 * @return always PR_TRUE, unless memory allocation failed
161 PRBool
Put(KeyType aKey
, UserDataType aData
)
163 EntryType
* ent
= this->PutEntry(aKey
);
174 * remove the data for the associated key
175 * @param aKey the key to remove from the hashtable
177 void Remove(KeyType aKey
) { this->RemoveEntry(aKey
); }
180 * function type provided by the application for enumeration.
181 * @param aKey the key being enumerated
182 * @param aData data being enumerated
183 * @parm userArg passed unchanged from Enumerate
185 * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink or
186 * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink
188 typedef PLDHashOperator
189 (* EnumReadFunction
)(KeyType aKey
,
194 * enumerate entries in the hashtable, without allowing changes
195 * @param enumFunc enumeration callback
196 * @param userArg passed unchanged to the EnumReadFunction
198 PRUint32
EnumerateRead(EnumReadFunction enumFunc
, void* userArg
) const
200 NS_ASSERTION(this->mTable
.entrySize
,
201 "nsBaseHashtable was not initialized properly.");
203 s_EnumReadArgs enumData
= { enumFunc
, userArg
};
204 return PL_DHashTableEnumerate(const_cast<PLDHashTable
*>(&this->mTable
),
210 * function type provided by the application for enumeration.
211 * @param aKey the key being enumerated
212 * @param aData Reference to data being enumerated, may be altered. e.g. for
213 * nsInterfaceHashtable this is an nsCOMPtr reference...
214 * @parm userArg passed unchanged from Enumerate
215 * @return bitflag combination of
216 * @link PLDHashOperator::PL_DHASH_REMOVE @endlink,
217 * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink, or
218 * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink
220 typedef PLDHashOperator
221 (* EnumFunction
)(KeyType aKey
,
226 * enumerate entries in the hashtable, allowing changes. This
227 * functions write-locks the hashtable.
228 * @param enumFunc enumeration callback
229 * @param userArg passed unchanged to the EnumFunction
231 PRUint32
Enumerate(EnumFunction enumFunc
, void* userArg
)
233 NS_ASSERTION(this->mTable
.entrySize
,
234 "nsBaseHashtable was not initialized properly.");
236 s_EnumArgs enumData
= { enumFunc
, userArg
};
237 return PL_DHashTableEnumerate(&this->mTable
,
243 * reset the hashtable, removing all entries
245 void Clear() { nsTHashtable
<EntryType
>::Clear(); }
249 * used internally during EnumerateRead. Allocated on the stack.
250 * @param func the enumerator passed to EnumerateRead
251 * @param userArg the userArg passed to EnumerateRead
253 struct s_EnumReadArgs
255 EnumReadFunction func
;
259 static PLDHashOperator
s_EnumReadStub(PLDHashTable
*table
,
260 PLDHashEntryHdr
*hdr
,
270 static PLDHashOperator
s_EnumStub(PLDHashTable
*table
,
271 PLDHashEntryHdr
*hdr
,
277 * This class is a thread-safe version of nsBaseHashtable.
279 template<class KeyClass
,class DataType
,class UserDataType
>
280 class nsBaseHashtableMT
:
281 protected nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>
285 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::EntryType EntryType
;
287 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::KeyType KeyType
;
289 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::EnumFunction EnumFunction
;
291 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::EnumReadFunction EnumReadFunction
;
293 nsBaseHashtableMT() : mLock(nsnull
) { }
294 ~nsBaseHashtableMT();
296 PRBool
Init(PRUint32 initSize
= PL_DHASH_MIN_SIZE
);
297 PRBool
IsInitialized() const { return mLock
!= nsnull
; }
298 PRUint32
Count() const;
299 PRBool
Get(KeyType aKey
, UserDataType
* pData
) const;
300 PRBool
Put(KeyType aKey
, UserDataType aData
);
301 void Remove(KeyType aKey
);
303 PRUint32
EnumerateRead(EnumReadFunction enumFunc
, void* userArg
) const;
304 PRUint32
Enumerate(EnumFunction enumFunc
, void* userArg
);
313 // nsBaseHashtableET definitions
316 template<class KeyClass
,class DataType
>
317 nsBaseHashtableET
<KeyClass
,DataType
>::nsBaseHashtableET(KeyTypePointer aKey
) :
321 template<class KeyClass
,class DataType
>
322 nsBaseHashtableET
<KeyClass
,DataType
>::nsBaseHashtableET
323 (nsBaseHashtableET
<KeyClass
,DataType
>& toCopy
) :
328 template<class KeyClass
,class DataType
>
329 nsBaseHashtableET
<KeyClass
,DataType
>::~nsBaseHashtableET()
334 // nsBaseHashtable definitions
337 template<class KeyClass
,class DataType
,class UserDataType
>
339 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::s_EnumReadStub
340 (PLDHashTable
*table
, PLDHashEntryHdr
*hdr
, PRUint32 number
, void* arg
)
342 EntryType
* ent
= static_cast<EntryType
*>(hdr
);
343 s_EnumReadArgs
* eargs
= (s_EnumReadArgs
*) arg
;
345 PLDHashOperator res
= (eargs
->func
)(ent
->GetKey(), ent
->mData
, eargs
->userArg
);
347 NS_ASSERTION( !(res
& PL_DHASH_REMOVE
),
348 "PL_DHASH_REMOVE return during const enumeration; ignoring.");
350 if (res
& PL_DHASH_STOP
)
351 return PL_DHASH_STOP
;
353 return PL_DHASH_NEXT
;
356 template<class KeyClass
,class DataType
,class UserDataType
>
358 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::s_EnumStub
359 (PLDHashTable
*table
, PLDHashEntryHdr
*hdr
, PRUint32 number
, void* arg
)
361 EntryType
* ent
= static_cast<EntryType
*>(hdr
);
362 s_EnumArgs
* eargs
= (s_EnumArgs
*) arg
;
364 return (eargs
->func
)(ent
->GetKey(), ent
->mData
, eargs
->userArg
);
369 // nsBaseHashtableMT definitions
372 template<class KeyClass
,class DataType
,class UserDataType
>
373 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::~nsBaseHashtableMT()
376 PR_DestroyLock(this->mLock
);
379 template<class KeyClass
,class DataType
,class UserDataType
>
381 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::Init(PRUint32 initSize
)
383 if (!nsTHashtable
<EntryType
>::IsInitialized() && !nsTHashtable
<EntryType
>::Init(initSize
))
386 this->mLock
= PR_NewLock();
387 NS_ASSERTION(this->mLock
, "Error creating lock during nsBaseHashtableL::Init()");
389 return (this->mLock
!= nsnull
);
392 template<class KeyClass
,class DataType
,class UserDataType
>
394 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::Count() const
396 PR_Lock(this->mLock
);
397 PRUint32 count
= nsTHashtable
<EntryType
>::Count();
398 PR_Unlock(this->mLock
);
403 template<class KeyClass
,class DataType
,class UserDataType
>
405 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::Get(KeyType aKey
,
406 UserDataType
* pData
) const
408 PR_Lock(this->mLock
);
410 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::Get(aKey
, pData
);
411 PR_Unlock(this->mLock
);
416 template<class KeyClass
,class DataType
,class UserDataType
>
418 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::Put(KeyType aKey
,
421 PR_Lock(this->mLock
);
423 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::Put(aKey
, aData
);
424 PR_Unlock(this->mLock
);
429 template<class KeyClass
,class DataType
,class UserDataType
>
431 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::Remove(KeyType aKey
)
433 PR_Lock(this->mLock
);
434 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::Remove(aKey
);
435 PR_Unlock(this->mLock
);
438 template<class KeyClass
,class DataType
,class UserDataType
>
440 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::EnumerateRead
441 (EnumReadFunction fEnumCall
, void* userArg
) const
443 PR_Lock(this->mLock
);
445 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::EnumerateRead(fEnumCall
, userArg
);
446 PR_Unlock(this->mLock
);
451 template<class KeyClass
,class DataType
,class UserDataType
>
453 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::Enumerate
454 (EnumFunction fEnumCall
, void* userArg
)
456 PR_Lock(this->mLock
);
458 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::Enumerate(fEnumCall
, userArg
);
459 PR_Unlock(this->mLock
);
464 template<class KeyClass
,class DataType
,class UserDataType
>
466 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::Clear()
468 PR_Lock(this->mLock
);
469 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::Clear();
470 PR_Unlock(this->mLock
);
473 #endif // nsBaseHashtable_h__