|  | // 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; } | 
|  | 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), | 
|  | 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) { | 
|  | AllocateNewList(element_count > 0 ? element_count | 
|  | : kDefaultNumElementTypesToReserve); | 
|  | } | 
|  |  | 
|  | ~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>::crbegin() const { | 
|  | if (data_->IsEmpty()) | 
|  | return ConstReverseIterator(data_.get(), 0, NULL, 0); | 
|  |  | 
|  | size_t last_id = data_->list_count() - 1; | 
|  | return ConstReverseIterator( | 
|  | data_.get(), last_id, data_->InnerListById(last_id)->LastElement(), 0); | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | typename ListContainer<BaseElementType>::ConstReverseIterator | 
|  | ListContainer<BaseElementType>::crend() const { | 
|  | return ConstReverseIterator(data_.get(), 0, NULL, size()); | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | typename ListContainer<BaseElementType>::ConstReverseIterator | 
|  | ListContainer<BaseElementType>::rbegin() const { | 
|  | return crbegin(); | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | typename ListContainer<BaseElementType>::ConstReverseIterator | 
|  | ListContainer<BaseElementType>::rend() const { | 
|  | return crend(); | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | typename ListContainer<BaseElementType>::ReverseIterator | 
|  | ListContainer<BaseElementType>::rbegin() { | 
|  | if (data_->IsEmpty()) | 
|  | return ReverseIterator(data_.get(), 0, NULL, 0); | 
|  |  | 
|  | size_t last_id = data_->list_count() - 1; | 
|  | return ReverseIterator( | 
|  | data_.get(), last_id, data_->InnerListById(last_id)->LastElement(), 0); | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | typename ListContainer<BaseElementType>::ReverseIterator | 
|  | ListContainer<BaseElementType>::rend() { | 
|  | return ReverseIterator(data_.get(), 0, NULL, size()); | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | typename ListContainer<BaseElementType>::ConstIterator | 
|  | ListContainer<BaseElementType>::cbegin() const { | 
|  | if (data_->IsEmpty()) | 
|  | return ConstIterator(data_.get(), 0, NULL, 0); | 
|  |  | 
|  | return ConstIterator(data_.get(), 0, data_->InnerListById(0)->Begin(), 0); | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | typename ListContainer<BaseElementType>::ConstIterator | 
|  | ListContainer<BaseElementType>::cend() const { | 
|  | if (data_->IsEmpty()) | 
|  | return ConstIterator(data_.get(), 0, NULL, size()); | 
|  |  | 
|  | size_t last_id = data_->list_count() - 1; | 
|  | return ConstIterator(data_.get(), last_id, NULL, size()); | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | typename ListContainer<BaseElementType>::ConstIterator | 
|  | ListContainer<BaseElementType>::begin() const { | 
|  | return cbegin(); | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | typename ListContainer<BaseElementType>::ConstIterator | 
|  | ListContainer<BaseElementType>::end() const { | 
|  | return cend(); | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | typename ListContainer<BaseElementType>::Iterator | 
|  | ListContainer<BaseElementType>::begin() { | 
|  | if (data_->IsEmpty()) | 
|  | return Iterator(data_.get(), 0, NULL, 0); | 
|  |  | 
|  | return Iterator(data_.get(), 0, data_->InnerListById(0)->Begin(), 0); | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | typename ListContainer<BaseElementType>::Iterator | 
|  | ListContainer<BaseElementType>::end() { | 
|  | if (data_->IsEmpty()) | 
|  | return Iterator(data_.get(), 0, NULL, size()); | 
|  |  | 
|  | size_t last_id = data_->list_count() - 1; | 
|  | return Iterator(data_.get(), last_id, NULL, size()); | 
|  | } | 
|  |  | 
|  | 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> | 
|  | const BaseElementType* ListContainer<BaseElementType>::ElementAt( | 
|  | 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); | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | BaseElementType* ListContainer<BaseElementType>::ElementAt(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); | 
|  | } | 
|  |  | 
|  | 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, | 
|  | size_t index) | 
|  | : PositionInListContainerCharAllocator(container, vector_ind, item_iter), | 
|  | index_(index) { | 
|  | } | 
|  |  | 
|  | 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(); | 
|  | ++index_; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | size_t ListContainer<BaseElementType>::Iterator::index() const { | 
|  | return index_; | 
|  | } | 
|  |  | 
|  | // ListContainer::ConstIterator | 
|  | ///////////////////////////////////////////////// | 
|  | template <typename BaseElementType> | 
|  | ListContainer<BaseElementType>::ConstIterator::ConstIterator( | 
|  | const typename ListContainer<BaseElementType>::Iterator& other) | 
|  | : PositionInListContainerCharAllocator(other), index_(other.index()) { | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | ListContainer<BaseElementType>::ConstIterator::ConstIterator( | 
|  | ListContainerCharAllocator* container, | 
|  | size_t vector_ind, | 
|  | char* item_iter, | 
|  | size_t index) | 
|  | : PositionInListContainerCharAllocator(container, vector_ind, item_iter), | 
|  | index_(index) { | 
|  | } | 
|  |  | 
|  | 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(); | 
|  | ++index_; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | size_t ListContainer<BaseElementType>::ConstIterator::index() const { | 
|  | return index_; | 
|  | } | 
|  |  | 
|  | // ListContainer::ReverseIterator | 
|  | ///////////////////////////////////////////////// | 
|  | template <typename BaseElementType> | 
|  | ListContainer<BaseElementType>::ReverseIterator::ReverseIterator( | 
|  | ListContainerCharAllocator* container, | 
|  | size_t vector_ind, | 
|  | char* item_iter, | 
|  | size_t index) | 
|  | : PositionInListContainerCharAllocator(container, vector_ind, item_iter), | 
|  | index_(index) { | 
|  | } | 
|  |  | 
|  | 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(); | 
|  | ++index_; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | size_t ListContainer<BaseElementType>::ReverseIterator::index() const { | 
|  | return index_; | 
|  | } | 
|  |  | 
|  | // ListContainer::ConstReverseIterator | 
|  | ///////////////////////////////////////////////// | 
|  | template <typename BaseElementType> | 
|  | ListContainer<BaseElementType>::ConstReverseIterator::ConstReverseIterator( | 
|  | const typename ListContainer<BaseElementType>::ReverseIterator& other) | 
|  | : PositionInListContainerCharAllocator(other), index_(other.index()) { | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | ListContainer<BaseElementType>::ConstReverseIterator::ConstReverseIterator( | 
|  | ListContainerCharAllocator* container, | 
|  | size_t vector_ind, | 
|  | char* item_iter, | 
|  | size_t index) | 
|  | : PositionInListContainerCharAllocator(container, vector_ind, item_iter), | 
|  | index_(index) { | 
|  | } | 
|  |  | 
|  | 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(); | 
|  | ++index_; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | template <typename BaseElementType> | 
|  | size_t ListContainer<BaseElementType>::ConstReverseIterator::index() const { | 
|  | return index_; | 
|  | } | 
|  |  | 
|  | template class ListContainer<SharedQuadState>; | 
|  | template class ListContainer<DrawQuad>; | 
|  |  | 
|  | }  // namespace cc |