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"
15 // ListContainer is a container type that handles allocating contiguous memory
16 // for new elements and traversing through elements with either iterator or
17 // reverse iterator. Since this container hands out raw pointers of its
18 // elements, it is very important that this container never reallocate its
19 // memory so those raw pointer will continue to be valid. This class is used to
20 // contain SharedQuadState or DrawQuad. Since the size of each DrawQuad varies,
21 // to hold DrawQuads, the allocations size of each element in this class is
22 // LargestDrawQuadSize while BaseElementType is DrawQuad.
24 // Base class for non-templated logic. All methods are protected, and only
25 // exposed by ListContainer<BaseElementType>.
26 // For usage, see comments in ListContainer.
27 class CC_EXPORT ListContainerBase
{
29 explicit ListContainerBase(size_t max_size_for_derived_class
);
30 ListContainerBase(size_t max_size_for_derived_class
,
31 size_t num_of_elements_to_reserve_for
);
34 // This class deals only with char* and void*. It does allocation and passing
35 // out raw pointers, as well as memory deallocation when being destroyed.
36 class ListContainerCharAllocator
;
38 // This class points to a certain position inside memory of
39 // ListContainerCharAllocator. It is a base class for ListContainer iterators.
40 struct CC_EXPORT PositionInListContainerCharAllocator
{
41 ListContainerCharAllocator
* ptr_to_container
;
45 PositionInListContainerCharAllocator(
46 const PositionInListContainerCharAllocator
& other
);
48 PositionInListContainerCharAllocator(ListContainerCharAllocator
* container
,
52 bool operator==(const PositionInListContainerCharAllocator
& other
) const;
53 bool operator!=(const PositionInListContainerCharAllocator
& other
) const;
55 PositionInListContainerCharAllocator
Increment();
56 PositionInListContainerCharAllocator
ReverseIncrement();
59 // Iterator classes that can be used to access data.
60 /////////////////////////////////////////////////////////////////
61 class CC_EXPORT Iterator
: public PositionInListContainerCharAllocator
{
62 // This class is only defined to forward iterate through
63 // ListContainerCharAllocator.
65 Iterator(ListContainerCharAllocator
* container
,
74 // This is used to track how many increment has happened since begin(). It
75 // is used to avoid double increment at places an index reference is
76 // needed. For iterator this means begin() corresponds to index 0 and end()
77 // corresponds to index |size|.
81 class CC_EXPORT ConstIterator
: public PositionInListContainerCharAllocator
{
82 // This class is only defined to forward iterate through
83 // ListContainerCharAllocator.
85 ConstIterator(ListContainerCharAllocator
* container
,
89 ConstIterator(const Iterator
& other
); // NOLINT
95 // This is used to track how many increment has happened since begin(). It
96 // is used to avoid double increment at places an index reference is
97 // needed. For iterator this means begin() corresponds to index 0 and end()
98 // corresponds to index |size|.
102 class CC_EXPORT ReverseIterator
103 : public PositionInListContainerCharAllocator
{
104 // This class is only defined to reverse iterate through
105 // ListContainerCharAllocator.
107 ReverseIterator(ListContainerCharAllocator
* container
,
113 size_t index() const;
116 // This is used to track how many increment has happened since rbegin(). It
117 // is used to avoid double increment at places an index reference is
118 // needed. For reverse iterator this means rbegin() corresponds to index 0
119 // and rend() corresponds to index |size|.
123 class CC_EXPORT ConstReverseIterator
124 : public PositionInListContainerCharAllocator
{
125 // This class is only defined to reverse iterate through
126 // ListContainerCharAllocator.
128 ConstReverseIterator(ListContainerCharAllocator
* container
,
132 ConstReverseIterator(const ReverseIterator
& other
); // NOLINT
133 ~ConstReverseIterator();
135 size_t index() const;
138 // This is used to track how many increment has happened since rbegin(). It
139 // is used to avoid double increment at places an index reference is
140 // needed. For reverse iterator this means rbegin() corresponds to index 0
141 // and rend() corresponds to index |size|.
145 // Unlike the ListContainer methods, these do not invoke element destructors.
147 void EraseAndInvalidateAllPointers(Iterator
* position
);
148 void InsertBeforeAndInvalidateAllPointers(Iterator
* position
,
149 size_t number_of_elements
);
151 ConstReverseIterator
crbegin() const;
152 ConstReverseIterator
crend() const;
153 ReverseIterator
rbegin();
154 ReverseIterator
rend();
155 ConstIterator
cbegin() const;
156 ConstIterator
cend() const;
160 Iterator
IteratorAt(size_t index
);
161 ConstIterator
IteratorAt(size_t index
) const;
166 size_t MaxSizeForDerivedClass() const;
168 size_t GetCapacityInBytes() const;
170 // Unlike the ListContainer method, this one does not invoke element
174 size_t AvailableSizeWithoutAnotherAllocationForTesting() const;
176 // Hands out memory location for an element at the end of data structure.
177 void* Allocate(size_t size_of_actual_element_in_bytes
);
179 scoped_ptr
<ListContainerCharAllocator
> data_
;
182 DISALLOW_COPY_AND_ASSIGN(ListContainerBase
);
185 template <class BaseElementType
>
186 class ListContainer
: public ListContainerBase
{
188 // BaseElementType is the type of raw pointers this class hands out; however,
189 // its derived classes might require different memory sizes.
190 // max_size_for_derived_class the largest memory size required for all the
191 // derived classes to use for allocation.
192 explicit ListContainer(size_t max_size_for_derived_class
)
193 : ListContainerBase(max_size_for_derived_class
) {}
195 // This constructor omits input variable for max_size_for_derived_class. This
196 // is used when there is no derived classes from BaseElementType we need to
197 // worry about, and allocation size is just sizeof(BaseElementType).
198 ListContainer() : ListContainerBase(sizeof(BaseElementType
)) {}
200 // This constructor reserves the requested memory up front so only single
201 // allocation is needed. When num_of_elements_to_reserve_for is zero, use the
203 ListContainer(size_t max_size_for_derived_class
,
204 size_t num_of_elements_to_reserve_for
)
205 : ListContainerBase(max_size_for_derived_class
,
206 num_of_elements_to_reserve_for
) {}
209 for (Iterator i
= begin(); i
!= end(); ++i
) {
210 i
->~BaseElementType();
216 class ReverseIterator
;
217 class ConstReverseIterator
;
219 // Removes the last element of the list and makes its space available for
223 back()->~BaseElementType();
224 ListContainerBase::RemoveLast();
227 // When called, all raw pointers that have been handed out are no longer
228 // valid. Use with caution.
229 // Returns a valid Iterator pointing to the element after the erased element.
230 // This function does not deallocate memory.
231 Iterator
EraseAndInvalidateAllPointers(Iterator position
) {
232 BaseElementType
* item
= *position
;
233 item
->~BaseElementType();
234 ListContainerBase::EraseAndInvalidateAllPointers(&position
);
235 return empty() ? end() : position
;
238 ConstReverseIterator
crbegin() const {
239 return ConstReverseIterator(ListContainerBase::crbegin());
241 ConstReverseIterator
crend() const {
242 return ConstReverseIterator(ListContainerBase::crend());
244 ConstReverseIterator
rbegin() const { return crbegin(); }
245 ConstReverseIterator
rend() const { return crend(); }
246 ReverseIterator
rbegin() {
247 return ReverseIterator(ListContainerBase::rbegin());
249 ReverseIterator
rend() { return ReverseIterator(ListContainerBase::rend()); }
250 ConstIterator
cbegin() const {
251 return ConstIterator(ListContainerBase::cbegin());
253 ConstIterator
cend() const {
254 return ConstIterator(ListContainerBase::cend());
256 ConstIterator
begin() const { return cbegin(); }
257 ConstIterator
end() const { return cend(); }
258 Iterator
begin() { return Iterator(ListContainerBase::begin()); }
259 Iterator
end() { return Iterator(ListContainerBase::end()); }
261 // TODO(weiliangc): front(), back() and ElementAt() function should return
262 // reference, consistent with container-of-object.
263 BaseElementType
* front() { return *begin(); }
264 BaseElementType
* back() { return *rbegin(); }
265 const BaseElementType
* front() const { return *begin(); }
266 const BaseElementType
* back() const { return *rbegin(); }
268 BaseElementType
* ElementAt(size_t index
) {
269 return *Iterator(IteratorAt(index
));
271 const BaseElementType
* ElementAt(size_t index
) const {
272 return *ConstIterator(IteratorAt(index
));
275 // Take in derived element type and construct it at location generated by
277 template <typename DerivedElementType
>
278 DerivedElementType
* AllocateAndConstruct() {
279 return new (Allocate(sizeof(DerivedElementType
))) DerivedElementType
;
282 // Take in derived element type and copy construct it at location generated by
284 template <typename DerivedElementType
>
285 DerivedElementType
* AllocateAndCopyFrom(const DerivedElementType
* source
) {
286 return new (Allocate(sizeof(DerivedElementType
)))
287 DerivedElementType(*source
);
290 // Construct a new element on top of an existing one.
291 template <typename DerivedElementType
>
292 DerivedElementType
* ReplaceExistingElement(Iterator at
) {
293 at
->~BaseElementType();
294 return new (*at
) DerivedElementType();
297 // Insert |count| new elements of |DerivedElementType| before |at|. This will
298 // invalidate all outstanding pointers and iterators. Return a valid iterator
299 // for the beginning of the newly inserted segment.
300 template <typename DerivedElementType
>
301 Iterator
InsertBeforeAndInvalidateAllPointers(Iterator at
, size_t count
) {
302 ListContainerBase::InsertBeforeAndInvalidateAllPointers(&at
, count
);
303 Iterator result
= at
;
304 for (size_t i
= 0; i
< count
; ++i
) {
305 new (*at
) DerivedElementType();
311 template <typename DerivedElementType
>
312 void swap(ListContainer
<DerivedElementType
>& other
) {
313 data_
.swap(other
.data_
);
316 // Appends a new item without copying. The original item will not be
317 // destructed and will be replaced with a new DerivedElementType. The
318 // DerivedElementType does not have to match the moved type as a full block
319 // of memory will be moved (up to MaxSizeForDerivedClass()). A pointer to
320 // the moved element is returned.
321 template <typename DerivedElementType
>
322 DerivedElementType
* AppendByMoving(DerivedElementType
* item
) {
323 size_t max_size_for_derived_class
= MaxSizeForDerivedClass();
324 void* new_item
= Allocate(max_size_for_derived_class
);
325 memcpy(new_item
, static_cast<void*>(item
), max_size_for_derived_class
);
326 // Construct a new element in-place so it can be destructed safely.
327 new (item
) DerivedElementType
;
328 return static_cast<DerivedElementType
*>(new_item
);
331 using ListContainerBase::size
;
332 using ListContainerBase::empty
;
333 using ListContainerBase::GetCapacityInBytes
;
336 for (Iterator i
= begin(); i
!= end(); ++i
) {
337 i
->~BaseElementType();
339 ListContainerBase::clear();
342 using ListContainerBase::AvailableSizeWithoutAnotherAllocationForTesting
;
344 // Iterator classes that can be used to access data.
345 /////////////////////////////////////////////////////////////////
346 class Iterator
: public ListContainerBase::Iterator
{
347 // This class is only defined to forward iterate through
348 // ListContainerCharAllocator.
350 Iterator(ListContainerCharAllocator
* container
,
354 : ListContainerBase::Iterator(container
, vector_ind
, item_iter
, index
) {
356 BaseElementType
* operator->() const {
357 return reinterpret_cast<BaseElementType
*>(item_iterator
);
359 BaseElementType
* operator*() const {
360 return reinterpret_cast<BaseElementType
*>(item_iterator
);
362 Iterator
operator++(int unused_post_increment
) {
363 Iterator tmp
= *this;
367 Iterator
& operator++() {
374 explicit Iterator(const ListContainerBase::Iterator
& base_iterator
)
375 : ListContainerBase::Iterator(base_iterator
) {}
376 friend Iterator ListContainer
<BaseElementType
>::begin();
377 friend Iterator ListContainer
<BaseElementType
>::end();
378 friend BaseElementType
* ListContainer
<BaseElementType
>::ElementAt(
382 class ConstIterator
: public ListContainerBase::ConstIterator
{
383 // This class is only defined to forward iterate through
384 // ListContainerCharAllocator.
386 ConstIterator(ListContainerCharAllocator
* container
,
390 : ListContainerBase::ConstIterator(container
,
394 ConstIterator(const Iterator
& other
) // NOLINT
395 : ListContainerBase::ConstIterator(other
) {}
396 const BaseElementType
* operator->() const {
397 return reinterpret_cast<const BaseElementType
*>(item_iterator
);
399 const BaseElementType
* operator*() const {
400 return reinterpret_cast<const BaseElementType
*>(item_iterator
);
402 ConstIterator
operator++(int unused_post_increment
) {
403 ConstIterator tmp
= *this;
407 ConstIterator
& operator++() {
414 explicit ConstIterator(
415 const ListContainerBase::ConstIterator
& base_iterator
)
416 : ListContainerBase::ConstIterator(base_iterator
) {}
417 friend ConstIterator ListContainer
<BaseElementType
>::cbegin() const;
418 friend ConstIterator ListContainer
<BaseElementType
>::cend() const;
419 friend const BaseElementType
* ListContainer
<BaseElementType
>::ElementAt(
423 class ReverseIterator
: public ListContainerBase::ReverseIterator
{
424 // This class is only defined to reverse iterate through
425 // ListContainerCharAllocator.
427 ReverseIterator(ListContainerCharAllocator
* container
,
431 : ListContainerBase::ReverseIterator(container
,
435 BaseElementType
* operator->() const {
436 return reinterpret_cast<BaseElementType
*>(item_iterator
);
438 BaseElementType
* operator*() const {
439 return reinterpret_cast<BaseElementType
*>(item_iterator
);
441 ReverseIterator
operator++(int unused_post_increment
) {
442 ReverseIterator tmp
= *this;
446 ReverseIterator
& operator++() {
453 explicit ReverseIterator(ListContainerBase::ReverseIterator base_iterator
)
454 : ListContainerBase::ReverseIterator(base_iterator
) {}
455 friend ReverseIterator ListContainer
<BaseElementType
>::rbegin();
456 friend ReverseIterator ListContainer
<BaseElementType
>::rend();
459 class ConstReverseIterator
: public ListContainerBase::ConstReverseIterator
{
460 // This class is only defined to reverse iterate through
461 // ListContainerCharAllocator.
463 ConstReverseIterator(ListContainerCharAllocator
* container
,
467 : ListContainerBase::ConstReverseIterator(container
,
471 ConstReverseIterator(const ReverseIterator
& other
) // NOLINT
472 : ListContainerBase::ConstReverseIterator(other
) {}
473 const BaseElementType
* operator->() const {
474 return reinterpret_cast<const BaseElementType
*>(item_iterator
);
476 const BaseElementType
* operator*() const {
477 return reinterpret_cast<const BaseElementType
*>(item_iterator
);
479 ConstReverseIterator
operator++(int unused_post_increment
) {
480 ConstReverseIterator tmp
= *this;
484 ConstReverseIterator
& operator++() {
491 explicit ConstReverseIterator(
492 ListContainerBase::ConstReverseIterator base_iterator
)
493 : ListContainerBase::ConstReverseIterator(base_iterator
) {}
494 friend ConstReverseIterator ListContainer
<BaseElementType
>::crbegin() const;
495 friend ConstReverseIterator ListContainer
<BaseElementType
>::crend() const;
501 #endif // CC_BASE_LIST_CONTAINER_H_