Skip to content

Commit

Permalink
Bug 1264642 - Part 3. Add BufferList::MoveFallible. r=billm
Browse files Browse the repository at this point in the history
It works like a move constructor but it's fallible. It can also move
data to different but compatible AllocPolicy.

MozReview-Commit-ID: LAbPWCwnrr6
  • Loading branch information
kanru committed Aug 22, 2016
1 parent b97374c commit f874364
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 2 deletions.
38 changes: 37 additions & 1 deletion mfbt/BufferList.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
}
Expand All @@ -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)
Expand Down
16 changes: 15 additions & 1 deletion mfbt/tests/TestBufferList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,14 +213,28 @@ 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;
const size_t kBorrowSize = 24;

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);
Expand Down

0 comments on commit f874364

Please sign in to comment.