xpcom/glue/nsBaseHashtable.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #ifndef nsBaseHashtable_h__
michael@0 7 #define nsBaseHashtable_h__
michael@0 8
michael@0 9 #include "mozilla/MemoryReporting.h"
michael@0 10 #include "mozilla/Move.h"
michael@0 11 #include "nsTHashtable.h"
michael@0 12 #include "prlock.h"
michael@0 13 #include "nsDebug.h"
michael@0 14
michael@0 15 template<class KeyClass,class DataType,class UserDataType>
michael@0 16 class nsBaseHashtable; // forward declaration
michael@0 17
michael@0 18 /**
michael@0 19 * the private nsTHashtable::EntryType class used by nsBaseHashtable
michael@0 20 * @see nsTHashtable for the specification of this class
michael@0 21 * @see nsBaseHashtable for template parameters
michael@0 22 */
michael@0 23 template<class KeyClass,class DataType>
michael@0 24 class nsBaseHashtableET : public KeyClass
michael@0 25 {
michael@0 26 public:
michael@0 27 DataType mData;
michael@0 28 friend class nsTHashtable< nsBaseHashtableET<KeyClass,DataType> >;
michael@0 29
michael@0 30 private:
michael@0 31 typedef typename KeyClass::KeyType KeyType;
michael@0 32 typedef typename KeyClass::KeyTypePointer KeyTypePointer;
michael@0 33
michael@0 34 nsBaseHashtableET(KeyTypePointer aKey);
michael@0 35 nsBaseHashtableET(nsBaseHashtableET<KeyClass,DataType>&& toMove);
michael@0 36 ~nsBaseHashtableET();
michael@0 37 };
michael@0 38
michael@0 39 /**
michael@0 40 * templated hashtable for simple data types
michael@0 41 * This class manages simple data types that do not need construction or
michael@0 42 * destruction.
michael@0 43 *
michael@0 44 * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
michael@0 45 * for a complete specification.
michael@0 46 * @param DataType the datatype stored in the hashtable,
michael@0 47 * for example, uint32_t or nsCOMPtr. If UserDataType is not the same,
michael@0 48 * DataType must implicitly cast to UserDataType
michael@0 49 * @param UserDataType the user sees, for example uint32_t or nsISupports*
michael@0 50 */
michael@0 51 template<class KeyClass,class DataType,class UserDataType>
michael@0 52 class nsBaseHashtable :
michael@0 53 protected nsTHashtable< nsBaseHashtableET<KeyClass,DataType> >
michael@0 54 {
michael@0 55 typedef mozilla::fallible_t fallible_t;
michael@0 56
michael@0 57 public:
michael@0 58 typedef typename KeyClass::KeyType KeyType;
michael@0 59 typedef nsBaseHashtableET<KeyClass,DataType> EntryType;
michael@0 60
michael@0 61 using nsTHashtable<EntryType>::Contains;
michael@0 62
michael@0 63 nsBaseHashtable()
michael@0 64 {
michael@0 65 }
michael@0 66 explicit nsBaseHashtable(uint32_t aInitSize)
michael@0 67 : nsTHashtable<EntryType>(aInitSize)
michael@0 68 {
michael@0 69 }
michael@0 70
michael@0 71 /**
michael@0 72 * Return the number of entries in the table.
michael@0 73 * @return number of entries
michael@0 74 */
michael@0 75 uint32_t Count() const
michael@0 76 { return nsTHashtable<EntryType>::Count(); }
michael@0 77
michael@0 78 /**
michael@0 79 * retrieve the value for a key.
michael@0 80 * @param aKey the key to retreive
michael@0 81 * @param pData data associated with this key will be placed at this
michael@0 82 * pointer. If you only need to check if the key exists, pData
michael@0 83 * may be null.
michael@0 84 * @return true if the key exists. If key does not exist, pData is not
michael@0 85 * modified.
michael@0 86 */
michael@0 87 bool Get(KeyType aKey, UserDataType* pData) const
michael@0 88 {
michael@0 89 EntryType* ent = this->GetEntry(aKey);
michael@0 90
michael@0 91 if (!ent)
michael@0 92 return false;
michael@0 93
michael@0 94 if (pData)
michael@0 95 *pData = ent->mData;
michael@0 96
michael@0 97 return true;
michael@0 98 }
michael@0 99
michael@0 100 /**
michael@0 101 * For pointer types, get the value, returning nullptr if the entry is not
michael@0 102 * present in the table.
michael@0 103 *
michael@0 104 * @param aKey the key to retrieve
michael@0 105 * @return The found value, or nullptr if no entry was found with the given key.
michael@0 106 * @note If nullptr values are stored in the table, it is not possible to
michael@0 107 * distinguish between a nullptr value and a missing entry.
michael@0 108 */
michael@0 109 UserDataType Get(KeyType aKey) const
michael@0 110 {
michael@0 111 EntryType* ent = this->GetEntry(aKey);
michael@0 112 if (!ent)
michael@0 113 return 0;
michael@0 114
michael@0 115 return ent->mData;
michael@0 116 }
michael@0 117
michael@0 118 /**
michael@0 119 * put a new value for the associated key
michael@0 120 * @param aKey the key to put
michael@0 121 * @param aData the new data
michael@0 122 * @return always true, unless memory allocation failed
michael@0 123 */
michael@0 124 void Put(KeyType aKey, const UserDataType& aData)
michael@0 125 {
michael@0 126 if (!Put(aKey, aData, fallible_t()))
michael@0 127 NS_ABORT_OOM(this->mTable.entrySize * this->mTable.entryCount);
michael@0 128 }
michael@0 129
michael@0 130 bool Put(KeyType aKey, const UserDataType& aData, const fallible_t&) NS_WARN_UNUSED_RESULT
michael@0 131 {
michael@0 132 EntryType* ent = this->PutEntry(aKey);
michael@0 133
michael@0 134 if (!ent)
michael@0 135 return false;
michael@0 136
michael@0 137 ent->mData = aData;
michael@0 138
michael@0 139 return true;
michael@0 140 }
michael@0 141
michael@0 142 /**
michael@0 143 * remove the data for the associated key
michael@0 144 * @param aKey the key to remove from the hashtable
michael@0 145 */
michael@0 146 void Remove(KeyType aKey) { this->RemoveEntry(aKey); }
michael@0 147
michael@0 148 /**
michael@0 149 * function type provided by the application for enumeration.
michael@0 150 * @param aKey the key being enumerated
michael@0 151 * @param aData data being enumerated
michael@0 152 * @parm userArg passed unchanged from Enumerate
michael@0 153 * @return either
michael@0 154 * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink or
michael@0 155 * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink
michael@0 156 */
michael@0 157 typedef PLDHashOperator
michael@0 158 (* EnumReadFunction)(KeyType aKey,
michael@0 159 UserDataType aData,
michael@0 160 void* userArg);
michael@0 161
michael@0 162 /**
michael@0 163 * enumerate entries in the hashtable, without allowing changes
michael@0 164 * @param enumFunc enumeration callback
michael@0 165 * @param userArg passed unchanged to the EnumReadFunction
michael@0 166 */
michael@0 167 uint32_t EnumerateRead(EnumReadFunction enumFunc, void* userArg) const
michael@0 168 {
michael@0 169 NS_ASSERTION(this->mTable.entrySize,
michael@0 170 "nsBaseHashtable was not initialized properly.");
michael@0 171
michael@0 172 s_EnumReadArgs enumData = { enumFunc, userArg };
michael@0 173 return PL_DHashTableEnumerate(const_cast<PLDHashTable*>(&this->mTable),
michael@0 174 s_EnumReadStub,
michael@0 175 &enumData);
michael@0 176 }
michael@0 177
michael@0 178 /**
michael@0 179 * function type provided by the application for enumeration.
michael@0 180 * @param aKey the key being enumerated
michael@0 181 * @param aData Reference to data being enumerated, may be altered. e.g. for
michael@0 182 * nsInterfaceHashtable this is an nsCOMPtr reference...
michael@0 183 * @parm userArg passed unchanged from Enumerate
michael@0 184 * @return bitflag combination of
michael@0 185 * @link PLDHashOperator::PL_DHASH_REMOVE @endlink,
michael@0 186 * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink, or
michael@0 187 * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink
michael@0 188 */
michael@0 189 typedef PLDHashOperator
michael@0 190 (* EnumFunction)(KeyType aKey,
michael@0 191 DataType& aData,
michael@0 192 void* userArg);
michael@0 193
michael@0 194 /**
michael@0 195 * enumerate entries in the hashtable, allowing changes. This
michael@0 196 * functions write-locks the hashtable.
michael@0 197 * @param enumFunc enumeration callback
michael@0 198 * @param userArg passed unchanged to the EnumFunction
michael@0 199 */
michael@0 200 uint32_t Enumerate(EnumFunction enumFunc, void* userArg)
michael@0 201 {
michael@0 202 NS_ASSERTION(this->mTable.entrySize,
michael@0 203 "nsBaseHashtable was not initialized properly.");
michael@0 204
michael@0 205 s_EnumArgs enumData = { enumFunc, userArg };
michael@0 206 return PL_DHashTableEnumerate(&this->mTable,
michael@0 207 s_EnumStub,
michael@0 208 &enumData);
michael@0 209 }
michael@0 210
michael@0 211 /**
michael@0 212 * reset the hashtable, removing all entries
michael@0 213 */
michael@0 214 void Clear() { nsTHashtable<EntryType>::Clear(); }
michael@0 215
michael@0 216 /**
michael@0 217 * client must provide a SizeOfEntryExcludingThisFun function for
michael@0 218 * SizeOfExcludingThis.
michael@0 219 * @param aKey the key being enumerated
michael@0 220 * @param aData Reference to data being enumerated.
michael@0 221 * @param mallocSizeOf the function used to measure heap-allocated blocks
michael@0 222 * @param userArg passed unchanged from SizeOf{In,Ex}cludingThis
michael@0 223 * @return summed size of the things pointed to by the entries
michael@0 224 */
michael@0 225 typedef size_t
michael@0 226 (* SizeOfEntryExcludingThisFun)(KeyType aKey,
michael@0 227 const DataType &aData,
michael@0 228 mozilla::MallocSizeOf mallocSizeOf,
michael@0 229 void* userArg);
michael@0 230
michael@0 231 /**
michael@0 232 * Measure the size of the table's entry storage and the table itself.
michael@0 233 * If |sizeOfEntryExcludingThis| is non-nullptr, measure the size of things
michael@0 234 * pointed to by entries.
michael@0 235 *
michael@0 236 * @param sizeOfEntryExcludingThis
michael@0 237 * the <code>SizeOfEntryExcludingThisFun</code> function to call
michael@0 238 * @param mallocSizeOf the function used to meeasure heap-allocated blocks
michael@0 239 * @param userArg a point to pass to the
michael@0 240 * <code>SizeOfEntryExcludingThisFun</code> function
michael@0 241 * @return the summed size of the entries, the table, and the table's storage
michael@0 242 */
michael@0 243 size_t SizeOfIncludingThis(SizeOfEntryExcludingThisFun sizeOfEntryExcludingThis,
michael@0 244 mozilla::MallocSizeOf mallocSizeOf, void *userArg = nullptr)
michael@0 245 {
michael@0 246 return mallocSizeOf(this) + this->SizeOfExcludingThis(sizeOfEntryExcludingThis,
michael@0 247 mallocSizeOf, userArg);
michael@0 248 }
michael@0 249
michael@0 250 /**
michael@0 251 * Measure the size of the table's entry storage, and if
michael@0 252 * |sizeOfEntryExcludingThis| is non-nullptr, measure the size of things pointed
michael@0 253 * to by entries.
michael@0 254 *
michael@0 255 * @param sizeOfEntryExcludingThis the
michael@0 256 * <code>SizeOfEntryExcludingThisFun</code> function to call
michael@0 257 * @param mallocSizeOf the function used to measure heap-allocated blocks
michael@0 258 * @param userArg a pointer to pass to the
michael@0 259 * <code>SizeOfEntryExcludingThisFun</code> function
michael@0 260 * @return the summed size of all the entries
michael@0 261 */
michael@0 262 size_t SizeOfExcludingThis(SizeOfEntryExcludingThisFun sizeOfEntryExcludingThis,
michael@0 263 mozilla::MallocSizeOf mallocSizeOf, void *userArg = nullptr) const
michael@0 264 {
michael@0 265 if (sizeOfEntryExcludingThis) {
michael@0 266 s_SizeOfArgs args = { sizeOfEntryExcludingThis, userArg };
michael@0 267 return PL_DHashTableSizeOfExcludingThis(&this->mTable, s_SizeOfStub,
michael@0 268 mallocSizeOf, &args);
michael@0 269 }
michael@0 270 return PL_DHashTableSizeOfExcludingThis(&this->mTable, nullptr,
michael@0 271 mallocSizeOf);
michael@0 272 }
michael@0 273
michael@0 274 #ifdef DEBUG
michael@0 275 using nsTHashtable<EntryType>::MarkImmutable;
michael@0 276 #endif
michael@0 277
michael@0 278 protected:
michael@0 279 /**
michael@0 280 * used internally during EnumerateRead. Allocated on the stack.
michael@0 281 * @param func the enumerator passed to EnumerateRead
michael@0 282 * @param userArg the userArg passed to EnumerateRead
michael@0 283 */
michael@0 284 struct s_EnumReadArgs
michael@0 285 {
michael@0 286 EnumReadFunction func;
michael@0 287 void* userArg;
michael@0 288 };
michael@0 289
michael@0 290 static PLDHashOperator s_EnumReadStub(PLDHashTable *table,
michael@0 291 PLDHashEntryHdr *hdr,
michael@0 292 uint32_t number,
michael@0 293 void *arg);
michael@0 294
michael@0 295 struct s_EnumArgs
michael@0 296 {
michael@0 297 EnumFunction func;
michael@0 298 void* userArg;
michael@0 299 };
michael@0 300
michael@0 301 static PLDHashOperator s_EnumStub(PLDHashTable *table,
michael@0 302 PLDHashEntryHdr *hdr,
michael@0 303 uint32_t number,
michael@0 304 void *arg);
michael@0 305
michael@0 306 struct s_SizeOfArgs
michael@0 307 {
michael@0 308 SizeOfEntryExcludingThisFun func;
michael@0 309 void* userArg;
michael@0 310 };
michael@0 311
michael@0 312 static size_t s_SizeOfStub(PLDHashEntryHdr *entry,
michael@0 313 mozilla::MallocSizeOf mallocSizeOf,
michael@0 314 void *arg);
michael@0 315 };
michael@0 316
michael@0 317 class nsCycleCollectionTraversalCallback;
michael@0 318
michael@0 319 struct MOZ_STACK_CLASS nsBaseHashtableCCTraversalData
michael@0 320 {
michael@0 321 nsBaseHashtableCCTraversalData(nsCycleCollectionTraversalCallback& aCallback,
michael@0 322 const char* aName,
michael@0 323 uint32_t aFlags)
michael@0 324 : mCallback(aCallback),
michael@0 325 mName(aName),
michael@0 326 mFlags(aFlags)
michael@0 327 {
michael@0 328 }
michael@0 329
michael@0 330 nsCycleCollectionTraversalCallback& mCallback;
michael@0 331 const char* mName;
michael@0 332 uint32_t mFlags;
michael@0 333
michael@0 334 };
michael@0 335
michael@0 336 template <typename K, typename T>
michael@0 337 PLDHashOperator
michael@0 338 ImplCycleCollectionTraverse_EnumFunc(K aKey,
michael@0 339 T aData,
michael@0 340 void* aUserData)
michael@0 341 {
michael@0 342 nsBaseHashtableCCTraversalData* userData =
michael@0 343 static_cast<nsBaseHashtableCCTraversalData*>(aUserData);
michael@0 344
michael@0 345 CycleCollectionNoteChild(userData->mCallback,
michael@0 346 aData,
michael@0 347 userData->mName,
michael@0 348 userData->mFlags);
michael@0 349 return PL_DHASH_NEXT;
michael@0 350 }
michael@0 351
michael@0 352 //
michael@0 353 // nsBaseHashtableET definitions
michael@0 354 //
michael@0 355
michael@0 356 template<class KeyClass,class DataType>
michael@0 357 nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET(KeyTypePointer aKey) :
michael@0 358 KeyClass(aKey)
michael@0 359 { }
michael@0 360
michael@0 361 template<class KeyClass,class DataType>
michael@0 362 nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET
michael@0 363 (nsBaseHashtableET<KeyClass,DataType>&& toMove) :
michael@0 364 KeyClass(mozilla::Move(toMove)),
michael@0 365 mData(mozilla::Move(toMove.mData))
michael@0 366 { }
michael@0 367
michael@0 368 template<class KeyClass,class DataType>
michael@0 369 nsBaseHashtableET<KeyClass,DataType>::~nsBaseHashtableET()
michael@0 370 { }
michael@0 371
michael@0 372
michael@0 373 //
michael@0 374 // nsBaseHashtable definitions
michael@0 375 //
michael@0 376
michael@0 377 template<class KeyClass,class DataType,class UserDataType>
michael@0 378 PLDHashOperator
michael@0 379 nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumReadStub
michael@0 380 (PLDHashTable *table, PLDHashEntryHdr *hdr, uint32_t number, void* arg)
michael@0 381 {
michael@0 382 EntryType* ent = static_cast<EntryType*>(hdr);
michael@0 383 s_EnumReadArgs* eargs = (s_EnumReadArgs*) arg;
michael@0 384
michael@0 385 PLDHashOperator res = (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg);
michael@0 386
michael@0 387 NS_ASSERTION( !(res & PL_DHASH_REMOVE ),
michael@0 388 "PL_DHASH_REMOVE return during const enumeration; ignoring.");
michael@0 389
michael@0 390 if (res & PL_DHASH_STOP)
michael@0 391 return PL_DHASH_STOP;
michael@0 392
michael@0 393 return PL_DHASH_NEXT;
michael@0 394 }
michael@0 395
michael@0 396 template<class KeyClass,class DataType,class UserDataType>
michael@0 397 PLDHashOperator
michael@0 398 nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumStub
michael@0 399 (PLDHashTable *table, PLDHashEntryHdr *hdr, uint32_t number, void* arg)
michael@0 400 {
michael@0 401 EntryType* ent = static_cast<EntryType*>(hdr);
michael@0 402 s_EnumArgs* eargs = (s_EnumArgs*) arg;
michael@0 403
michael@0 404 return (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg);
michael@0 405 }
michael@0 406
michael@0 407 template<class KeyClass,class DataType,class UserDataType>
michael@0 408 size_t
michael@0 409 nsBaseHashtable<KeyClass,DataType,UserDataType>::s_SizeOfStub
michael@0 410 (PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *arg)
michael@0 411 {
michael@0 412 EntryType* ent = static_cast<EntryType*>(hdr);
michael@0 413 s_SizeOfArgs* eargs = static_cast<s_SizeOfArgs*>(arg);
michael@0 414
michael@0 415 return (eargs->func)(ent->GetKey(), ent->mData, mallocSizeOf, eargs->userArg);
michael@0 416 }
michael@0 417
michael@0 418 #endif // nsBaseHashtable_h__

mercurial