Blender V4.3
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
5#pragma once
6
7#include <array>
8
11#include "BLI_utility_mixins.hh"
12
14
19template<typename T, int64_t Capacity> struct ChunkedListSegment {
26 int64_t size = 0;
31 std::array<TypedBuffer<T>, Capacity> values;
32};
33
51template<typename T, int64_t SegmentCapacity = 4> class ChunkedList : NonCopyable {
52 private:
54 Segment *current_segment_ = nullptr;
55
56 public:
57 ChunkedList() = default;
58
60 {
61 current_segment_ = other.current_segment_;
62 other.current_segment_ = nullptr;
63 }
64
66 {
67 /* This code assumes that the #ChunkedListSegment does not have to be destructed if the
68 * contained type is trivially destructible. */
69 static_assert(std::is_trivially_destructible_v<ChunkedListSegment<int, 4>>);
70 if constexpr (!std::is_trivially_destructible_v<T>) {
71 for (Segment *segment = current_segment_; segment; segment = segment->next) {
72 for (const int64_t i : IndexRange(segment->size)) {
73 T &value = *segment->values[i];
74 std::destroy_at(&value);
75 }
76 }
77 }
78 }
79
81 {
82 if (this == &other) {
83 return *this;
84 }
85 std::destroy_at(this);
86 new (this) ChunkedList(std::move(other));
87 return *this;
88 }
89
94 void append(LinearAllocator<> &allocator, const T &value)
95 {
96 this->append_as(allocator, value);
97 }
98
99 void append(LinearAllocator<> &allocator, T &&value)
100 {
101 this->append_as(allocator, std::move(value));
102 }
103
104 template<typename... Args> void append_as(LinearAllocator<> &allocator, Args &&...args)
105 {
106 if (current_segment_ == nullptr || current_segment_->size == SegmentCapacity) {
107 /* Allocate a new segment if necessary. */
108 static_assert(std::is_trivially_destructible_v<Segment>);
109 Segment *new_segment = allocator.construct<Segment>().release();
110 new_segment->next = current_segment_;
111 current_segment_ = new_segment;
112 }
113 T *value = &*current_segment_->values[current_segment_->size++];
114 new (value) T(std::forward<Args>(args)...);
115 }
116
118 private:
119 const Segment *segment_ = nullptr;
120 int64_t index_ = 0;
121
122 public:
123 ConstIterator(const Segment *segment, int64_t index = 0) : segment_(segment), index_(index) {}
124
126 {
127 index_++;
128 if (index_ == segment_->size) {
129 segment_ = segment_->next;
130 index_ = 0;
131 }
132 return *this;
133 }
134
135 const T &operator*() const
136 {
137 return *segment_->values[index_];
138 }
139
141 };
142
144 private:
145 Segment *segment_ = nullptr;
146 int64_t index_ = 0;
147
148 public:
149 MutableIterator(Segment *segment, int64_t index = 0) : segment_(segment), index_(index) {}
150
152 {
153 index_++;
154 if (index_ == segment_->size) {
155 segment_ = segment_->next;
156 index_ = 0;
157 }
158 return *this;
159 }
160
162 {
163 return *segment_->values[index_];
164 }
165
167 };
168
170 {
171 return ConstIterator(current_segment_, 0);
172 }
173
175 {
176 return ConstIterator(nullptr, 0);
177 }
178
180 {
181 return MutableIterator(current_segment_, 0);
182 }
183
185 {
186 return MutableIterator(nullptr, 0);
187 }
188};
189
190} // namespace blender::linear_allocator
#define BLI_STRUCT_EQUALITY_OPERATORS_2(Type, m1, m2)
destruct_ptr< T > construct(Args &&...args)
void append(LinearAllocator<> &allocator, const T &value)
void append_as(LinearAllocator<> &allocator, Args &&...args)
void append(LinearAllocator<> &allocator, T &&value)
#define T
__int64 int64_t
Definition stdint.h:89