Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / cc / base / sidecar_list_container.h
blob5135ab1d7d2a8a78d48b5a85ed230abacda6cf6c
1 // Copyright 2015 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_SIDECAR_LIST_CONTAINER_H_
6 #define CC_BASE_SIDECAR_LIST_CONTAINER_H_
8 #include "base/logging.h"
9 #include "cc/base/list_container.h"
11 namespace cc {
13 // This is a container, based on ListContainer, which allocates space in a
14 // contiguous block for objects subclassing BaseElementType, as well as an
15 // additional "sidecar" of opaque type.
17 // It takes a pointer to a function for tearing down sidecar objects, which must
18 // free any resources held by it as its memory will be deallocated by the
19 // container afterwards. When an element is constructed, callers are expected to
20 // immediately construct the sidecar as well (such that the sidecar destroyer
21 // will run safely and successfully).
23 // TODO(jbroman): It would be nice to be clear about the memory alignment
24 // constraints here, but that probably requires closer inspection of
25 // ListContainer first.
26 template <class BaseElementType>
27 class SidecarListContainer {
28 public:
29 using SidecarDestroyer = void (*)(void* sidecar);
30 using Iterator = typename ListContainer<BaseElementType>::Iterator;
31 using ConstIterator = typename ListContainer<BaseElementType>::ConstIterator;
32 using ReverseIterator =
33 typename ListContainer<BaseElementType>::ReverseIterator;
34 using ConstReverseIterator =
35 typename ListContainer<BaseElementType>::ConstReverseIterator;
37 explicit SidecarListContainer(size_t max_size_for_derived_class,
38 size_t max_size_for_sidecar,
39 size_t num_of_elements_to_reserve_for,
40 SidecarDestroyer destroyer)
41 : list_(max_size_for_derived_class + max_size_for_sidecar,
42 num_of_elements_to_reserve_for),
43 destroyer_(destroyer),
44 sidecar_offset_(max_size_for_derived_class) {}
45 ~SidecarListContainer() { DestroyAllSidecars(); }
47 // Forward most of the reading logic to ListContainer.
48 bool empty() const { return list_.empty(); }
49 size_t size() const { return list_.size(); }
50 size_t GetCapacityInBytes() const { return list_.GetCapacityInBytes(); }
51 ConstIterator begin() const { return list_.begin(); }
52 ConstIterator end() const { return list_.end(); }
54 template <typename DerivedElementType>
55 DerivedElementType* AllocateAndConstruct() {
56 return list_.template AllocateAndConstruct<DerivedElementType>();
58 template <typename DerivedElementType>
59 DerivedElementType* AllocateAndCopyFrom(const DerivedElementType* source) {
60 return list_.template AllocateAndCopyFrom<DerivedElementType>(source);
63 void clear() {
64 DestroyAllSidecars();
65 list_.clear();
68 void RemoveLast() {
69 destroyer_(GetSidecar(*list_.rbegin()));
70 list_.RemoveLast();
73 // This permits a client to exchange a pointer to an element to a pointer to
74 // its corresponding sidecar.
75 void* GetSidecar(BaseElementType* element) {
76 DCHECK_GT(sidecar_offset_, 0u);
77 return reinterpret_cast<char*>(element) + sidecar_offset_;
79 const void* GetSidecar(const BaseElementType* element) {
80 DCHECK_GT(sidecar_offset_, 0u);
81 return reinterpret_cast<const char*>(element) + sidecar_offset_;
84 private:
85 void DestroyAllSidecars() {
86 for (auto* element : list_)
87 destroyer_(GetSidecar(element));
90 ListContainer<BaseElementType> list_;
91 SidecarDestroyer destroyer_;
92 size_t sidecar_offset_;
95 } // namespace cc
97 #endif // CC_BASE_SIDECAR_LIST_CONTAINER_H_