зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1187197 (part 3) - Convert pldhash.{cpp,h} to C++ style comments. r=froydnj.
--HG-- extra : rebase_source : 4615862ad586e24050a6f5571b8d21689ba3fdf3
This commit is contained in:
Родитель
42e338fc52
Коммит
10da8efa1c
|
@ -4,9 +4,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Double hashing implementation.
|
||||
*/
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -14,7 +11,6 @@
|
|||
#include "pldhash.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "nsDebug.h" /* for PR_ASSERT */
|
||||
#include "nsAlgorithm.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
|
@ -95,7 +91,7 @@ PL_DHashMatchStringKey(PLDHashTable* aTable,
|
|||
{
|
||||
const PLDHashEntryStub* stub = (const PLDHashEntryStub*)aEntry;
|
||||
|
||||
/* XXX tolerate null keys on account of sloppy Mozilla callers. */
|
||||
// XXX tolerate null keys on account of sloppy Mozilla callers.
|
||||
return stub->key == aKey ||
|
||||
(stub->key && aKey &&
|
||||
strcmp((const char*)stub->key, (const char*)aKey) == 0);
|
||||
|
@ -150,13 +146,11 @@ SizeOfEntryStore(uint32_t aCapacity, uint32_t aEntrySize, uint32_t* aNbytes)
|
|||
return uint64_t(*aNbytes) == nbytes64; // returns false on overflow
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute max and min load numbers (entry counts). We have a secondary max
|
||||
* that allows us to overload a table reasonably if it cannot be grown further
|
||||
* (i.e. if ChangeTable() fails). The table slows down drastically if the
|
||||
* secondary max is too close to 1, but 0.96875 gives only a slight slowdown
|
||||
* while allowing 1.3x more elements.
|
||||
*/
|
||||
// Compute max and min load numbers (entry counts). We have a secondary max
|
||||
// that allows us to overload a table reasonably if it cannot be grown further
|
||||
// (i.e. if ChangeTable() fails). The table slows down drastically if the
|
||||
// secondary max is too close to 1, but 0.96875 gives only a slight slowdown
|
||||
// while allowing 1.3x more elements.
|
||||
static inline uint32_t
|
||||
MaxLoad(uint32_t aCapacity)
|
||||
{
|
||||
|
@ -288,14 +282,12 @@ PLDHashTable::Hash2(PLDHashNumber aHash,
|
|||
aSizeMaskOut = (PLDHashNumber(1) << sizeLog2) - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reserve mKeyHash 0 for free entries and 1 for removed-entry sentinels. Note
|
||||
* that a removed-entry sentinel need be stored only if the removed entry had
|
||||
* a colliding entry added after it. Therefore we can use 1 as the collision
|
||||
* flag in addition to the removed-entry sentinel value. Multiplicative hash
|
||||
* uses the high order bits of mKeyHash, so this least-significant reservation
|
||||
* should not hurt the hash function's effectiveness much.
|
||||
*/
|
||||
// Reserve mKeyHash 0 for free entries and 1 for removed-entry sentinels. Note
|
||||
// that a removed-entry sentinel need be stored only if the removed entry had
|
||||
// a colliding entry added after it. Therefore we can use 1 as the collision
|
||||
// flag in addition to the removed-entry sentinel value. Multiplicative hash
|
||||
// uses the high order bits of mKeyHash, so this least-significant reservation
|
||||
// should not hurt the hash function's effectiveness much.
|
||||
|
||||
/* static */ MOZ_ALWAYS_INLINE bool
|
||||
PLDHashTable::EntryIsFree(PLDHashEntryHdr* aEntry)
|
||||
|
@ -324,14 +316,14 @@ PLDHashTable::MarkEntryRemoved(PLDHashEntryHdr* aEntry)
|
|||
aEntry->mKeyHash = 1;
|
||||
}
|
||||
|
||||
/* Match an entry's mKeyHash against an unstored one computed from a key. */
|
||||
// Match an entry's mKeyHash against an unstored one computed from a key.
|
||||
/* static */ bool
|
||||
PLDHashTable::MatchEntryKeyhash(PLDHashEntryHdr* aEntry, PLDHashNumber aKeyHash)
|
||||
{
|
||||
return (aEntry->mKeyHash & ~kCollisionFlag) == aKeyHash;
|
||||
}
|
||||
|
||||
/* Compute the address of the indexed entry in table. */
|
||||
// Compute the address of the indexed entry in table.
|
||||
PLDHashEntryHdr*
|
||||
PLDHashTable::AddressEntry(uint32_t aIndex)
|
||||
{
|
||||
|
@ -348,7 +340,7 @@ PLDHashTable::~PLDHashTable()
|
|||
return;
|
||||
}
|
||||
|
||||
/* Clear any remaining live entries. */
|
||||
// Clear any remaining live entries.
|
||||
char* entryAddr = mEntryStore;
|
||||
char* entryLimit = entryAddr + Capacity() * mEntrySize;
|
||||
while (entryAddr < entryLimit) {
|
||||
|
@ -359,7 +351,7 @@ PLDHashTable::~PLDHashTable()
|
|||
entryAddr += mEntrySize;
|
||||
}
|
||||
|
||||
/* Free entry storage last. */
|
||||
// Free entry storage last.
|
||||
free(mEntryStore);
|
||||
mEntryStore = nullptr;
|
||||
}
|
||||
|
@ -394,31 +386,29 @@ PLDHashTable::SearchTable(const void* aKey, PLDHashNumber aKeyHash)
|
|||
NS_ASSERTION(!(aKeyHash & kCollisionFlag),
|
||||
"!(aKeyHash & kCollisionFlag)");
|
||||
|
||||
/* Compute the primary hash address. */
|
||||
// Compute the primary hash address.
|
||||
PLDHashNumber hash1 = Hash1(aKeyHash);
|
||||
PLDHashEntryHdr* entry = AddressEntry(hash1);
|
||||
|
||||
/* Miss: return space for a new entry. */
|
||||
// Miss: return space for a new entry.
|
||||
if (EntryIsFree(entry)) {
|
||||
return (Reason == ForAdd) ? entry : nullptr;
|
||||
}
|
||||
|
||||
/* Hit: return entry. */
|
||||
// Hit: return entry.
|
||||
PLDHashMatchEntry matchEntry = mOps->matchEntry;
|
||||
if (MatchEntryKeyhash(entry, aKeyHash) &&
|
||||
matchEntry(this, entry, aKey)) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* Collision: double hash. */
|
||||
// Collision: double hash.
|
||||
PLDHashNumber hash2;
|
||||
uint32_t sizeMask;
|
||||
Hash2(aKeyHash, hash2, sizeMask);
|
||||
|
||||
/*
|
||||
* Save the first removed entry pointer so Add() can recycle it. (Only used
|
||||
* if Reason==ForAdd.)
|
||||
*/
|
||||
// Save the first removed entry pointer so Add() can recycle it. (Only used
|
||||
// if Reason==ForAdd.)
|
||||
PLDHashEntryHdr* firstRemoved = nullptr;
|
||||
|
||||
for (;;) {
|
||||
|
@ -447,20 +437,17 @@ PLDHashTable::SearchTable(const void* aKey, PLDHashNumber aKeyHash)
|
|||
}
|
||||
}
|
||||
|
||||
/* NOTREACHED */
|
||||
// NOTREACHED
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a copy of SearchTable, used by ChangeTable, hardcoded to
|
||||
* 1. assume |aIsAdd| is true,
|
||||
* 2. assume that |aKey| will never match an existing entry, and
|
||||
* 3. assume that no entries have been removed from the current table
|
||||
* structure.
|
||||
* Avoiding the need for |aKey| means we can avoid needing a way to map
|
||||
* entries to keys, which means callers can use complex key types more
|
||||
* easily.
|
||||
*/
|
||||
// This is a copy of SearchTable(), used by ChangeTable(), hardcoded to
|
||||
// 1. assume |aIsAdd| is true,
|
||||
// 2. assume that |aKey| will never match an existing entry, and
|
||||
// 3. assume that no entries have been removed from the current table
|
||||
// structure.
|
||||
// Avoiding the need for |aKey| means we can avoid needing a way to map entries
|
||||
// to keys, which means callers can use complex key types more easily.
|
||||
PLDHashEntryHdr* PL_DHASH_FASTCALL
|
||||
PLDHashTable::FindFreeEntry(PLDHashNumber aKeyHash)
|
||||
{
|
||||
|
@ -468,16 +455,16 @@ PLDHashTable::FindFreeEntry(PLDHashNumber aKeyHash)
|
|||
NS_ASSERTION(!(aKeyHash & kCollisionFlag),
|
||||
"!(aKeyHash & kCollisionFlag)");
|
||||
|
||||
/* Compute the primary hash address. */
|
||||
// Compute the primary hash address.
|
||||
PLDHashNumber hash1 = Hash1(aKeyHash);
|
||||
PLDHashEntryHdr* entry = AddressEntry(hash1);
|
||||
|
||||
/* Miss: return space for a new entry. */
|
||||
// Miss: return space for a new entry.
|
||||
if (EntryIsFree(entry)) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* Collision: double hash. */
|
||||
// Collision: double hash.
|
||||
PLDHashNumber hash2;
|
||||
uint32_t sizeMask;
|
||||
Hash2(aKeyHash, hash2, sizeMask);
|
||||
|
@ -496,7 +483,7 @@ PLDHashTable::FindFreeEntry(PLDHashNumber aKeyHash)
|
|||
}
|
||||
}
|
||||
|
||||
/* NOTREACHED */
|
||||
// NOTREACHED
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -505,7 +492,7 @@ PLDHashTable::ChangeTable(int32_t aDeltaLog2)
|
|||
{
|
||||
MOZ_ASSERT(mEntryStore);
|
||||
|
||||
/* Look, but don't touch, until we succeed in getting new entry store. */
|
||||
// Look, but don't touch, until we succeed in getting new entry store.
|
||||
int32_t oldLog2 = kHashBits - mHashShift;
|
||||
int32_t newLog2 = oldLog2 + aDeltaLog2;
|
||||
uint32_t newCapacity = 1u << newLog2;
|
||||
|
@ -523,12 +510,12 @@ PLDHashTable::ChangeTable(int32_t aDeltaLog2)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* We can't fail from here on, so update table parameters. */
|
||||
// We can't fail from here on, so update table parameters.
|
||||
mHashShift = kHashBits - newLog2;
|
||||
mRemovedCount = 0;
|
||||
mGeneration++;
|
||||
|
||||
/* Assign the new entry store to table. */
|
||||
// Assign the new entry store to table.
|
||||
memset(newEntryStore, 0, nbytes);
|
||||
char* oldEntryStore;
|
||||
char* oldEntryAddr;
|
||||
|
@ -536,7 +523,7 @@ PLDHashTable::ChangeTable(int32_t aDeltaLog2)
|
|||
mEntryStore = newEntryStore;
|
||||
PLDHashMoveEntry moveEntry = mOps->moveEntry;
|
||||
|
||||
/* Copy only live entries, leaving removed ones behind. */
|
||||
// Copy only live entries, leaving removed ones behind.
|
||||
uint32_t oldCapacity = 1u << oldLog2;
|
||||
for (uint32_t i = 0; i < oldCapacity; ++i) {
|
||||
PLDHashEntryHdr* oldEntry = (PLDHashEntryHdr*)oldEntryAddr;
|
||||
|
@ -562,7 +549,7 @@ PLDHashTable::ComputeKeyHash(const void* aKey)
|
|||
PLDHashNumber keyHash = mOps->hashKey(this, aKey);
|
||||
keyHash *= kGoldenRatio;
|
||||
|
||||
/* Avoid 0 and 1 hash codes, they indicate free and removed entries. */
|
||||
// Avoid 0 and 1 hash codes, they indicate free and removed entries.
|
||||
if (keyHash < 2) {
|
||||
keyHash -= 2;
|
||||
}
|
||||
|
@ -605,14 +592,12 @@ PLDHashTable::Add(const void* aKey, const mozilla::fallible_t&)
|
|||
memset(mEntryStore, 0, nbytes);
|
||||
}
|
||||
|
||||
/*
|
||||
* If alpha is >= .75, grow or compress the table. If aKey is already
|
||||
* in the table, we may grow once more than necessary, but only if we
|
||||
* are on the edge of being overloaded.
|
||||
*/
|
||||
// If alpha is >= .75, grow or compress the table. If aKey is already in the
|
||||
// table, we may grow once more than necessary, but only if we are on the
|
||||
// edge of being overloaded.
|
||||
uint32_t capacity = Capacity();
|
||||
if (mEntryCount + mRemovedCount >= MaxLoad(capacity)) {
|
||||
/* Compress if a quarter or more of all entries are removed. */
|
||||
// Compress if a quarter or more of all entries are removed.
|
||||
int deltaLog2;
|
||||
if (mRemovedCount >= capacity >> 2) {
|
||||
deltaLog2 = 0;
|
||||
|
@ -620,25 +605,20 @@ PLDHashTable::Add(const void* aKey, const mozilla::fallible_t&)
|
|||
deltaLog2 = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Grow or compress the table. If ChangeTable() fails, allow
|
||||
* overloading up to the secondary max. Once we hit the secondary
|
||||
* max, return null.
|
||||
*/
|
||||
// Grow or compress the table. If ChangeTable() fails, allow overloading up
|
||||
// to the secondary max. Once we hit the secondary max, return null.
|
||||
if (!ChangeTable(deltaLog2) &&
|
||||
mEntryCount + mRemovedCount >= MaxLoadOnGrowthFailure(capacity)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for entry after possibly growing, so we don't have to add it,
|
||||
* then skip it while growing the table and re-add it after.
|
||||
*/
|
||||
// Look for entry after possibly growing, so we don't have to add it,
|
||||
// then skip it while growing the table and re-add it after.
|
||||
PLDHashNumber keyHash = ComputeKeyHash(aKey);
|
||||
PLDHashEntryHdr* entry = SearchTable<ForAdd>(aKey, keyHash);
|
||||
if (!EntryIsLive(entry)) {
|
||||
/* Initialize the entry, indicating that it's no longer free. */
|
||||
// Initialize the entry, indicating that it's no longer free.
|
||||
if (EntryIsRemoved(entry)) {
|
||||
mRemovedCount--;
|
||||
keyHash |= kCollisionFlag;
|
||||
|
@ -685,10 +665,10 @@ PLDHashTable::Remove(const void* aKey)
|
|||
mEntryStore ? SearchTable<ForSearchOrRemove>(aKey, ComputeKeyHash(aKey))
|
||||
: nullptr;
|
||||
if (entry) {
|
||||
/* Clear this entry and mark it as "removed". */
|
||||
// Clear this entry and mark it as "removed".
|
||||
RawRemove(entry);
|
||||
|
||||
/* Shrink if alpha is <= .25 and the table isn't too small already. */
|
||||
// Shrink if alpha is <= .25 and the table isn't too small already.
|
||||
uint32_t capacity = Capacity();
|
||||
if (capacity > kMinCapacity &&
|
||||
mEntryCount <= MinLoad(capacity)) {
|
||||
|
@ -734,7 +714,7 @@ PLDHashTable::RawRemove(PLDHashEntryHdr* aEntry)
|
|||
|
||||
NS_ASSERTION(EntryIsLive(aEntry), "EntryIsLive(aEntry)");
|
||||
|
||||
/* Load keyHash first in case clearEntry() goofs it. */
|
||||
// Load keyHash first in case clearEntry() goofs it.
|
||||
PLDHashNumber keyHash = aEntry->mKeyHash;
|
||||
mOps->clearEntry(this, aEntry);
|
||||
if (keyHash & kCollisionFlag) {
|
||||
|
|
|
@ -6,9 +6,7 @@
|
|||
|
||||
#ifndef pldhash_h___
|
||||
#define pldhash_h___
|
||||
/*
|
||||
* Double hashing, a la Knuth 6.
|
||||
*/
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Attributes.h" // for MOZ_ALWAYS_INLINE
|
||||
#include "mozilla/fallible.h"
|
||||
|
@ -30,24 +28,22 @@ typedef uint32_t PLDHashNumber;
|
|||
class PLDHashTable;
|
||||
struct PLDHashTableOps;
|
||||
|
||||
/*
|
||||
* Table entry header structure.
|
||||
*
|
||||
* In order to allow in-line allocation of key and value, we do not declare
|
||||
* either here. Instead, the API uses const void *key as a formal parameter.
|
||||
* The key need not be stored in the entry; it may be part of the value, but
|
||||
* need not be stored at all.
|
||||
*
|
||||
* Callback types are defined below and grouped into the PLDHashTableOps
|
||||
* structure, for single static initialization per hash table sub-type.
|
||||
*
|
||||
* Each hash table sub-type should make its entry type a subclass of
|
||||
* PLDHashEntryHdr. The mKeyHash member contains the result of multiplying the
|
||||
* hash code returned from the hashKey callback (see below) by kGoldenRatio,
|
||||
* then constraining the result to avoid the magic 0 and 1 values. The stored
|
||||
* mKeyHash value is table size invariant, and it is maintained automatically
|
||||
* -- users need never access it.
|
||||
*/
|
||||
// Table entry header structure.
|
||||
//
|
||||
// In order to allow in-line allocation of key and value, we do not declare
|
||||
// either here. Instead, the API uses const void *key as a formal parameter.
|
||||
// The key need not be stored in the entry; it may be part of the value, but
|
||||
// need not be stored at all.
|
||||
//
|
||||
// Callback types are defined below and grouped into the PLDHashTableOps
|
||||
// structure, for single static initialization per hash table sub-type.
|
||||
//
|
||||
// Each hash table sub-type should make its entry type a subclass of
|
||||
// PLDHashEntryHdr. The mKeyHash member contains the result of multiplying the
|
||||
// hash code returned from the hashKey callback (see below) by kGoldenRatio,
|
||||
// then constraining the result to avoid the magic 0 and 1 values. The stored
|
||||
// mKeyHash value is table size invariant, and it is maintained automatically
|
||||
// -- users need never access it.
|
||||
struct PLDHashEntryHdr
|
||||
{
|
||||
private:
|
||||
|
@ -206,31 +202,29 @@ private:
|
|||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A PLDHashTable may be allocated on the stack or within another structure or
|
||||
* class. No entry storage is allocated until the first element is added. This
|
||||
* means that empty hash tables are cheap, which is good because they are
|
||||
* common.
|
||||
*
|
||||
* There used to be a long, math-heavy comment here about the merits of
|
||||
* double hashing vs. chaining; it was removed in bug 1058335. In short, double
|
||||
* hashing is more space-efficient unless the element size gets large (in which
|
||||
* case you should keep using double hashing but switch to using pointer
|
||||
* elements). Also, with double hashing, you can't safely hold an entry pointer
|
||||
* and use it after an ADD or REMOVE operation, unless you sample
|
||||
* aTable->mGeneration before adding or removing, and compare the sample after,
|
||||
* dereferencing the entry pointer only if aTable->mGeneration has not changed.
|
||||
*/
|
||||
// A PLDHashTable may be allocated on the stack or within another structure or
|
||||
// class. No entry storage is allocated until the first element is added. This
|
||||
// means that empty hash tables are cheap, which is good because they are
|
||||
// common.
|
||||
//
|
||||
// There used to be a long, math-heavy comment here about the merits of
|
||||
// double hashing vs. chaining; it was removed in bug 1058335. In short, double
|
||||
// hashing is more space-efficient unless the element size gets large (in which
|
||||
// case you should keep using double hashing but switch to using pointer
|
||||
// elements). Also, with double hashing, you can't safely hold an entry pointer
|
||||
// and use it after an ADD or REMOVE operation, unless you sample
|
||||
// aTable->mGeneration before adding or removing, and compare the sample after,
|
||||
// dereferencing the entry pointer only if aTable->mGeneration has not changed.
|
||||
class PLDHashTable
|
||||
{
|
||||
private:
|
||||
const PLDHashTableOps* const mOps; /* Virtual operations; see below. */
|
||||
int16_t mHashShift; /* multiplicative hash shift */
|
||||
const uint32_t mEntrySize; /* number of bytes in an entry */
|
||||
uint32_t mEntryCount; /* number of entries in table */
|
||||
uint32_t mRemovedCount; /* removed entry sentinels in table */
|
||||
uint32_t mGeneration; /* entry storage generation number */
|
||||
char* mEntryStore; /* entry storage; allocated lazily */
|
||||
const PLDHashTableOps* const mOps; // Virtual operations; see below.
|
||||
int16_t mHashShift; // Multiplicative hash shift.
|
||||
const uint32_t mEntrySize; // Number of bytes in an entry.
|
||||
uint32_t mEntryCount; // Number of entries in table.
|
||||
uint32_t mRemovedCount; // Removed entry sentinels in table.
|
||||
uint32_t mGeneration; // Entry storage generation number.
|
||||
char* mEntryStore; // Entry storage; allocated lazily.
|
||||
|
||||
#ifdef DEBUG
|
||||
mutable Checker mChecker;
|
||||
|
@ -287,11 +281,9 @@ public:
|
|||
// This should be used rarely.
|
||||
const PLDHashTableOps* const Ops() { return mOps; }
|
||||
|
||||
/*
|
||||
* Size in entries (gross, not net of free and removed sentinels) for table.
|
||||
* This can be zero if no elements have been added yet, in which case the
|
||||
* entry storage will not have yet been allocated.
|
||||
*/
|
||||
// Size in entries (gross, not net of free and removed sentinels) for table.
|
||||
// This can be zero if no elements have been added yet, in which case the
|
||||
// entry storage will not have yet been allocated.
|
||||
uint32_t Capacity() const
|
||||
{
|
||||
return mEntryStore ? CapacityFromHashShift() : 0;
|
||||
|
@ -495,88 +487,74 @@ private:
|
|||
PLDHashTable& operator=(const PLDHashTable& aOther) = delete;
|
||||
};
|
||||
|
||||
/*
|
||||
* Compute the hash code for a given key to be looked up, added, or removed
|
||||
* from aTable. A hash code may have any PLDHashNumber value.
|
||||
*/
|
||||
// Compute the hash code for a given key to be looked up, added, or removed
|
||||
// from aTable. A hash code may have any PLDHashNumber value.
|
||||
typedef PLDHashNumber (*PLDHashHashKey)(PLDHashTable* aTable,
|
||||
const void* aKey);
|
||||
|
||||
/*
|
||||
* Compare the key identifying aEntry in aTable with the provided key parameter.
|
||||
* Return true if keys match, false otherwise.
|
||||
*/
|
||||
// Compare the key identifying aEntry in aTable with the provided key parameter.
|
||||
// Return true if keys match, false otherwise.
|
||||
typedef bool (*PLDHashMatchEntry)(PLDHashTable* aTable,
|
||||
const PLDHashEntryHdr* aEntry,
|
||||
const void* aKey);
|
||||
|
||||
/*
|
||||
* Copy the data starting at aFrom to the new entry storage at aTo. Do not add
|
||||
* reference counts for any strong references in the entry, however, as this
|
||||
* is a "move" operation: the old entry storage at from will be freed without
|
||||
* any reference-decrementing callback shortly.
|
||||
*/
|
||||
// Copy the data starting at aFrom to the new entry storage at aTo. Do not add
|
||||
// reference counts for any strong references in the entry, however, as this
|
||||
// is a "move" operation: the old entry storage at from will be freed without
|
||||
// any reference-decrementing callback shortly.
|
||||
typedef void (*PLDHashMoveEntry)(PLDHashTable* aTable,
|
||||
const PLDHashEntryHdr* aFrom,
|
||||
PLDHashEntryHdr* aTo);
|
||||
|
||||
/*
|
||||
* Clear the entry and drop any strong references it holds. This callback is
|
||||
* invoked by Remove(), but only if the given key is found in the table.
|
||||
*/
|
||||
// Clear the entry and drop any strong references it holds. This callback is
|
||||
// invoked by Remove(), but only if the given key is found in the table.
|
||||
typedef void (*PLDHashClearEntry)(PLDHashTable* aTable,
|
||||
PLDHashEntryHdr* aEntry);
|
||||
|
||||
/*
|
||||
* Initialize a new entry, apart from mKeyHash. This function is called when
|
||||
* Add() finds no existing entry for the given key, and must add a new one. At
|
||||
* that point, |aEntry->mKeyHash| is not set yet, to avoid claiming the last
|
||||
* free entry in a severely overloaded table.
|
||||
*/
|
||||
// Initialize a new entry, apart from mKeyHash. This function is called when
|
||||
// Add() finds no existing entry for the given key, and must add a new one. At
|
||||
// that point, |aEntry->mKeyHash| is not set yet, to avoid claiming the last
|
||||
// free entry in a severely overloaded table.
|
||||
typedef void (*PLDHashInitEntry)(PLDHashEntryHdr* aEntry, const void* aKey);
|
||||
|
||||
/*
|
||||
* Finally, the "vtable" structure for PLDHashTable. The first four hooks
|
||||
* must be provided by implementations; they're called unconditionally by the
|
||||
* generic pldhash.c code. Hooks after these may be null.
|
||||
*
|
||||
* Summary of allocation-related hook usage with C++ placement new emphasis:
|
||||
* initEntry Call placement new using default key-based ctor.
|
||||
* moveEntry Call placement new using copy ctor, run dtor on old
|
||||
* entry storage.
|
||||
* clearEntry Run dtor on entry.
|
||||
*
|
||||
* Note the reason why initEntry is optional: the default hooks (stubs) clear
|
||||
* entry storage: On successful Add(tbl, key), the returned entry pointer
|
||||
* addresses an entry struct whose mKeyHash member has been set non-zero, but
|
||||
* all other entry members are still clear (null). Add() callers can test such
|
||||
* members to see whether the entry was newly created by the Add() call that
|
||||
* just succeeded. If placement new or similar initialization is required,
|
||||
* define an |initEntry| hook. Of course, the |clearEntry| hook must zero or
|
||||
* null appropriately.
|
||||
*
|
||||
* XXX assumes 0 is null for pointer types.
|
||||
*/
|
||||
// Finally, the "vtable" structure for PLDHashTable. The first four hooks
|
||||
// must be provided by implementations; they're called unconditionally by the
|
||||
// generic pldhash.c code. Hooks after these may be null.
|
||||
//
|
||||
// Summary of allocation-related hook usage with C++ placement new emphasis:
|
||||
// initEntry Call placement new using default key-based ctor.
|
||||
// moveEntry Call placement new using copy ctor, run dtor on old
|
||||
// entry storage.
|
||||
// clearEntry Run dtor on entry.
|
||||
//
|
||||
// Note the reason why initEntry is optional: the default hooks (stubs) clear
|
||||
// entry storage: On successful Add(tbl, key), the returned entry pointer
|
||||
// addresses an entry struct whose mKeyHash member has been set non-zero, but
|
||||
// all other entry members are still clear (null). Add() callers can test such
|
||||
// members to see whether the entry was newly created by the Add() call that
|
||||
// just succeeded. If placement new or similar initialization is required,
|
||||
// define an |initEntry| hook. Of course, the |clearEntry| hook must zero or
|
||||
// null appropriately.
|
||||
//
|
||||
// XXX assumes 0 is null for pointer types.
|
||||
struct PLDHashTableOps
|
||||
{
|
||||
/* Mandatory hooks. All implementations must provide these. */
|
||||
// Mandatory hooks. All implementations must provide these.
|
||||
PLDHashHashKey hashKey;
|
||||
PLDHashMatchEntry matchEntry;
|
||||
PLDHashMoveEntry moveEntry;
|
||||
PLDHashClearEntry clearEntry;
|
||||
|
||||
/* Optional hooks start here. If null, these are not called. */
|
||||
// Optional hooks start here. If null, these are not called.
|
||||
PLDHashInitEntry initEntry;
|
||||
};
|
||||
|
||||
/*
|
||||
* Default implementations for the above mOps.
|
||||
*/
|
||||
// Default implementations for the above mOps.
|
||||
|
||||
PLDHashNumber
|
||||
PL_DHashStringKey(PLDHashTable* aTable, const void* aKey);
|
||||
|
||||
/* A minimal entry is a subclass of PLDHashEntryHdr and has void key pointer. */
|
||||
// A minimal entry is a subclass of PLDHashEntryHdr and has void key pointer.
|
||||
struct PLDHashEntryStub : public PLDHashEntryHdr
|
||||
{
|
||||
const void* key;
|
||||
|
@ -603,11 +581,9 @@ PL_DHashMoveEntryStub(PLDHashTable* aTable,
|
|||
void
|
||||
PL_DHashClearEntryStub(PLDHashTable* aTable, PLDHashEntryHdr* aEntry);
|
||||
|
||||
/*
|
||||
* If you use PLDHashEntryStub or a subclass of it as your entry struct, and
|
||||
* if your entries move via memcpy and clear via memset(0), you can use these
|
||||
* stub operations.
|
||||
*/
|
||||
// If you use PLDHashEntryStub or a subclass of it as your entry struct, and
|
||||
// if your entries move via memcpy and clear via memset(0), you can use these
|
||||
// stub operations.
|
||||
const PLDHashTableOps*
|
||||
PL_DHashGetStubOps(void);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче