diff --git a/mfbt/SmallPointerArray.h b/mfbt/SmallPointerArray.h index 2eba8f96f034..7863f6e04e52 100644 --- a/mfbt/SmallPointerArray.h +++ b/mfbt/SmallPointerArray.h @@ -10,6 +10,7 @@ #define mozilla_SmallPointerArray_h #include "mozilla/Assertions.h" +#include "mozilla/PodOperations.h" #include #include @@ -19,7 +20,7 @@ namespace mozilla { // Array class for situations where a small number of NON-NULL elements (<= 2) -// is expected, a large number of elements must be accomodated if necessary, +// is expected, a large number of elements must be accommodated if necessary, // and the size of the class must be minimal. Typical vector implementations // will fulfill the first two requirements by simply adding inline storage // alongside the rest of their member variables. While this strategy works, @@ -49,6 +50,17 @@ class SmallPointerArray { } } + SmallPointerArray(SmallPointerArray&& aOther) { + PodCopy(mArray, aOther.mArray, 2); + aOther.mArray[0].mValue = nullptr; + aOther.mArray[1].mVector = nullptr; + } + + SmallPointerArray& operator=(SmallPointerArray&& aOther) { + std::swap(mArray, aOther.mArray); + return *this; + } + void Clear() { if (first()) { first() = nullptr; @@ -160,6 +172,8 @@ class SmallPointerArray { return 0; } + bool IsEmpty() const { return Length() == 0; } + T* ElementAt(size_t aIndex) const { MOZ_ASSERT(aIndex < Length()); if (first()) { diff --git a/mfbt/tests/TestSmallPointerArray.cpp b/mfbt/tests/TestSmallPointerArray.cpp index 42d97003e4f3..163b2b1df81f 100644 --- a/mfbt/tests/TestSmallPointerArray.cpp +++ b/mfbt/tests/TestSmallPointerArray.cpp @@ -192,8 +192,46 @@ void TestRangeBasedLoops() { MOZ_RELEASE_ASSERT(entries == 0); } +void TestMove() { + using namespace mozilla; + + SmallPointerArray testArray; + testArray.AppendElement(PTR1); + testArray.AppendElement(PTR2); + + SmallPointerArray moved = std::move(testArray); + + MOZ_RELEASE_ASSERT(testArray.IsEmpty()); + MOZ_RELEASE_ASSERT(moved.Length() == 2); + MOZ_RELEASE_ASSERT(moved[0] == PTR1); + MOZ_RELEASE_ASSERT(moved[1] == PTR2); + + // Heap case. + moved.AppendElement(PTR3); + + SmallPointerArray another = std::move(moved); + + MOZ_RELEASE_ASSERT(testArray.IsEmpty()); + MOZ_RELEASE_ASSERT(moved.IsEmpty()); + MOZ_RELEASE_ASSERT(another.Length() == 3); + MOZ_RELEASE_ASSERT(another[0] == PTR1); + MOZ_RELEASE_ASSERT(another[1] == PTR2); + MOZ_RELEASE_ASSERT(another[2] == PTR3); + + // Move assignment. + testArray = std::move(another); + + MOZ_RELEASE_ASSERT(moved.IsEmpty()); + MOZ_RELEASE_ASSERT(another.IsEmpty()); + MOZ_RELEASE_ASSERT(testArray.Length() == 3); + MOZ_RELEASE_ASSERT(testArray[0] == PTR1); + MOZ_RELEASE_ASSERT(testArray[1] == PTR2); + MOZ_RELEASE_ASSERT(testArray[2] == PTR3); +} + int main() { TestArrayManipulation(); TestRangeBasedLoops(); + TestMove(); return 0; }