Reland "Non-SFI mode: Switch to newlib. (patchset #4 id:60001 of https://codereview...
[chromium-blink-merge.git] / cc / base / sidecar_list_container.h
blob842795fad1b3a94d2ea644a89c6fbd99301e5e4e
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 ConstIterator begin() const { return list_.begin(); }
51 ConstIterator end() const { return list_.end(); }
53 template <typename DerivedElementType>
54 DerivedElementType* AllocateAndConstruct() {
55 return list_.template AllocateAndConstruct<DerivedElementType>();
57 template <typename DerivedElementType>
58 DerivedElementType* AllocateAndCopyFrom(const DerivedElementType* source) {
59 return list_.template AllocateAndCopyFrom<DerivedElementType>(source);
62 void clear() {
63 DestroyAllSidecars();
64 list_.clear();
67 void RemoveLast() {
68 destroyer_(GetSidecar(*list_.rbegin()));
69 list_.RemoveLast();
72 // This permits a client to exchange a pointer to an element to a pointer to
73 // its corresponding sidecar.
74 void* GetSidecar(BaseElementType* element) {
75 DCHECK_GT(sidecar_offset_, 0u);
76 return reinterpret_cast<char*>(element) + sidecar_offset_;
78 const void* GetSidecar(const BaseElementType* element) {
79 DCHECK_GT(sidecar_offset_, 0u);
80 return reinterpret_cast<const char*>(element) + sidecar_offset_;
83 private:
84 void DestroyAllSidecars() {
85 for (auto* element : list_)
86 destroyer_(GetSidecar(element));
89 ListContainer<BaseElementType> list_;
90 SidecarDestroyer destroyer_;
91 size_t sidecar_offset_;
94 } // namespace cc
96 #endif // CC_BASE_SIDECAR_LIST_CONTAINER_H_