mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 20:05:49 +00:00
Bug 1168007 (part 1) - Add PLDHashTable::{Clear,ClearAndPrepareForLength}(). r=froydnj.
--HG-- extra : rebase_source : 05445de53b178173bfbaed29095e0ca4c11639a2
This commit is contained in:
parent
e517cc3f1e
commit
249958c03d
@ -400,6 +400,25 @@ PLDHashTable2::~PLDHashTable2()
|
||||
PLDHashTable::Finish();
|
||||
}
|
||||
|
||||
void
|
||||
PLDHashTable2::ClearAndPrepareForLength(uint32_t aLength)
|
||||
{
|
||||
MOZ_ASSERT(IsInitialized());
|
||||
|
||||
// Get these values before the call to Finish() clobbers them.
|
||||
const PLDHashTableOps* ops = mOps;
|
||||
uint32_t entrySize = mEntrySize;
|
||||
|
||||
PLDHashTable::Finish();
|
||||
PLDHashTable::Init(ops, entrySize, aLength);
|
||||
}
|
||||
|
||||
void
|
||||
PLDHashTable2::Clear()
|
||||
{
|
||||
ClearAndPrepareForLength(PL_DHASH_DEFAULT_INITIAL_LENGTH);
|
||||
}
|
||||
|
||||
// If |IsAdd| is true, the return value is always non-null and it may be a
|
||||
// previously-removed entry. If |IsAdd| is false, the return value is null on a
|
||||
// miss, and will never be a previously-removed entry on a hit. This
|
||||
|
@ -161,6 +161,8 @@ typedef size_t (*PLDHashSizeOfEntryExcludingThisFun)(
|
||||
*/
|
||||
class PLDHashTable
|
||||
{
|
||||
friend class PLDHashTable2;
|
||||
|
||||
private:
|
||||
const PLDHashTableOps* mOps; /* Virtual operations; see below. */
|
||||
int16_t mHashShift; /* multiplicative hash shift */
|
||||
@ -370,6 +372,20 @@ public:
|
||||
|
||||
void Finish() { MOZ_CRASH("PLDHashTable2::Finish()"); }
|
||||
|
||||
// This function is equivalent to
|
||||
// ClearAndPrepareForLength(PL_DHASH_DEFAULT_INITIAL_LENGTH).
|
||||
void Clear();
|
||||
|
||||
// This function clears the table's contents and frees its entry storage,
|
||||
// leaving it in a empty state ready to be used again. Afterwards, when the
|
||||
// first element is added the entry storage that gets allocated will have a
|
||||
// capacity large enough to fit |aLength| elements without rehashing.
|
||||
//
|
||||
// It's conceptually the same as calling the destructor and then re-calling
|
||||
// the constructor with the original |aOps| and |aEntrySize| arguments, and
|
||||
// a new |aLength| argument.
|
||||
void ClearAndPrepareForLength(uint32_t aLength);
|
||||
|
||||
private:
|
||||
PLDHashTable2(const PLDHashTable2& aOther) = delete;
|
||||
PLDHashTable2& operator=(const PLDHashTable2& aOther) = delete;
|
||||
|
@ -109,28 +109,28 @@ static bool test_pldhash_lazy_storage()
|
||||
return true;
|
||||
}
|
||||
|
||||
// We insert the integers 0.., so this hash function is (a) as simple as
|
||||
// possible, and (b) collision-free. Both of which are good, because we want
|
||||
// this test to be as fast as possible.
|
||||
// A trivial hash function is good enough here. It's also super-fast for
|
||||
// test_pldhash_grow_to_max_capacity() because we insert the integers 0..,
|
||||
// which means it's collision-free.
|
||||
static PLDHashNumber
|
||||
trivial_hash(PLDHashTable *table, const void *key)
|
||||
{
|
||||
return (PLDHashNumber)(size_t)key;
|
||||
}
|
||||
|
||||
static const PLDHashTableOps trivialOps = {
|
||||
trivial_hash,
|
||||
PL_DHashMatchEntryStub,
|
||||
PL_DHashMoveEntryStub,
|
||||
PL_DHashClearEntryStub,
|
||||
nullptr
|
||||
};
|
||||
|
||||
static bool test_pldhash_move_semantics()
|
||||
{
|
||||
static const PLDHashTableOps ops = {
|
||||
trivial_hash,
|
||||
PL_DHashMatchEntryStub,
|
||||
PL_DHashMoveEntryStub,
|
||||
PL_DHashClearEntryStub,
|
||||
nullptr
|
||||
};
|
||||
|
||||
PLDHashTable2 t1(&ops, sizeof(PLDHashEntryStub));
|
||||
PLDHashTable2 t1(&trivialOps, sizeof(PLDHashEntryStub));
|
||||
PL_DHashTableAdd(&t1, (const void*)88);
|
||||
PLDHashTable2 t2(&ops, sizeof(PLDHashEntryStub));
|
||||
PLDHashTable2 t2(&trivialOps, sizeof(PLDHashEntryStub));
|
||||
PL_DHashTableAdd(&t2, (const void*)99);
|
||||
|
||||
t1 = mozilla::Move(t1); // self-move
|
||||
@ -138,7 +138,7 @@ static bool test_pldhash_move_semantics()
|
||||
t1 = mozilla::Move(t2); // inited overwritten with inited
|
||||
|
||||
PLDHashTable t3, t4;
|
||||
PL_DHashTableInit(&t3, &ops, sizeof(PLDHashEntryStub));
|
||||
PL_DHashTableInit(&t3, &trivialOps, sizeof(PLDHashEntryStub));
|
||||
PL_DHashTableAdd(&t3, (const void*)88);
|
||||
|
||||
t3 = mozilla::Move(t4); // inited overwritten with uninited
|
||||
@ -147,7 +147,7 @@ static bool test_pldhash_move_semantics()
|
||||
PL_DHashTableFinish(&t4);
|
||||
|
||||
PLDHashTable t5, t6;
|
||||
PL_DHashTableInit(&t6, &ops, sizeof(PLDHashEntryStub));
|
||||
PL_DHashTableInit(&t6, &trivialOps, sizeof(PLDHashEntryStub));
|
||||
PL_DHashTableAdd(&t6, (const void*)88);
|
||||
|
||||
t5 = mozilla::Move(t6); // uninited overwritten with inited
|
||||
@ -158,27 +158,63 @@ static bool test_pldhash_move_semantics()
|
||||
PLDHashTable t7;
|
||||
PLDHashTable t8(mozilla::Move(t7)); // new table constructed with uninited
|
||||
|
||||
PLDHashTable2 t9(&ops, sizeof(PLDHashEntryStub));
|
||||
PLDHashTable2 t9(&trivialOps, sizeof(PLDHashEntryStub));
|
||||
PL_DHashTableAdd(&t9, (const void*)88);
|
||||
PLDHashTable t10(mozilla::Move(t9)); // new table constructed with inited
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_pldhash_Clear()
|
||||
{
|
||||
PLDHashTable2 t1(&trivialOps, sizeof(PLDHashEntryStub));
|
||||
|
||||
t1.Clear();
|
||||
if (t1.EntryCount() != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
t1.ClearAndPrepareForLength(100);
|
||||
if (t1.EntryCount() != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PL_DHashTableAdd(&t1, (const void*)77);
|
||||
PL_DHashTableAdd(&t1, (const void*)88);
|
||||
PL_DHashTableAdd(&t1, (const void*)99);
|
||||
if (t1.EntryCount() != 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
t1.Clear();
|
||||
if (t1.EntryCount() != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PL_DHashTableAdd(&t1, (const void*)55);
|
||||
PL_DHashTableAdd(&t1, (const void*)66);
|
||||
PL_DHashTableAdd(&t1, (const void*)77);
|
||||
PL_DHashTableAdd(&t1, (const void*)88);
|
||||
PL_DHashTableAdd(&t1, (const void*)99);
|
||||
if (t1.EntryCount() != 5) {
|
||||
return false;
|
||||
}
|
||||
|
||||
t1.ClearAndPrepareForLength(8192);
|
||||
if (t1.EntryCount() != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// See bug 931062, we skip this test on Android due to OOM.
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
static bool test_pldhash_grow_to_max_capacity()
|
||||
{
|
||||
static const PLDHashTableOps ops = {
|
||||
trivial_hash,
|
||||
PL_DHashMatchEntryStub,
|
||||
PL_DHashMoveEntryStub,
|
||||
PL_DHashClearEntryStub,
|
||||
nullptr
|
||||
};
|
||||
|
||||
// This is infallible.
|
||||
PLDHashTable2* t = new PLDHashTable2(&ops, sizeof(PLDHashEntryStub), 128);
|
||||
PLDHashTable2* t =
|
||||
new PLDHashTable2(&trivialOps, sizeof(PLDHashEntryStub), 128);
|
||||
|
||||
// Check that New() sets |t->ops|.
|
||||
if (!t->IsInitialized()) {
|
||||
@ -219,6 +255,7 @@ static const struct Test {
|
||||
DECL_TEST(test_pldhash_Init_capacity_ok),
|
||||
DECL_TEST(test_pldhash_lazy_storage),
|
||||
DECL_TEST(test_pldhash_move_semantics),
|
||||
DECL_TEST(test_pldhash_Clear),
|
||||
// See bug 931062, we skip this test on Android due to OOM.
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
DECL_TEST(test_pldhash_grow_to_max_capacity),
|
||||
@ -235,7 +272,7 @@ int main(int argc, char *argv[])
|
||||
bool success = true;
|
||||
for (const Test* t = tests; t->name != nullptr; ++t) {
|
||||
bool test_result = t->func();
|
||||
printf("%25s : %s\n", t->name, test_result ? "SUCCESS" : "FAILURE");
|
||||
printf("%35s : %s\n", t->name, test_result ? "SUCCESS" : "FAILURE");
|
||||
if (!test_result)
|
||||
success = false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user