Back to index

lightning-sunbird  0.9+nobinonly
nsBaseHashtable.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is C++ hashtable templates.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Benjamin Smedberg.
00019  * Portions created by the Initial Developer are Copyright (C) 2002
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifndef nsBaseHashtable_h__
00039 #define nsBaseHashtable_h__
00040 
00041 #include "nsTHashtable.h"
00042 #include "prlock.h"
00043 #include "nsDebug.h"
00044 
00045 template<class KeyClass,class DataType,class UserDataType>
00046 class nsBaseHashtable; // forward declaration
00047 
00053 template<class KeyClass,class DataType>
00054 class nsBaseHashtableET : public KeyClass
00055 {
00056 public:
00057   DataType mData;
00058   friend class nsTHashtable< nsBaseHashtableET<KeyClass,DataType> >;
00059 
00060 private:
00061   typedef typename KeyClass::KeyType KeyType;
00062   typedef typename KeyClass::KeyTypePointer KeyTypePointer;
00063   
00064   nsBaseHashtableET(KeyTypePointer aKey);
00065   nsBaseHashtableET(nsBaseHashtableET<KeyClass,DataType>& toCopy);
00066   ~nsBaseHashtableET();
00067 };
00068 
00081 template<class KeyClass,class DataType,class UserDataType>
00082 class nsBaseHashtable :
00083   protected nsTHashtable< nsBaseHashtableET<KeyClass,DataType> >
00084 {
00085 public:
00086   typedef typename KeyClass::KeyType KeyType;
00087   typedef nsBaseHashtableET<KeyClass,DataType> EntryType;
00088 
00089   // default constructor+destructor are fine
00090 
00098   PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE)
00099   { return nsTHashtable<EntryType>::Init(initSize); }
00100 
00106   PRBool IsInitialized() const { return this->mTable.entrySize; }
00107 
00112   PRUint32 Count() const
00113   { return nsTHashtable<EntryType>::Count(); }
00114 
00124   PRBool Get(KeyType aKey, UserDataType* pData) const
00125   {
00126     EntryType* ent = GetEntry(aKey);
00127 
00128     if (!ent)
00129       return PR_FALSE;
00130 
00131     if (pData)
00132       *pData = ent->mData;
00133 
00134     return PR_TRUE;
00135   }
00136 
00143   PRBool Put(KeyType aKey, UserDataType aData)
00144   {
00145     EntryType* ent = PutEntry(aKey);
00146 
00147     if (!ent)
00148       return PR_FALSE;
00149 
00150     ent->mData = aData;
00151 
00152     return PR_TRUE;
00153   }
00154 
00159   void Remove(KeyType aKey) { RemoveEntry(aKey); }
00160 
00170   typedef PLDHashOperator
00171     (*PR_CALLBACK EnumReadFunction)(KeyType      aKey,
00172                                     UserDataType aData,
00173                                     void*        userArg);
00174 
00180   PRUint32 EnumerateRead(EnumReadFunction enumFunc, void* userArg) const
00181   {
00182     NS_ASSERTION(this->mTable.entrySize,
00183                  "nsBaseHashtable was not initialized properly.");
00184 
00185     s_EnumReadArgs enumData = { enumFunc, userArg };
00186     return PL_DHashTableEnumerate(NS_CONST_CAST(PLDHashTable*, &this->mTable),
00187                                   s_EnumReadStub,
00188                                   &enumData);
00189   }
00190 
00202   typedef PLDHashOperator
00203     (*PR_CALLBACK EnumFunction)(KeyType       aKey,
00204                                 DataType&     aData,
00205                                 void*         userArg);
00206 
00213   PRUint32 Enumerate(EnumFunction enumFunc, void* userArg)
00214   {
00215     NS_ASSERTION(this->mTable.entrySize,
00216                  "nsBaseHashtable was not initialized properly.");
00217 
00218     s_EnumArgs enumData = { enumFunc, userArg };
00219     return PL_DHashTableEnumerate(&this->mTable,
00220                                   s_EnumStub,
00221                                   &enumData);
00222   }
00223 
00227   void Clear() { nsTHashtable<EntryType>::Clear(); }
00228 
00229 protected:
00235   struct s_EnumReadArgs
00236   {
00237     EnumReadFunction func;
00238     void* userArg;
00239   };
00240 
00241   static PLDHashOperator s_EnumReadStub(PLDHashTable    *table,
00242                                         PLDHashEntryHdr *hdr,
00243                                         PRUint32         number,
00244                                         void            *arg);
00245 
00246   struct s_EnumArgs
00247   {
00248     EnumFunction func;
00249     void* userArg;
00250   };
00251 
00252   static PLDHashOperator s_EnumStub(PLDHashTable      *table,
00253                                     PLDHashEntryHdr   *hdr,
00254                                     PRUint32           number,
00255                                     void              *arg);
00256 };
00257 
00261 template<class KeyClass,class DataType,class UserDataType>
00262 class nsBaseHashtableMT :
00263   protected nsBaseHashtable<KeyClass,DataType,UserDataType>
00264 {
00265 public:
00266   typedef typename
00267     nsBaseHashtable<KeyClass,DataType,UserDataType>::EntryType EntryType;
00268   typedef typename
00269     nsBaseHashtable<KeyClass,DataType,UserDataType>::KeyType KeyType;
00270   typedef typename
00271     nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumFunction EnumFunction;
00272   typedef typename
00273     nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumReadFunction EnumReadFunction;
00274 
00275   nsBaseHashtableMT() : mLock(nsnull) { }
00276   ~nsBaseHashtableMT();
00277 
00278   PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE);
00279   PRBool IsInitialized() const { return (PRBool) mLock; }
00280   PRUint32 Count() const;
00281   PRBool Get(KeyType aKey, UserDataType* pData) const;
00282   PRBool Put(KeyType aKey, UserDataType aData);
00283   void Remove(KeyType aKey);
00284 
00285   PRUint32 EnumerateRead(EnumReadFunction enumFunc, void* userArg) const;
00286   PRUint32 Enumerate(EnumFunction enumFunc, void* userArg);
00287   void Clear();
00288 
00289 protected:
00290   PRLock* mLock;
00291 };
00292   
00293 
00294 //
00295 // nsBaseHashtableET definitions
00296 //
00297 
00298 template<class KeyClass,class DataType>
00299 nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET(KeyTypePointer aKey) :
00300   KeyClass(aKey)
00301 { }
00302 
00303 template<class KeyClass,class DataType>
00304 nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET
00305   (nsBaseHashtableET<KeyClass,DataType>& toCopy) :
00306   KeyClass(toCopy),
00307   mData(toCopy.mData)
00308 { }
00309 
00310 template<class KeyClass,class DataType>
00311 nsBaseHashtableET<KeyClass,DataType>::~nsBaseHashtableET()
00312 { }
00313 
00314 
00315 //
00316 // nsBaseHashtable definitions
00317 //
00318 
00319 template<class KeyClass,class DataType,class UserDataType>
00320 PLDHashOperator
00321 nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumReadStub
00322   (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void* arg)
00323 {
00324   EntryType* ent = NS_STATIC_CAST(EntryType*, hdr);
00325   s_EnumReadArgs* eargs = (s_EnumReadArgs*) arg;
00326 
00327   PLDHashOperator res = (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg);
00328 
00329   NS_ASSERTION( !(res & PL_DHASH_REMOVE ),
00330                 "PL_DHASH_REMOVE return during const enumeration; ignoring.");
00331 
00332   if (res & PL_DHASH_STOP)
00333     return PL_DHASH_STOP;
00334 
00335   return PL_DHASH_NEXT;
00336 }
00337 
00338 template<class KeyClass,class DataType,class UserDataType>
00339 PLDHashOperator
00340 nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumStub
00341   (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void* arg)
00342 {
00343   EntryType* ent = NS_STATIC_CAST(EntryType*, hdr);
00344   s_EnumArgs* eargs = (s_EnumArgs*) arg;
00345 
00346   return (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg);
00347 }
00348 
00349 
00350 //
00351 // nsBaseHashtableMT  definitions
00352 //
00353 
00354 template<class KeyClass,class DataType,class UserDataType>
00355 nsBaseHashtableMT<KeyClass,DataType,UserDataType>::~nsBaseHashtableMT()
00356 {
00357   if (this->mLock)
00358     PR_DestroyLock(this->mLock);
00359 }
00360 
00361 template<class KeyClass,class DataType,class UserDataType>
00362 PRBool
00363 nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Init(PRUint32 initSize)
00364 {
00365   if (!nsTHashtable<EntryType>::IsInitialized() && !nsTHashtable<EntryType>::Init(initSize))
00366     return PR_FALSE;
00367 
00368   this->mLock = PR_NewLock();
00369   NS_WARN_IF_FALSE(this->mLock, "Error creating lock during nsBaseHashtableL::Init()");
00370 
00371   return (this->mLock != nsnull);
00372 }
00373 
00374 template<class KeyClass,class DataType,class UserDataType>
00375 PRUint32
00376 nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Count() const
00377 {
00378   PR_Lock(this->mLock);
00379   PRUint32 count = nsTHashtable<EntryType>::Count();
00380   PR_Unlock(this->mLock);
00381 
00382   return count;
00383 }
00384 
00385 template<class KeyClass,class DataType,class UserDataType>
00386 PRBool
00387 nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Get(KeyType       aKey,
00388                                                            UserDataType* pData) const
00389 {
00390   PR_Lock(this->mLock);
00391   PRBool res =
00392     nsBaseHashtable<KeyClass,DataType,UserDataType>::Get(aKey, pData);
00393   PR_Unlock(this->mLock);
00394 
00395   return res;
00396 }
00397 
00398 template<class KeyClass,class DataType,class UserDataType>
00399 PRBool
00400 nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Put(KeyType      aKey,
00401                                                            UserDataType aData)
00402 {
00403   PR_Lock(this->mLock);
00404   PRBool res =
00405     nsBaseHashtable<KeyClass,DataType,UserDataType>::Put(aKey, aData);
00406   PR_Unlock(this->mLock);
00407 
00408   return res;
00409 }
00410 
00411 template<class KeyClass,class DataType,class UserDataType>
00412 void
00413 nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Remove(KeyType aKey)
00414 {
00415   PR_Lock(this->mLock);
00416   nsBaseHashtable<KeyClass,DataType,UserDataType>::Remove(aKey);
00417   PR_Unlock(this->mLock);
00418 }
00419 
00420 template<class KeyClass,class DataType,class UserDataType>
00421 PRUint32
00422 nsBaseHashtableMT<KeyClass,DataType,UserDataType>::EnumerateRead
00423   (EnumReadFunction fEnumCall, void* userArg) const
00424 {
00425   PR_Lock(this->mLock);
00426   PRUint32 count =
00427     nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumerateRead(fEnumCall, userArg);
00428   PR_Unlock(this->mLock);
00429 
00430   return count;
00431 }
00432 
00433 template<class KeyClass,class DataType,class UserDataType>
00434 PRUint32
00435 nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Enumerate
00436   (EnumFunction fEnumCall, void* userArg)
00437 {
00438   PR_Lock(this->mLock);
00439   PRUint32 count =
00440     nsBaseHashtable<KeyClass,DataType,UserDataType>::Enumerate(fEnumCall, userArg);
00441   PR_Unlock(this->mLock);
00442 
00443   return count;
00444 }
00445 
00446 template<class KeyClass,class DataType,class UserDataType>
00447 void
00448 nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Clear()
00449 {
00450   PR_Lock(this->mLock);
00451   nsBaseHashtable<KeyClass,DataType,UserDataType>::Clear();
00452   PR_Unlock(this->mLock);
00453 }
00454 
00455 #endif // nsBaseHashtable_h__