Blender V5.0
BLI_linear_allocator_chunked_list.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#pragma once
10
11#include <array>
12
15#include "BLI_utility_mixins.hh"
16
18
23template<typename T, int64_t Capacity> struct ChunkedListSegment {
35 std::array<TypedBuffer<T>, Capacity> values;
36};
37
55template<typename T, int64_t SegmentCapacity = 4> class ChunkedList : NonCopyable {
56 private:
58 Segment *current_segment_ = nullptr;
59
60 public:
61 ChunkedList() = default;
62
64 {
65 current_segment_ = other.current_segment_;
66 other.current_segment_ = nullptr;
67 }
68
70 {
71 /* This code assumes that the #ChunkedListSegment does not have to be destructed if the
72 * contained type is trivially destructible. */
73 static_assert(std::is_trivially_destructible_v<ChunkedListSegment<int, 4>>);
74 if constexpr (!std::is_trivially_destructible_v<T>) {
75 for (Segment *segment = current_segment_; segment; segment = segment->next) {
76 for (const int64_t i : IndexRange(segment->size)) {
77 T &value = *segment->values[i];
78 std::destroy_at(&value);
79 }
80 }
81 }
82 }
83
85 {
86 if (this == &other) {
87 return *this;
88 }
89 std::destroy_at(this);
90 new (this) ChunkedList(std::move(other));
91 return *this;
92 }
93
98 void append(LinearAllocator<> &allocator, const T &value)
99 {
100 this->append_as(allocator, value);
101 }
102
103 void append(LinearAllocator<> &allocator, T &&value)
104 {
105 this->append_as(allocator, std::move(value));
106 }
107
108 template<typename... Args> void append_as(LinearAllocator<> &allocator, Args &&...args)
109 {
110 if (current_segment_ == nullptr || current_segment_->size == SegmentCapacity) {
111 /* Allocate a new segment if necessary. */
112 static_assert(std::is_trivially_destructible_v<Segment>);
113 Segment *new_segment = allocator.construct<Segment>().release();
114 new_segment->next = current_segment_;
115 current_segment_ = new_segment;
116 }
117 T *value = &*current_segment_->values[current_segment_->size++];
118 new (value) T(std::forward<Args>(args)...);
119 }
120
122 private:
123 const Segment *segment_ = nullptr;
124 int64_t index_ = 0;
125
126 public:
127 ConstIterator(const Segment *segment, int64_t index = 0) : segment_(segment), index_(index) {}
128
130 {
131 index_++;
132 if (index_ == segment_->size) {
133 segment_ = segment_->next;
134 index_ = 0;
135 }
136 return *this;
137 }
138
139 const T &operator*() const
140 {
141 return *segment_->values[index_];
142 }
143
145 };
146
148 private:
149 Segment *segment_ = nullptr;
150 int64_t index_ = 0;
151
152 public:
153 MutableIterator(Segment *segment, int64_t index = 0) : segment_(segment), index_(index) {}
154
156 {
157 index_++;
158 if (index_ == segment_->size) {
159 segment_ = segment_->next;
160 index_ = 0;
161 }
162 return *this;
163 }
164
166 {
167 return *segment_->values[index_];
168 }
169
171 };
172
174 {
175 return ConstIterator(current_segment_, 0);
176 }
177
179 {
180 return ConstIterator(nullptr, 0);
181 }
182
184 {
185 return MutableIterator(current_segment_, 0);
186 }
187
189 {
190 return MutableIterator(nullptr, 0);
191 }
192};
193
194} // namespace blender::linear_allocator
#define BLI_STRUCT_EQUALITY_OPERATORS_2(Type, m1, m2)
long long int int64_t
destruct_ptr< T > construct(Args &&...args)
NonCopyable(const NonCopyable &other)=delete
void append(LinearAllocator<> &allocator, const T &value)
void append_as(LinearAllocator<> &allocator, Args &&...args)
void append(LinearAllocator<> &allocator, T &&value)
#define T
i
Definition text_draw.cc:230