Bug 853548 - Make nsTArray::SetCapacity and InfallibleTArray::SetCapacity return void; r=jlebar

This commit is contained in:
Ehsan Akhgari 2013-03-21 15:02:20 -04:00
parent 8137c577f8
commit 26e9dbb207
3 changed files with 102 additions and 24 deletions

View File

@ -154,7 +154,9 @@ public:
// Ensures there is enough space to store a total of aCapacity objects.
// This method never deletes any objects.
bool SetCapacity(uint32_t aCapacity) {
return mArray.SetCapacity(aCapacity);
mArray.SetCapacity(aCapacity);
// TODO: Make this method return void
return true;
}
uint32_t Capacity() {
return mArray.Capacity();

View File

@ -97,11 +97,11 @@ bool nsTArray_base<Alloc>::UsesAutoArrayBuffer() const {
template<class Alloc>
bool
typename Alloc::ResultTypeProxy
nsTArray_base<Alloc>::EnsureCapacity(size_type capacity, size_type elemSize) {
// This should be the most common case so test this first
if (capacity <= mHdr->mCapacity)
return true;
return Alloc::SuccessResult();
// If the requested memory allocation exceeds size_type(-1)/2, then
// our doubling algorithm may not be able to allocate it.
@ -110,7 +110,7 @@ nsTArray_base<Alloc>::EnsureCapacity(size_type capacity, size_type elemSize) {
// allocating 2 GB+ arrays anyway.
if ((uint64_t)capacity * elemSize > size_type(-1)/2) {
Alloc::SizeTooBig();
return false;
return Alloc::FailureResult();
}
if (mHdr == EmptyHdr()) {
@ -118,13 +118,13 @@ nsTArray_base<Alloc>::EnsureCapacity(size_type capacity, size_type elemSize) {
Header *header = static_cast<Header*>
(Alloc::Malloc(sizeof(Header) + capacity * elemSize));
if (!header)
return false;
return Alloc::FailureResult();
header->mLength = 0;
header->mCapacity = capacity;
header->mIsAutoArray = 0;
mHdr = header;
return true;
return Alloc::SuccessResult();
}
// We increase our capacity so |capacity * elemSize + sizeof(Header)| is the
@ -159,14 +159,14 @@ nsTArray_base<Alloc>::EnsureCapacity(size_type capacity, size_type elemSize) {
// Malloc() and copy
header = static_cast<Header*>(Alloc::Malloc(bytesToAlloc));
if (!header)
return false;
return Alloc::FailureResult();
memcpy(header, mHdr, sizeof(Header) + Length() * elemSize);
} else {
// Realloc() existing data
header = static_cast<Header*>(Alloc::Realloc(mHdr, bytesToAlloc));
if (!header)
return false;
return Alloc::FailureResult();
}
// How many elements can we fit in bytesToAlloc?
@ -176,7 +176,7 @@ nsTArray_base<Alloc>::EnsureCapacity(size_type capacity, size_type elemSize) {
mHdr = header;
return true;
return Alloc::SuccessResult();
}
template<class Alloc>
@ -342,8 +342,8 @@ nsTArray_base<Alloc>::SwapArrayElements(nsTArray_base<Allocator>& other,
// write Y straight into X's auto buffer, write X's malloc'ed buffer on top
// of Y, and then switch X to using its auto buffer.)
if (!EnsureCapacity(other.Length(), elemSize) ||
!other.EnsureCapacity(Length(), elemSize)) {
if (!Alloc::Successful(EnsureCapacity(other.Length(), elemSize)) ||
!Allocator::Successful(other.EnsureCapacity(Length(), elemSize))) {
return false;
}
@ -371,7 +371,7 @@ nsTArray_base<Alloc>::SwapArrayElements(nsTArray_base<Allocator>& other,
// auto buffer, so we're likely not allocating a lot of space here. But one
// could, in theory, allocate a huge AutoTArray on the heap.)
nsAutoArrayBase<nsTArray_Impl<uint8_t, Alloc>, 64> temp;
if (!temp.SetCapacity(smallerLength * elemSize)) {
if (!Alloc::Successful(temp.EnsureCapacity(smallerLength, elemSize))) {
return false;
}

View File

@ -74,15 +74,91 @@
//
//
// nsTArrayFallibleResult and nsTArrayInfallibleResult types are proxy types
// which are used because you cannot use a templated type which is bound to
// void as an argument to a void function. In order to work around that, we
// encode either a void or a boolean inside these proxy objects, and pass them
// to the aforementioned function instead, and then use the type information to
// decide what to do in the function.
//
// Note that public nsTArray methods should never return a proxy type. Such
// types are only meant to be used in the internal nsTArray helper methods.
// Public methods returning non-proxy types cannot be called from other
// nsTArray members.
//
struct nsTArrayFallibleResult
{
// Note: allows implicit conversions from and to bool
nsTArrayFallibleResult(bool result)
: mResult(result)
{}
operator bool() {
return mResult;
}
private:
bool mResult;
};
struct nsTArrayInfallibleResult
{
};
//
// nsTArray*Allocators must all use the same |free()|, to allow swap()'ing
// between fallible and infallible variants.
//
struct nsTArrayFallibleAllocatorBase
{
typedef bool ResultType;
typedef nsTArrayFallibleResult ResultTypeProxy;
static ResultType Result(ResultTypeProxy result) {
return result;
}
static bool Successful(ResultTypeProxy result) {
return result;
}
static ResultTypeProxy SuccessResult() {
return true;
}
static ResultTypeProxy FailureResult() {
return false;
}
};
struct nsTArrayInfallibleAllocatorBase
{
typedef void ResultType;
typedef nsTArrayInfallibleResult ResultTypeProxy;
static ResultType Result(ResultTypeProxy result) {
}
static bool Successful(ResultTypeProxy) {
return true;
}
static ResultTypeProxy SuccessResult() {
return ResultTypeProxy();
}
static ResultTypeProxy FailureResult() {
NS_RUNTIMEABORT("Infallible nsTArray should never fail");
return ResultTypeProxy();
}
};
#if defined(MOZALLOC_HAVE_XMALLOC)
#include "mozilla/mozalloc_abort.h"
struct nsTArrayFallibleAllocator
struct nsTArrayFallibleAllocator : nsTArrayFallibleAllocatorBase
{
static void* Malloc(size_t size) {
return moz_malloc(size);
@ -100,7 +176,7 @@ struct nsTArrayFallibleAllocator
}
};
struct nsTArrayInfallibleAllocator
struct nsTArrayInfallibleAllocator : nsTArrayInfallibleAllocatorBase
{
static void* Malloc(size_t size) {
return moz_xmalloc(size);
@ -122,7 +198,7 @@ struct nsTArrayInfallibleAllocator
#else
#include <stdlib.h>
struct nsTArrayFallibleAllocator
struct nsTArrayFallibleAllocator : nsTArrayFallibleAllocatorBase
{
static void* Malloc(size_t size) {
return malloc(size);
@ -140,7 +216,7 @@ struct nsTArrayFallibleAllocator
}
};
struct nsTArrayInfallibleAllocator
struct nsTArrayInfallibleAllocator : nsTArrayInfallibleAllocatorBase
{
static void* Malloc(size_t size) {
void* ptr = malloc(size);
@ -304,7 +380,7 @@ protected:
// @param capacity The requested number of array elements.
// @param elemSize The size of an array element.
// @return False if insufficient memory is available; true otherwise.
bool EnsureCapacity(size_type capacity, size_type elemSize);
typename Alloc::ResultTypeProxy EnsureCapacity(size_type capacity, size_type elemSize);
// Resize the storage to the minimum required amount.
// @param elemSize The size of an array element.
@ -828,7 +904,7 @@ public:
elem_type *ReplaceElementsAt(index_type start, size_type count,
const Item* array, size_type arrayLen) {
// Adjust memory allocation up-front to catch errors.
if (!this->EnsureCapacity(Length() + arrayLen - count, sizeof(elem_type)))
if (!Alloc::Successful(this->EnsureCapacity(Length() + arrayLen - count, sizeof(elem_type))))
return nullptr;
DestructRange(start, count);
this->ShiftData(start, count, arrayLen, sizeof(elem_type), MOZ_ALIGNOF(elem_type));
@ -879,7 +955,7 @@ public:
// temporaries.
// @return A pointer to the newly inserted element, or null on OOM.
elem_type* InsertElementAt(index_type index) {
if (!this->EnsureCapacity(Length() + 1, sizeof(elem_type)))
if (!Alloc::Successful(this->EnsureCapacity(Length() + 1, sizeof(elem_type))))
return nullptr;
this->ShiftData(index, 0, 1, sizeof(elem_type), MOZ_ALIGNOF(elem_type));
elem_type *elem = Elements() + index;
@ -954,7 +1030,7 @@ public:
// the operation failed due to insufficient memory.
template<class Item>
elem_type *AppendElements(const Item* array, size_type arrayLen) {
if (!this->EnsureCapacity(Length() + arrayLen, sizeof(elem_type)))
if (!Alloc::Successful(this->EnsureCapacity(Length() + arrayLen, sizeof(elem_type))))
return nullptr;
index_type len = Length();
AssignRange(len, arrayLen, array);
@ -978,7 +1054,7 @@ public:
// temporaries.
// @return A pointer to the newly appended elements, or null on OOM.
elem_type *AppendElements(size_type count) {
if (!this->EnsureCapacity(Length() + count, sizeof(elem_type)))
if (!Alloc::Successful(this->EnsureCapacity(Length() + count, sizeof(elem_type))))
return nullptr;
elem_type *elems = Elements() + Length();
size_type i;
@ -1004,7 +1080,7 @@ public:
MOZ_ASSERT(&array != this, "argument must be different array");
index_type len = Length();
index_type otherLen = array.Length();
if (!this->EnsureCapacity(len + otherLen, sizeof(elem_type)))
if (!Alloc::Successful(this->EnsureCapacity(len + otherLen, sizeof(elem_type))))
return nullptr;
memcpy(Elements() + len, array.Elements(), otherLen * sizeof(elem_type));
this->IncrementLength(otherLen);
@ -1095,8 +1171,8 @@ public:
// will not reduce the number of elements in this array.
// @param capacity The desired capacity of this array.
// @return True if the operation succeeded; false if we ran out of memory
bool SetCapacity(size_type capacity) {
return this->EnsureCapacity(capacity, sizeof(elem_type));
typename Alloc::ResultType SetCapacity(size_type capacity) {
return Alloc::Result(this->EnsureCapacity(capacity, sizeof(elem_type)));
}
// This method modifies the length of the array. If the new length is