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_[last_list_index_]; |
| 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 // This is equivalent to |storage_[last_list_index_]|. |
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 |