| Index: cc/base/list_container.cc
|
| diff --git a/cc/base/list_container.cc b/cc/base/list_container.cc
|
| deleted file mode 100644
|
| index 48d2bf58ce63c78796216a26b9143dd90ab85fe0..0000000000000000000000000000000000000000
|
| --- a/cc/base/list_container.cc
|
| +++ /dev/null
|
| @@ -1,576 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "cc/base/list_container.h"
|
| -
|
| -#include <algorithm>
|
| -#include <vector>
|
| -
|
| -#include "cc/base/scoped_ptr_vector.h"
|
| -
|
| -namespace {
|
| -const size_t kDefaultNumElementTypesToReserve = 32;
|
| -} // namespace
|
| -
|
| -namespace cc {
|
| -
|
| -// ListContainerCharAllocator
|
| -////////////////////////////////////////////////////
|
| -// This class deals only with char* and void*. It does allocation and passing
|
| -// out raw pointers, as well as memory deallocation when being destroyed.
|
| -class ListContainerBase::ListContainerCharAllocator {
|
| - public:
|
| - // ListContainerCharAllocator::InnerList
|
| - /////////////////////////////////////////////
|
| - // This class holds the raw memory chunk, as well as information about its
|
| - // size and availability.
|
| - struct InnerList {
|
| - scoped_ptr<char[]> data;
|
| - // The number of elements in total the memory can hold. The difference
|
| - // between capacity and size is the how many more elements this list can
|
| - // hold.
|
| - size_t capacity;
|
| - // The number of elements have been put into this list.
|
| - size_t size;
|
| - // The size of each element is in bytes. This is used to move from between
|
| - // elements' memory locations.
|
| - size_t step;
|
| -
|
| - InnerList() : capacity(0), size(0), step(0) {}
|
| -
|
| - void Erase(char* position) {
|
| - // Confident that destructor is called by caller of this function. Since
|
| - // ListContainerCharAllocator does not handle construction after
|
| - // allocation, it doesn't handle desctrution before deallocation.
|
| - DCHECK_LE(position, LastElement());
|
| - DCHECK_GE(position, Begin());
|
| - char* start = position + step;
|
| - std::copy(start, End(), position);
|
| -
|
| - --size;
|
| - // Decrease capacity to avoid creating not full not last InnerList.
|
| - --capacity;
|
| - }
|
| -
|
| - void InsertBefore(char** position, size_t count) {
|
| - DCHECK_LE(*position, LastElement() + step);
|
| - DCHECK_GE(*position, Begin());
|
| -
|
| - // Adjust the size and capacity
|
| - size_t old_size = size;
|
| - size += count;
|
| - capacity = size;
|
| -
|
| - // Allocate the new data and update the iterator's pointer.
|
| - scoped_ptr<char[]> new_data(new char[size * step]);
|
| - size_t position_offset = *position - Begin();
|
| - *position = new_data.get() + position_offset;
|
| -
|
| - // Copy the data before the inserted segment
|
| - memcpy(new_data.get(), data.get(), position_offset);
|
| - // Copy the data after the inserted segment.
|
| - memcpy(new_data.get() + position_offset + count * step,
|
| - data.get() + position_offset, old_size * step - position_offset);
|
| - new_data.swap(data);
|
| - }
|
| -
|
| - bool IsEmpty() const { return !size; }
|
| - bool IsFull() { return capacity == size; }
|
| - size_t NumElementsAvailable() const { return capacity - size; }
|
| -
|
| - void* AddElement() {
|
| - DCHECK_LT(size, capacity);
|
| - ++size;
|
| - 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; }
|
| - char* ElementAt(size_t index) const { return data.get() + index * step; }
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(InnerList);
|
| - };
|
| -
|
| - explicit ListContainerCharAllocator(size_t element_size)
|
| - : element_size_(element_size),
|
| - size_(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),
|
| - 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()) {
|
| - // 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 storage_.size(); }
|
| - size_t size() const { return size_; }
|
| - bool IsEmpty() const { return size() == 0; }
|
| -
|
| - size_t Capacity() const {
|
| - size_t capacity_sum = 0;
|
| - for (const auto& inner_list : storage_)
|
| - capacity_sum += inner_list->capacity;
|
| - return capacity_sum;
|
| - }
|
| -
|
| - void Clear() {
|
| - // Remove all except for the first InnerList.
|
| - DCHECK(!storage_.empty());
|
| - storage_.erase(storage_.begin() + 1, storage_.end());
|
| - last_list_index_ = 0;
|
| - last_list_ = storage_[0];
|
| - last_list_->size = 0;
|
| - size_ = 0;
|
| - }
|
| -
|
| - 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) {
|
| - DCHECK_EQ(this, position->ptr_to_container);
|
| -
|
| - // Update |position| to point to the element after the erased element.
|
| - InnerList* list = storage_[position->vector_index];
|
| - char* item_iterator = position->item_iterator;
|
| - if (item_iterator == list->LastElement())
|
| - position->Increment();
|
| -
|
| - list->Erase(item_iterator);
|
| - // TODO(weiliangc): Free the InnerList if it is empty.
|
| - --size_;
|
| - }
|
| -
|
| - void InsertBefore(ListContainerBase::Iterator* position, size_t count) {
|
| - if (!count)
|
| - return;
|
| -
|
| - // If |position| is End(), then append |count| elements at the end. This
|
| - // will happen to not invalidate any iterators or memory.
|
| - if (!position->item_iterator) {
|
| - // Set |position| to be the first inserted element.
|
| - Allocate();
|
| - position->vector_index = storage_.size() - 1;
|
| - position->item_iterator = storage_[position->vector_index]->LastElement();
|
| - // Allocate the rest.
|
| - for (size_t i = 1; i < count; ++i)
|
| - Allocate();
|
| - } else {
|
| - storage_[position->vector_index]->InsertBefore(&position->item_iterator,
|
| - count);
|
| - size_ += count;
|
| - }
|
| - }
|
| -
|
| - InnerList* InnerListById(size_t id) const {
|
| - DCHECK_LT(id, storage_.size());
|
| - return storage_[id];
|
| - }
|
| -
|
| - size_t FirstInnerListId() const {
|
| - // |size_| > 0 means that at least one vector in |storage_| will be
|
| - // non-empty.
|
| - DCHECK_GT(size_, 0u);
|
| - size_t id = 0;
|
| - while (storage_[id]->size == 0)
|
| - ++id;
|
| - return id;
|
| - }
|
| -
|
| - size_t LastInnerListId() const {
|
| - // |size_| > 0 means that at least one vector in |storage_| will be
|
| - // non-empty.
|
| - DCHECK_GT(size_, 0u);
|
| - size_t id = storage_.size() - 1;
|
| - while (storage_[id]->size == 0)
|
| - --id;
|
| - return id;
|
| - }
|
| -
|
| - 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_;
|
| -
|
| - // 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);
|
| -};
|
| -
|
| -// PositionInListContainerCharAllocator
|
| -//////////////////////////////////////////////////////
|
| -ListContainerBase::PositionInListContainerCharAllocator::
|
| - PositionInListContainerCharAllocator(
|
| - const ListContainerBase::PositionInListContainerCharAllocator& other)
|
| - : ptr_to_container(other.ptr_to_container),
|
| - vector_index(other.vector_index),
|
| - item_iterator(other.item_iterator) {
|
| -}
|
| -
|
| -ListContainerBase::PositionInListContainerCharAllocator::
|
| - PositionInListContainerCharAllocator(
|
| - ListContainerBase::ListContainerCharAllocator* container,
|
| - size_t vector_ind,
|
| - char* item_iter)
|
| - : ptr_to_container(container),
|
| - vector_index(vector_ind),
|
| - item_iterator(item_iter) {
|
| -}
|
| -
|
| -bool ListContainerBase::PositionInListContainerCharAllocator::operator==(
|
| - const ListContainerBase::PositionInListContainerCharAllocator& other)
|
| - const {
|
| - DCHECK_EQ(ptr_to_container, other.ptr_to_container);
|
| - return vector_index == other.vector_index &&
|
| - item_iterator == other.item_iterator;
|
| -}
|
| -
|
| -bool ListContainerBase::PositionInListContainerCharAllocator::operator!=(
|
| - const ListContainerBase::PositionInListContainerCharAllocator& other)
|
| - const {
|
| - return !(*this == other);
|
| -}
|
| -
|
| -ListContainerBase::PositionInListContainerCharAllocator
|
| -ListContainerBase::PositionInListContainerCharAllocator::Increment() {
|
| - ListContainerCharAllocator::InnerList* list =
|
| - ptr_to_container->InnerListById(vector_index);
|
| - if (item_iterator == list->LastElement()) {
|
| - ++vector_index;
|
| - while (vector_index < ptr_to_container->list_count()) {
|
| - if (ptr_to_container->InnerListById(vector_index)->size != 0)
|
| - break;
|
| - ++vector_index;
|
| - }
|
| - if (vector_index < ptr_to_container->list_count())
|
| - item_iterator = ptr_to_container->InnerListById(vector_index)->Begin();
|
| - else
|
| - item_iterator = NULL;
|
| - } else {
|
| - item_iterator += list->step;
|
| - }
|
| - return *this;
|
| -}
|
| -
|
| -ListContainerBase::PositionInListContainerCharAllocator
|
| -ListContainerBase::PositionInListContainerCharAllocator::ReverseIncrement() {
|
| - ListContainerCharAllocator::InnerList* list =
|
| - ptr_to_container->InnerListById(vector_index);
|
| - if (item_iterator == list->Begin()) {
|
| - --vector_index;
|
| - // Since |vector_index| is unsigned, we compare < list_count() instead of
|
| - // comparing >= 0, as the variable will wrap around when it goes out of
|
| - // range (below 0).
|
| - while (vector_index < ptr_to_container->list_count()) {
|
| - if (ptr_to_container->InnerListById(vector_index)->size != 0)
|
| - break;
|
| - --vector_index;
|
| - }
|
| - if (vector_index < ptr_to_container->list_count()) {
|
| - item_iterator =
|
| - ptr_to_container->InnerListById(vector_index)->LastElement();
|
| - } else {
|
| - item_iterator = NULL;
|
| - }
|
| - } else {
|
| - item_iterator -= list->step;
|
| - }
|
| - return *this;
|
| -}
|
| -
|
| -// ListContainerBase
|
| -////////////////////////////////////////////
|
| -ListContainerBase::ListContainerBase(size_t max_size_for_derived_class)
|
| - : data_(new ListContainerCharAllocator(max_size_for_derived_class)) {
|
| -}
|
| -
|
| -ListContainerBase::ListContainerBase(size_t max_size_for_derived_class,
|
| - size_t num_of_elements_to_reserve_for)
|
| - : data_(new ListContainerCharAllocator(max_size_for_derived_class,
|
| - num_of_elements_to_reserve_for)) {
|
| -}
|
| -
|
| -ListContainerBase::~ListContainerBase() {
|
| -}
|
| -
|
| -void ListContainerBase::RemoveLast() {
|
| - data_->RemoveLast();
|
| -}
|
| -
|
| -void ListContainerBase::EraseAndInvalidateAllPointers(
|
| - ListContainerBase::Iterator* position) {
|
| - data_->Erase(position);
|
| -}
|
| -
|
| -void ListContainerBase::InsertBeforeAndInvalidateAllPointers(
|
| - ListContainerBase::Iterator* position,
|
| - size_t count) {
|
| - data_->InsertBefore(position, count);
|
| -}
|
| -
|
| -ListContainerBase::ConstReverseIterator ListContainerBase::crbegin() const {
|
| - if (data_->IsEmpty())
|
| - return crend();
|
| -
|
| - size_t id = data_->LastInnerListId();
|
| - return ConstReverseIterator(data_.get(), id,
|
| - data_->InnerListById(id)->LastElement(), 0);
|
| -}
|
| -
|
| -ListContainerBase::ConstReverseIterator ListContainerBase::crend() const {
|
| - return ConstReverseIterator(data_.get(), static_cast<size_t>(-1), NULL,
|
| - size());
|
| -}
|
| -
|
| -ListContainerBase::ReverseIterator ListContainerBase::rbegin() {
|
| - if (data_->IsEmpty())
|
| - return rend();
|
| -
|
| - size_t id = data_->LastInnerListId();
|
| - return ReverseIterator(data_.get(), id,
|
| - data_->InnerListById(id)->LastElement(), 0);
|
| -}
|
| -
|
| -ListContainerBase::ReverseIterator ListContainerBase::rend() {
|
| - return ReverseIterator(data_.get(), static_cast<size_t>(-1), NULL, size());
|
| -}
|
| -
|
| -ListContainerBase::ConstIterator ListContainerBase::cbegin() const {
|
| - if (data_->IsEmpty())
|
| - return cend();
|
| -
|
| - size_t id = data_->FirstInnerListId();
|
| - return ConstIterator(data_.get(), id, data_->InnerListById(id)->Begin(), 0);
|
| -}
|
| -
|
| -ListContainerBase::ConstIterator ListContainerBase::cend() const {
|
| - if (data_->IsEmpty())
|
| - return ConstIterator(data_.get(), 0, NULL, size());
|
| -
|
| - size_t id = data_->list_count();
|
| - return ConstIterator(data_.get(), id, NULL, size());
|
| -}
|
| -
|
| -ListContainerBase::Iterator ListContainerBase::begin() {
|
| - if (data_->IsEmpty())
|
| - return end();
|
| -
|
| - size_t id = data_->FirstInnerListId();
|
| - return Iterator(data_.get(), id, data_->InnerListById(id)->Begin(), 0);
|
| -}
|
| -
|
| -ListContainerBase::Iterator ListContainerBase::end() {
|
| - if (data_->IsEmpty())
|
| - return Iterator(data_.get(), 0, NULL, size());
|
| -
|
| - size_t id = data_->list_count();
|
| - return Iterator(data_.get(), id, NULL, size());
|
| -}
|
| -
|
| -ListContainerBase::ConstIterator ListContainerBase::IteratorAt(
|
| - size_t index) const {
|
| - DCHECK_LT(index, size());
|
| - size_t original_index = index;
|
| - size_t list_index;
|
| - for (list_index = 0; list_index < data_->list_count(); ++list_index) {
|
| - size_t current_size = data_->InnerListById(list_index)->size;
|
| - if (index < current_size)
|
| - break;
|
| - index -= current_size;
|
| - }
|
| - return ConstIterator(data_.get(), list_index,
|
| - data_->InnerListById(list_index)->ElementAt(index),
|
| - original_index);
|
| -}
|
| -
|
| -ListContainerBase::Iterator ListContainerBase::IteratorAt(size_t index) {
|
| - DCHECK_LT(index, size());
|
| - size_t original_index = index;
|
| - size_t list_index;
|
| - for (list_index = 0; list_index < data_->list_count(); ++list_index) {
|
| - size_t current_size = data_->InnerListById(list_index)->size;
|
| - if (index < current_size)
|
| - break;
|
| - index -= current_size;
|
| - }
|
| - return Iterator(data_.get(), list_index,
|
| - data_->InnerListById(list_index)->ElementAt(index),
|
| - original_index);
|
| -}
|
| -
|
| -void* ListContainerBase::Allocate(size_t size_of_actual_element_in_bytes) {
|
| - DCHECK_LE(size_of_actual_element_in_bytes, data_->element_size());
|
| - return data_->Allocate();
|
| -}
|
| -
|
| -size_t ListContainerBase::size() const {
|
| - return data_->size();
|
| -}
|
| -
|
| -bool ListContainerBase::empty() const {
|
| - return data_->IsEmpty();
|
| -}
|
| -
|
| -size_t ListContainerBase::MaxSizeForDerivedClass() const {
|
| - return data_->element_size();
|
| -}
|
| -
|
| -size_t ListContainerBase::GetCapacityInBytes() const {
|
| - return data_->Capacity() * data_->element_size();
|
| -}
|
| -
|
| -void ListContainerBase::clear() {
|
| - data_->Clear();
|
| -}
|
| -
|
| -size_t ListContainerBase::AvailableSizeWithoutAnotherAllocationForTesting()
|
| - const {
|
| - return data_->NumAvailableElementsInLastList();
|
| -}
|
| -
|
| -// ListContainerBase::Iterator
|
| -/////////////////////////////////////////////////
|
| -ListContainerBase::Iterator::Iterator(ListContainerCharAllocator* container,
|
| - size_t vector_ind,
|
| - char* item_iter,
|
| - size_t index)
|
| - : PositionInListContainerCharAllocator(container, vector_ind, item_iter),
|
| - index_(index) {
|
| -}
|
| -
|
| -ListContainerBase::Iterator::~Iterator() {
|
| -}
|
| -
|
| -size_t ListContainerBase::Iterator::index() const {
|
| - return index_;
|
| -}
|
| -
|
| -// ListContainerBase::ConstIterator
|
| -/////////////////////////////////////////////////
|
| -ListContainerBase::ConstIterator::ConstIterator(
|
| - const ListContainerBase::Iterator& other)
|
| - : PositionInListContainerCharAllocator(other), index_(other.index()) {
|
| -}
|
| -
|
| -ListContainerBase::ConstIterator::ConstIterator(
|
| - ListContainerCharAllocator* container,
|
| - size_t vector_ind,
|
| - char* item_iter,
|
| - size_t index)
|
| - : PositionInListContainerCharAllocator(container, vector_ind, item_iter),
|
| - index_(index) {
|
| -}
|
| -
|
| -ListContainerBase::ConstIterator::~ConstIterator() {
|
| -}
|
| -
|
| -size_t ListContainerBase::ConstIterator::index() const {
|
| - return index_;
|
| -}
|
| -
|
| -// ListContainerBase::ReverseIterator
|
| -/////////////////////////////////////////////////
|
| -ListContainerBase::ReverseIterator::ReverseIterator(
|
| - ListContainerCharAllocator* container,
|
| - size_t vector_ind,
|
| - char* item_iter,
|
| - size_t index)
|
| - : PositionInListContainerCharAllocator(container, vector_ind, item_iter),
|
| - index_(index) {
|
| -}
|
| -
|
| -ListContainerBase::ReverseIterator::~ReverseIterator() {
|
| -}
|
| -
|
| -size_t ListContainerBase::ReverseIterator::index() const {
|
| - return index_;
|
| -}
|
| -
|
| -// ListContainerBase::ConstReverseIterator
|
| -/////////////////////////////////////////////////
|
| -ListContainerBase::ConstReverseIterator::ConstReverseIterator(
|
| - const ListContainerBase::ReverseIterator& other)
|
| - : PositionInListContainerCharAllocator(other), index_(other.index()) {
|
| -}
|
| -
|
| -ListContainerBase::ConstReverseIterator::ConstReverseIterator(
|
| - ListContainerCharAllocator* container,
|
| - size_t vector_ind,
|
| - char* item_iter,
|
| - size_t index)
|
| - : PositionInListContainerCharAllocator(container, vector_ind, item_iter),
|
| - index_(index) {
|
| -}
|
| -
|
| -ListContainerBase::ConstReverseIterator::~ConstReverseIterator() {
|
| -}
|
| -
|
| -size_t ListContainerBase::ConstReverseIterator::index() const {
|
| - return index_;
|
| -}
|
| -
|
| -} // namespace cc
|
|
|