PageRenderTime 38ms CodeModel.GetById 7ms RepoModel.GetById 1ms app.codeStats 0ms

/gecko_api/include/nsBaseHashtable.h

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