Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/base/list_container.h" | 5 #include "cc/base/list_container.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "cc/base/scoped_ptr_vector.h" | 10 #include "cc/base/scoped_ptr_vector.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 DCHECK_LE(position, LastElement()); | 46 DCHECK_LE(position, LastElement()); |
| 47 DCHECK_GE(position, Begin()); | 47 DCHECK_GE(position, Begin()); |
| 48 char* start = position + step; | 48 char* start = position + step; |
| 49 std::copy(start, End(), position); | 49 std::copy(start, End(), position); |
| 50 | 50 |
| 51 --size; | 51 --size; |
| 52 // Decrease capacity to avoid creating not full not last InnerList. | 52 // Decrease capacity to avoid creating not full not last InnerList. |
| 53 --capacity; | 53 --capacity; |
| 54 } | 54 } |
| 55 | 55 |
| 56 bool IsEmpty() const { return !size; } | |
| 56 bool IsFull() { return capacity == size; } | 57 bool IsFull() { return capacity == size; } |
| 57 size_t NumElementsAvailable() const { return capacity - size; } | 58 size_t NumElementsAvailable() const { return capacity - size; } |
| 58 | 59 |
| 59 void* AddElement() { | 60 void* AddElement() { |
| 60 DCHECK_LT(size, capacity); | 61 DCHECK_LT(size, capacity); |
| 61 ++size; | 62 ++size; |
| 62 return LastElement(); | 63 return LastElement(); |
| 63 } | 64 } |
| 64 | 65 |
| 66 void RemoveLast() { | |
| 67 DCHECK(!IsEmpty()); | |
| 68 --size; | |
| 69 } | |
| 70 | |
| 65 char* Begin() const { return data.get(); } | 71 char* Begin() const { return data.get(); } |
| 66 char* End() const { return data.get() + size * step; } | 72 char* End() const { return data.get() + size * step; } |
| 67 char* LastElement() const { return data.get() + (size - 1) * step; } | 73 char* LastElement() const { return data.get() + (size - 1) * step; } |
| 68 char* ElementAt(size_t index) const { return data.get() + index * step; } | 74 char* ElementAt(size_t index) const { return data.get() + index * step; } |
| 69 | 75 |
| 70 private: | 76 private: |
| 71 DISALLOW_COPY_AND_ASSIGN(InnerList); | 77 DISALLOW_COPY_AND_ASSIGN(InnerList); |
| 72 }; | 78 }; |
| 73 | 79 |
| 74 explicit ListContainerCharAllocator(size_t element_size) | 80 explicit ListContainerCharAllocator(size_t element_size) |
| 75 : element_size_(element_size), | 81 : element_size_(element_size), |
| 76 size_(0), | 82 size_(0), |
| 77 list_count_(0), | 83 last_list_index_(0), |
| 78 last_list_(NULL) { | 84 last_list_(NULL) { |
| 79 AllocateNewList(kDefaultNumElementTypesToReserve); | 85 AllocateNewList(kDefaultNumElementTypesToReserve); |
| 86 last_list_ = storage_[last_list_index_]; | |
| 80 } | 87 } |
| 81 | 88 |
| 82 ListContainerCharAllocator(size_t element_size, size_t element_count) | 89 ListContainerCharAllocator(size_t element_size, size_t element_count) |
| 83 : element_size_(element_size), | 90 : element_size_(element_size), |
| 84 size_(0), | 91 size_(0), |
| 85 list_count_(0), | 92 last_list_index_(0), |
| 86 last_list_(NULL) { | 93 last_list_(NULL) { |
| 87 AllocateNewList(element_count > 0 ? element_count | 94 AllocateNewList(element_count > 0 ? element_count |
| 88 : kDefaultNumElementTypesToReserve); | 95 : kDefaultNumElementTypesToReserve); |
| 96 last_list_ = storage_[last_list_index_]; | |
| 89 } | 97 } |
| 90 | 98 |
| 91 ~ListContainerCharAllocator() {} | 99 ~ListContainerCharAllocator() {} |
| 92 | 100 |
| 93 void* Allocate() { | 101 void* Allocate() { |
| 94 if (last_list_->IsFull()) | 102 if (last_list_->IsFull()) { |
| 95 AllocateNewList(last_list_->capacity * 2); | 103 // Only allocate a new list if there isn't a spare one still there from |
| 104 // previous usage. | |
| 105 if (last_list_index_ + 1 >= storage_.size()) | |
| 106 AllocateNewList(last_list_->capacity * 2); | |
| 107 | |
| 108 ++last_list_index_; | |
| 109 last_list_ = storage_[last_list_index_]; | |
| 110 } | |
| 96 | 111 |
| 97 ++size_; | 112 ++size_; |
| 98 return last_list_->AddElement(); | 113 return last_list_->AddElement(); |
| 99 } | 114 } |
| 100 | 115 |
| 101 size_t element_size() const { return element_size_; } | 116 size_t element_size() const { return element_size_; } |
| 102 size_t list_count() const { return list_count_; } | 117 size_t list_count() const { return storage_.size(); } |
| 103 size_t size() const { return size_; } | 118 size_t size() const { return size_; } |
| 104 bool IsEmpty() const { return size() == 0; } | 119 bool IsEmpty() const { return size() == 0; } |
| 105 | 120 |
| 106 size_t Capacity() const { | 121 size_t Capacity() const { |
| 107 size_t capacity_sum = 0; | 122 size_t capacity_sum = 0; |
| 108 for (ScopedPtrVector<InnerList>::const_iterator iter = storage_.begin(); | 123 for (ScopedPtrVector<InnerList>::const_iterator iter = storage_.begin(); |
| 109 iter != storage_.end(); ++iter) { | 124 iter != storage_.end(); ++iter) { |
| 110 capacity_sum += (*iter)->capacity; | 125 capacity_sum += (*iter)->capacity; |
| 111 } | 126 } |
| 112 return capacity_sum; | 127 return capacity_sum; |
| 113 } | 128 } |
| 114 | 129 |
| 115 void Clear() { | 130 void Clear() { |
| 116 size_t initial_allocation_size = storage_.front()->capacity; | 131 size_t initial_allocation_size = storage_.front()->capacity; |
| 117 storage_.clear(); | 132 storage_.clear(); |
| 118 list_count_ = 0; | |
| 119 last_list_ = NULL; | 133 last_list_ = NULL; |
| 134 last_list_index_ = 0; | |
| 120 size_ = 0; | 135 size_ = 0; |
| 121 AllocateNewList(initial_allocation_size); | 136 AllocateNewList(initial_allocation_size); |
| 137 last_list_ = storage_[0]; | |
|
danakj
2015/06/03 23:21:23
nit: storage_[last_list_index_]
jbroman
2015/06/04 00:00:47
Done.
| |
| 138 } | |
| 139 | |
| 140 void RemoveLast() { | |
| 141 DCHECK(!IsEmpty()); | |
| 142 last_list_->RemoveLast(); | |
| 143 if (last_list_->IsEmpty() && last_list_index_ > 0) { | |
| 144 --last_list_index_; | |
| 145 last_list_ = storage_[last_list_index_]; | |
| 146 | |
| 147 // If there are now two empty inner lists, free one of them. | |
| 148 if (last_list_index_ + 2 < storage_.size()) | |
| 149 storage_.pop_back(); | |
| 150 } | |
| 151 --size_; | |
| 122 } | 152 } |
| 123 | 153 |
| 124 void Erase(PositionInListContainerCharAllocator position) { | 154 void Erase(PositionInListContainerCharAllocator position) { |
| 125 DCHECK_EQ(this, position.ptr_to_container); | 155 DCHECK_EQ(this, position.ptr_to_container); |
| 126 storage_[position.vector_index]->Erase(position.item_iterator); | 156 storage_[position.vector_index]->Erase(position.item_iterator); |
| 127 // TODO(weiliangc): Free the InnerList if it is empty. | 157 // TODO(weiliangc): Free the InnerList if it is empty. |
| 128 --size_; | 158 --size_; |
| 129 } | 159 } |
| 130 | 160 |
| 131 InnerList* InnerListById(size_t id) const { | 161 InnerList* InnerListById(size_t id) const { |
| 132 DCHECK_LT(id, list_count_); | 162 DCHECK_LT(id, storage_.size()); |
| 133 return storage_[id]; | 163 return storage_[id]; |
| 134 } | 164 } |
| 135 | 165 |
| 136 size_t FirstInnerListId() const { | 166 size_t FirstInnerListId() const { |
| 137 // |size_| > 0 means that at least one vector in |storage_| will be | 167 // |size_| > 0 means that at least one vector in |storage_| will be |
| 138 // non-empty. | 168 // non-empty. |
| 139 DCHECK_GT(size_, 0u); | 169 DCHECK_GT(size_, 0u); |
| 140 size_t id = 0; | 170 size_t id = 0; |
| 141 while (storage_[id]->size == 0) | 171 while (storage_[id]->size == 0) |
| 142 ++id; | 172 ++id; |
| 143 return id; | 173 return id; |
| 144 } | 174 } |
| 145 | 175 |
| 146 size_t LastInnerListId() const { | 176 size_t LastInnerListId() const { |
| 147 // |size_| > 0 means that at least one vector in |storage_| will be | 177 // |size_| > 0 means that at least one vector in |storage_| will be |
| 148 // non-empty. | 178 // non-empty. |
| 149 DCHECK_GT(size_, 0u); | 179 DCHECK_GT(size_, 0u); |
| 150 size_t id = list_count_ - 1; | 180 size_t id = storage_.size() - 1; |
| 151 while (storage_[id]->size == 0) | 181 while (storage_[id]->size == 0) |
| 152 --id; | 182 --id; |
| 153 return id; | 183 return id; |
| 154 } | 184 } |
| 155 | 185 |
| 156 void AllocateNewList(size_t list_size) { | |
| 157 ++list_count_; | |
| 158 scoped_ptr<InnerList> new_list(new InnerList); | |
| 159 storage_.push_back(new_list.Pass()); | |
| 160 last_list_ = storage_.back(); | |
| 161 InnerList* list = last_list_; | |
| 162 list->capacity = list_size; | |
| 163 list->size = 0; | |
| 164 list->step = element_size_; | |
| 165 list->data.reset(new char[list->capacity * list->step]); | |
| 166 } | |
| 167 | |
| 168 size_t NumAvailableElementsInLastList() const { | 186 size_t NumAvailableElementsInLastList() const { |
| 169 return last_list_->NumElementsAvailable(); | 187 return last_list_->NumElementsAvailable(); |
| 170 } | 188 } |
| 171 | 189 |
| 172 private: | 190 private: |
| 191 void AllocateNewList(size_t list_size) { | |
| 192 scoped_ptr<InnerList> new_list(new InnerList); | |
| 193 new_list->capacity = list_size; | |
| 194 new_list->size = 0; | |
| 195 new_list->step = element_size_; | |
| 196 new_list->data.reset(new char[list_size * element_size_]); | |
| 197 storage_.push_back(new_list.Pass()); | |
| 198 } | |
| 199 | |
| 173 ScopedPtrVector<InnerList> storage_; | 200 ScopedPtrVector<InnerList> storage_; |
| 174 const size_t element_size_; | 201 const size_t element_size_; |
| 202 | |
| 203 // The number of elements in the list. | |
| 175 size_t size_; | 204 size_t size_; |
| 176 size_t list_count_; | 205 |
| 206 // The index of the last list to have had elements added to it, or the only | |
| 207 // list if the container has not had elements added since being cleared. | |
| 208 size_t last_list_index_; | |
| 209 | |
| 210 // storage_[last_list_index_] | |
|
danakj
2015/06/03 23:21:23
can you make this a sentence?
jbroman
2015/06/04 00:00:47
Done.
| |
| 177 InnerList* last_list_; | 211 InnerList* last_list_; |
| 178 | 212 |
| 179 DISALLOW_COPY_AND_ASSIGN(ListContainerCharAllocator); | 213 DISALLOW_COPY_AND_ASSIGN(ListContainerCharAllocator); |
| 180 }; | 214 }; |
| 181 | 215 |
| 182 // PositionInListContainerCharAllocator | 216 // PositionInListContainerCharAllocator |
| 183 ////////////////////////////////////////////////////// | 217 ////////////////////////////////////////////////////// |
| 184 ListContainerBase::PositionInListContainerCharAllocator:: | 218 ListContainerBase::PositionInListContainerCharAllocator:: |
| 185 PositionInListContainerCharAllocator( | 219 PositionInListContainerCharAllocator( |
| 186 const ListContainerBase::PositionInListContainerCharAllocator& other) | 220 const ListContainerBase::PositionInListContainerCharAllocator& other) |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 | 302 |
| 269 ListContainerBase::ListContainerBase(size_t max_size_for_derived_class, | 303 ListContainerBase::ListContainerBase(size_t max_size_for_derived_class, |
| 270 size_t num_of_elements_to_reserve_for) | 304 size_t num_of_elements_to_reserve_for) |
| 271 : data_(new ListContainerCharAllocator(max_size_for_derived_class, | 305 : data_(new ListContainerCharAllocator(max_size_for_derived_class, |
| 272 num_of_elements_to_reserve_for)) { | 306 num_of_elements_to_reserve_for)) { |
| 273 } | 307 } |
| 274 | 308 |
| 275 ListContainerBase::~ListContainerBase() { | 309 ListContainerBase::~ListContainerBase() { |
| 276 } | 310 } |
| 277 | 311 |
| 312 void ListContainerBase::RemoveLast() { | |
| 313 data_->RemoveLast(); | |
| 314 } | |
| 315 | |
| 278 void ListContainerBase::EraseAndInvalidateAllPointers( | 316 void ListContainerBase::EraseAndInvalidateAllPointers( |
| 279 ListContainerBase::Iterator position) { | 317 ListContainerBase::Iterator position) { |
| 280 data_->Erase(position); | 318 data_->Erase(position); |
| 281 } | 319 } |
| 282 | 320 |
| 283 ListContainerBase::ConstReverseIterator ListContainerBase::crbegin() const { | 321 ListContainerBase::ConstReverseIterator ListContainerBase::crbegin() const { |
| 284 if (data_->IsEmpty()) | 322 if (data_->IsEmpty()) |
| 285 return crend(); | 323 return crend(); |
| 286 | 324 |
| 287 size_t id = data_->LastInnerListId(); | 325 size_t id = data_->LastInnerListId(); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 467 } | 505 } |
| 468 | 506 |
| 469 ListContainerBase::ConstReverseIterator::~ConstReverseIterator() { | 507 ListContainerBase::ConstReverseIterator::~ConstReverseIterator() { |
| 470 } | 508 } |
| 471 | 509 |
| 472 size_t ListContainerBase::ConstReverseIterator::index() const { | 510 size_t ListContainerBase::ConstReverseIterator::index() const { |
| 473 return index_; | 511 return index_; |
| 474 } | 512 } |
| 475 | 513 |
| 476 } // namespace cc | 514 } // namespace cc |
| OLD | NEW |