Bug 1913111 - mfbt: Add HashTable::swap. r=glandium

I'm replacing a usage of Vector with HashMap, and I need the
equivalent of Vector::swap for HashMap.

Differential Revision: https://phabricator.services.mozilla.com/D231455
This commit is contained in:
Ryan Hunt
2024-12-15 19:20:54 +00:00
parent 5238a36108
commit dd41bfe7a8
2 changed files with 65 additions and 0 deletions

View File

@@ -180,6 +180,9 @@ class HashMap {
HashMap(HashMap&& aRhs) = default;
HashMap& operator=(HashMap&& aRhs) = default;
// Swap the contents of this hash map with another.
void swap(HashMap& aOther) { mImpl.swap(aOther.mImpl); }
// -- Status and sizing ----------------------------------------------------
// The map's current generation.
@@ -477,6 +480,9 @@ class HashSet {
HashSet(HashSet&& aRhs) = default;
HashSet& operator=(HashSet&& aRhs) = default;
// Swap the contents of this hash set with another.
void swap(HashSet& aOther) { mImpl.swap(aOther.mImpl); }
// -- Status and sizing ----------------------------------------------------
// The set's current generation.
@@ -1558,6 +1564,29 @@ class HashTable : private AllocPolicy {
return *this;
}
void swap(HashTable& aOther) {
ReentrancyGuard g1(*this);
ReentrancyGuard g2(aOther);
// Manual swap of generation because it's a bitfield
uint64_t generation = mGen;
mGen = aOther.mGen;
aOther.mGen = generation;
// Manual swap of hashShift because it's a bitfield
uint64_t hashShift = mHashShift;
mHashShift = aOther.mHashShift;
aOther.mHashShift = hashShift;
std::swap(mTable, aOther.mTable);
std::swap(mEntryCount, aOther.mEntryCount);
std::swap(mRemovedCount, aOther.mRemovedCount);
#ifdef DEBUG
std::swap(mMutationCount, aOther.mMutationCount);
std::swap(mEntered, aOther.mEntered);
#endif
}
private:
void moveFrom(HashTable& aRhs) {
mGen = aRhs.mGen;

View File

@@ -32,6 +32,42 @@ void TestMoveConstructor() {
MOZ_RELEASE_ASSERT(!map.count());
}
void CheckSwapMap1(const mozilla::HashMap<int, int>& map1) {
MOZ_RELEASE_ASSERT(map1.count() == 2);
MOZ_RELEASE_ASSERT(!map1.empty());
MOZ_RELEASE_ASSERT(!map1.lookup(3));
MOZ_RELEASE_ASSERT(!map1.lookup(4));
MOZ_RELEASE_ASSERT(map1.lookup(1)->value() == 10);
MOZ_RELEASE_ASSERT(map1.lookup(2)->value() == 20);
}
void CheckSwapMap2(const mozilla::HashMap<int, int>& map2) {
MOZ_RELEASE_ASSERT(map2.count() == 2);
MOZ_RELEASE_ASSERT(!map2.empty());
MOZ_RELEASE_ASSERT(!map2.lookup(1));
MOZ_RELEASE_ASSERT(!map2.lookup(2));
MOZ_RELEASE_ASSERT(map2.lookup(3)->value() == 30);
MOZ_RELEASE_ASSERT(map2.lookup(4)->value() == 40);
}
void TestSwap() {
using namespace mozilla;
HashMap<int, int> map1;
MOZ_RELEASE_ASSERT(map1.putNew(1, 10));
MOZ_RELEASE_ASSERT(map1.putNew(2, 20));
CheckSwapMap1(map1);
HashMap<int, int> map2;
MOZ_RELEASE_ASSERT(map2.putNew(3, 30));
MOZ_RELEASE_ASSERT(map2.putNew(4, 40));
CheckSwapMap2(map2);
map1.swap(map2);
CheckSwapMap2(map1);
CheckSwapMap1(map2);
}
enum SimpleEnum { SIMPLE_1, SIMPLE_2 };
enum class ClassEnum : int {