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 #ifndef CC_BASE_LIST_CONTAINER_H_
6 #define CC_BASE_LIST_CONTAINER_H_
8 #include "base/logging.h"
9 #include "base/macros.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "cc/base/cc_export.h"
12 #include "cc/base/list_container_helper.h"
16 // ListContainer is a container type that handles allocating contiguous memory
17 // for new elements and traversing through elements with either iterator or
18 // reverse iterator. Since this container hands out raw pointers of its
19 // elements, it is very important that this container never reallocate its
20 // memory so those raw pointer will continue to be valid. This class is used to
21 // contain SharedQuadState or DrawQuad. Since the size of each DrawQuad varies,
22 // to hold DrawQuads, the allocations size of each element in this class is
23 // LargestDrawQuadSize while BaseElementType is DrawQuad.
24 template <class BaseElementType
>
27 // BaseElementType is the type of raw pointers this class hands out; however,
28 // its derived classes might require different memory sizes.
29 // max_size_for_derived_class the largest memory size required for all the
30 // derived classes to use for allocation.
31 explicit ListContainer(size_t max_size_for_derived_class
)
32 : helper_(max_size_for_derived_class
) {}
34 // This constructor omits input variable for max_size_for_derived_class. This
35 // is used when there is no derived classes from BaseElementType we need to
36 // worry about, and allocation size is just sizeof(BaseElementType).
37 ListContainer() : helper_(sizeof(BaseElementType
)) {}
39 // This constructor reserves the requested memory up front so only single
40 // allocation is needed. When num_of_elements_to_reserve_for is zero, use the
42 ListContainer(size_t max_size_for_derived_class
,
43 size_t num_of_elements_to_reserve_for
)
44 : helper_(max_size_for_derived_class
, num_of_elements_to_reserve_for
) {}
47 for (Iterator i
= begin(); i
!= end(); ++i
) {
48 i
->~BaseElementType();
54 class ReverseIterator
;
55 class ConstReverseIterator
;
57 // Removes the last element of the list and makes its space available for
61 back()->~BaseElementType();
65 // When called, all raw pointers that have been handed out are no longer
66 // valid. Use with caution.
67 // Returns a valid Iterator pointing to the element after the erased element.
68 // This function does not deallocate memory.
69 Iterator
EraseAndInvalidateAllPointers(Iterator position
) {
70 BaseElementType
* item
= *position
;
71 item
->~BaseElementType();
72 helper_
.EraseAndInvalidateAllPointers(&position
);
73 return empty() ? end() : position
;
76 ConstReverseIterator
crbegin() const {
77 return ConstReverseIterator(helper_
.crbegin());
79 ConstReverseIterator
crend() const {
80 return ConstReverseIterator(helper_
.crend());
82 ConstReverseIterator
rbegin() const { return crbegin(); }
83 ConstReverseIterator
rend() const { return crend(); }
84 ReverseIterator
rbegin() { return ReverseIterator(helper_
.rbegin()); }
85 ReverseIterator
rend() { return ReverseIterator(helper_
.rend()); }
86 ConstIterator
cbegin() const { return ConstIterator(helper_
.cbegin()); }
87 ConstIterator
cend() const { return ConstIterator(helper_
.cend()); }
88 ConstIterator
begin() const { return cbegin(); }
89 ConstIterator
end() const { return cend(); }
90 Iterator
begin() { return Iterator(helper_
.begin()); }
91 Iterator
end() { return Iterator(helper_
.end()); }
93 // TODO(weiliangc): front(), back() and ElementAt() function should return
94 // reference, consistent with container-of-object.
95 BaseElementType
* front() { return *begin(); }
96 BaseElementType
* back() { return *rbegin(); }
97 const BaseElementType
* front() const { return *begin(); }
98 const BaseElementType
* back() const { return *rbegin(); }
100 BaseElementType
* ElementAt(size_t index
) {
101 return *Iterator(helper_
.IteratorAt(index
));
103 const BaseElementType
* ElementAt(size_t index
) const {
104 return *ConstIterator(helper_
.IteratorAt(index
));
107 // Take in derived element type and construct it at location generated by
109 template <typename DerivedElementType
>
110 DerivedElementType
* AllocateAndConstruct() {
111 return new (helper_
.Allocate(sizeof(DerivedElementType
)))
115 // Take in derived element type and copy construct it at location generated by
117 template <typename DerivedElementType
>
118 DerivedElementType
* AllocateAndCopyFrom(const DerivedElementType
* source
) {
119 return new (helper_
.Allocate(sizeof(DerivedElementType
)))
120 DerivedElementType(*source
);
123 // Construct a new element on top of an existing one.
124 template <typename DerivedElementType
>
125 DerivedElementType
* ReplaceExistingElement(Iterator at
) {
126 at
->~BaseElementType();
127 return new (at
.item_iterator
) DerivedElementType();
130 // Insert |count| new elements of |DerivedElementType| before |at|. This will
131 // invalidate all outstanding pointers and iterators. Return a valid iterator
132 // for the beginning of the newly inserted segment.
133 template <typename DerivedElementType
>
134 Iterator
InsertBeforeAndInvalidateAllPointers(Iterator at
, size_t count
) {
135 helper_
.InsertBeforeAndInvalidateAllPointers(&at
, count
);
136 Iterator result
= at
;
137 for (size_t i
= 0; i
< count
; ++i
) {
138 new (at
.item_iterator
) DerivedElementType();
144 template <typename DerivedElementType
>
145 void swap(ListContainer
<DerivedElementType
>& other
) {
146 helper_
.data_
.swap(other
.helper_
.data_
);
149 // Appends a new item without copying. The original item will not be
150 // destructed and will be replaced with a new DerivedElementType. The
151 // DerivedElementType does not have to match the moved type as a full block
152 // of memory will be moved (up to MaxSizeForDerivedClass()). A pointer to
153 // the moved element is returned.
154 template <typename DerivedElementType
>
155 DerivedElementType
* AppendByMoving(DerivedElementType
* item
) {
156 size_t max_size_for_derived_class
= helper_
.MaxSizeForDerivedClass();
157 void* new_item
= helper_
.Allocate(max_size_for_derived_class
);
158 memcpy(new_item
, static_cast<void*>(item
), max_size_for_derived_class
);
159 // Construct a new element in-place so it can be destructed safely.
160 new (item
) DerivedElementType
;
161 return static_cast<DerivedElementType
*>(new_item
);
164 size_t size() const { return helper_
.size(); }
165 bool empty() const { return helper_
.empty(); }
166 size_t GetCapacityInBytes() const { return helper_
.GetCapacityInBytes(); }
169 for (Iterator i
= begin(); i
!= end(); ++i
) {
170 i
->~BaseElementType();
175 size_t AvailableSizeWithoutAnotherAllocationForTesting() const {
176 return helper_
.AvailableSizeWithoutAnotherAllocationForTesting();
179 // Iterator classes that can be used to access data.
180 /////////////////////////////////////////////////////////////////
181 class Iterator
: public ListContainerHelper::Iterator
{
182 // This class is only defined to forward iterate through
185 Iterator(ListContainerHelper::CharAllocator
* container
,
189 : ListContainerHelper::Iterator(container
,
193 BaseElementType
* operator->() const {
194 return reinterpret_cast<BaseElementType
*>(item_iterator
);
196 BaseElementType
* operator*() const {
197 return reinterpret_cast<BaseElementType
*>(item_iterator
);
199 Iterator
operator++(int unused_post_increment
) {
200 Iterator tmp
= *this;
204 Iterator
& operator++() {
211 explicit Iterator(const ListContainerHelper::Iterator
& base_iterator
)
212 : ListContainerHelper::Iterator(base_iterator
) {}
213 friend Iterator ListContainer
<BaseElementType
>::begin();
214 friend Iterator ListContainer
<BaseElementType
>::end();
215 friend BaseElementType
* ListContainer
<BaseElementType
>::ElementAt(
219 class ConstIterator
: public ListContainerHelper::ConstIterator
{
220 // This class is only defined to forward iterate through
223 ConstIterator(ListContainerHelper::CharAllocator
* container
,
227 : ListContainerHelper::ConstIterator(container
,
231 ConstIterator(const Iterator
& other
) // NOLINT
232 : ListContainerHelper::ConstIterator(other
) {}
233 const BaseElementType
* operator->() const {
234 return reinterpret_cast<const BaseElementType
*>(item_iterator
);
236 const BaseElementType
* operator*() const {
237 return reinterpret_cast<const BaseElementType
*>(item_iterator
);
239 ConstIterator
operator++(int unused_post_increment
) {
240 ConstIterator tmp
= *this;
244 ConstIterator
& operator++() {
251 explicit ConstIterator(
252 const ListContainerHelper::ConstIterator
& base_iterator
)
253 : ListContainerHelper::ConstIterator(base_iterator
) {}
254 friend ConstIterator ListContainer
<BaseElementType
>::cbegin() const;
255 friend ConstIterator ListContainer
<BaseElementType
>::cend() const;
256 friend const BaseElementType
* ListContainer
<BaseElementType
>::ElementAt(
260 class ReverseIterator
: public ListContainerHelper::ReverseIterator
{
261 // This class is only defined to reverse iterate through
264 ReverseIterator(ListContainerHelper::CharAllocator
* container
,
268 : ListContainerHelper::ReverseIterator(container
,
272 BaseElementType
* operator->() const {
273 return reinterpret_cast<BaseElementType
*>(item_iterator
);
275 BaseElementType
* operator*() const {
276 return reinterpret_cast<BaseElementType
*>(item_iterator
);
278 ReverseIterator
operator++(int unused_post_increment
) {
279 ReverseIterator tmp
= *this;
283 ReverseIterator
& operator++() {
290 explicit ReverseIterator(ListContainerHelper::ReverseIterator base_iterator
)
291 : ListContainerHelper::ReverseIterator(base_iterator
) {}
292 friend ReverseIterator ListContainer
<BaseElementType
>::rbegin();
293 friend ReverseIterator ListContainer
<BaseElementType
>::rend();
296 class ConstReverseIterator
297 : public ListContainerHelper::ConstReverseIterator
{
298 // This class is only defined to reverse iterate through
301 ConstReverseIterator(ListContainerHelper::CharAllocator
* container
,
305 : ListContainerHelper::ConstReverseIterator(container
,
309 ConstReverseIterator(const ReverseIterator
& other
) // NOLINT
310 : ListContainerHelper::ConstReverseIterator(other
) {}
311 const BaseElementType
* operator->() const {
312 return reinterpret_cast<const BaseElementType
*>(item_iterator
);
314 const BaseElementType
* operator*() const {
315 return reinterpret_cast<const BaseElementType
*>(item_iterator
);
317 ConstReverseIterator
operator++(int unused_post_increment
) {
318 ConstReverseIterator tmp
= *this;
322 ConstReverseIterator
& operator++() {
329 explicit ConstReverseIterator(
330 ListContainerHelper::ConstReverseIterator base_iterator
)
331 : ListContainerHelper::ConstReverseIterator(base_iterator
) {}
332 friend ConstReverseIterator ListContainer
<BaseElementType
>::crbegin() const;
333 friend ConstReverseIterator ListContainer
<BaseElementType
>::crend() const;
337 ListContainerHelper helper_
;
339 DISALLOW_COPY_AND_ASSIGN(ListContainer
);
344 #endif // CC_BASE_LIST_CONTAINER_H_