Skip to content

Commit

Permalink
Bug 1869256 - Add move assignment operator for SegmentedVector r=mccr8
Browse files Browse the repository at this point in the history
The patch implements the move assigment operator in terms of the move
constructor. This fulfills the requirements for std::swap to compile.

Differential Revision: https://phabricator.services.mozilla.com/D196035
  • Loading branch information
jonco3 committed Dec 11, 2023
1 parent 7b90cdd commit 55354b5
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 22 deletions.
7 changes: 7 additions & 0 deletions mfbt/SegmentedVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ class SegmentedVector : private AllocPolicy {

SegmentedVector(SegmentedVector&& aOther)
: mSegments(std::move(aOther.mSegments)) {}
SegmentedVector& operator=(SegmentedVector&& aOther) {
if (&aOther != this) {
this->~SegmentedVector();
new (this) SegmentedVector(std::move(aOther));
}
return *this;
}

~SegmentedVector() { Clear(); }

Expand Down
63 changes: 41 additions & 22 deletions mfbt/tests/TestSegmentedVector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ class InfallibleAllocPolicy {
}
};

template <typename Vector>
void CheckContents(Vector& vector, size_t expectedLength) {
MOZ_RELEASE_ASSERT(vector.Length() == expectedLength);
size_t n = 0;
for (auto iter = vector.Iter(); !iter.Done(); iter.Next()) {
MOZ_RELEASE_ASSERT(iter.Get() == int(n));
n++;
}
MOZ_RELEASE_ASSERT(n == expectedLength);
}

// We want to test Append(), which is fallible and marked with
// [[nodiscard]]. But we're using an infallible alloc policy, and so
// don't really need to check the result. Casting to |void| works with clang
Expand All @@ -47,7 +58,7 @@ void TestBasics() {
// A SegmentedVector with a POD element type.
typedef SegmentedVector<int, 1024, InfallibleAllocPolicy> MyVector;
MyVector v;
int i, n;
int i;

MOZ_RELEASE_ASSERT(v.IsEmpty());

Expand All @@ -57,28 +68,14 @@ void TestBasics() {
gDummy = v.Append(std::move(i));
}
MOZ_RELEASE_ASSERT(!v.IsEmpty());
MOZ_RELEASE_ASSERT(v.Length() == 100);

n = 0;
for (auto iter = v.Iter(); !iter.Done(); iter.Next()) {
MOZ_RELEASE_ASSERT(iter.Get() == n);
n++;
}
MOZ_RELEASE_ASSERT(n == 100);
CheckContents(v, 100);

// Add another 900 elements, then re-check.
for (; i < 1000; i++) {
v.InfallibleAppend(std::move(i));
}
MOZ_RELEASE_ASSERT(!v.IsEmpty());
MOZ_RELEASE_ASSERT(v.Length() == 1000);

n = 0;
for (auto iter = v.Iter(); !iter.Done(); iter.Next()) {
MOZ_RELEASE_ASSERT(iter.Get() == n);
n++;
}
MOZ_RELEASE_ASSERT(n == 1000);
CheckContents(v, 1000);

// Pop off all of the elements.
MOZ_RELEASE_ASSERT(v.Length() == 1000);
Expand Down Expand Up @@ -112,12 +109,33 @@ void TestBasics() {
MOZ_RELEASE_ASSERT(v.Length() == 700);

// Verify the contents are what we expect.
n = 0;
for (auto iter = v.Iter(); !iter.Done(); iter.Next()) {
MOZ_RELEASE_ASSERT(iter.Get() == n);
n++;
CheckContents(v, 700);
}

void TestMoveAndSwap() {
typedef SegmentedVector<int, 32, InfallibleAllocPolicy> MyVector;
MyVector v;

for (int i = 0; i < 100; i++) {
(void)v.Append(i);
}
MOZ_RELEASE_ASSERT(n == 700);
MOZ_RELEASE_ASSERT(!v.IsEmpty());
CheckContents(v, 100);

// Test move constructor.
MyVector w(std::move(v));
CheckContents(w, 100);
MOZ_RELEASE_ASSERT(v.IsEmpty());

// Test move assignment.
v = std::move(w);
CheckContents(v, 100);
MOZ_RELEASE_ASSERT(w.IsEmpty());

// Test swap.
std::swap(v, w);
CheckContents(w, 100);
MOZ_RELEASE_ASSERT(v.IsEmpty());
}

static size_t gNumDefaultCtors;
Expand Down Expand Up @@ -361,6 +379,7 @@ void TestIterator() {

int main(void) {
TestBasics();
TestMoveAndSwap();
TestConstructorsAndDestructors();
TestSegmentCapacitiesAndAlignments();
TestIterator();
Expand Down

0 comments on commit 55354b5

Please sign in to comment.