Bug 1264642 - Part 3. Add BufferList::MoveFallible. r=billm

It works like a move constructor but it's fallible. It can also move
data to different but compatible AllocPolicy.

MozReview-Commit-ID: LAbPWCwnrr6
This commit is contained in:
Kan-Ru Chen 2016-07-14 16:27:29 +08:00
parent 6f3e6b1234
commit 3dcef6a932
2 changed files with 52 additions and 2 deletions

View File

@ -52,6 +52,9 @@ class BufferList : private AllocPolicy
char* End() const { return mData + mSize; }
};
template<typename OtherAllocPolicy>
friend class BufferList;
public:
// For the convenience of callers, all segments are required to be a multiple
// of 8 bytes in capacity. Also, every buffer except the last one is required
@ -258,6 +261,15 @@ class BufferList : private AllocPolicy
BufferList<BorrowingAllocPolicy> Borrow(IterImpl& aIter, size_t aSize, bool* aSuccess,
BorrowingAllocPolicy aAP = BorrowingAllocPolicy());
// Return a new BufferList and move storage from this BufferList to it. The
// new BufferList owns the buffers. Move can fail, in which case *aSuccess
// will be false upon return. The new BufferList can use a different
// AllocPolicy than the original one. The new OtherAllocPolicy is responsible
// for freeing buffers, so the OtherAllocPolicy must use freeing method
// compatible to the original one.
template<typename OtherAllocPolicy>
BufferList<OtherAllocPolicy> MoveFallible(bool* aSuccess, OtherAllocPolicy aAP = OtherAllocPolicy());
// Return a new BufferList that adopts the byte range starting at Iter so that
// range [aIter, aIter + aSize) is transplanted to the returned BufferList.
// Contents of the buffer before aIter + aSize is left undefined.
@ -428,7 +440,7 @@ BufferList<AllocPolicy>::Borrow(IterImpl& aIter, size_t aSize, bool* aSuccess,
while (size) {
size_t toAdvance = std::min(size, aIter.RemainingInSegment());
if (!toAdvance || !result.mSegments.append(Segment(aIter.mData, toAdvance, toAdvance))) {
if (!toAdvance || !result.mSegments.append(typename BufferList<BorrowingAllocPolicy>::Segment(aIter.mData, toAdvance, toAdvance))) {
*aSuccess = false;
return result;
}
@ -441,6 +453,30 @@ BufferList<AllocPolicy>::Borrow(IterImpl& aIter, size_t aSize, bool* aSuccess,
return result;
}
template<typename AllocPolicy> template<typename OtherAllocPolicy>
BufferList<OtherAllocPolicy>
BufferList<AllocPolicy>::MoveFallible(bool* aSuccess, OtherAllocPolicy aAP)
{
BufferList<OtherAllocPolicy> result(0, 0, mStandardCapacity, aAP);
IterImpl iter = Iter();
while (!iter.Done()) {
size_t toAdvance = iter.RemainingInSegment();
if (!toAdvance || !result.mSegments.append(typename BufferList<OtherAllocPolicy>::Segment(iter.mData, toAdvance, toAdvance))) {
*aSuccess = false;
return result;
}
iter.Advance(*this, toAdvance);
}
result.mSize = mSize;
mSegments.clear();
mSize = 0;
*aSuccess = true;
return result;
}
template<typename AllocPolicy>
BufferList<AllocPolicy>
BufferList<AllocPolicy>::Extract(IterImpl& aIter, size_t aSize, bool* aSuccess)

View File

@ -213,6 +213,21 @@ int main(void)
MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl, kSmallWrite * 3));
MOZ_RELEASE_ASSERT(iter.Done());
// MoveFallible
bool success;
bl2 = bl.MoveFallible<InfallibleAllocPolicy>(&success);
MOZ_RELEASE_ASSERT(success);
MOZ_RELEASE_ASSERT(bl.Size() == 0);
MOZ_RELEASE_ASSERT(bl.Iter().Done());
MOZ_RELEASE_ASSERT(bl2.Size() == kSmallWrite * 3);
iter = bl2.Iter();
MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl2, kSmallWrite * 3));
MOZ_RELEASE_ASSERT(iter.Done());
bl = bl2.MoveFallible<InfallibleAllocPolicy>(&success);
// Borrowing.
const size_t kBorrowStart = 4;
@ -220,7 +235,6 @@ int main(void)
iter = bl.Iter();
iter.Advance(bl, kBorrowStart);
bool success;
bl2 = bl.Borrow<InfallibleAllocPolicy>(iter, kBorrowSize, &success);
MOZ_RELEASE_ASSERT(success);
MOZ_RELEASE_ASSERT(bl2.Size() == kBorrowSize);