Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(468)

Unified Diff: cc/quads/list_container.cc

Issue 400463002: Class for allocating a chunk of memory for RenderPass (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mojojojo
Patch Set: use reset instead of assignment Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/quads/list_container.h ('k') | cc/quads/list_container_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/quads/list_container.cc
diff --git a/cc/quads/list_container.cc b/cc/quads/list_container.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5d092a113e8502e9c34286a1a326ae8b672028e3
--- /dev/null
+++ b/cc/quads/list_container.cc
@@ -0,0 +1,592 @@
+// 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/quads/list_container.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "cc/base/scoped_ptr_vector.h"
+#include "cc/quads/draw_quad.h"
+#include "cc/quads/shared_quad_state.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.
+template <typename BaseElementType>
+class ListContainer<BaseElementType>::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;
+ }
+
+ bool IsFull() { return capacity == size; }
+ size_t NumElementsAvailable() const { return capacity - size; }
+
+ void* AddElement() {
+ DCHECK_LT(size, capacity);
+ ++size;
+ return LastElement();
+ }
+
+ char* Begin() const { return data.get(); }
+ char* End() const { return data.get() + size * step; }
+ char* LastElement() const { return data.get() + (size - 1) * step; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InnerList);
+ };
+
+ explicit ListContainerCharAllocator(size_t element_size)
+ : element_size_(element_size),
+ size_(0),
+ list_count_(0),
+ last_list_(NULL) {
+ AllocateNewList(kDefaultNumElementTypesToReserve);
+ }
+
+ ListContainerCharAllocator(size_t element_size, size_t element_count)
+ : element_size_(element_size),
+ size_(0),
+ list_count_(0),
+ last_list_(NULL) {
+ DCHECK_NE(0u, element_count);
+ AllocateNewList(element_count);
+ }
+
+ ~ListContainerCharAllocator() {}
+
+ void* Allocate() {
+ if (last_list_->IsFull())
+ AllocateNewList(last_list_->capacity * 2);
+
+ ++size_;
+ return last_list_->AddElement();
+ }
+
+ size_t element_size() const { return element_size_; }
+ size_t list_count() const { return list_count_; }
+ size_t size() const { return size_; }
+ bool IsEmpty() const { return size() == 0; }
+
+ size_t Capacity() const {
+ size_t capacity_sum = 0;
+ for (typename ScopedPtrVector<InnerList>::const_iterator iter =
+ storage_.begin();
+ iter != storage_.end();
+ ++iter) {
+ capacity_sum += (*iter)->capacity;
+ }
+ return capacity_sum;
+ }
+
+ void Clear() {
+ size_t initial_allocation_size = storage_.front()->capacity;
+ storage_.clear();
+ list_count_ = 0;
+ last_list_ = NULL;
+ size_ = 0;
+ AllocateNewList(initial_allocation_size);
+ }
+
+ void Erase(PositionInListContainerCharAllocator position) {
+ DCHECK_EQ(this, position.ptr_to_container);
+ storage_[position.vector_index]->Erase(position.item_iterator);
+ // TODO(weiliangc): Free the InnerList if it is empty.
+ --size_;
+ }
+
+ InnerList* InnerListById(size_t id) const {
+ DCHECK_LT(id, list_count_);
+ return storage_[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:
+ ScopedPtrVector<InnerList> storage_;
+ const size_t element_size_;
+ size_t size_;
+ size_t list_count_;
+ InnerList* last_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(ListContainerCharAllocator);
+};
+
+// PositionInListContainerCharAllocator
+//////////////////////////////////////////////////////
+template <typename BaseElementType>
+ListContainer<BaseElementType>::PositionInListContainerCharAllocator::
+ PositionInListContainerCharAllocator(const typename ListContainer<
+ BaseElementType>::PositionInListContainerCharAllocator& other)
+ : ptr_to_container(other.ptr_to_container),
+ vector_index(other.vector_index),
+ item_iterator(other.item_iterator) {
+}
+
+template <typename BaseElementType>
+ListContainer<BaseElementType>::PositionInListContainerCharAllocator::
+ PositionInListContainerCharAllocator(
+ typename ListContainer<BaseElementType>::ListContainerCharAllocator*
+ container,
+ size_t vector_ind,
+ char* item_iter)
+ : ptr_to_container(container),
+ vector_index(vector_ind),
+ item_iterator(item_iter) {
+}
+
+template <typename BaseElementType>
+bool ListContainer<BaseElementType>::PositionInListContainerCharAllocator::
+operator==(const typename ListContainer<
+ BaseElementType>::PositionInListContainerCharAllocator& other) const {
+ DCHECK_EQ(ptr_to_container, other.ptr_to_container);
+ return vector_index == other.vector_index &&
+ item_iterator == other.item_iterator;
+}
+
+template <typename BaseElementType>
+bool ListContainer<BaseElementType>::PositionInListContainerCharAllocator::
+operator!=(const typename ListContainer<
+ BaseElementType>::PositionInListContainerCharAllocator& other) const {
+ return !(*this == other);
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::PositionInListContainerCharAllocator
+ListContainer<
+ BaseElementType>::PositionInListContainerCharAllocator::Increment() {
+ typename ListContainerCharAllocator::InnerList* list =
+ ptr_to_container->InnerListById(vector_index);
+ if (item_iterator == list->LastElement()) {
+ if (vector_index < ptr_to_container->list_count() - 1) {
+ ++vector_index;
+ item_iterator = ptr_to_container->InnerListById(vector_index)->Begin();
+ } else {
+ item_iterator = NULL;
+ }
+ } else {
+ item_iterator += list->step;
+ }
+ return *this;
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::PositionInListContainerCharAllocator
+ListContainer<
+ BaseElementType>::PositionInListContainerCharAllocator::ReverseIncrement() {
+ typename ListContainerCharAllocator::InnerList* list =
+ ptr_to_container->InnerListById(vector_index);
+ if (item_iterator == list->Begin()) {
+ if (vector_index > 0) {
+ --vector_index;
+ item_iterator =
+ ptr_to_container->InnerListById(vector_index)->LastElement();
+ } else {
+ item_iterator = NULL;
+ }
+ } else {
+ item_iterator -= list->step;
+ }
+ return *this;
+}
+
+// ListContainer
+////////////////////////////////////////////
+template <typename BaseElementType>
+ListContainer<BaseElementType>::ListContainer(size_t max_size_for_derived_class)
+ : data_(new ListContainerCharAllocator(max_size_for_derived_class)) {
+}
+
+template <typename BaseElementType>
+ListContainer<BaseElementType>::ListContainer(
+ 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)) {
+}
+
+template <typename BaseElementType>
+ListContainer<BaseElementType>::ListContainer()
+ : data_(new ListContainerCharAllocator(sizeof(BaseElementType))) {
+}
+
+template <typename BaseElementType>
+ListContainer<BaseElementType>::~ListContainer() {
+ for (Iterator i = begin(); i != end(); ++i) {
+ i->~BaseElementType();
+ }
+}
+
+template <typename BaseElementType>
+void ListContainer<BaseElementType>::EraseAndInvalidateAllPointers(
+ typename ListContainer<BaseElementType>::Iterator position) {
+ BaseElementType* item = &*position;
+ item->~BaseElementType();
+ data_->Erase(position);
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::ConstReverseIterator
+ListContainer<BaseElementType>::rbegin() const {
+ if (data_->IsEmpty())
+ return ConstReverseIterator(data_.get(), 0, NULL);
+
+ size_t last_id = data_->list_count() - 1;
+ return ConstReverseIterator(
+ data_.get(), last_id, data_->InnerListById(last_id)->LastElement());
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::ConstReverseIterator
+ListContainer<BaseElementType>::rend() const {
+ return ConstReverseIterator(data_.get(), 0, NULL);
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::ReverseIterator
+ListContainer<BaseElementType>::rbegin() {
+ if (data_->IsEmpty())
+ return ReverseIterator(data_.get(), 0, NULL);
+
+ size_t last_id = data_->list_count() - 1;
+ return ReverseIterator(
+ data_.get(), last_id, data_->InnerListById(last_id)->LastElement());
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::ReverseIterator
+ListContainer<BaseElementType>::rend() {
+ return ReverseIterator(data_.get(), 0, NULL);
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::ConstIterator
+ListContainer<BaseElementType>::begin() const {
+ if (data_->IsEmpty())
+ return ConstIterator(data_.get(), 0, NULL);
+
+ return ConstIterator(data_.get(), 0, data_->InnerListById(0)->Begin());
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::ConstIterator
+ListContainer<BaseElementType>::end() const {
+ if (data_->IsEmpty())
+ return ConstIterator(data_.get(), 0, NULL);
+
+ size_t last_id = data_->list_count() - 1;
+ return ConstIterator(data_.get(), last_id, NULL);
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::Iterator
+ListContainer<BaseElementType>::begin() {
+ if (data_->IsEmpty())
+ return Iterator(data_.get(), 0, NULL);
+
+ return Iterator(data_.get(), 0, data_->InnerListById(0)->Begin());
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::Iterator
+ListContainer<BaseElementType>::end() {
+ if (data_->IsEmpty())
+ return Iterator(data_.get(), 0, NULL);
+
+ size_t last_id = data_->list_count() - 1;
+ return Iterator(data_.get(), last_id, NULL);
+}
+
+template <typename BaseElementType>
+BaseElementType* ListContainer<BaseElementType>::front() {
+ Iterator iter = begin();
+ return &*iter;
+}
+
+template <typename BaseElementType>
+BaseElementType* ListContainer<BaseElementType>::back() {
+ ReverseIterator iter = rbegin();
+ return &*iter;
+}
+
+template <typename BaseElementType>
+const BaseElementType* ListContainer<BaseElementType>::front() const {
+ ConstIterator iter = begin();
+ return &*iter;
+}
+
+template <typename BaseElementType>
+const BaseElementType* ListContainer<BaseElementType>::back() const {
+ ConstReverseIterator iter = rbegin();
+ return &*iter;
+}
+
+template <typename BaseElementType>
+BaseElementType* ListContainer<BaseElementType>::Allocate(
+ size_t size_of_actual_element_in_bytes) {
+ DCHECK_LE(size_of_actual_element_in_bytes, data_->element_size());
+ void* result = data_->Allocate();
+ return static_cast<BaseElementType*>(result);
+}
+
+template <typename BaseElementType>
+size_t ListContainer<BaseElementType>::size() const {
+ return data_->size();
+}
+
+template <typename BaseElementType>
+bool ListContainer<BaseElementType>::empty() const {
+ return data_->IsEmpty();
+}
+
+template <typename BaseElementType>
+void ListContainer<BaseElementType>::clear() {
+ for (Iterator i = begin(); i != end(); ++i) {
+ i->~BaseElementType();
+ }
+ data_->Clear();
+}
+
+template <typename BaseElementType>
+size_t ListContainer<
+ BaseElementType>::AvailableSizeWithoutAnotherAllocationForTesting() const {
+ return data_->NumAvailableElementsInLastList();
+}
+
+// ListContainer::Iterator
+/////////////////////////////////////////////////
+template <typename BaseElementType>
+ListContainer<BaseElementType>::Iterator::Iterator(
+ ListContainerCharAllocator* container,
+ size_t vector_ind,
+ char* item_iter)
+ : PositionInListContainerCharAllocator(container, vector_ind, item_iter) {
+}
+
+template <typename BaseElementType>
+ListContainer<BaseElementType>::Iterator::~Iterator() {
+}
+
+template <typename BaseElementType>
+BaseElementType* ListContainer<BaseElementType>::Iterator::operator->() const {
+ return reinterpret_cast<BaseElementType*>(this->item_iterator);
+}
+
+template <typename BaseElementType>
+BaseElementType& ListContainer<BaseElementType>::Iterator::operator*() const {
+ return *(reinterpret_cast<BaseElementType*>(this->item_iterator));
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::Iterator
+ListContainer<BaseElementType>::Iterator::
+operator++(int unused_post_increment) {
+ Iterator tmp = *this;
+ operator++();
+ return tmp;
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::Iterator
+ListContainer<BaseElementType>::Iterator::
+operator++() {
+ this->Increment();
+ return *this;
+}
+
+// ListContainer::ConstIterator
+/////////////////////////////////////////////////
+template <typename BaseElementType>
+ListContainer<BaseElementType>::ConstIterator::ConstIterator(
+ const typename ListContainer<BaseElementType>::Iterator& other)
+ : PositionInListContainerCharAllocator(other) {
+}
+
+template <typename BaseElementType>
+ListContainer<BaseElementType>::ConstIterator::ConstIterator(
+ ListContainerCharAllocator* container,
+ size_t vector_ind,
+ char* item_iter)
+ : PositionInListContainerCharAllocator(container, vector_ind, item_iter) {
+}
+
+template <typename BaseElementType>
+ListContainer<BaseElementType>::ConstIterator::~ConstIterator() {
+}
+
+template <typename BaseElementType>
+const BaseElementType* ListContainer<BaseElementType>::ConstIterator::
+operator->() const {
+ return reinterpret_cast<const BaseElementType*>(this->item_iterator);
+}
+
+template <typename BaseElementType>
+const BaseElementType& ListContainer<BaseElementType>::ConstIterator::
+operator*() const {
+ return *(reinterpret_cast<const BaseElementType*>(this->item_iterator));
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::ConstIterator
+ListContainer<BaseElementType>::ConstIterator::
+operator++(int unused_post_increment) {
+ ConstIterator tmp = *this;
+ operator++();
+ return tmp;
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::ConstIterator
+ListContainer<BaseElementType>::ConstIterator::
+operator++() {
+ this->Increment();
+ return *this;
+}
+
+// ListContainer::ReverseIterator
+/////////////////////////////////////////////////
+template <typename BaseElementType>
+ListContainer<BaseElementType>::ReverseIterator::ReverseIterator(
+ ListContainerCharAllocator* container,
+ size_t vector_ind,
+ char* item_iter)
+ : PositionInListContainerCharAllocator(container, vector_ind, item_iter) {
+}
+
+template <typename BaseElementType>
+ListContainer<BaseElementType>::ReverseIterator::~ReverseIterator() {
+}
+
+template <typename BaseElementType>
+BaseElementType* ListContainer<BaseElementType>::ReverseIterator::operator->()
+ const {
+ return reinterpret_cast<BaseElementType*>(this->item_iterator);
+}
+
+template <typename BaseElementType>
+BaseElementType& ListContainer<BaseElementType>::ReverseIterator::operator*()
+ const {
+ return *(reinterpret_cast<BaseElementType*>(this->item_iterator));
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::ReverseIterator
+ListContainer<BaseElementType>::ReverseIterator::
+operator++(int unused_post_increment) {
+ ReverseIterator tmp = *this;
+ operator++();
+ return tmp;
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::ReverseIterator
+ListContainer<BaseElementType>::ReverseIterator::
+operator++() {
+ this->ReverseIncrement();
+ return *this;
+}
+
+// ListContainer::ConstReverseIterator
+/////////////////////////////////////////////////
+template <typename BaseElementType>
+ListContainer<BaseElementType>::ConstReverseIterator::ConstReverseIterator(
+ const typename ListContainer<BaseElementType>::ReverseIterator& other)
+ : PositionInListContainerCharAllocator(other) {
+}
+
+template <typename BaseElementType>
+ListContainer<BaseElementType>::ConstReverseIterator::ConstReverseIterator(
+ ListContainerCharAllocator* container,
+ size_t vector_ind,
+ char* item_iter)
+ : PositionInListContainerCharAllocator(container, vector_ind, item_iter) {
+}
+
+template <typename BaseElementType>
+ListContainer<BaseElementType>::ConstReverseIterator::~ConstReverseIterator() {
+}
+
+template <typename BaseElementType>
+const BaseElementType* ListContainer<BaseElementType>::ConstReverseIterator::
+operator->() const {
+ return reinterpret_cast<const BaseElementType*>(this->item_iterator);
+}
+
+template <typename BaseElementType>
+const BaseElementType& ListContainer<BaseElementType>::ConstReverseIterator::
+operator*() const {
+ return *(reinterpret_cast<const BaseElementType*>(this->item_iterator));
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::ConstReverseIterator
+ListContainer<BaseElementType>::ConstReverseIterator::
+operator++(int unused_post_increment) {
+ ConstReverseIterator tmp = *this;
+ operator++();
+ return tmp;
+}
+
+template <typename BaseElementType>
+typename ListContainer<BaseElementType>::ConstReverseIterator
+ListContainer<BaseElementType>::ConstReverseIterator::
+operator++() {
+ this->ReverseIncrement();
+ return *this;
+}
+
+template class ListContainer<SharedQuadState>;
+template class ListContainer<DrawQuad>;
+
+} // namespace cc
« no previous file with comments | « cc/quads/list_container.h ('k') | cc/quads/list_container_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698