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.
5 #include "cc/quads/list_container.h"
10 #include "cc/base/scoped_ptr_vector.h"
11 #include "cc/quads/draw_quad.h"
12 #include "cc/quads/shared_quad_state.h"
15 const size_t kDefaultNumElementTypesToReserve
= 32;
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
{
27 // ListContainerCharAllocator::InnerList
28 /////////////////////////////////////////////
29 // This class holds the raw memory chunk, as well as information about its
30 // size and availability.
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
37 // The number of elements have been put into this list.
39 // The size of each element is in bytes. This is used to move from between
40 // elements' memory locations.
43 InnerList() : capacity(0), size(0), step(0) {}
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
);
55 // Decrease capacity to avoid creating not full not last InnerList.
59 bool IsFull() { return capacity
== size
; }
60 size_t NumElementsAvailable() const { return capacity
- size
; }
63 DCHECK_LT(size
, capacity
);
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 char* ElementAt(size_t index
) const { return data
.get() + index
* step
; }
74 DISALLOW_COPY_AND_ASSIGN(InnerList
);
77 explicit ListContainerCharAllocator(size_t element_size
)
78 : element_size_(element_size
),
82 AllocateNewList(kDefaultNumElementTypesToReserve
);
85 ListContainerCharAllocator(size_t element_size
, size_t element_count
)
86 : element_size_(element_size
),
90 AllocateNewList(element_count
> 0 ? element_count
91 : kDefaultNumElementTypesToReserve
);
94 ~ListContainerCharAllocator() {}
97 if (last_list_
->IsFull())
98 AllocateNewList(last_list_
->capacity
* 2);
101 return last_list_
->AddElement();
104 size_t element_size() const { return element_size_
; }
105 size_t list_count() const { return list_count_
; }
106 size_t size() const { return size_
; }
107 bool IsEmpty() const { return size() == 0; }
109 size_t Capacity() const {
110 size_t capacity_sum
= 0;
111 for (typename ScopedPtrVector
<InnerList
>::const_iterator iter
=
113 iter
!= storage_
.end();
115 capacity_sum
+= (*iter
)->capacity
;
121 size_t initial_allocation_size
= storage_
.front()->capacity
;
126 AllocateNewList(initial_allocation_size
);
129 void Erase(PositionInListContainerCharAllocator position
) {
130 DCHECK_EQ(this, position
.ptr_to_container
);
131 storage_
[position
.vector_index
]->Erase(position
.item_iterator
);
132 // TODO(weiliangc): Free the InnerList if it is empty.
136 InnerList
* InnerListById(size_t id
) const {
137 DCHECK_LT(id
, list_count_
);
141 size_t FirstInnerListId() const {
142 // |size_| > 0 means that at least one vector in |storage_| will be
144 DCHECK_GT(size_
, 0u);
146 while (storage_
[id
]->size
== 0)
151 size_t LastInnerListId() const {
152 // |size_| > 0 means that at least one vector in |storage_| will be
154 DCHECK_GT(size_
, 0u);
155 size_t id
= list_count_
- 1;
156 while (storage_
[id
]->size
== 0)
161 void AllocateNewList(size_t list_size
) {
163 scoped_ptr
<InnerList
> new_list(new InnerList
);
164 storage_
.push_back(new_list
.Pass());
165 last_list_
= storage_
.back();
166 InnerList
* list
= last_list_
;
167 list
->capacity
= list_size
;
169 list
->step
= element_size_
;
170 list
->data
.reset(new char[list
->capacity
* list
->step
]);
173 size_t NumAvailableElementsInLastList() const {
174 return last_list_
->NumElementsAvailable();
178 ScopedPtrVector
<InnerList
> storage_
;
179 const size_t element_size_
;
182 InnerList
* last_list_
;
184 DISALLOW_COPY_AND_ASSIGN(ListContainerCharAllocator
);
187 // PositionInListContainerCharAllocator
188 //////////////////////////////////////////////////////
189 template <typename BaseElementType
>
190 ListContainer
<BaseElementType
>::PositionInListContainerCharAllocator::
191 PositionInListContainerCharAllocator(const typename ListContainer
<
192 BaseElementType
>::PositionInListContainerCharAllocator
& other
)
193 : ptr_to_container(other
.ptr_to_container
),
194 vector_index(other
.vector_index
),
195 item_iterator(other
.item_iterator
) {
198 template <typename BaseElementType
>
199 ListContainer
<BaseElementType
>::PositionInListContainerCharAllocator::
200 PositionInListContainerCharAllocator(
201 typename ListContainer
<BaseElementType
>::ListContainerCharAllocator
*
205 : ptr_to_container(container
),
206 vector_index(vector_ind
),
207 item_iterator(item_iter
) {
210 template <typename BaseElementType
>
211 bool ListContainer
<BaseElementType
>::PositionInListContainerCharAllocator::
212 operator==(const typename ListContainer
<
213 BaseElementType
>::PositionInListContainerCharAllocator
& other
) const {
214 DCHECK_EQ(ptr_to_container
, other
.ptr_to_container
);
215 return vector_index
== other
.vector_index
&&
216 item_iterator
== other
.item_iterator
;
219 template <typename BaseElementType
>
220 bool ListContainer
<BaseElementType
>::PositionInListContainerCharAllocator::
221 operator!=(const typename ListContainer
<
222 BaseElementType
>::PositionInListContainerCharAllocator
& other
) const {
223 return !(*this == other
);
226 template <typename BaseElementType
>
227 typename ListContainer
<BaseElementType
>::PositionInListContainerCharAllocator
229 BaseElementType
>::PositionInListContainerCharAllocator::Increment() {
230 typename
ListContainerCharAllocator::InnerList
* list
=
231 ptr_to_container
->InnerListById(vector_index
);
232 if (item_iterator
== list
->LastElement()) {
234 while (vector_index
< ptr_to_container
->list_count()) {
235 if (ptr_to_container
->InnerListById(vector_index
)->size
!= 0)
239 if (vector_index
< ptr_to_container
->list_count())
240 item_iterator
= ptr_to_container
->InnerListById(vector_index
)->Begin();
242 item_iterator
= NULL
;
244 item_iterator
+= list
->step
;
249 template <typename BaseElementType
>
250 typename ListContainer
<BaseElementType
>::PositionInListContainerCharAllocator
252 BaseElementType
>::PositionInListContainerCharAllocator::ReverseIncrement() {
253 typename
ListContainerCharAllocator::InnerList
* list
=
254 ptr_to_container
->InnerListById(vector_index
);
255 if (item_iterator
== list
->Begin()) {
257 // Since |vector_index| is unsigned, we compare < list_count() instead of
258 // comparing >= 0, as the variable will wrap around when it goes out of
260 while (vector_index
< ptr_to_container
->list_count()) {
261 if (ptr_to_container
->InnerListById(vector_index
)->size
!= 0)
265 if (vector_index
< ptr_to_container
->list_count()) {
267 ptr_to_container
->InnerListById(vector_index
)->LastElement();
269 item_iterator
= NULL
;
272 item_iterator
-= list
->step
;
278 ////////////////////////////////////////////
279 template <typename BaseElementType
>
280 ListContainer
<BaseElementType
>::ListContainer(size_t max_size_for_derived_class
)
281 : data_(new ListContainerCharAllocator(max_size_for_derived_class
)) {
284 template <typename BaseElementType
>
285 ListContainer
<BaseElementType
>::ListContainer(
286 size_t max_size_for_derived_class
,
287 size_t num_of_elements_to_reserve_for
)
288 : data_(new ListContainerCharAllocator(max_size_for_derived_class
,
289 num_of_elements_to_reserve_for
)) {
292 template <typename BaseElementType
>
293 ListContainer
<BaseElementType
>::ListContainer()
294 : data_(new ListContainerCharAllocator(sizeof(BaseElementType
))) {
297 template <typename BaseElementType
>
298 ListContainer
<BaseElementType
>::~ListContainer() {
299 for (Iterator i
= begin(); i
!= end(); ++i
) {
300 i
->~BaseElementType();
304 template <typename BaseElementType
>
305 void ListContainer
<BaseElementType
>::EraseAndInvalidateAllPointers(
306 typename ListContainer
<BaseElementType
>::Iterator position
) {
307 BaseElementType
* item
= *position
;
308 item
->~BaseElementType();
309 data_
->Erase(position
);
312 template <typename BaseElementType
>
313 typename ListContainer
<BaseElementType
>::ConstReverseIterator
314 ListContainer
<BaseElementType
>::crbegin() const {
315 if (data_
->IsEmpty())
318 size_t id
= data_
->LastInnerListId();
319 return ConstReverseIterator(data_
.get(), id
,
320 data_
->InnerListById(id
)->LastElement(), 0);
323 template <typename BaseElementType
>
324 typename ListContainer
<BaseElementType
>::ConstReverseIterator
325 ListContainer
<BaseElementType
>::crend() const {
326 return ConstReverseIterator(data_
.get(), static_cast<size_t>(-1), NULL
,
330 template <typename BaseElementType
>
331 typename ListContainer
<BaseElementType
>::ConstReverseIterator
332 ListContainer
<BaseElementType
>::rbegin() const {
336 template <typename BaseElementType
>
337 typename ListContainer
<BaseElementType
>::ConstReverseIterator
338 ListContainer
<BaseElementType
>::rend() const {
342 template <typename BaseElementType
>
343 typename ListContainer
<BaseElementType
>::ReverseIterator
344 ListContainer
<BaseElementType
>::rbegin() {
345 if (data_
->IsEmpty())
348 size_t id
= data_
->LastInnerListId();
349 return ReverseIterator(data_
.get(), id
,
350 data_
->InnerListById(id
)->LastElement(), 0);
353 template <typename BaseElementType
>
354 typename ListContainer
<BaseElementType
>::ReverseIterator
355 ListContainer
<BaseElementType
>::rend() {
356 return ReverseIterator(data_
.get(), static_cast<size_t>(-1), NULL
, size());
359 template <typename BaseElementType
>
360 typename ListContainer
<BaseElementType
>::ConstIterator
361 ListContainer
<BaseElementType
>::cbegin() const {
362 if (data_
->IsEmpty())
365 size_t id
= data_
->FirstInnerListId();
366 return ConstIterator(data_
.get(), id
, data_
->InnerListById(id
)->Begin(), 0);
369 template <typename BaseElementType
>
370 typename ListContainer
<BaseElementType
>::ConstIterator
371 ListContainer
<BaseElementType
>::cend() const {
372 if (data_
->IsEmpty())
373 return ConstIterator(data_
.get(), 0, NULL
, size());
375 size_t id
= data_
->list_count();
376 return ConstIterator(data_
.get(), id
, NULL
, size());
379 template <typename BaseElementType
>
380 typename ListContainer
<BaseElementType
>::ConstIterator
381 ListContainer
<BaseElementType
>::begin() const {
385 template <typename BaseElementType
>
386 typename ListContainer
<BaseElementType
>::ConstIterator
387 ListContainer
<BaseElementType
>::end() const {
391 template <typename BaseElementType
>
392 typename ListContainer
<BaseElementType
>::Iterator
393 ListContainer
<BaseElementType
>::begin() {
394 if (data_
->IsEmpty())
397 size_t id
= data_
->FirstInnerListId();
398 return Iterator(data_
.get(), id
, data_
->InnerListById(id
)->Begin(), 0);
401 template <typename BaseElementType
>
402 typename ListContainer
<BaseElementType
>::Iterator
403 ListContainer
<BaseElementType
>::end() {
404 if (data_
->IsEmpty())
405 return Iterator(data_
.get(), 0, NULL
, size());
407 size_t id
= data_
->list_count();
408 return Iterator(data_
.get(), id
, NULL
, size());
411 template <typename BaseElementType
>
412 BaseElementType
* ListContainer
<BaseElementType
>::front() {
413 Iterator iter
= begin();
417 template <typename BaseElementType
>
418 BaseElementType
* ListContainer
<BaseElementType
>::back() {
419 ReverseIterator iter
= rbegin();
423 template <typename BaseElementType
>
424 const BaseElementType
* ListContainer
<BaseElementType
>::front() const {
425 ConstIterator iter
= begin();
429 template <typename BaseElementType
>
430 const BaseElementType
* ListContainer
<BaseElementType
>::back() const {
431 ConstReverseIterator iter
= rbegin();
435 template <typename BaseElementType
>
436 const BaseElementType
* ListContainer
<BaseElementType
>::ElementAt(
437 size_t index
) const {
438 DCHECK_LT(index
, size());
439 size_t original_index
= index
;
441 for (list_index
= 0; list_index
< data_
->list_count(); ++list_index
) {
442 size_t current_size
= data_
->InnerListById(list_index
)->size
;
443 if (index
< current_size
)
445 index
-= current_size
;
447 return *ConstIterator(data_
.get(),
449 data_
->InnerListById(list_index
)->ElementAt(index
),
453 template <typename BaseElementType
>
454 BaseElementType
* ListContainer
<BaseElementType
>::ElementAt(size_t index
) {
455 DCHECK_LT(index
, size());
456 size_t original_index
= index
;
458 for (list_index
= 0; list_index
< data_
->list_count(); ++list_index
) {
459 size_t current_size
= data_
->InnerListById(list_index
)->size
;
460 if (index
< current_size
)
462 index
-= current_size
;
464 return *Iterator(data_
.get(),
466 data_
->InnerListById(list_index
)->ElementAt(index
),
470 template <typename BaseElementType
>
471 void* ListContainer
<BaseElementType
>::Allocate(
472 size_t size_of_actual_element_in_bytes
) {
473 DCHECK_LE(size_of_actual_element_in_bytes
, data_
->element_size());
474 return data_
->Allocate();
477 template <typename BaseElementType
>
478 size_t ListContainer
<BaseElementType
>::size() const {
479 return data_
->size();
482 template <typename BaseElementType
>
483 bool ListContainer
<BaseElementType
>::empty() const {
484 return data_
->IsEmpty();
487 template <typename BaseElementType
>
488 void ListContainer
<BaseElementType
>::clear() {
489 for (Iterator i
= begin(); i
!= end(); ++i
) {
490 i
->~BaseElementType();
495 template <typename BaseElementType
>
496 size_t ListContainer
<
497 BaseElementType
>::AvailableSizeWithoutAnotherAllocationForTesting() const {
498 return data_
->NumAvailableElementsInLastList();
501 // ListContainer::Iterator
502 /////////////////////////////////////////////////
503 template <typename BaseElementType
>
504 ListContainer
<BaseElementType
>::Iterator::Iterator(
505 ListContainerCharAllocator
* container
,
509 : PositionInListContainerCharAllocator(container
, vector_ind
, item_iter
),
513 template <typename BaseElementType
>
514 ListContainer
<BaseElementType
>::Iterator::~Iterator() {
517 template <typename BaseElementType
>
518 BaseElementType
* ListContainer
<BaseElementType
>::Iterator::operator->() const {
519 return reinterpret_cast<BaseElementType
*>(this->item_iterator
);
522 template <typename BaseElementType
>
523 BaseElementType
* ListContainer
<BaseElementType
>::Iterator::operator*() const {
524 return reinterpret_cast<BaseElementType
*>(this->item_iterator
);
527 template <typename BaseElementType
>
528 typename ListContainer
<BaseElementType
>::Iterator
529 ListContainer
<BaseElementType
>::Iterator::
530 operator++(int unused_post_increment
) {
531 Iterator tmp
= *this;
536 template <typename BaseElementType
>
537 typename ListContainer
<BaseElementType
>::Iterator
&
538 ListContainer
<BaseElementType
>::Iterator::
545 template <typename BaseElementType
>
546 size_t ListContainer
<BaseElementType
>::Iterator::index() const {
550 // ListContainer::ConstIterator
551 /////////////////////////////////////////////////
552 template <typename BaseElementType
>
553 ListContainer
<BaseElementType
>::ConstIterator::ConstIterator(
554 const typename ListContainer
<BaseElementType
>::Iterator
& other
)
555 : PositionInListContainerCharAllocator(other
), index_(other
.index()) {
558 template <typename BaseElementType
>
559 ListContainer
<BaseElementType
>::ConstIterator::ConstIterator(
560 ListContainerCharAllocator
* container
,
564 : PositionInListContainerCharAllocator(container
, vector_ind
, item_iter
),
568 template <typename BaseElementType
>
569 ListContainer
<BaseElementType
>::ConstIterator::~ConstIterator() {
572 template <typename BaseElementType
>
573 const BaseElementType
* ListContainer
<BaseElementType
>::ConstIterator::
575 return reinterpret_cast<const BaseElementType
*>(this->item_iterator
);
578 template <typename BaseElementType
>
579 const BaseElementType
* ListContainer
<BaseElementType
>::ConstIterator::
581 return reinterpret_cast<const BaseElementType
*>(this->item_iterator
);
584 template <typename BaseElementType
>
585 typename ListContainer
<BaseElementType
>::ConstIterator
586 ListContainer
<BaseElementType
>::ConstIterator::
587 operator++(int unused_post_increment
) {
588 ConstIterator tmp
= *this;
593 template <typename BaseElementType
>
594 typename ListContainer
<BaseElementType
>::ConstIterator
&
595 ListContainer
<BaseElementType
>::ConstIterator::
602 template <typename BaseElementType
>
603 size_t ListContainer
<BaseElementType
>::ConstIterator::index() const {
607 // ListContainer::ReverseIterator
608 /////////////////////////////////////////////////
609 template <typename BaseElementType
>
610 ListContainer
<BaseElementType
>::ReverseIterator::ReverseIterator(
611 ListContainerCharAllocator
* container
,
615 : PositionInListContainerCharAllocator(container
, vector_ind
, item_iter
),
619 template <typename BaseElementType
>
620 ListContainer
<BaseElementType
>::ReverseIterator::~ReverseIterator() {
623 template <typename BaseElementType
>
624 BaseElementType
* ListContainer
<BaseElementType
>::ReverseIterator::operator->()
626 return reinterpret_cast<BaseElementType
*>(this->item_iterator
);
629 template <typename BaseElementType
>
630 BaseElementType
* ListContainer
<BaseElementType
>::ReverseIterator::operator*()
632 return reinterpret_cast<BaseElementType
*>(this->item_iterator
);
635 template <typename BaseElementType
>
636 typename ListContainer
<BaseElementType
>::ReverseIterator
637 ListContainer
<BaseElementType
>::ReverseIterator::
638 operator++(int unused_post_increment
) {
639 ReverseIterator tmp
= *this;
644 template <typename BaseElementType
>
645 typename ListContainer
<BaseElementType
>::ReverseIterator
&
646 ListContainer
<BaseElementType
>::ReverseIterator::
648 this->ReverseIncrement();
653 template <typename BaseElementType
>
654 size_t ListContainer
<BaseElementType
>::ReverseIterator::index() const {
658 // ListContainer::ConstReverseIterator
659 /////////////////////////////////////////////////
660 template <typename BaseElementType
>
661 ListContainer
<BaseElementType
>::ConstReverseIterator::ConstReverseIterator(
662 const typename ListContainer
<BaseElementType
>::ReverseIterator
& other
)
663 : PositionInListContainerCharAllocator(other
), index_(other
.index()) {
666 template <typename BaseElementType
>
667 ListContainer
<BaseElementType
>::ConstReverseIterator::ConstReverseIterator(
668 ListContainerCharAllocator
* container
,
672 : PositionInListContainerCharAllocator(container
, vector_ind
, item_iter
),
676 template <typename BaseElementType
>
677 ListContainer
<BaseElementType
>::ConstReverseIterator::~ConstReverseIterator() {
680 template <typename BaseElementType
>
681 const BaseElementType
* ListContainer
<BaseElementType
>::ConstReverseIterator::
683 return reinterpret_cast<const BaseElementType
*>(this->item_iterator
);
686 template <typename BaseElementType
>
687 const BaseElementType
* ListContainer
<BaseElementType
>::ConstReverseIterator::
689 return reinterpret_cast<const BaseElementType
*>(this->item_iterator
);
692 template <typename BaseElementType
>
693 typename ListContainer
<BaseElementType
>::ConstReverseIterator
694 ListContainer
<BaseElementType
>::ConstReverseIterator::
695 operator++(int unused_post_increment
) {
696 ConstReverseIterator tmp
= *this;
701 template <typename BaseElementType
>
702 typename ListContainer
<BaseElementType
>::ConstReverseIterator
&
703 ListContainer
<BaseElementType
>::ConstReverseIterator::
705 this->ReverseIncrement();
710 template <typename BaseElementType
>
711 size_t ListContainer
<BaseElementType
>::ConstReverseIterator::index() const {
715 template class ListContainer
<SharedQuadState
>;
716 template class ListContainer
<DrawQuad
>;