| Index: cc/base/list_container.cc
|
| diff --git a/cc/base/list_container.cc b/cc/base/list_container.cc
|
| index df21a5b2e486a144736e9c817c66aa30d5acccda..ef4d08c116faecd8033d11ff4a82a8135f290fef 100644
|
| --- a/cc/base/list_container.cc
|
| +++ b/cc/base/list_container.cc
|
| @@ -53,6 +53,7 @@ class ListContainerBase::ListContainerCharAllocator {
|
| --capacity;
|
| }
|
|
|
| + bool IsEmpty() const { return !size; }
|
| bool IsFull() { return capacity == size; }
|
| size_t NumElementsAvailable() const { return capacity - size; }
|
|
|
| @@ -62,6 +63,11 @@ class ListContainerBase::ListContainerCharAllocator {
|
| return LastElement();
|
| }
|
|
|
| + void RemoveLast() {
|
| + DCHECK(!IsEmpty());
|
| + --size;
|
| + }
|
| +
|
| char* Begin() const { return data.get(); }
|
| char* End() const { return data.get() + size * step; }
|
| char* LastElement() const { return data.get() + (size - 1) * step; }
|
| @@ -74,32 +80,41 @@ class ListContainerBase::ListContainerCharAllocator {
|
| explicit ListContainerCharAllocator(size_t element_size)
|
| : element_size_(element_size),
|
| size_(0),
|
| - list_count_(0),
|
| + last_list_index_(0),
|
| last_list_(NULL) {
|
| AllocateNewList(kDefaultNumElementTypesToReserve);
|
| + last_list_ = storage_[last_list_index_];
|
| }
|
|
|
| ListContainerCharAllocator(size_t element_size, size_t element_count)
|
| : element_size_(element_size),
|
| size_(0),
|
| - list_count_(0),
|
| + last_list_index_(0),
|
| last_list_(NULL) {
|
| AllocateNewList(element_count > 0 ? element_count
|
| : kDefaultNumElementTypesToReserve);
|
| + last_list_ = storage_[last_list_index_];
|
| }
|
|
|
| ~ListContainerCharAllocator() {}
|
|
|
| void* Allocate() {
|
| - if (last_list_->IsFull())
|
| - AllocateNewList(last_list_->capacity * 2);
|
| + if (last_list_->IsFull()) {
|
| + // Only allocate a new list if there isn't a spare one still there from
|
| + // previous usage.
|
| + if (last_list_index_ + 1 >= storage_.size())
|
| + AllocateNewList(last_list_->capacity * 2);
|
| +
|
| + ++last_list_index_;
|
| + last_list_ = storage_[last_list_index_];
|
| + }
|
|
|
| ++size_;
|
| return last_list_->AddElement();
|
| }
|
|
|
| size_t element_size() const { return element_size_; }
|
| - size_t list_count() const { return list_count_; }
|
| + size_t list_count() const { return storage_.size(); }
|
| size_t size() const { return size_; }
|
| bool IsEmpty() const { return size() == 0; }
|
|
|
| @@ -115,10 +130,25 @@ class ListContainerBase::ListContainerCharAllocator {
|
| void Clear() {
|
| size_t initial_allocation_size = storage_.front()->capacity;
|
| storage_.clear();
|
| - list_count_ = 0;
|
| last_list_ = NULL;
|
| + last_list_index_ = 0;
|
| size_ = 0;
|
| AllocateNewList(initial_allocation_size);
|
| + last_list_ = storage_[last_list_index_];
|
| + }
|
| +
|
| + void RemoveLast() {
|
| + DCHECK(!IsEmpty());
|
| + last_list_->RemoveLast();
|
| + if (last_list_->IsEmpty() && last_list_index_ > 0) {
|
| + --last_list_index_;
|
| + last_list_ = storage_[last_list_index_];
|
| +
|
| + // If there are now two empty inner lists, free one of them.
|
| + if (last_list_index_ + 2 < storage_.size())
|
| + storage_.pop_back();
|
| + }
|
| + --size_;
|
| }
|
|
|
| void Erase(PositionInListContainerCharAllocator position) {
|
| @@ -129,7 +159,7 @@ class ListContainerBase::ListContainerCharAllocator {
|
| }
|
|
|
| InnerList* InnerListById(size_t id) const {
|
| - DCHECK_LT(id, list_count_);
|
| + DCHECK_LT(id, storage_.size());
|
| return storage_[id];
|
| }
|
|
|
| @@ -147,33 +177,37 @@ class ListContainerBase::ListContainerCharAllocator {
|
| // |size_| > 0 means that at least one vector in |storage_| will be
|
| // non-empty.
|
| DCHECK_GT(size_, 0u);
|
| - size_t id = list_count_ - 1;
|
| + size_t id = storage_.size() - 1;
|
| while (storage_[id]->size == 0)
|
| --id;
|
| return id;
|
| }
|
|
|
| - void AllocateNewList(size_t list_size) {
|
| - ++list_count_;
|
| - scoped_ptr<InnerList> new_list(new InnerList);
|
| - storage_.push_back(new_list.Pass());
|
| - last_list_ = storage_.back();
|
| - InnerList* list = last_list_;
|
| - list->capacity = list_size;
|
| - list->size = 0;
|
| - list->step = element_size_;
|
| - list->data.reset(new char[list->capacity * list->step]);
|
| - }
|
| -
|
| size_t NumAvailableElementsInLastList() const {
|
| return last_list_->NumElementsAvailable();
|
| }
|
|
|
| private:
|
| + void AllocateNewList(size_t list_size) {
|
| + scoped_ptr<InnerList> new_list(new InnerList);
|
| + new_list->capacity = list_size;
|
| + new_list->size = 0;
|
| + new_list->step = element_size_;
|
| + new_list->data.reset(new char[list_size * element_size_]);
|
| + storage_.push_back(new_list.Pass());
|
| + }
|
| +
|
| ScopedPtrVector<InnerList> storage_;
|
| const size_t element_size_;
|
| +
|
| + // The number of elements in the list.
|
| size_t size_;
|
| - size_t list_count_;
|
| +
|
| + // The index of the last list to have had elements added to it, or the only
|
| + // list if the container has not had elements added since being cleared.
|
| + size_t last_list_index_;
|
| +
|
| + // This is equivalent to |storage_[last_list_index_]|.
|
| InnerList* last_list_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(ListContainerCharAllocator);
|
| @@ -275,6 +309,10 @@ ListContainerBase::ListContainerBase(size_t max_size_for_derived_class,
|
| ListContainerBase::~ListContainerBase() {
|
| }
|
|
|
| +void ListContainerBase::RemoveLast() {
|
| + data_->RemoveLast();
|
| +}
|
| +
|
| void ListContainerBase::EraseAndInvalidateAllPointers(
|
| ListContainerBase::Iterator position) {
|
| data_->Erase(position);
|
|
|