OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "cc/quads/list_container.h" | |
6 | |
7 #include <algorithm> | |
8 #include <vector> | |
9 | |
10 #include "cc/base/scoped_ptr_vector.h" | |
11 #include "cc/quads/draw_quad.h" | |
12 #include "cc/quads/shared_quad_state.h" | |
13 | |
14 namespace { | |
15 const size_t kDefaultNumElementTypesToReserve = 32; | |
16 } // namespace | |
17 | |
18 namespace cc { | |
19 | |
20 // ListContainerCharAllocator | |
21 //////////////////////////////////////////////////// | |
22 // This class deals only with char* and void*. It does allocation and passing | |
23 // out raw pointers, as well as memory deallocation when being destroyed. | |
24 template <typename BaseElementType> | |
25 class ListContainer<BaseElementType>::ListContainerCharAllocator { | |
26 public: | |
27 // ListContainerCharAllocator::InnerList | |
28 ///////////////////////////////////////////// | |
29 // This class holds the raw memory chunk, as well as information about its | |
30 // size and availability. | |
31 struct InnerList { | |
32 scoped_ptr<char> data; | |
33 // The number of elements in total the memory can hold. The difference | |
34 // between capacity and size is the how many more elements this list can | |
35 // hold. | |
36 size_t capacity; | |
37 // The number of elements have been put into this list. | |
38 size_t size; | |
39 // The size of each element is in bytes. This is used to move from between | |
40 // elements' memory locations. | |
41 size_t step; | |
42 | |
43 InnerList() : capacity(0), size(0), step(0) {} | |
44 | |
45 void Erase(char* position) { | |
46 // Confident that destructor is called by caller of this function. Since | |
47 // ListContainerCharAllocator does not handle construction after | |
48 // allocation, it doesn't handle desctrution before deallocation. | |
49 DCHECK_LE(position, LastElement()); | |
50 DCHECK_GE(position, Begin()); | |
51 char* start = position + step; | |
52 std::copy(start, End(), position); | |
53 | |
54 --size; | |
55 // Decrease capacity to avoid creating not full not last InnerList. | |
56 --capacity; | |
57 } | |
58 | |
59 bool IsFull() { return capacity == size; } | |
60 size_t NumElementsAvailable() const { return capacity - size; } | |
61 | |
62 void* AddElement() { | |
63 DCHECK_LT(size, capacity); | |
64 ++size; | |
65 return LastElement(); | |
66 } | |
67 | |
68 char* Begin() const { return data.get(); } | |
69 char* End() const { return data.get() + size * step; } | |
70 char* LastElement() const { return data.get() + (size - 1) * step; } | |
71 | |
72 private: | |
73 DISALLOW_COPY_AND_ASSIGN(InnerList); | |
74 }; | |
75 | |
76 explicit ListContainerCharAllocator(size_t element_size) | |
77 : element_size_(element_size), | |
78 size_(0), | |
79 list_count_(0), | |
80 last_list_(NULL) { | |
81 AllocateNewList(kDefaultNumElementTypesToReserve); | |
82 } | |
83 | |
84 ListContainerCharAllocator(size_t element_size, size_t element_count) | |
85 : element_size_(element_size), | |
86 size_(0), | |
87 list_count_(0), | |
88 last_list_(NULL) { | |
89 DCHECK_NE(0u, element_count); | |
90 AllocateNewList(element_count); | |
91 } | |
92 | |
93 ~ListContainerCharAllocator() {} | |
94 | |
95 void* Allocate() { | |
96 if (last_list_->IsFull()) | |
97 AllocateNewList(last_list_->capacity * 2); | |
98 | |
99 ++size_; | |
100 return last_list_->AddElement(); | |
101 } | |
102 | |
103 size_t element_size() const { return element_size_; } | |
104 size_t list_count() const { return list_count_; } | |
105 size_t size() const { return size_; } | |
106 bool IsEmpty() const { return size() == 0; } | |
107 | |
108 size_t Capacity() const { | |
109 size_t capacity_sum = 0; | |
110 for (typename ScopedPtrVector<InnerList>::const_iterator iter = | |
111 storage_.begin(); | |
112 iter != storage_.end(); | |
113 ++iter) { | |
114 capacity_sum += (*iter)->capacity; | |
115 } | |
116 return capacity_sum; | |
117 } | |
118 | |
119 void Clear() { | |
120 size_t initial_allocation_size = storage_.front()->capacity; | |
121 storage_.clear(); | |
122 list_count_ = 0; | |
123 last_list_ = NULL; | |
124 size_ = 0; | |
125 AllocateNewList(initial_allocation_size); | |
126 } | |
127 | |
128 void Erase(PositionInListContainerCharAllocator position) { | |
129 DCHECK_EQ(this, position.ptr_to_container); | |
130 storage_[position.vector_index]->Erase(position.item_iterator); | |
131 // TODO(weiliangc): Free the InnerList if it is empty. | |
132 --size_; | |
133 } | |
134 | |
135 InnerList* InnerListById(size_t id) const { | |
136 DCHECK_LT(id, list_count_); | |
137 return storage_[id]; | |
138 } | |
139 | |
140 void AllocateNewList(size_t list_size) { | |
141 ++list_count_; | |
142 scoped_ptr<InnerList> new_list(new InnerList); | |
143 storage_.push_back(new_list.Pass()); | |
144 last_list_ = storage_.back(); | |
145 InnerList* list = last_list_; | |
146 list->capacity = list_size; | |
147 list->size = 0; | |
148 list->step = element_size_; | |
149 list->data = make_scoped_ptr(new char[list->capacity * list->step]); | |
150 } | |
151 | |
152 size_t NumAvailableElementsInLastList() const { | |
153 return last_list_->NumElementsAvailable(); | |
154 } | |
155 | |
156 private: | |
157 ScopedPtrVector<InnerList> storage_; | |
158 const size_t element_size_; | |
159 size_t size_; | |
160 size_t list_count_; | |
161 InnerList* last_list_; | |
162 | |
163 DISALLOW_COPY_AND_ASSIGN(ListContainerCharAllocator); | |
164 }; | |
165 | |
166 // PositionInListContainerCharAllocator | |
167 ////////////////////////////////////////////////////// | |
168 template <typename BaseElementType> | |
169 ListContainer<BaseElementType>::PositionInListContainerCharAllocator:: | |
170 PositionInListContainerCharAllocator(const typename ListContainer< | |
171 BaseElementType>::PositionInListContainerCharAllocator& other) | |
172 : ptr_to_container(other.ptr_to_container), | |
173 vector_index(other.vector_index), | |
174 item_iterator(other.item_iterator) { | |
175 } | |
176 | |
177 template <typename BaseElementType> | |
178 ListContainer<BaseElementType>::PositionInListContainerCharAllocator:: | |
179 PositionInListContainerCharAllocator( | |
180 typename ListContainer<BaseElementType>::ListContainerCharAllocator* | |
181 container, | |
182 size_t vector_ind, | |
183 char* item_iter) | |
184 : ptr_to_container(container), | |
185 vector_index(vector_ind), | |
186 item_iterator(item_iter) { | |
187 } | |
188 | |
189 template <typename BaseElementType> | |
190 bool ListContainer<BaseElementType>::PositionInListContainerCharAllocator:: | |
191 operator==(const typename ListContainer< | |
192 BaseElementType>::PositionInListContainerCharAllocator& other) const { | |
193 DCHECK_EQ(ptr_to_container, other.ptr_to_container); | |
194 return vector_index == other.vector_index && | |
195 item_iterator == other.item_iterator; | |
196 } | |
197 | |
198 template <typename BaseElementType> | |
199 bool ListContainer<BaseElementType>::PositionInListContainerCharAllocator:: | |
200 operator!=(const typename ListContainer< | |
201 BaseElementType>::PositionInListContainerCharAllocator& other) const { | |
202 return !(*this == other); | |
203 } | |
204 | |
205 template <typename BaseElementType> | |
206 typename ListContainer<BaseElementType>::PositionInListContainerCharAllocator | |
207 ListContainer< | |
208 BaseElementType>::PositionInListContainerCharAllocator::Increment() { | |
209 typename ListContainerCharAllocator::InnerList* list = | |
210 ptr_to_container->InnerListById(vector_index); | |
211 if (item_iterator == list->LastElement()) { | |
212 if (vector_index < ptr_to_container->list_count() - 1) { | |
213 ++vector_index; | |
214 item_iterator = ptr_to_container->InnerListById(vector_index)->Begin(); | |
215 } else { | |
216 item_iterator = NULL; | |
217 } | |
218 } else { | |
219 item_iterator += list->step; | |
220 } | |
221 return *this; | |
222 } | |
223 | |
224 template <typename BaseElementType> | |
225 typename ListContainer<BaseElementType>::PositionInListContainerCharAllocator | |
226 ListContainer< | |
227 BaseElementType>::PositionInListContainerCharAllocator::ReverseIncrement() { | |
228 typename ListContainerCharAllocator::InnerList* list = | |
229 ptr_to_container->InnerListById(vector_index); | |
230 if (item_iterator == list->Begin()) { | |
231 if (vector_index > 0) { | |
232 --vector_index; | |
233 item_iterator = | |
234 ptr_to_container->InnerListById(vector_index)->LastElement(); | |
235 } else { | |
236 item_iterator = NULL; | |
237 } | |
238 } else { | |
239 item_iterator -= list->step; | |
240 } | |
241 return *this; | |
242 } | |
243 | |
244 // ListContainer | |
245 //////////////////////////////////////////// | |
246 template <typename BaseElementType> | |
247 ListContainer<BaseElementType>::ListContainer(size_t max_size_for_derived_class) | |
248 : data_(new ListContainerCharAllocator(max_size_for_derived_class)) { | |
249 } | |
250 | |
251 template <typename BaseElementType> | |
252 ListContainer<BaseElementType>::ListContainer( | |
253 size_t max_size_for_derived_class, | |
254 size_t num_of_elements_to_reserve_for) | |
255 : data_(new ListContainerCharAllocator(max_size_for_derived_class, | |
256 num_of_elements_to_reserve_for)) { | |
257 } | |
258 | |
259 template <typename BaseElementType> | |
260 ListContainer<BaseElementType>::ListContainer() | |
261 : data_(new ListContainerCharAllocator(sizeof(BaseElementType))) { | |
262 } | |
263 | |
264 template <typename BaseElementType> | |
265 ListContainer<BaseElementType>::~ListContainer() { | |
266 for (Iterator i = begin(); i != end(); ++i) { | |
267 i->~BaseElementType(); | |
268 } | |
269 } | |
270 | |
271 template <typename BaseElementType> | |
272 void ListContainer<BaseElementType>::EraseAndInvalidateAllPointers( | |
273 typename ListContainer<BaseElementType>::Iterator position) { | |
274 BaseElementType* item = &*position; | |
275 item->~BaseElementType(); | |
276 data_->Erase(position); | |
277 } | |
278 | |
279 template <typename BaseElementType> | |
280 typename ListContainer<BaseElementType>::ConstReverseIterator | |
281 ListContainer<BaseElementType>::rbegin() const { | |
282 if (data_->IsEmpty()) | |
283 return ConstReverseIterator(data_.get(), 0, NULL); | |
284 | |
285 size_t last_id = data_->list_count() - 1; | |
286 return ConstReverseIterator( | |
287 data_.get(), last_id, data_->InnerListById(last_id)->LastElement()); | |
288 } | |
289 | |
290 template <typename BaseElementType> | |
291 typename ListContainer<BaseElementType>::ConstReverseIterator | |
292 ListContainer<BaseElementType>::rend() const { | |
293 return ConstReverseIterator(data_.get(), 0, NULL); | |
294 } | |
295 | |
296 template <typename BaseElementType> | |
297 typename ListContainer<BaseElementType>::ReverseIterator | |
298 ListContainer<BaseElementType>::rbegin() { | |
299 if (data_->IsEmpty()) | |
300 return ReverseIterator(data_.get(), 0, NULL); | |
301 | |
302 size_t last_id = data_->list_count() - 1; | |
303 return ReverseIterator( | |
304 data_.get(), last_id, data_->InnerListById(last_id)->LastElement()); | |
305 } | |
306 | |
307 template <typename BaseElementType> | |
308 typename ListContainer<BaseElementType>::ReverseIterator | |
309 ListContainer<BaseElementType>::rend() { | |
310 return ReverseIterator(data_.get(), 0, NULL); | |
311 } | |
312 | |
313 template <typename BaseElementType> | |
314 typename ListContainer<BaseElementType>::ConstIterator | |
315 ListContainer<BaseElementType>::begin() const { | |
316 if (data_->IsEmpty()) | |
317 return ConstIterator(data_.get(), 0, NULL); | |
318 | |
319 return ConstIterator(data_.get(), 0, data_->InnerListById(0)->Begin()); | |
320 } | |
321 | |
322 template <typename BaseElementType> | |
323 typename ListContainer<BaseElementType>::ConstIterator | |
324 ListContainer<BaseElementType>::end() const { | |
325 if (data_->IsEmpty()) | |
326 return ConstIterator(data_.get(), 0, NULL); | |
327 | |
328 size_t last_id = data_->list_count() - 1; | |
329 return ConstIterator(data_.get(), last_id, NULL); | |
330 } | |
331 | |
332 template <typename BaseElementType> | |
333 typename ListContainer<BaseElementType>::Iterator | |
334 ListContainer<BaseElementType>::begin() { | |
335 if (data_->IsEmpty()) | |
336 return Iterator(data_.get(), 0, NULL); | |
337 | |
338 return Iterator(data_.get(), 0, data_->InnerListById(0)->Begin()); | |
339 } | |
340 | |
341 template <typename BaseElementType> | |
342 typename ListContainer<BaseElementType>::Iterator | |
343 ListContainer<BaseElementType>::end() { | |
344 if (data_->IsEmpty()) | |
345 return Iterator(data_.get(), 0, NULL); | |
346 | |
347 size_t last_id = data_->list_count() - 1; | |
348 return Iterator(data_.get(), last_id, NULL); | |
349 } | |
350 | |
351 template <typename BaseElementType> | |
352 BaseElementType* ListContainer<BaseElementType>::front() { | |
353 Iterator iter = begin(); | |
354 return &*iter; | |
355 } | |
356 | |
357 template <typename BaseElementType> | |
358 BaseElementType* ListContainer<BaseElementType>::back() { | |
359 ReverseIterator iter = rbegin(); | |
360 return &*iter; | |
361 } | |
362 | |
363 template <typename BaseElementType> | |
364 const BaseElementType* ListContainer<BaseElementType>::front() const { | |
365 ConstIterator iter = begin(); | |
366 return &*iter; | |
367 } | |
368 | |
369 template <typename BaseElementType> | |
370 const BaseElementType* ListContainer<BaseElementType>::back() const { | |
371 ConstReverseIterator iter = rbegin(); | |
372 return &*iter; | |
373 } | |
374 | |
375 template <typename BaseElementType> | |
376 BaseElementType* ListContainer<BaseElementType>::Allocate( | |
377 size_t size_of_actual_element_in_bytes) { | |
378 DCHECK_LE(size_of_actual_element_in_bytes, data_->element_size()); | |
379 void* result = data_->Allocate(); | |
380 return static_cast<BaseElementType*>(result); | |
381 } | |
382 | |
383 template <typename BaseElementType> | |
384 size_t ListContainer<BaseElementType>::size() const { | |
385 return data_->size(); | |
386 } | |
387 | |
388 template <typename BaseElementType> | |
389 bool ListContainer<BaseElementType>::empty() const { | |
390 return data_->IsEmpty(); | |
391 } | |
392 | |
393 template <typename BaseElementType> | |
394 void ListContainer<BaseElementType>::clear() { | |
395 for (Iterator i = begin(); i != end(); ++i) { | |
396 i->~BaseElementType(); | |
397 } | |
398 data_->Clear(); | |
399 } | |
400 | |
401 template <typename BaseElementType> | |
402 size_t ListContainer< | |
403 BaseElementType>::AvailableSizeWithoutAnotherAllocationForTesting() const { | |
404 return data_->NumAvailableElementsInLastList(); | |
405 } | |
406 | |
407 // ListContainer::Iterator | |
408 ///////////////////////////////////////////////// | |
409 template <typename BaseElementType> | |
410 ListContainer<BaseElementType>::Iterator::Iterator( | |
411 ListContainerCharAllocator* container, | |
412 size_t vector_ind, | |
413 char* item_iter) | |
414 : PositionInListContainerCharAllocator(container, vector_ind, item_iter) { | |
415 } | |
416 | |
417 template <typename BaseElementType> | |
418 ListContainer<BaseElementType>::Iterator::~Iterator() { | |
419 } | |
420 | |
421 template <typename BaseElementType> | |
422 BaseElementType* ListContainer<BaseElementType>::Iterator::operator->() const { | |
423 return reinterpret_cast<BaseElementType*>(this->item_iterator); | |
424 } | |
425 | |
426 template <typename BaseElementType> | |
427 BaseElementType& ListContainer<BaseElementType>::Iterator::operator*() const { | |
428 return *(reinterpret_cast<BaseElementType*>(this->item_iterator)); | |
429 } | |
430 | |
431 template <typename BaseElementType> | |
432 typename ListContainer<BaseElementType>::Iterator | |
433 ListContainer<BaseElementType>::Iterator:: | |
434 operator++(int unused_post_increment) { | |
435 Iterator tmp = *this; | |
436 operator++(); | |
437 return tmp; | |
438 } | |
439 | |
440 template <typename BaseElementType> | |
441 typename ListContainer<BaseElementType>::Iterator | |
442 ListContainer<BaseElementType>::Iterator:: | |
443 operator++() { | |
444 this->Increment(); | |
445 return *this; | |
446 } | |
447 | |
448 // ListContainer::ConstIterator | |
449 ///////////////////////////////////////////////// | |
450 template <typename BaseElementType> | |
451 ListContainer<BaseElementType>::ConstIterator::ConstIterator( | |
452 const typename ListContainer<BaseElementType>::Iterator& other) | |
453 : PositionInListContainerCharAllocator(other) { | |
454 } | |
455 | |
456 template <typename BaseElementType> | |
457 ListContainer<BaseElementType>::ConstIterator::ConstIterator( | |
458 ListContainerCharAllocator* container, | |
459 size_t vector_ind, | |
460 char* item_iter) | |
461 : PositionInListContainerCharAllocator(container, vector_ind, item_iter) { | |
462 } | |
463 | |
464 template <typename BaseElementType> | |
465 ListContainer<BaseElementType>::ConstIterator::~ConstIterator() { | |
466 } | |
467 | |
468 template <typename BaseElementType> | |
469 const BaseElementType* ListContainer<BaseElementType>::ConstIterator:: | |
470 operator->() const { | |
471 return reinterpret_cast<const BaseElementType*>(this->item_iterator); | |
472 } | |
473 | |
474 template <typename BaseElementType> | |
475 const BaseElementType& ListContainer<BaseElementType>::ConstIterator:: | |
476 operator*() const { | |
477 return *(reinterpret_cast<const BaseElementType*>(this->item_iterator)); | |
478 } | |
479 | |
480 template <typename BaseElementType> | |
481 typename ListContainer<BaseElementType>::ConstIterator | |
482 ListContainer<BaseElementType>::ConstIterator:: | |
483 operator++(int unused_post_increment) { | |
484 ConstIterator tmp = *this; | |
485 operator++(); | |
486 return tmp; | |
487 } | |
488 | |
489 template <typename BaseElementType> | |
490 typename ListContainer<BaseElementType>::ConstIterator | |
491 ListContainer<BaseElementType>::ConstIterator:: | |
492 operator++() { | |
493 this->Increment(); | |
494 return *this; | |
495 } | |
496 | |
497 // ListContainer::ReverseIterator | |
498 ///////////////////////////////////////////////// | |
499 template <typename BaseElementType> | |
500 ListContainer<BaseElementType>::ReverseIterator::ReverseIterator( | |
501 ListContainerCharAllocator* container, | |
502 size_t vector_ind, | |
503 char* item_iter) | |
504 : PositionInListContainerCharAllocator(container, vector_ind, item_iter) { | |
505 } | |
506 | |
507 template <typename BaseElementType> | |
508 ListContainer<BaseElementType>::ReverseIterator::~ReverseIterator() { | |
509 } | |
510 | |
511 template <typename BaseElementType> | |
512 BaseElementType* ListContainer<BaseElementType>::ReverseIterator::operator->() | |
513 const { | |
514 return reinterpret_cast<BaseElementType*>(this->item_iterator); | |
515 } | |
516 | |
517 template <typename BaseElementType> | |
518 BaseElementType& ListContainer<BaseElementType>::ReverseIterator::operator*() | |
519 const { | |
520 return *(reinterpret_cast<BaseElementType*>(this->item_iterator)); | |
521 } | |
522 | |
523 template <typename BaseElementType> | |
524 typename ListContainer<BaseElementType>::ReverseIterator | |
525 ListContainer<BaseElementType>::ReverseIterator:: | |
526 operator++(int unused_post_increment) { | |
527 ReverseIterator tmp = *this; | |
528 operator++(); | |
529 return tmp; | |
530 } | |
531 | |
532 template <typename BaseElementType> | |
533 typename ListContainer<BaseElementType>::ReverseIterator | |
534 ListContainer<BaseElementType>::ReverseIterator:: | |
535 operator++() { | |
536 this->ReverseIncrement(); | |
537 return *this; | |
538 } | |
539 | |
540 // ListContainer::ConstReverseIterator | |
541 ///////////////////////////////////////////////// | |
542 template <typename BaseElementType> | |
543 ListContainer<BaseElementType>::ConstReverseIterator::ConstReverseIterator( | |
544 const typename ListContainer<BaseElementType>::ReverseIterator& other) | |
545 : PositionInListContainerCharAllocator(other) { | |
546 } | |
547 | |
548 template <typename BaseElementType> | |
549 ListContainer<BaseElementType>::ConstReverseIterator::ConstReverseIterator( | |
550 ListContainerCharAllocator* container, | |
551 size_t vector_ind, | |
552 char* item_iter) | |
553 : PositionInListContainerCharAllocator(container, vector_ind, item_iter) { | |
554 } | |
555 | |
556 template <typename BaseElementType> | |
557 ListContainer<BaseElementType>::ConstReverseIterator::~ConstReverseIterator() { | |
558 } | |
559 | |
560 template <typename BaseElementType> | |
561 const BaseElementType* ListContainer<BaseElementType>::ConstReverseIterator:: | |
562 operator->() const { | |
563 return reinterpret_cast<const BaseElementType*>(this->item_iterator); | |
564 } | |
565 | |
566 template <typename BaseElementType> | |
567 const BaseElementType& ListContainer<BaseElementType>::ConstReverseIterator:: | |
568 operator*() const { | |
569 return *(reinterpret_cast<const BaseElementType*>(this->item_iterator)); | |
570 } | |
571 | |
572 template <typename BaseElementType> | |
573 typename ListContainer<BaseElementType>::ConstReverseIterator | |
574 ListContainer<BaseElementType>::ConstReverseIterator:: | |
575 operator++(int unused_post_increment) { | |
576 ConstReverseIterator tmp = *this; | |
577 operator++(); | |
578 return tmp; | |
579 } | |
580 | |
581 template <typename BaseElementType> | |
582 typename ListContainer<BaseElementType>::ConstReverseIterator | |
583 ListContainer<BaseElementType>::ConstReverseIterator:: | |
584 operator++() { | |
585 this->ReverseIncrement(); | |
586 return *this; | |
587 } | |
588 | |
589 template class ListContainer<SharedQuadState>; | |
590 template class ListContainer<DrawQuad>; | |
591 | |
592 } // namespace cc | |
OLD | NEW |