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
) const
126 EntryType
* ent
= GetEntry(aKey
);
138 * put a new value for the associated key
139 * @param aKey the key to put
140 * @param aData the new data
141 * @return always PR_TRUE, unless memory allocation failed
143 PRBool
Put(KeyType aKey
, UserDataType aData
)
145 EntryType
* ent
= PutEntry(aKey
);
156 * remove the data for the associated key
157 * @param aKey the key to remove from the hashtable
159 void Remove(KeyType aKey
) { RemoveEntry(aKey
); }
162 * function type provided by the application for enumeration.
163 * @param aKey the key being enumerated
164 * @param aData data being enumerated
165 * @parm userArg passed unchanged from Enumerate
167 * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink or
168 * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink
170 typedef PLDHashOperator
171 (*PR_CALLBACK EnumReadFunction
)(KeyType aKey
,
176 * enumerate entries in the hashtable, without allowing changes
177 * @param enumFunc enumeration callback
178 * @param userArg passed unchanged to the EnumReadFunction
180 PRUint32
EnumerateRead(EnumReadFunction enumFunc
, void* userArg
) const
182 NS_ASSERTION(this->mTable
.entrySize
,
183 "nsBaseHashtable was not initialized properly.");
185 s_EnumReadArgs enumData
= { enumFunc
, userArg
};
186 return PL_DHashTableEnumerate(const_cast<PLDHashTable
*>(&this->mTable
),
192 * function type provided by the application for enumeration.
193 * @param aKey the key being enumerated
194 * @param aData Reference to data being enumerated, may be altered. e.g. for
195 * nsInterfaceHashtable this is an nsCOMPtr reference...
196 * @parm userArg passed unchanged from Enumerate
197 * @return bitflag combination of
198 * @link PLDHashOperator::PL_DHASH_REMOVE @endlink,
199 * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink, or
200 * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink
202 typedef PLDHashOperator
203 (*PR_CALLBACK EnumFunction
)(KeyType aKey
,
208 * enumerate entries in the hashtable, allowing changes. This
209 * functions write-locks the hashtable.
210 * @param enumFunc enumeration callback
211 * @param userArg passed unchanged to the EnumFunction
213 PRUint32
Enumerate(EnumFunction enumFunc
, void* userArg
)
215 NS_ASSERTION(this->mTable
.entrySize
,
216 "nsBaseHashtable was not initialized properly.");
218 s_EnumArgs enumData
= { enumFunc
, userArg
};
219 return PL_DHashTableEnumerate(&this->mTable
,
225 * reset the hashtable, removing all entries
227 void Clear() { nsTHashtable
<EntryType
>::Clear(); }
231 * used internally during EnumerateRead. Allocated on the stack.
232 * @param func the enumerator passed to EnumerateRead
233 * @param userArg the userArg passed to EnumerateRead
235 struct s_EnumReadArgs
237 EnumReadFunction func
;
241 static PLDHashOperator
s_EnumReadStub(PLDHashTable
*table
,
242 PLDHashEntryHdr
*hdr
,
252 static PLDHashOperator
s_EnumStub(PLDHashTable
*table
,
253 PLDHashEntryHdr
*hdr
,
259 * This class is a thread-safe version of nsBaseHashtable.
261 template<class KeyClass
,class DataType
,class UserDataType
>
262 class nsBaseHashtableMT
:
263 protected nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>
267 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::EntryType EntryType
;
269 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::KeyType KeyType
;
271 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::EnumFunction EnumFunction
;
273 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::EnumReadFunction EnumReadFunction
;
275 nsBaseHashtableMT() : mLock(nsnull
) { }
276 ~nsBaseHashtableMT();
278 PRBool
Init(PRUint32 initSize
= PL_DHASH_MIN_SIZE
);
279 PRBool
IsInitialized() const { return mLock
!= nsnull
; }
280 PRUint32
Count() const;
281 PRBool
Get(KeyType aKey
, UserDataType
* pData
) const;
282 PRBool
Put(KeyType aKey
, UserDataType aData
);
283 void Remove(KeyType aKey
);
285 PRUint32
EnumerateRead(EnumReadFunction enumFunc
, void* userArg
) const;
286 PRUint32
Enumerate(EnumFunction enumFunc
, void* userArg
);
295 // nsBaseHashtableET definitions
298 template<class KeyClass
,class DataType
>
299 nsBaseHashtableET
<KeyClass
,DataType
>::nsBaseHashtableET(KeyTypePointer aKey
) :
303 template<class KeyClass
,class DataType
>
304 nsBaseHashtableET
<KeyClass
,DataType
>::nsBaseHashtableET
305 (nsBaseHashtableET
<KeyClass
,DataType
>& toCopy
) :
310 template<class KeyClass
,class DataType
>
311 nsBaseHashtableET
<KeyClass
,DataType
>::~nsBaseHashtableET()
316 // nsBaseHashtable definitions
319 template<class KeyClass
,class DataType
,class UserDataType
>
321 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::s_EnumReadStub
322 (PLDHashTable
*table
, PLDHashEntryHdr
*hdr
, PRUint32 number
, void* arg
)
324 EntryType
* ent
= static_cast<EntryType
*>(hdr
);
325 s_EnumReadArgs
* eargs
= (s_EnumReadArgs
*) arg
;
327 PLDHashOperator res
= (eargs
->func
)(ent
->GetKey(), ent
->mData
, eargs
->userArg
);
329 NS_ASSERTION( !(res
& PL_DHASH_REMOVE
),
330 "PL_DHASH_REMOVE return during const enumeration; ignoring.");
332 if (res
& PL_DHASH_STOP
)
333 return PL_DHASH_STOP
;
335 return PL_DHASH_NEXT
;
338 template<class KeyClass
,class DataType
,class UserDataType
>
340 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::s_EnumStub
341 (PLDHashTable
*table
, PLDHashEntryHdr
*hdr
, PRUint32 number
, void* arg
)
343 EntryType
* ent
= static_cast<EntryType
*>(hdr
);
344 s_EnumArgs
* eargs
= (s_EnumArgs
*) arg
;
346 return (eargs
->func
)(ent
->GetKey(), ent
->mData
, eargs
->userArg
);
351 // nsBaseHashtableMT definitions
354 template<class KeyClass
,class DataType
,class UserDataType
>
355 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::~nsBaseHashtableMT()
358 PR_DestroyLock(this->mLock
);
361 template<class KeyClass
,class DataType
,class UserDataType
>
363 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::Init(PRUint32 initSize
)
365 if (!nsTHashtable
<EntryType
>::IsInitialized() && !nsTHashtable
<EntryType
>::Init(initSize
))
368 this->mLock
= PR_NewLock();
369 NS_ASSERTION(this->mLock
, "Error creating lock during nsBaseHashtableL::Init()");
371 return (this->mLock
!= nsnull
);
374 template<class KeyClass
,class DataType
,class UserDataType
>
376 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::Count() const
378 PR_Lock(this->mLock
);
379 PRUint32 count
= nsTHashtable
<EntryType
>::Count();
380 PR_Unlock(this->mLock
);
385 template<class KeyClass
,class DataType
,class UserDataType
>
387 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::Get(KeyType aKey
,
388 UserDataType
* pData
) const
390 PR_Lock(this->mLock
);
392 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::Get(aKey
, pData
);
393 PR_Unlock(this->mLock
);
398 template<class KeyClass
,class DataType
,class UserDataType
>
400 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::Put(KeyType aKey
,
403 PR_Lock(this->mLock
);
405 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::Put(aKey
, aData
);
406 PR_Unlock(this->mLock
);
411 template<class KeyClass
,class DataType
,class UserDataType
>
413 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::Remove(KeyType aKey
)
415 PR_Lock(this->mLock
);
416 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::Remove(aKey
);
417 PR_Unlock(this->mLock
);
420 template<class KeyClass
,class DataType
,class UserDataType
>
422 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::EnumerateRead
423 (EnumReadFunction fEnumCall
, void* userArg
) const
425 PR_Lock(this->mLock
);
427 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::EnumerateRead(fEnumCall
, userArg
);
428 PR_Unlock(this->mLock
);
433 template<class KeyClass
,class DataType
,class UserDataType
>
435 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::Enumerate
436 (EnumFunction fEnumCall
, void* userArg
)
438 PR_Lock(this->mLock
);
440 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::Enumerate(fEnumCall
, userArg
);
441 PR_Unlock(this->mLock
);
446 template<class KeyClass
,class DataType
,class UserDataType
>
448 nsBaseHashtableMT
<KeyClass
,DataType
,UserDataType
>::Clear()
450 PR_Lock(this->mLock
);
451 nsBaseHashtable
<KeyClass
,DataType
,UserDataType
>::Clear();
452 PR_Unlock(this->mLock
);
455 #endif // nsBaseHashtable_h__